diff --git a/SUMMARY.md b/SUMMARY.md index c297becb..25d2b07a 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -1,10 +1,9 @@ # Summary * [The LHCb Starterkit](README.md) - * [Contributing](CONTRIBUTING.md) - ----- + * [Contributing](CONTRIBUTING.md) +----- * [First analysis steps](first-analysis-steps/README.md) * [Pre-workshop checklist](first-analysis-steps/prerequisites.md) * [Goals of the course](first-analysis-steps/introduction-to-course.md) @@ -18,6 +17,7 @@ * [Running a minimal DaVinci job locally](first-analysis-steps/minimal-dv-job.md) * [Running DaVinci on the grid](first-analysis-steps/davinci-grid.md) * [TupleTools and branches](first-analysis-steps/add-tupletools.md) + * [TupleTools](first-analysis-steps/TupleTools.md) * [How do I use DecayTreeFitter?](first-analysis-steps/decay-tree-fitter.md) * [More Ganga](first-analysis-steps/ganga-data.md) * [Storing large files on EOS](first-analysis-steps/eos-storage.md) @@ -27,31 +27,30 @@ * [Early career, gender and diversity](first-analysis-steps/ecgd.md) * [Contribute to this lesson](first-analysis-steps/contributing-lesson.md) ----- - +----- * [Second analysis steps](second-analysis-steps/README.md) * [Using git to develop LHCb software](second-analysis-steps/lb-git.md) * [Building your own decay](second-analysis-steps/building-decays.md) - * [The Selection Framework](second-analysis-steps/building-decays-part0.md) - * [A Historical Approach](second-analysis-steps/building-decays-part1.md) - * [Modern Selection Framework](second-analysis-steps/building-decays-part2.md) + * [The Selection Framework](second-analysis-steps/building-decays-part0.md) + * [A Historical Approach](second-analysis-steps/building-decays-part1.md) + * [Modern Selection Framework](second-analysis-steps/building-decays-part2.md) * [What to do when something fails](second-analysis-steps/fixing-errors.md) * [Run a different stripping line on simulated data](second-analysis-steps/rerun-stripping.md) * [Replace a mass hypothesis](second-analysis-steps/switch-mass-hypo.md) * [Reuse particles from a decay tree](second-analysis-steps/filter-in-trees.md) * [The simulation framework](second-analysis-steps/simulation.md) - * [Introduction: The basics of Gauss](second-analysis-steps/simulation-intro.md) - * [Getting the correct option files](second-analysis-steps/simulation-running-gauss.md) - * [Controlling the decay](second-analysis-steps/simulation-dkfiles.md) - * [Advanced: Controlling the decay](second-analysis-steps/simulation-advanced-dkfiles.md) - * [Modifying generator cuts](second-analysis-steps/simulation-gencuts.md) - * [Fast simulation options](second-analysis-steps/simulation-fastsim.md) + * [Introduction: The basics of Gauss](second-analysis-steps/simulation-intro.md) + * [Getting the correct option files](second-analysis-steps/simulation-running-gauss.md) + * [Controlling the decay](second-analysis-steps/simulation-dkfiles.md) + * [Advanced: Controlling the decay](second-analysis-steps/simulation-advanced-dkfiles.md) + * [Modifying generator cuts](second-analysis-steps/simulation-gencuts.md) + * [Fast simulation options](second-analysis-steps/simulation-fastsim.md) * [HLT intro](second-analysis-steps/hlt-intro.md) * [TisTos DIY](second-analysis-steps/tistos-diy.md) * [Ganga Scripting](second-analysis-steps/ganga-scripting.md) * [Managing files in Ganga](second-analysis-steps/managing-files-with-ganga.md) * [Analysis automation: snakemake](second-analysis-steps/analysis-automation-snakemake.md) ----- +----- +* [Download PDF](ref://starterkit-lessons.pdf) - * [Download PDF](ref://starterkit-lessons.pdf) diff --git a/first-analysis-steps/DecayTrees/MCTupleToolAngles.cpp b/first-analysis-steps/DecayTrees/MCTupleToolAngles.cpp new file mode 100644 index 00000000..3348ff25 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolAngles.cpp @@ -0,0 +1,65 @@ +// Include files +#include "gsl/gsl_sys.h" + +// from Gaudi +#include "GaudiKernel/PhysicalConstants.h" +#include "GaudiKernel/Vector3DTypes.h" + +// local +#include "MCTupleToolAngles.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/MCParticle.h" + +using namespace LHCb; +//----------------------------------------------------------------------------- +// Implementation file for class : MCTupleToolAngles +// +// 2009-01-19 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( MCTupleToolAngles ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + MCTupleToolAngles::MCTupleToolAngles( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); +} + +//============================================================================= +// Destructor +//============================================================================= +MCTupleToolAngles::~MCTupleToolAngles() {} + +//============================================================================= +// Fill +//============================================================================= +StatusCode MCTupleToolAngles::fill( const LHCb::MCParticle* mother + , const LHCb::MCParticle* mcp + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(head); + + bool test = true; + + double cosT =-999.; + + if ( 0!=mcp && 0!=mother && mcp!=mother ) cosT = cosTheta(mother->momentum(), mcp->momentum() ); + // fill the tuple: + test &= tuple->column( prefix+"_TRUECosTheta", cosT ); + if(isVerbose()) test &= tuple->column( prefix+"_TRUETheta", acos(cosT) ); + if ( msgLevel(MSG::DEBUG) && 0!=mcp && 0!=mother) + debug() << mother->particleID().pid() << " " << mother->momentum() << " " + << mcp->particleID().pid() << " " << mcp->momentum() << endmsg ; + + return StatusCode(test); +} diff --git a/first-analysis-steps/DecayTrees/MCTupleToolAngles.h b/first-analysis-steps/DecayTrees/MCTupleToolAngles.h new file mode 100644 index 00000000..194c24a0 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolAngles.h @@ -0,0 +1,60 @@ +// $Id: MCTupleToolAngles.h,v 1.3 2010-01-26 15:39:25 rlambert Exp $ +#ifndef MCTUPLETOOLANGLES_H +#define MCTUPLETOOLANGLES_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IMCParticleTupleTool.h" // Interface +#include "Math/Boost.h" +#include "GaudiKernel/Vector4DTypes.h" + +/** @class MCTupleToolAngles MCTupleToolAngles.h + * + * Fill MC Particle with decay angle in mother frame + * + * - head_TRUECosTheta : angle in mother's frame + * + * \sa TupleToolAngles, DecayTreeTuple, MCDecayTreeTuple + * + * @author Patrick Koppenburg + * @date 2009-01-19 + */ + +class MCTupleToolAngles : public TupleToolBase, + virtual public IMCParticleTupleTool +{ + +public: + + /// Standard constructor + MCTupleToolAngles( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~MCTupleToolAngles( ); ///< Destructor + + StatusCode fill( const LHCb::MCParticle* + , const LHCb::MCParticle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + inline double cosTheta( const Gaudi::LorentzVector& mother, + const Gaudi::LorentzVector& mcp ) + { + ROOT::Math::Boost boost( mother.BoostToCM() ); + const Gaudi::XYZVector boostedParticle = (boost( mcp )).Vect().unit(); + const Gaudi::XYZVector boostedMother = mother.Vect().unit(); + double cosT = boostedParticle.Dot(boostedMother) ; + if (msgLevel(MSG::VERBOSE)) verbose() << mother << " " + << mcp << " " << boostedMother + << " " << boostedParticle + << " " << cosT << endmsg ; + return cosT; + } + +}; + +#endif // MCTUPLETOOLANGLES_H diff --git a/first-analysis-steps/DecayTrees/MCTupleToolDalitz.cpp b/first-analysis-steps/DecayTrees/MCTupleToolDalitz.cpp new file mode 100644 index 00000000..52134873 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolDalitz.cpp @@ -0,0 +1,68 @@ +// Include files + +#include +#include + +// local +#include "MCTupleToolDalitz.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : MCTupleToolDalitz +// +// 2009-02-17 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( MCTupleToolDalitz ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + MCTupleToolDalitz::MCTupleToolDalitz( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_ppSvc(0) +{ + declareInterface(this); + +} +//============================================================================= +// Destructor +//============================================================================= +MCTupleToolDalitz::~MCTupleToolDalitz() {} + +//============================================================================= +//============================================================================= +// Fill +//============================================================================= +StatusCode MCTupleToolDalitz::fill( const LHCb::MCParticle* mother + , const LHCb::MCParticle* part + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(head); + + if (0==part) return StatusCode::FAILURE ; + if (msgLevel(MSG::DEBUG)) debug() << "Decay of " << part->particleID().pid() << " with mother " << mother << endmsg ; + LHCb::MCParticle::ConstVector dauts ; + for ( SmartRefVector::const_iterator iv = part->endVertices().begin() ; + iv != part->endVertices().end() ; ++iv){ + if (!(*iv)->isDecay()) continue ; + if (msgLevel(MSG::VERBOSE)) verbose() << "Decay vertex of type " << (*iv)->type() << " with " + << (*iv)->products().size() << " products" << endmsg ; + const SmartRefVector< LHCb::MCParticle > pr = (*iv)->products() ; + for ( SmartRefVector< LHCb::MCParticle >::const_iterator ip = pr.begin() ; ip != pr.end() ; ++ip){ + if (msgLevel(MSG::VERBOSE)) verbose() << "Pushing back " << (*ip)->particleID().pid() << endmsg ; + dauts.push_back(*ip); + } + break ; + } + + if ( 2>=dauts.size() ){ + return Warning("Will not fill Dalitz of two body decay "+prefix,StatusCode::SUCCESS,0); + } + + return fill(dauts,"MC",tuple,(part->particleID().pid()<0)) ; + +} diff --git a/first-analysis-steps/DecayTrees/MCTupleToolDalitz.h b/first-analysis-steps/DecayTrees/MCTupleToolDalitz.h new file mode 100644 index 00000000..de09409f --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolDalitz.h @@ -0,0 +1,51 @@ +// $Id: MCTupleToolDalitz.h,v 1.3 2010-01-26 15:39:25 rlambert Exp $ +#ifndef MCTUPLETOOLDALITZ_H +#define MCTUPLETOOLDALITZ_H 1 + +// Include files +// from Gaudi +#include "Kernel/IMCParticleTupleTool.h" +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/Escape.h" +#include "Event/MCParticle.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" + +// Boost +#include + +/** @class MCTupleToolDalitz MCTupleToolDalitz.h + * + * Fills square masses of all combinations of direct daughters + * + * @author Patrick Koppenburg + * @date 2009-02-17 + */ +class MCTupleToolDalitz : public TupleToolBase, + virtual public IMCParticleTupleTool +{ + +public: + + /// Standard constructor + MCTupleToolDalitz( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~MCTupleToolDalitz( ); ///< Destructor + + /// The filling method + StatusCode fill( const LHCb::MCParticle* + , const LHCb::MCParticle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + // Horrid way of sharing code. Should use inheritance instead ... +#include "TupleToolDalitz.icpp" + +}; +#endif // MCTUPLETOOLDALITZ_H diff --git a/first-analysis-steps/DecayTrees/MCTupleToolDecayType.cpp b/first-analysis-steps/DecayTrees/MCTupleToolDecayType.cpp new file mode 100755 index 00000000..4fed0550 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolDecayType.cpp @@ -0,0 +1,256 @@ +// Include files +#include "gsl/gsl_sys.h" +// from Gaudi +#include "GaudiKernel/PhysicalConstants.h" +// local +#include "MCTupleToolDecayType.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" +#include "Event/MCParticle.h" + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : MCTupleToolDecayType +// +// 2009-05-01 : Rob Lambert +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( MCTupleToolDecayType ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +MCTupleToolDecayType::MCTupleToolDecayType( const std::string& type, + const std::string& name, + const IInterface* parent ) +: TupleToolBase ( type, name , parent ) + , m_mother(0) + , m_fillSlowFind(0) + , m_fillPseudoFind(0) + , m_findEventTypes(0) + , m_hasEventType(0) + , m_hasMCDecay("") + , m_mcEventType(0) + , m_mcDecay(0) +{ + declareInterface(this); + + // categorise the mcmother of this mcparticle, not the associate itself + declareProperty( "mother", m_mother = false ); + + // categorise the ultimate mcmother of this mcparticle, not the associate itself + declareProperty( "top", m_mother = false ); + + // search through using decay strings, very slow method + declareProperty( "fillSlowFind", m_fillSlowFind=false ); + + // construct the event types logically, much faster but less accurate + declareProperty( "fillPseudoFind", m_fillPseudoFind=true ); + + // the full list of all event types to consider. + declareProperty( "allEventTypes", m_findEventTypes=std::vector(0) ); + + // list of event types, the number of these types in the event will appear as an entry in the ntuple + declareProperty( "hasEventTypes", m_hasEventType=std::vector(0) ); + + // look for this decay string aswell + declareProperty( "hasMCDecay", m_hasMCDecay="" ); + + //extra name. MCP in this case. + setProperty("ExtraName", "MCP"); +} + +//============================================================================= + +StatusCode MCTupleToolDecayType::initialize() +{ + StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_mcEventType = tool("MCEventTypeFinder","Event_Type",this); + m_mcDecay = tool("MCDecayFinder","Decay_Type",this); + + vec2set(m_findEventTypes,m_findEventTypeSet); + vec2set(m_hasEventType,m_hasEventTypeSet); + + if(!m_findEventTypes.empty()) sc=m_mcEventType->setEventTypes(m_findEventTypeSet); + if(!m_findEventTypes.empty() && sc.isFailure()) + { + warning()<<"Error setting the event types starting with " << m_findEventTypes[0] << endmsg; + m_findEventTypes.clear(); + } + + if (m_mcDecay && m_hasMCDecay!="") sc=m_mcDecay->setDecay(m_hasMCDecay); + if(sc.isFailure()) + { + warning()<<"Error setting this decay string " << m_hasMCDecay << endmsg; + m_mcDecay=NULL; + m_hasMCDecay=""; + + } + if(msgLevel(MSG::DEBUG)) + { + //output all the options + debug() << "MCTupleToolDecayType initialised. Values are set as follows:" << endmsg; + debug() << "-m_mother " << m_mother << endmsg; + debug() << "-m_fillSlowFind " << m_fillSlowFind << endmsg; + debug() << "-m_fillPseudoFind " << m_fillPseudoFind << endmsg; + debug() << "-m_hasMCDecay " << m_hasMCDecay << endmsg; + debug() << "-m_findEventTypeSet.size() " << m_findEventTypeSet.size() << endmsg; + debug() << "-m_hasEventTypeSet.size() " << m_hasEventTypeSet.size() << endmsg; + debug() << "-m_mcEventType " << (m_mcEventType!=NULL) << endmsg; + debug() << "-m_mcDecay " << (m_mcDecay!=NULL) << endmsg; + + } + + + return StatusCode::SUCCESS; +} + +StatusCode MCTupleToolDecayType::fill( const LHCb::MCParticle* + , const LHCb::MCParticle* mcp + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(head); + + if(msgLevel(MSG::DEBUG)) debug() << "Filling MCTupleToolDecayType" << endmsg; + + + //The fill method is is two stages and is steered by the options. + //Firstly, if asked, (fillWholeEvent) the full event is searched for all types + //Secondly, if asked, (fillAssociated) the MC associated particle is searched for all types + + StatusCode sc=StatusCode::SUCCESS; + + bool test=true; + + + if(msgLevel(MSG::DEBUG)) debug() << "finding event types for MCAssociate" << endmsg; + LHCb::EventTypeSet foundfull; + LHCb::EventTypeSet foundfast; + + // pointer is ready, prepare the sets: + if( mcp ) + { + verbose() << "found MC Particle" << endmsg; + //fast or slow? + if(m_fillSlowFind) sc=m_mcEventType->findDecayType(foundfull,mcp); + if(sc.isFailure()) + { + warning() << "Could not perform the fill using the slow method, reverting to the fast method" << endmsg; + m_fillSlowFind=false; + m_fillPseudoFind=true; + } + + if(m_fillPseudoFind) sc=m_mcEventType->constructDecayType(foundfast,mcp); + if(sc.isFailure()) + { + warning() << "Could not perform the fill using the fast method," + << " I therefore cannot find the overall event type" << endmsg; + m_fillPseudoFind=false; + } + } + if(msgLevel(MSG::DEBUG)) debug() << "filling info for MCAssociate" << endmsg; + if(m_fillSlowFind) + { + test &= tuple->column( prefix+"_numFoundTypes", foundfull.size() ); + //insert "found" as an farray + std::vector foundvec(0); + set2vec(foundfull,foundvec); + test &= tuple->farray( prefix+"_MCP_FoundTypes", foundvec, prefix+"_FoundLen", 20 ); + + if(!m_hasEventTypeSet.empty()) //book the matching types + { + + LHCb::EventTypeSet intersection; + std::set_intersection(foundfull.begin(),foundfull.end(), + m_hasEventTypeSet.begin(), m_hasEventTypeSet.end(), + std::inserter(intersection,intersection.begin()), + LHCb::EventTypeComp() ); + + //bool foundGiven=(intersection.size()>0); + test &= tuple->column( prefix+"_numMatchingTypes", intersection.size() ); + if(msgLevel(MSG::DEBUG)) debug() << "booked intersection of size:" + << intersection.size() << endmsg; + //insert "found" as an farray + std::vector _foundvec(0); + set2vec(intersection,_foundvec); + test &= tuple->farray( prefix+"_MatchingTypes", _foundvec, prefix+"_MatchLen", m_hasEventTypeSet.size() ); + } + } + if(m_fillPseudoFind) + { + test &= tuple->column( prefix+"_numPseudoTypes", foundfast.size() ); + //insert "found" as an farray + std::vector foundvec(0); + set2vec(foundfast,foundvec); + test &= tuple->farray( prefix+"_PseudoTypes", foundvec, prefix+"_MCP_PseudoLen", 20 ); + + if(!m_hasEventTypeSet.empty()) //book the matching types + { + + LHCb::EventTypeSet intersection; + std::set_intersection(foundfast.begin(),foundfast.end(), + m_hasEventTypeSet.begin(), m_hasEventTypeSet.end(), + std::inserter(intersection,intersection.begin()), + LHCb::EventTypeComp() ); + + //bool foundGiven=(intersection.size()>0); + test &= tuple->column( prefix+"_numMatchingPseudoTypes", intersection.size() ); + if(msgLevel(MSG::DEBUG)) debug() << "booked intersection of size:" + << intersection.size() << endmsg; + //insert "found" as an farray + std::vector _foundvec(0); + set2vec(intersection,_foundvec); + test &= tuple->farray( prefix+"_MatchingPseudoTypes", + _foundvec, prefix+"_MCP_MatchPseudoLen", + m_hasEventTypeSet.size() ); + } + } + + if(m_hasMCDecay!="" && m_mcDecay ) + { + bool hasMCDecay =false; + LHCb::MCParticle::ConstVector dummyvec(0); //stupid way, but is the only way! + if (mcp) + { + dummyvec.push_back(mcp); + hasMCDecay = m_mcDecay->hasDecay(dummyvec); + } + + test &= tuple->column( prefix+"_hasGivenDecay", hasMCDecay ); + //use the standard decay finding method + } + + if(msgLevel(MSG::DEBUG)) debug() << "done and returning" << endmsg; + + return StatusCode(test); +} + +bool MCTupleToolDecayType::vec2set(std::vector& avec, LHCb::EventTypeSet& aset) +{ + aset.clear(); + for(std::vector::iterator n=avec.begin(); n!=avec.end(); n++) + { + aset.insert(*n); + } + return (aset.size() > 0); +} + +bool MCTupleToolDecayType::set2vec(LHCb::EventTypeSet& aset,std::vector& avec) +{ + avec.clear(); + avec.reserve(aset.size()); + for(LHCb::EventTypeSet::iterator n=aset.begin(); n!=aset.end(); n++) + { + avec.push_back(*n); + } + return (avec.size() > 0); +} diff --git a/first-analysis-steps/DecayTrees/MCTupleToolDecayType.h b/first-analysis-steps/DecayTrees/MCTupleToolDecayType.h new file mode 100755 index 00000000..05ba43b3 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolDecayType.h @@ -0,0 +1,253 @@ +// $Id: MCTupleToolDecayType.h,v 1.3 2010-01-26 15:39:25 rlambert Exp $ +#ifndef TUPLETOOLMCDECAYTYPE_H +#define TUPLETOOLMCDECAYTYPE_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IMCParticleTupleTool.h" // Interface +#include "Event/GenCollision.h" +#include "Event/GenHeader.h" + +//struct Particle2MCLinker; +#include "Kernel/Particle2MCLinker.h" +#include "Kernel/IDaVinciAssociatorsWrapper.h" +#include "MCInterfaces/IMCEventTypeFinder.h" +#include "MCInterfaces/IMCDecayFinder.h" +#include "Kernel/IBackgroundCategory.h" +#include +/** @class MCTupleToolDecayType MCTupleToolDecayType.h jborel/MCTupleToolDecayType.h + * + * \brief + * \sa DecayTreeTuple + * + * @author Robert Lambert + * @date 2009-02-25 + * + * This TupleTool enables you to output the LHCb EventTypes for the MC particle associated to this candidate + * and/or search for a given MCDecay string + * The association should be done in TupleToolMCTruth + * + * There are two methods used to find the event type (Pseudo or Slow) + * and several places you can look for the event type (GenHeader, FullEvent, MCAssociate) + * + * CONFIGURATION: + + * You will also need to configure the EvtTypeSvc(), which takes the list of all possible decays from Gauss + + * EvtTypeSvc().EvtTypesFile='...fullpath.../table_event.txt' + + * Usually the file resides in $DECFILESROOT/doc/table_event.txt, copy and ship it with your job + + * METHODS: + + * + + * A) The Pseudo method: guesses the event type, by constructing the possible types + + * based on the definition of event types in the LHCb note + + * this is fast, works on all decays, but is ambiguous. + + * To look for inclusive types, this is the best method. + + * + + * B) The Slow Method : Finds the event type based on the decay string. + + * This is accurate, but relies on the string being correct + + * in the .dec file of this decay. Most of the time this is not the case. + + * To check the decay file you've written is correct, this is the best method. + + * + + * WHERE TO LOOK: + + * + + * 1) The GenHeader : The GenHeader contains the event type which was generated. + + * If this is all you need, and you want no information on the other + + * possible decays in this event, you can stop here. + + * If all you want to do is find the heaviest quark in the event, + + * use the TupleToolGeneration. + + * + + * 2) The Full Event : Every MCParticle in the event is checked to see how it decayed. + + * The full list of all possible event types of this event can then be found. + + * + + * 3) The MCAssociate : The decay of the MCAssociate, or it's mother, or the top of the tree, is checked. + + * A categorisation of any fully or partially reconstructed backgrounds + + * can then be made. + + * This output is complimentary to background category and the MCHierachy and + + * can be used as a rudimentary categorisation of backgrounds. + + * + + * For method (3) use this TupleTool. For methods (1) and (2) use the TupleToolMCEventType + + * + + * + + * OPTIONS: + + * + * + + * mother bool Actually categorise the mc mother of this particle, not the associate itself + + * by default this is false + + * top bool Actually categorise the ultimate mcmother of this mcparticle, not the associate itself + + * by default this is false + + * + + * UseChi2Method bool assosciate using chi2 + + * by default this is false + + * InputLocations bool Associator input location. + + * by default this is empty, fine for most cases + + * + + * fillSlowFind bool search through using decay strings, very slow method + + * by default this is false + + * fillPseudoFind bool construct the event types logically, much faster but less accurate + + * by default this is true + + * + + * allEventTypes std::vector the full list of all event types to consider. for the slow find. + + * This is ignored by the fast find. + + * By default this is the whole list in the DekFile doc + + * hasEventTypes std::vector list of event types, the number of these types in the event + + * will appear as an entry in the ntuple + + * by default this is empty + + * hasMCDecay std::string look for this decay string aswell + + * by default this is empty + + * + + * ENTRIES: + + * + + * Depending on the options, different entries will be written out. + + * By default, only the Pseudo event types will be looked for + + * + + * _MCP_FoundTypes (farray) List of all found event types for the assosciate + + * _MCP_FoundLen (unsigned int) Maximum length of this farray + + * _MCP_numFoundTypes (unsigned int) number of types found in this case + + * _MCP_MatchingTypes (farray) List of Event types which match those in hasEventType for the assosciate + + * _MCP_MatchLen (unsigned int) Maximum length of this farray + + * _MCP_numMatchingTypes (unsigned int) How many of hasEventType there are in the Event Types for the assosciate + + * + + * _MCP_PseudoTypes (farray) List of all found event types for the assosciate + + * _MCP_PseudoLen (unsigned int) Maximum length of this farray + + * _MCP_numPseudoTypes (unsigned int) number of pseudo types found in this case + + * _MCP_MatchingPseudoTypes (farray) List of Pseudo Event types which match those in hasEventType for the MCP + + * _MCP_MatchPseudoLen (unsigned int) Maximum length of this farray + + * _MCP_numMatchingPseudoTypes (unsigned int) How many of hasEventType are in the Pseudo Event Types for the assosciate + + * + + * _MCP_hasGivenDecay (bool) does this MCP decay by the string in hasMCDecay? + + * + */ + + +class MCTupleToolDecayType : public TupleToolBase, virtual public IMCParticleTupleTool +{ + +public: + + /// Standard constructor + MCTupleToolDecayType( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~MCTupleToolDecayType(){}; ///< Destructor + + StatusCode fill( const LHCb::MCParticle* + , const LHCb::MCParticle* + , const std::string& + , Tuples::Tuple& ) override; + + StatusCode initialize() override; + +private: + + // const GaudiAlgorithm* getParent() const ; + + //Members which are set by the options: + + bool m_mother; //!< set by mother option categorise the mcmother of this mcparticle, not the associate itself + bool m_fillSlowFind; //< set by the fillSlowFind option, search through using decay strings + bool m_fillPseudoFind; //< set by the fillPseudoFind option, construct the event types logically, much faster but less accurate + + ///m_findEventTypes set by the allEventTypes option, the full list of all event types to consider. + std::vector m_findEventTypes; + ///m_hasEventType set by the hasEventType option, how many of this list of types appear in this event? + std::vector m_hasEventType; + std::string m_hasMCDecay; //< set by the hasMCDecay option, look for this decay string aswell + + //Other Members + + LHCb::EventTypeSet m_findEventTypeSet; //< loaded from m_findEventTypes + LHCb::EventTypeSet m_hasEventTypeSet; //< loaded from m_hasEventType + + IMCEventTypeFinder* m_mcEventType; //< the EventTypeFinder tool + IMCDecayFinder* m_mcDecay; //< the DecayTypeFinder tool + + ///convert a std::vector to a std::set + bool vec2set(std::vector& avec,LHCb::EventTypeSet& aset); + bool set2vec(LHCb::EventTypeSet& aset,std::vector& avec); + //want to cache genEventID/string?? + +}; + +#endif // TUPLETOOLMCDECAYTYPE_H diff --git a/first-analysis-steps/DecayTrees/MCTupleToolEventType.cpp b/first-analysis-steps/DecayTrees/MCTupleToolEventType.cpp new file mode 100755 index 00000000..3ad5910a --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolEventType.cpp @@ -0,0 +1,320 @@ +// Include files +// from Gaudi +#include "GaudiKernel/PhysicalConstants.h" +// local +#include "MCTupleToolEventType.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : MCTupleToolEventType +// +// 2009-03-04 : R Lambert +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( MCTupleToolEventType ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + MCTupleToolEventType::MCTupleToolEventType( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_fillGenEvent(0) + , m_findGenEvent(0) + , m_fillWholeEvent(0) + , m_fillSlowFind(0) + , m_fillPseudoFind(0) + , m_findEventTypes(0) + , m_hasEventType(0) + , m_hasMCDecay("") + , m_mcEventType(0) + , m_mcDecay(0) +{ + declareInterface(this); + + // should I write out the gen event header? + declareProperty( "fillGenEvent", m_fillGenEvent=true ); + + // should I look for the generated type in the event? + declareProperty( "findGenEvent", m_findGenEvent=false ); + + // should I examine every MC particle in the event? + declareProperty( "fillWholeEvent", m_fillWholeEvent=true ); + + // search through using decay strings, very slow method + declareProperty( "fillSlowFind", m_fillSlowFind=false ); + + // construct the event types logically, much faster but less accurate + declareProperty( "fillPseudoFind", m_fillPseudoFind=true ); + + // the full list of all event types to consider.for the slow find. This is ignored by the fast/Pseudo find. + declareProperty( "allEventTypes", m_findEventTypes=std::vector(0) ); + + // list of event types, the number of these types in the event will appear as an entry in the ntuple + declareProperty( "hasEventTypes", m_hasEventType=std::vector(0) ); + + // look for this decay string aswell + declareProperty( "hasMCDecay", m_hasMCDecay="" ); + + //extra name. EVT in this case. + setProperty("ExtraName", "EVT"); +} + +//============================================================================= + +StatusCode MCTupleToolEventType::initialize() +{ + if( ! TupleToolBase::initialize() ) return StatusCode::FAILURE; + StatusCode sc=StatusCode::SUCCESS; + + m_mcEventType = tool("MCEventTypeFinder","Event_Type",this); + m_mcDecay = tool("MCDecayFinder","Decay_Type",this); + + vec2set(m_findEventTypes,m_findEventTypeSet); + vec2set(m_hasEventType,m_hasEventTypeSet); + + if(!m_findEventTypeSet.empty()) sc=m_mcEventType->setEventTypes(m_findEventTypeSet); + if(!m_findEventTypeSet.empty() && sc.isFailure()) + { + warning()<<"Error setting the event types starting with " << m_findEventTypes[0] << endmsg; + m_findEventTypes.clear(); + m_findEventTypeSet.clear(); + } + + if (m_mcDecay && m_hasMCDecay!="") sc=m_mcDecay->setDecay(m_hasMCDecay); + if(sc.isFailure()) + { + warning()<<"Error setting this decay string " << m_hasMCDecay << endmsg; + m_mcDecay=NULL; + m_hasMCDecay=""; + + } + if ( msgLevel(MSG::DEBUG) ) + { + //output all the options + debug() << "MCTupleToolEventType initialised. Values are set as follows:" << endmsg; + debug() << "-m_fillGenEvent " << m_fillGenEvent << endmsg; + debug() << "-m_findGenEvent " << m_findGenEvent << endmsg; + debug() << "-m_fillWholeEvent " << m_fillWholeEvent << endmsg; + debug() << "-m_fillSlowFind " << m_fillSlowFind << endmsg; + debug() << "-m_fillPseudoFind " << m_fillPseudoFind << endmsg; + debug() << "-m_hasMCDecay " << m_hasMCDecay << endmsg; + debug() << "-m_findEventTypeSet.size() " << m_findEventTypeSet.size() << endmsg; + debug() << "-m_hasEventTypeSet.size() " << m_hasEventTypeSet.size() << endmsg; + debug() << "-m_mcEventType " << (m_mcEventType!=NULL) << endmsg; + debug() << "-m_mcDecay " << (m_mcDecay!=NULL) << endmsg; + + } + if(!m_fillGenEvent && !m_fillWholeEvent) warning() << "Nothing to fill, choose at least one of" + << " fillGenEvent or fillWholeEvent" << endmsg; + + + return StatusCode::SUCCESS; +} + +StatusCode MCTupleToolEventType::fill( Tuples::Tuple& tuple )/*( const LHCb::Particle* + , const LHCb::Particle* P + , const std::string& + , Tuples::Tuple& tuple )*/{ + + const std::string prefix=fullName(); + + if ( msgLevel(MSG::DEBUG) ) debug() << "Filling MCTupleToolEventType" << endmsg; + + + //The fill method is is two stages and is steered by the options. + //Firstly, if asked, (fillWholeEvent) the full event is searched for all types + + StatusCode sc=StatusCode::SUCCESS; + + bool test=true; + + LHCb::EventTypeSet foundfull, foundfast; + + //1) Find event types from full event + + //fast or slow? + if(m_findGenEvent || m_fillWholeEvent) + { + if ( msgLevel(MSG::DEBUG) ) debug() << "Running event type finder on full event" << endmsg; + //slow or fast method? + if(m_fillSlowFind) sc=m_mcEventType->findEventTypes(foundfull); + if(sc.isFailure()) + { + warning() << "Could not perform the fill using the slow method, reverting to the fast method" << endmsg; + m_fillSlowFind=false; + m_fillPseudoFind=true; + } + + if(m_fillPseudoFind && msgLevel(MSG::DEBUG) ) + debug() << "Just about to call construct event types" << endmsg; + if(m_fillPseudoFind) sc=m_mcEventType->constructEventTypes(foundfast); + if(m_fillPseudoFind && msgLevel(MSG::DEBUG) ) + debug() << "Finished call to construct event types" << endmsg; + if(sc.isFailure()) + { + warning() << "Could not perform the fill using the fast method, I therefore cannot find the overall event type" << endmsg; + m_fillWholeEvent=m_findGenEvent=false; + } + else if(msgLevel(MSG::DEBUG) || msgLevel(MSG::VERBOSE)) debug() + << "Found types on full event. All OK. fast:" << foundfast.size() << " slow:" << foundfull.size() << endmsg; + + } + + //add the generated event type, if it exists. + + if(m_fillGenEvent) + { + + if(msgLevel(MSG::DEBUG) || msgLevel(MSG::VERBOSE)) debug() << "filling gen event" << endmsg; + LHCb::GenHeader* header = getIfExists( evtSvc(), LHCb::GenHeaderLocation::Default, false ); + if(!header) + { + warning() << "The GenHeader could not be found, therefore it will not be filled" <evType(); + + //add this to the tuple + test &= tuple->column( prefix+"GenEvent", genType ); + + if(m_findGenEvent) //find the event of this type :) + { + if(m_fillSlowFind) + { + + bool foundGenType = (foundfull.count(genType)); + test &= tuple->column( prefix+"hasGenEvent", foundGenType ); + if(msgLevel(MSG::DEBUG) || msgLevel(MSG::VERBOSE)) debug() << "Booked slow event find" << endmsg; + } + if(m_fillPseudoFind) + { + + bool foundGenType = (foundfast.count(genType)); + test &= tuple->column( prefix+"hasPseudoGenEvent", foundGenType ); + if(msgLevel(MSG::DEBUG) || msgLevel(MSG::VERBOSE)) debug() << "Booked fast event find" << endmsg; + } + + } + } + + + } + + //add the event types for the whole event + + if(m_fillWholeEvent) + { + if ( msgLevel(MSG::DEBUG) ) debug() << "filling info for whole event" << endmsg; + if(m_fillSlowFind) + { + + test &= tuple->column( prefix+"numFoundTypes", foundfull.size() ); + + //insert "found" as an farray + std::vector foundvec(0); + set2vec(foundfull,foundvec); + if ( msgLevel(MSG::DEBUG) ) debug() << "ready to book vector of size:" + << foundvec.size() << endmsg; + test &= tuple->farray( "FoundTypes", foundvec, "FoundLen", 20 ); + if ( msgLevel(MSG::DEBUG) ) debug() << "booked vector of size:" << foundvec.size() << endmsg; + + if(!m_hasEventTypeSet.empty()) //book the matching types + { + + LHCb::EventTypeSet intersection; + std::set_intersection(foundfull.begin(),foundfull.end(), + m_hasEventTypeSet.begin(), m_hasEventTypeSet.end(), + std::insert_iterator(intersection,intersection.begin()), + LHCb::EventTypeComp() ); + + test &= tuple->column( prefix+"numMatchingTypes", intersection.size() ); + if ( msgLevel(MSG::DEBUG) ) debug() << "booked intersection of size:" + << intersection.size() << endmsg; + //insert "found" as an farray + std::vector _foundvec(0); + set2vec(intersection,_foundvec); + test &= tuple->farray( prefix+"MatchingTypes", _foundvec, prefix+"MatchLen", m_hasEventTypeSet.size() ); + } + } + if(m_fillPseudoFind) + { + + test &= tuple->column( prefix+"numPseudoTypes", foundfast.size() ); + //insert "found" as an farray + std::vector foundvec(0); + set2vec(foundfast,foundvec); + if ( msgLevel(MSG::DEBUG) ) debug() << "ready to book vector of size:" + << foundvec.size() << endmsg; + test &= tuple->farray( prefix+"PseudoTypes", foundvec, prefix+"PseudoLen", 20 ); + if ( msgLevel(MSG::DEBUG) ) debug() << "booked vector of size:" << foundvec.size() << endmsg; + + + if(!m_hasEventTypeSet.empty()) //book the matching types + { + + LHCb::EventTypeSet intersection; + std::set_intersection(foundfast.begin(),foundfast.end(), + m_hasEventTypeSet.begin(), m_hasEventTypeSet.end(), + std::insert_iterator(intersection,intersection.begin()), + LHCb::EventTypeComp() ); + + test &= tuple->column( prefix+"numMatchingPseudoTypes", intersection.size() ); + if ( msgLevel(MSG::DEBUG) ) debug() << "booked intersection of size:" + << intersection.size() << endmsg; + //insert "found" as an farray + std::vector _foundvec(0); + set2vec(intersection,_foundvec); + test &= tuple->farray( prefix+"MatchingPseudoTypes", _foundvec, prefix+"MatchPseudoLen", m_hasEventTypeSet.size() ); + } + + } + if(m_hasMCDecay!="" && m_mcDecay ) + { + bool hasMCDecay = m_mcDecay->hasDecay(); + test &= tuple->column( prefix+"hasGivenDecay", hasMCDecay ); + //use the standard decay finding method + } + + + } + + + if(msgLevel(MSG::DEBUG) || msgLevel(MSG::VERBOSE)) debug() << "done and returning" << endmsg; + return StatusCode(test); +} + +bool MCTupleToolEventType::vec2set(std::vector& avec, LHCb::EventTypeSet& aset) +{ + aset.clear(); + for(std::vector::iterator n=avec.begin(); n!=avec.end(); n++) + { + aset.insert(*n); + } + return (aset.size() > 0); + +} + +bool MCTupleToolEventType::set2vec(LHCb::EventTypeSet& aset,std::vector& avec) +{ + avec.clear(); + avec.reserve(aset.size()); + for(LHCb::EventTypeSet::iterator n=aset.begin(); n!=aset.end(); n++) + { + avec.push_back(*n); + } + return (avec.size() > 0); + +} diff --git a/first-analysis-steps/DecayTrees/MCTupleToolEventType.h b/first-analysis-steps/DecayTrees/MCTupleToolEventType.h new file mode 100755 index 00000000..f45b36d5 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolEventType.h @@ -0,0 +1,245 @@ +// $Id: MCTupleToolEventType.h,v 1.3 2010-01-26 15:39:25 rlambert Exp $ +#ifndef MCTUPLETOOLEVENTTYPE_H +#define MCTUPLETOOLEVENTTYPE_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface +#include "Event/GenCollision.h" +#include "Event/GenHeader.h" + +//struct Particle2MCLinker; +#include "Kernel/Particle2MCLinker.h" +#include "Kernel/IDaVinciAssociatorsWrapper.h" +#include "MCInterfaces/IMCEventTypeFinder.h" +#include "MCInterfaces/IMCDecayFinder.h" +#include +/** @class MCTupleToolEventType MCTupleToolEventType.h jborel/MCTupleToolEventType.h + * + * \brief + * \sa DecayTreeTuple + * + * @author Robert Lambert + * @date 2009-02-25 + * + * This TupleTool enables you to output the LHCb EventTypes for this event and/or search for a given MCDecay string + * + * There are two methods used to find the event type (Pseudo or Slow) + * and several places you can look for the event type (GenHeader, FullEvent, MCAssociate) + * + * CONFIGURATION: + + * You will also need to configure the EvtTypeSvc(), which takes the list of all possible decays from Gauss + + * EvtTypeSvc().EvtTypesFile='...fullpath.../table_event.txt' + + * Usually the file resides in $DECFILESROOT/doc/table_event.txt, copy and ship it with your job + + * + * METHODS: + * + * A) The Pseudo method: guesses the event type, by constructing the possible types + + * based on the definition of event types in the LHCb note + + * this is fast, works on all decays, but is ambiguous. + + * To look for inclusive types, this is the best method. + * + + * B) The Slow Method : Finds the event type based on the decay string. + + * This is accurate, but relies on the string being correct + + * in the .dec file of this decay. Most of the time this is not the case. + + * To check the decay file you've written is correct, this is the best method. + + * + * WHERE TO LOOK: + + * + + * 1) The GenHeader : The GenHeader contains the event type which was generated. + + * If this is all you need, and you want no information on the other + + * possible decays in this event, you can stop here. + + * If all you want to do is find the heaviest quark in the event, + + * use the TupleToolGeneration + + * + * 2) The Full Event : Every MCParticle in the event is checked to see how it decayed. + + * The full list of all possible event types of this event can then be found. + + * + + * 3) The MCAssociate : The decay of the MCAssociate, or it's mother, or the top of the tree is checked. + + * A categorisation of any fully or partially reconstructed backgrounds + + * can then be made. + + * This output is complimentary to background category and the MCHierachy and + + * can be used as a rudimentary categorisation of backgrounds. + + * + * To check the GenHeader and the event (1,2), use this tool. + + * To check the MCAssociate (3), use TupleToolMCDecayType + + * + + * OPTIONS: + + * + * + + * fillGenEvent bool should I write out the gen event header? + + * by default this is true + + * findGenEvent bool should I look for the generated type in the event? + + * by default this is false + + * fillWholeEvent bool should I examine every MC particle in the event? + + * by default this is true + + * + + * fillSlowFind bool search through using decay strings, very slow method + + * by default this is false + + * fillPseudoFind bool construct the event types logically, much faster but less accurate + + * by default this is true + + * + + * allEventTypes std::vector the full list of all event types to consider. for the slow find. + + * This is ignored by the fast find. + + * By default this is the whole list in the DekFile doc + + * hasEventTypes std::vector list of event types, the number of these types in the event + + * will appear as an entry in the ntuple + + * by default this is empty + + * hasMCDecay std::string look for this decay string aswell + + * by default this is empty + + * + + * ENTRIES: + + * + + * Depending on the options, different entries will be written out. + + * By default, only the Pseudo event types will be looked for + + * + + * EVT_GenEvent (long unsigned int) The event type in the GenHeader + + * EVT_hasGenEvent (bool) Does the GenEvent decay string appear? + + * EVT_hasPseudoGenEvent (bool) is there a pseudo decay like the one generated? + + * + + * EVT_FoundTypes (farray) List of all found event types + + * EVT_FoundLen (unsigned int) Maximum length of this farray + + * EVT_numFoundTypes (unsigned int) number of types found in this case + + * EVT_MatchingTypes (farray) List of Event types which match those in hasEventType + + * EVT_MatchLen (unsigned int) Maximum length of this farray + + * EVT_numMatchingTypes (unsigned int) How many of hasEventType there are in the Event Types + + * + + * EVT_PseudoTypes (farray) List of all found event types + + * EVT_PseudoLen (unsigned int) Maximum length of this farray + + * EVT_numPseudoTypes (unsigned int) number of pseudo types found in this case + + * EVT_MatchingPseudoTypes (farray) List of Pseudo Event types which match those in hasEventType + + * EVT_MatchPseudoLen (unsigned int) Maximum length of this farray + + * EVT_numMatchingPseudoTypes (unsigned int) How many of hasEventType there are in the Pseudo Event Types + + * + + * EVT_hasGivenDecay (bool) does this event contain the decay in hasMCDecay + + * + * + */ + + +class MCTupleToolEventType : public TupleToolBase, virtual public IEventTupleTool { +public: + /// Standard constructor + MCTupleToolEventType( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~MCTupleToolEventType(){}; ///< Destructor + + StatusCode fill(Tuples::Tuple&) override;/*( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& );*/ + + StatusCode initialize() override; + // virtual StatusCode finalize(); + +private: + + //Members which are set by the options: + + bool m_fillGenEvent; //< set by the fillGenEvent option, should I check the gen event header? + bool m_findGenEvent; //< set by the findGenEvent option, should I look for the gen event header in the events? + bool m_fillWholeEvent; //< set by the fillWholeEvent option, to fill info on the whole event + bool m_fillSlowFind; //< set by the fillSlowFind option, search through using decay strings + bool m_fillPseudoFind; //< set by the fillPseudoFind option, construct the event types logically, much faster but less accurate + + /// m_findEventTypes set by the allEventTypes option, the full list of all event types to consider. + std::vector m_findEventTypes; + /// m_hasEventType set by the hasEventType option, how many of this list of types appear in this event? + std::vector m_hasEventType; + std::string m_hasMCDecay; //< set by the hasMCDecay option, look for this decay string aswell + + //Other Members + + LHCb::EventTypeSet m_findEventTypeSet; //< loaded from m_findEventTypes + LHCb::EventTypeSet m_hasEventTypeSet; //< loaded from m_hasEventType + + IMCEventTypeFinder* m_mcEventType; //< the EventTypeFinder tool + IMCDecayFinder* m_mcDecay; //< the DecayTypeFinder tool + + ///convert a std::vector to a std::set + bool vec2set(std::vector& avec,LHCb::EventTypeSet& aset); + bool set2vec(LHCb::EventTypeSet& aset,std::vector& avec); + +}; + +#endif // MCTUPLETOOLEVENTTYPE_H diff --git a/first-analysis-steps/DecayTrees/MCTupleToolHierarchy.cpp b/first-analysis-steps/DecayTrees/MCTupleToolHierarchy.cpp new file mode 100755 index 00000000..b95c12a9 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolHierarchy.cpp @@ -0,0 +1,86 @@ +// Include files +#include "gsl/gsl_sys.h" +// from Gaudi +#include "GaudiKernel/PhysicalConstants.h" +// local +#include "MCTupleToolHierarchy.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" +#include "Event/MCParticle.h" + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : EventInfoTupleTool +// +// 2008-02-28 : Stephane Poss +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( MCTupleToolHierarchy ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + MCTupleToolHierarchy::MCTupleToolHierarchy( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); +} + +//============================================================================= +StatusCode MCTupleToolHierarchy::fill( const LHCb::MCParticle* + , const LHCb::MCParticle* mcp + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(head); + bool test=true; + + + int mc_mother_id = 0; + int mc_mother_key = 0; + int mc_gd_mother_id = 0; + int mc_gd_mother_key = 0; + int mc_gd_gd_mother_id = 0; + int mc_gd_gd_mother_key = 0; + + + // pointer is ready, prepare the values: + if( mcp ){ + const MCParticle* mcpmom(0); + mcpmom = mcp->mother(); + if(mcpmom){ + mc_mother_id = mcpmom->particleID().pid(); + mc_mother_key = mcpmom->key(); + const MCParticle* mcpmom_mom(0); + mcpmom_mom = mcpmom->mother(); + if(mcpmom_mom){ + mc_gd_mother_id = mcpmom_mom->particleID().pid(); + mc_gd_mother_key = mcpmom_mom->key(); + const MCParticle* mcpmom_mom_mom(0); + mcpmom_mom_mom = mcpmom_mom->mother(); + if(mcpmom_mom_mom){ + mc_gd_gd_mother_id = mcpmom_mom_mom->particleID().pid(); + mc_gd_gd_mother_key = mcpmom_mom_mom->key(); + } + } + } + } + + // fill the tuple: + test &= tuple->column( prefix+"_MC_MOTHER_ID", mc_mother_id ); + test &= tuple->column( prefix+"_MC_MOTHER_KEY", mc_mother_key ); + test &= tuple->column( prefix+"_MC_GD_MOTHER_ID", mc_gd_mother_id ); + test &= tuple->column( prefix+"_MC_GD_MOTHER_KEY", mc_gd_mother_key ); + test &= tuple->column( prefix+"_MC_GD_GD_MOTHER_ID", mc_gd_gd_mother_id ); + test &= tuple->column( prefix+"_MC_GD_GD_MOTHER_KEY", mc_gd_gd_mother_key ); + + return StatusCode(test); +} diff --git a/first-analysis-steps/DecayTrees/MCTupleToolHierarchy.h b/first-analysis-steps/DecayTrees/MCTupleToolHierarchy.h new file mode 100755 index 00000000..28f77d7e --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolHierarchy.h @@ -0,0 +1,58 @@ +// $Id: MCTupleToolHierarchy.h,v 1.2 2010-01-26 15:39:25 rlambert Exp $ +#ifndef SPOSS_TUPLETOOLMCHIERARCHY_H +#define SPOSS_TUPLETOOLMCHIERARCHY_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IMCParticleTupleTool.h" // Interface + +//struct Particle2MCLinker; +#include "Kernel/Particle2MCLinker.h" +#include "Kernel/IDaVinciAssociatorsWrapper.h" + +/** @class MCTupleToolHierarchy + * + * \brief Fill MC hierarchy info if a link is present + * + * Requires association from TupleToolMCTruth, or a MCDecayTreeTuple + * + * + * - head_MC_MOTHER_ID : true mc mother ID + + * - head_MC_MOTHER_KEY : true mc mother key + + * - head_MC_GD_MOTHER_ID : grand mother ID + + * - head_MC_GD_MOTHER_KEY : grand mother key + + * - head_MC_GD_GD_MOTHER_ID : grand grand mother ID + + * - head_MC_GD_GD_MOTHER_KEY : grand grand mother key + + * \sa DecayTreeTuple + * + * @author Stephane Poss + * @date 2008-02-28 + */ +class MCTupleToolHierarchy : public TupleToolBase, + virtual public IMCParticleTupleTool +{ + +public: + + /// Standard constructor + MCTupleToolHierarchy( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~MCTupleToolHierarchy(){}; ///< Destructor + + StatusCode fill( const LHCb::MCParticle* + , const LHCb::MCParticle* + , const std::string& + , Tuples::Tuple& ) override; + +}; + +#endif // SPOSS_TUPLETOOLMCHIERARCHY_H diff --git a/first-analysis-steps/DecayTrees/MCTupleToolInteractions.cpp b/first-analysis-steps/DecayTrees/MCTupleToolInteractions.cpp new file mode 100755 index 00000000..1619a5cd --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolInteractions.cpp @@ -0,0 +1,153 @@ +// $Id: MCTupleToolInteractions.cpp,v 1.2 2010-01-26 15:39:25 rlambert Exp $ + +// local +#include "MCTupleToolInteractions.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : GenerationTupleTool +// +// 2008-07-01 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +using namespace Gaudi; +using namespace LHCb; + +// Declaration of the Tool Factory +DECLARE_COMPONENT( MCTupleToolInteractions ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +MCTupleToolInteractions::MCTupleToolInteractions( const std::string& type, + const std::string& name, + const IInterface* parent ) +: TupleToolBase ( type, name , parent ) + ,m_mean(0.) + ,m_adjustmean(0.) + ,m_normaliseAt(0) + ,m_useRecPV(false) +{ + declareInterface(this); + + // overwrite the mean value of interactions for this event + declareProperty( "Mean", m_mean=0. ); + + // calculate a scaling factor to approximate this number of interactions per event + declareProperty( "AdjustMean", m_adjustmean=0. ); + + // normalise the scaling factor such that it is equal to 1 at this value of I + declareProperty( "NormaliseAt", m_normaliseAt=0 ); + + // use the #of reconstructed PVs, rather than the MC Collisions. + declareProperty( "UseRecPV", m_useRecPV=false ); + + //deprecated, use Verbose + // fill extra information on MCPV, MC Collisions and Reconstructed PVs + //declareProperty( "FillDetails", m_fillDetails=false ); + + // change the default PV location + declareProperty( "RecPVLocation", m_RecPVLocation=LHCb::RecVertexLocation::Primary ); + + // prefix to give to the variables, in case you want to use two copies of this tool + setProperty( "ExtraName", "EVT_Int" ); +} + +//============================================================================= + +StatusCode MCTupleToolInteractions::fill( Tuples::Tuple& tuple ) +{ + const std::string prefix = fullName(); + unsigned int n = 1; + int MCI = -1; + int MCPV = -1; + int RecPV = -1; + const LHCb::GenHeader* gh = get(LHCb::GenHeaderLocation::Default); + + if ( gh && !gh->collisions().empty() ) + { + MCI = gh->collisions().size() ; + if ( msgLevel(MSG::VERBOSE) ) verbose() << "retrieved I from genHeader" << endmsg; + } + + if ( MCI<=0 || isVerbose() ) + { + const LHCb::MCHeader* mch = get(LHCb::MCHeaderLocation::Default); + if(mch) + { + MCPV = mch->primaryVertices().size() ; + } + } + + if(isVerbose() || m_useRecPV) + { + const RecVertex::Container* PV = get(m_RecPVLocation); + if(PV) + { + RecPV = PV->size() ; + } + } + if ( m_useRecPV && RecPV>=0 ) { n=RecPV; } + else if ( !m_useRecPV && MCI > 0 ) { n=MCI; } + else if ( !m_useRecPV && MCPV > 0 ) { n=MCPV; } + else + { + Warning( "Could not retrieve number of interactions, filling as if n=1", + StatusCode::SUCCESS ).ignore(); + } + + + double mean=m_mean; + if ( mean == 0. ) + { + if ( msgLevel(MSG::VERBOSE) ) verbose() << "calculating mean" << endmsg; + //extract it from the GenHeader + + //as in the IPileUpTool for FixedLuminosity.{h,cpp} + if(gh && gh->crossingFreq() && gh->luminosity() && gh->totCrossSection()) + { + if ( msgLevel(MSG::VERBOSE) ) verbose() << "using genheader " << mean << endmsg; + mean=gh->luminosity()*gh->totCrossSection()/gh->crossingFreq(); + } + + //if it isn't in the GenHeader, then make a default, the DC06 mean + else + { + if ( msgLevel(MSG::VERBOSE) ) verbose() << "using default for DC06 data " << mean << endmsg; + mean=(2.e32 /Gaudi::Units::cm2/Gaudi::Units::s)*(102.4 * Gaudi::Units::millibarn)/(30.0 * Gaudi::Units::megahertz); + } + + + if ( msgLevel(MSG::VERBOSE) ) verbose() << "calculated mean " << mean << endmsg; + //if it isn't in the GenHeader, then make a default + } + + if ( msgLevel(MSG::VERBOSE) ) verbose() << "Filling tuples" << endmsg; + bool test = true; + test &= tuple->column( prefix + "_I" , n ); + test &= tuple->column( prefix + "_Mean" , mean ); + test &= tuple->column( prefix + "_Prob" , poisson(mean,n) ); + + if(m_adjustmean!=0.) + { + if ( msgLevel(MSG::VERBOSE) ) verbose() << "Filling adjusted tuples" << endmsg; + double normalise=1; + if(m_normaliseAt) normalise=weight(mean,m_adjustmean,m_normaliseAt); + test &= tuple->column( prefix + "_AdjustMean" , m_adjustmean ); + test &= tuple->column( prefix + "_AdjustProb" , poisson(m_adjustmean,n) ); + test &= tuple->column( prefix + "_AdjustWeight" , weight(mean,m_adjustmean,n)/normalise ); + if(isVerbose()) test &= tuple->column( prefix + "_NormalisedAt" , m_normaliseAt ); + if(isVerbose()) test &= tuple->column( prefix + "_NormalisedTo" , normalise ); + } + + if(isVerbose()) + { + if ( msgLevel(MSG::VERBOSE) ) verbose() << "Filling detailed tuples" << endmsg; + test &= tuple->column( prefix + "_nMCI" , MCI ); + test &= tuple->column( prefix + "_nMCPV" ,MCPV ); + test &= tuple->column( prefix + "_nRecPV" , RecPV ); + } + + return StatusCode(test); +} + +//============================================================================= diff --git a/first-analysis-steps/DecayTrees/MCTupleToolInteractions.h b/first-analysis-steps/DecayTrees/MCTupleToolInteractions.h new file mode 100755 index 00000000..29491800 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolInteractions.h @@ -0,0 +1,125 @@ +#ifndef MCTUPLETOOLINTERACTIONS_H +#define MCTUPLETOOLINTERACTIONS_H 1 + +#include + +// from Gaudi +#include "GaudiKernel/SystemOfUnits.h" + +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" + +#include "Event/GenHeader.h" +#include "Event/MCHeader.h" +#include "Kernel/ParticleID.h" +#include + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/ITupleTool.h" + +#include "GaudiKernel/IRegistry.h" // IOpaqueAddress + +class ITupleTool; + +/** @class MCTupleToolInteractions MCTupleToolInteractions.h rlambert/MCTupleToolInteractions.h + * + * \brief Number of interactions. This TupleTool will allow the calculation of a scaling factor + * as an event-by-event weight. When applied to events it will approximate a different mean number of + * interactions per event. + * The starting mean number of interactions will by default be taken from the GenHeader. + * If this is not available it will set to the DC06 default + * The mean can be overwritten by setting the option "Mean" as below + * + * Tuple columns: + * + * EVT_Int_I unsigned int number of interactions + * EVT_Int_Mean double mean number of interactions + * EVT_Int_Prob double probability of generating this number of interactions + * + * If the scaling option (AdjustMean) is set + * EVT_Int_AdjustMean double mean number of interactions to weight to + * EVT_Int_AdjustProb double probability of this event in the adjusted case + * EVT_Int_AdjustWeight double weight to apply to change from mean to adjust mean + * + * If the Verbose option is set + * EVT_Int_NormalisedAt unsigned int chosen place to normalise the weight + * EVT_Int_NormalisedTo double weights normalised to this value + * EVT_Int_nMCI unsigned int number of collisions from the GenHeader + * EVT_Int_nMCPV unsigned int number of collisions from the MCHeader + * EVT_Int_nRecPV unsigned int number of reconstructed PVs + * + * Options: + * Mean double overwrite the mean value of interactions for this event + * -default is described above + * AdjustMean double calculate a scaling factor to approximate this number of interactions per event + * -by default this is zero, and no scaling information is filled + * NormaliseAt int normalise the scaling factor such that it is equal to 1 at this value of I + * -by default this is set to zero, and no normalisation is performed + * Prefix string prefix to give to the variables, in case you want to use two copies of this tool + * -by default this is "EVT_Int" + * UseRecPV bool use the #of reconstructed PVs, rather than the MC Collisions + * -by default this is false + * FillDetails bool fill extra information on MCPV, MC Collisions and Reconstructed PV + * -by default this is false, fine for most purposes + * RecPVLocation string change the default PV location + * -by default this is LHCb::RecVertexLocation::Primary + * + * \sa DecayTreeTuple + * @author R. Lambert + * @date 2009-05-01 + */ +class MCTupleToolInteractions : public TupleToolBase, virtual public IEventTupleTool +{ + +public: + + /// Standard constructor + MCTupleToolInteractions( const std::string& type, + const std::string& name, + const IInterface* parent); + + ~MCTupleToolInteractions( ){}; ///< Destructor + + StatusCode fill( Tuples::Tuple& ) override; + +private : + + double m_mean; ///(this); + + // Store kinetic information from the associated candidate + declareProperty( "StoreKineticInfo", m_storeKinetic = true ); + + // Store the end and origin true vertex information + declareProperty( "StoreVertexInfo", m_storeVertexes = true ); + + // Store the propertime information for associated composite particle + declareProperty( "StorePropertimeInfo", m_storePT = true ); + + // Store propertime and endvertex also for stable particles + // This is needed in case you study, for example, K-> pi pi pi + // As the Kaon is considerad stable in LHCb + // False by default as it will store properime also of pions, electrons etc + declareProperty( "StoreStablePropertime", m_storeStablePropertime = false); + + +} +//============================================================================= +// Destructor +//============================================================================= +MCTupleToolKinematic::~MCTupleToolKinematic() {} + +//============================================================================= +// initialize +//============================================================================= + +StatusCode MCTupleToolKinematic::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return StatusCode::FAILURE; + if ( isVerbose() ) + { + m_storePT = m_storeVertexes = m_storeKinetic = true; + } + return sc; +} +//============================================================================= +// Fill +//============================================================================= +StatusCode MCTupleToolKinematic::fill( const LHCb::MCParticle* + , const LHCb::MCParticle* mcp + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix = fullName(head); + bool test = true; + + if (msgLevel(MSG::DEBUG)) debug() << "MCTupleToolKinematic::fill " << head << endmsg ; + + double mcTau = -1; + double mcPT = 0; + + Gaudi::XYZVector endVertex, originVertex; + Gaudi::LorentzVector trueP; + bool hasOsc = false ; + + if ( msgLevel(MSG::VERBOSE) ) verbose() << "MCTupleToolKinematic::fill mcp " << mcp << endmsg ; + // pointer is ready, prepare the values: + if ( mcp ) + { + trueP = mcp->momentum(); + mcPT = mcp->pt(); + if (msgLevel(MSG::VERBOSE)) verbose() << " " << trueP << endmsg ; + + originVertex = mcp->originVertex()->position(); + if (msgLevel(MSG::VERBOSE)) verbose() << " origin vertex position " << originVertex << endmsg ; + + if ( !isStable(mcp) || m_storeStablePropertime ) + { + const SmartRefVector & endVertices = mcp->endVertices(); + if (msgLevel(MSG::VERBOSE)) verbose() << " vertices " << endVertices.size() << endmsg ; + + const LHCb::MCVertex * mcV = NULL; + if ( !endVertices.empty() ) + { + for ( SmartRefVector::const_iterator v = + endVertices.begin(); v != endVertices.end(); ++v ){ + if( (*v)->type() == LHCb::MCVertex::DecayVertex || (*v)->type() == LHCb::MCVertex::OscillatedAndDecay + || (*v)->type() == LHCb::MCVertex::HadronicInteraction ){ + mcV = *v; + break; + } + } + }else{ + Warning( "No end vertices for " + prefix ).ignore(); + } + + if ( mcV ) + { + endVertex = mcV->position(); + } + else + { + Warning( "NULL end vertex for " + prefix ).ignore(); + } + + if (msgLevel(MSG::VERBOSE)) verbose() << " end vertex " << endVertex << endmsg ; + + // lifetime + if ( mcV && m_storePT ) + { + const Gaudi::XYZVector dist = endVertex - originVertex; + // copied from DecayChainNTuple // + mcTau = trueP.M() * dist.Dot( trueP.Vect() ) / trueP.Vect().mag2(); + mcTau /= Gaudi::Units::c_light; // nanoseconds + hasOsc = mcp->hasOscillated() ; + if (msgLevel(MSG::DEBUG)) + { + debug() << head << " " << mcp->particleID().pid() << " time " << mcTau << " oscil" << hasOsc << endmsg ; + } + } + } + } + + if (msgLevel(MSG::VERBOSE)) verbose() << "MCTupleToolKinematic::fill filling " << head << endmsg ; + + // fill the tuple: + //test &= tuple->column( head+"_TRUEID", mcPid ); + if ( m_storeKinetic ) + { + test &= tuple->column( prefix + "_TRUEP_", trueP ); + test &= tuple->column( prefix+"_TRUEPT", mcPT ); + } + + if ( m_storeVertexes ) + { + test &= tuple->column( prefix + "_TRUEORIGINVERTEX_", originVertex ); + test &= tuple->column( prefix + "_TRUEENDVERTEX_", endVertex ); + test &= tuple->column( prefix + "_TRUEISSTABLE", isStable(mcp)); + } + + if ( m_storePT ) + { + test &= tuple->column( prefix + "_TRUETAU", mcTau ); + if ( isVerbose() ) + { + test &= tuple->column( prefix + "_OSCIL", hasOsc ); + } + } + + if (msgLevel(MSG::VERBOSE)) verbose() << "MCTupleToolKinematic::fill bye " << prefix << endmsg ; + + return StatusCode(test); +} diff --git a/first-analysis-steps/DecayTrees/MCTupleToolKinematic.h b/first-analysis-steps/DecayTrees/MCTupleToolKinematic.h new file mode 100644 index 00000000..abc210d0 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolKinematic.h @@ -0,0 +1,56 @@ +// $Id: MCTupleToolKinematic.h,v 1.4 2010-01-26 15:39:25 rlambert Exp $ +#ifndef MCTUPLETOOLKINEMATIC_H +#define MCTUPLETOOLKINEMATIC_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IMCParticleTupleTool.h" // Interface +#include "Event/MCParticle.h" // Interface +/** @class MCTupleToolKinematic MCTupleToolKinematic.h + * + * Fill MC Particle + * + * See the properties inline documentation to toggle on/off some of + * the columns + * + * - head_TRUEP[E|X|Y|Z] : true four vector momentum + * - head_TRUEPT : true transverse momentum, PT + * - head_TRUEORIGINVERTEX_[X|Y|Z] : position of the true origin vertex. + * - head_TRUEENDVERTEX_[X|Y|Z] : position of the true end vertex (the + first one) + * - head_TRUEISSTABLE : MCAssociate has no daughters. + * - head_TRUETAU : true propertime + * + * \sa MCTupleToolKinematic, DecayTreeTuple, MCDecayTreeTuple + * + * @author Patrick Koppenburg + * @date 2009-01-19 + */ + +class MCTupleToolKinematic : public TupleToolBase, virtual public IMCParticleTupleTool { +public: + /// Standard constructor + MCTupleToolKinematic( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~MCTupleToolKinematic( ); ///< Destructor + StatusCode initialize() override; + StatusCode fill( const LHCb::MCParticle* + , const LHCb::MCParticle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + bool m_storeKinetic; //!< Store kinetic information from the associated candidate + bool m_storePT; //!< Store the propertime information for associated composite particle + bool m_storeVertexes; //!< Store the end and origin true vertex information + bool m_storeStablePropertime; //!< Store the propertime and vertex also for "stable" particles + + +#include "DecayTreeTupleBase/isStable.h" + +}; +#endif // MCTUPLETOOLKINEMATIC_H diff --git a/first-analysis-steps/DecayTrees/MCTupleToolP2VV.cpp b/first-analysis-steps/DecayTrees/MCTupleToolP2VV.cpp new file mode 100644 index 00000000..519c7d20 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolP2VV.cpp @@ -0,0 +1,109 @@ +// Include files + +// local +#include "MCTupleToolP2VV.h" +#include "Kernel/IP2VVMCPartAngleCalculator.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +using namespace LHCb ; +//----------------------------------------------------------------------------- +// Implementation file for class : MCTupleToolP2VV +// +// 2009-01-19 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( MCTupleToolP2VV ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + MCTupleToolP2VV::MCTupleToolP2VV( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_angleTool(0) +{ + declareInterface(this); + + declareProperty( "Calculator", m_calculator = "MCBd2KstarMuMuAngleCalculator" ); +} + +//============================================================================= +// Destructor +//============================================================================= +MCTupleToolP2VV::~MCTupleToolP2VV() {} + +//============================================================================= +StatusCode MCTupleToolP2VV::initialize( ) +{ + if( ! TupleToolBase::initialize() ) return StatusCode::FAILURE; + m_angleTool = tool(m_calculator,this); + return StatusCode::SUCCESS ; +} + +//============================================================================= +// Fill +//============================================================================= +StatusCode MCTupleToolP2VV::fill( const LHCb::MCParticle* + , const LHCb::MCParticle* mcp + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(head); + + bool test = true; + + //Helicity + double thetaL(9999), thetaK(9999), phi(9999); + + StatusCode sc_hel = StatusCode::FAILURE; + if (mcp) sc_hel = m_angleTool->calculateAngles( mcp, thetaL, thetaK, phi); + + if ( !sc_hel ) { + thetaL=9999.; + thetaK=9999.; + phi=9999.; + } + + if (msgLevel(MSG::DEBUG)) + { + debug() << "Three true helicity angles are theta_L : " + << thetaL + << " K: "<< thetaK + << " phi: " << phi << endmsg ; + } + + test &= tuple->column( prefix+"_TRUEThetaL", thetaL ); + test &= tuple->column( prefix+"_TRUEThetaK", thetaK ); + test &= tuple->column( prefix+"_TRUEPhi", phi ); + + //Transversity + double Theta_tr(9999), Phi_tr(9999), Theta_V(9999); + + StatusCode sc_tr = StatusCode::FAILURE; + if (mcp) sc_tr = m_angleTool->calculateTransversityAngles( mcp,Theta_tr,Phi_tr,Theta_V ); + + if ( !sc_tr ) { + Theta_tr=9999.; + Phi_tr=9999.; + Theta_V=9999.; + } + + if (msgLevel(MSG::DEBUG)) + { + debug() << "Three true transversity angles are Theta_tr : " + << Theta_tr + << " Phi_tr: " << Phi_tr + << " Theta_phi_tr: " << Theta_V + << endmsg ; + } + + test &= tuple->column( prefix+"_TRUEThetaTr", Theta_tr ); + test &= tuple->column( prefix+"_TRUEPhiTr", Phi_tr ); + test &= tuple->column( prefix+"_TRUEThetaVtr", Theta_V ); + + return StatusCode(test); +} diff --git a/first-analysis-steps/DecayTrees/MCTupleToolP2VV.h b/first-analysis-steps/DecayTrees/MCTupleToolP2VV.h new file mode 100644 index 00000000..7c2934d3 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolP2VV.h @@ -0,0 +1,46 @@ +// $Id: MCTupleToolP2VV.h,v 1.2 2010-01-26 15:39:26 rlambert Exp $ +#ifndef MCTUPLETOOLP2VV_H +#define MCTUPLETOOLP2VV_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IMCParticleTupleTool.h" // Interface + +/** @class MCTupleToolP2VV MCTupleToolP2VV.h + * + * + * Fill MC Particle + * + * See the properties inline documentation to toggle on/off some of + * the columns + * + * - head_XXXX : + * + * \sa TupleToolMCTruth, DecayTreeTuple + * + * @author Patrick Koppenburg + * @date 2009-01-19 + */ +class IP2VVMCPartAngleCalculator ; +class MCTupleToolP2VV : public TupleToolBase, virtual public IMCParticleTupleTool { +public: + /// Standard constructor + MCTupleToolP2VV( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~MCTupleToolP2VV( ); ///< Destructor + StatusCode initialize() override; + StatusCode fill( const LHCb::MCParticle* + , const LHCb::MCParticle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + IP2VVMCPartAngleCalculator* m_angleTool; + std::string m_calculator; //!< Name of the tool for the angles calculation + +}; +#endif // MCTUPLETOOLP2VV_H diff --git a/first-analysis-steps/DecayTrees/MCTupleToolPrimaries.cpp b/first-analysis-steps/DecayTrees/MCTupleToolPrimaries.cpp new file mode 100644 index 00000000..1a718e1f --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolPrimaries.cpp @@ -0,0 +1,66 @@ +// Include files + +// from Gaudi +#include "Event/MCHeader.h" +#include "Event/MCVertex.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +// local +#include "MCTupleToolPrimaries.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : MCTupleToolPrimaries +// +// 2009-11-16 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( MCTupleToolPrimaries ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + MCTupleToolPrimaries::MCTupleToolPrimaries( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); +} + +//============================================================================= +// Destructor +//============================================================================= +MCTupleToolPrimaries::~MCTupleToolPrimaries() {} + +//============================================================================= +StatusCode MCTupleToolPrimaries::fill( Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(); + + if (msgLevel(MSG::VERBOSE)) verbose() << "getting MCHeader" << endmsg; + if (!exist(LHCb::MCHeaderLocation::Default)) + { + Warning("No MCHeader at "+LHCb::MCHeaderLocation::Default,StatusCode::SUCCESS,1); + return StatusCode::SUCCESS ; + } + const LHCb::MCHeader* mch = get(LHCb::MCHeaderLocation::Default); + std::vector pvx, pvy, pvz, pvt; + for ( SmartRefVector< LHCb::MCVertex >::const_iterator i = mch->primaryVertices().begin() ; + i!=mch->primaryVertices().end() ; ++i) + { + if ((*i)->isPrimary()) + { + pvx.push_back((*i)->position().X()); + pvy.push_back((*i)->position().Y()); + pvz.push_back((*i)->position().Z()); + pvt.push_back((*i)->time()); + } + } + if (!(tuple->farray( prefix+"MCPVX", pvx, prefix+"MCPVs" , 50 ))) return StatusCode::FAILURE; + if (!(tuple->farray( prefix+"MCPVY", pvy, prefix+"MCPVs" , 50 ))) return StatusCode::FAILURE; + if (!(tuple->farray( prefix+"MCPVZ", pvz, prefix+"MCPVs" , 50 ))) return StatusCode::FAILURE; + if (!(tuple->farray( prefix+"MCPVT", pvt, prefix+"MCPVs" , 50 ))) return StatusCode::FAILURE; + + return StatusCode::SUCCESS ; +} diff --git a/first-analysis-steps/DecayTrees/MCTupleToolPrimaries.h b/first-analysis-steps/DecayTrees/MCTupleToolPrimaries.h new file mode 100644 index 00000000..5bb3c590 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolPrimaries.h @@ -0,0 +1,31 @@ +// $Id: MCTupleToolPrimaries.h,v 1.2 2010-01-26 15:39:26 rlambert Exp $ +#ifndef MCTUPLETOOLPRIMARIES_H +#define MCTUPLETOOLPRIMARIES_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface + +/** @class MCTupleToolPrimaries MCTupleToolPrimaries.h + * + * \brief Primary MC vertices properties for DecayTreeTuple + * + * Tuple columns: + * - coordinates PVX, PVY, PVZ, PVT (time) + * + * @author Patrick Koppenburg + * @date 2009-11-16 + */ +class MCTupleToolPrimaries : public TupleToolBase, virtual public IEventTupleTool { +public: + /// Standard constructor + MCTupleToolPrimaries( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~MCTupleToolPrimaries( ); ///< Destructor + StatusCode fill( Tuples::Tuple& ) override; + +}; +#endif // MCTUPLETOOLPRIMARIES_H diff --git a/first-analysis-steps/DecayTrees/MCTupleToolPrompt.cpp b/first-analysis-steps/DecayTrees/MCTupleToolPrompt.cpp new file mode 100644 index 00000000..68e1b0da --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolPrompt.cpp @@ -0,0 +1,126 @@ +// $Id: $ +// Include files + +// local +#include "MCTupleToolPrompt.h" + +//using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : MCTupleToolPrompt +// +// 2011-06-13 : Philip John Hunt +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( MCTupleToolPrompt ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + MCTupleToolPrompt::MCTupleToolPrompt( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_ppSvc(0) +{ + declareInterface(this); + + // maximum lifetime of short-lived particles (ns) + declareProperty( "MaxLifetime", m_maxLifetime = 1e-7 + , "Maximum lifetime of short-lived particles (ns)" ); + declareProperty( "StoreLongLivedParticleID", m_storeLongLivedPid=true); +} + +StatusCode MCTupleToolPrompt::initialize() +{ + StatusCode sc = TupleToolBase::initialize(); + if (sc.isFailure()) return sc; + + if (isVerbose()) m_storeLongLivedPid = true; + + sc = service( "LHCb::ParticlePropertySvc", m_ppSvc ); + + return sc; +} + +StatusCode MCTupleToolPrompt::fill( const LHCb::MCParticle* + , const LHCb::MCParticle* mcp + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix = fullName(head); + + bool test=true; + + int longLivedPid=0; + int longLivedKey=0; + + int isPrompt=-1; + + int mcParentPid=0; + int mcParentKey=0; + + double lcl_lifetime(0); + + const LHCb::MCParticle *mcp_parent = mcp; + + const LHCb::ParticleProperty * lclPprop = NULL; + + if (msgLevel(MSG::DEBUG)) debug() << "MCTupleToolPrompt::fill " << head << endmsg; + + if (mcp) + { + isPrompt=1; + while( isPrompt && mcp_parent->mother() ) + { + mcp_parent = mcp_parent->mother(); + + mcParentPid=mcp_parent->particleID().pid(); + mcParentKey=mcp_parent->key(); + + lclPprop = m_ppSvc->find( mcp_parent->particleID() ); + + // Some particle IDs are not known to the ppSvc + // Log a warning if that's the case and assign a large negative lifetime + if (lclPprop) + { + lcl_lifetime = lclPprop->lifetime(); + if(msgLevel(MSG::DEBUG)) + { + debug() << "Particle: " << lclPprop->evtGenName() + << " lifetime: " << lcl_lifetime << endmsg; + } + } else { + warning() << "Particle ID '" << mcp_parent->particleID() + << "' not found in particle property service" << endmsg; + lcl_lifetime = -999.0; + } + + if ( lcl_lifetime > m_maxLifetime*Gaudi::Units::ns ) + { + isPrompt=0; + longLivedPid=mcParentPid; + longLivedKey=mcParentKey; + } + } + } + + if (msgLevel(MSG::DEBUG)) debug() << "MCTupleToolPrompt::fill - filling " + << head << endmsg; + + test &= tuple->column( prefix+"_MC_ISPROMPT", isPrompt ); + if (m_storeLongLivedPid) + { + test &= tuple->column( prefix+"_MC_LONGLIVED_ID", longLivedPid ); + test &= tuple->column( prefix+"_MC_LONGLIVED_KEY", longLivedKey ); + } + return StatusCode(test); +} + +//============================================================================= +// Destructor +//============================================================================= +MCTupleToolPrompt::~MCTupleToolPrompt() {} + +//============================================================================= diff --git a/first-analysis-steps/DecayTrees/MCTupleToolPrompt.h b/first-analysis-steps/DecayTrees/MCTupleToolPrompt.h new file mode 100644 index 00000000..574081dd --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolPrompt.h @@ -0,0 +1,66 @@ +#ifndef MCTUPLETOOLPROMPT_H +#define MCTUPLETOOLPROMPT_H 1 + +// from Gaudi +#include "GaudiKernel/PhysicalConstants.h" + +// from Kernel +#include "Kernel/IMCParticleTupleTool.h" +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" + +#include "DecayTreeTupleBase/TupleToolBase.h" + +// from GaudiAlg +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +// from Event +#include "Event/MCParticle.h" + + +/** @class MCTupleToolPrompt MCTupleToolPrompt.h + * + * \brief Tool to determine whether a decay originates from prompt charm based on the true lifetime of its ancestors. + * Based on code written by Patrick Spradlin. + * + * Tuple columns: + * - MC_ISPROMPT, MC_LONGLIVED_ID, MC_LONGLIVED_KEY + * + * @author Philip John Hunt + * @date 2011-06-13 + */ + + +class MCTupleToolPrompt : public TupleToolBase, + virtual public IMCParticleTupleTool +{ + +public: + + /// Standard constructor + MCTupleToolPrompt( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~MCTupleToolPrompt( ); ///< Destructor + + StatusCode initialize() override; + + StatusCode fill( const LHCb::MCParticle* + , const LHCb::MCParticle* + , const std::string& + , Tuples::Tuple& ) override; + +protected: + + double m_maxLifetime; + bool m_storeLongLivedPid; + +private: + + LHCb::IParticlePropertySvc *m_ppSvc; + +}; + +#endif // MCTUPLETOOLPROMPT_H diff --git a/first-analysis-steps/DecayTrees/MCTupleToolReconstructed.cpp b/first-analysis-steps/DecayTrees/MCTupleToolReconstructed.cpp new file mode 100644 index 00000000..b93524d1 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolReconstructed.cpp @@ -0,0 +1,153 @@ +// Include files +#include "gsl/gsl_sys.h" + +// from Gaudi +#include "GaudiKernel/PhysicalConstants.h" +#include "GaudiKernel/Vector3DTypes.h" + +// local +#include "MCTupleToolReconstructed.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/MCParticle.h" +#include "MCInterfaces/IMCReconstructible.h" +#include "MCInterfaces/IMCReconstructed.h" + +using namespace LHCb; +//----------------------------------------------------------------------------- +// Implementation file for class : MCTupleToolReconstructed +// +// 2009-01-19 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( MCTupleToolReconstructed ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + MCTupleToolReconstructed::MCTupleToolReconstructed( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_recible(0) + , m_rected(0) + , m_pCPPAsct(0) + , m_pNPPAsct(0) +{ + declareInterface(this); + declareProperty("Associate",m_associate=true,"Fill associated protoparticle"); + declareProperty("FillPID",m_pid=true,"Fill PID, also set by Verbose"); +} + +//============================================================================= +// initialize +//============================================================================= + +StatusCode MCTupleToolReconstructed::initialize() +{ + if( ! TupleToolBase::initialize() ) return StatusCode::FAILURE; + + m_recible = tool("MCReconstructible"); + m_rected = tool("MCReconstructed"); + + if (m_associate) + { + m_pCPPAsct = new ProtoParticle2MCLinker( this, Particle2MCMethod::ChargedPP, LHCb::ProtoParticleLocation::Charged); + m_pNPPAsct = new ProtoParticle2MCLinker( this, Particle2MCMethod::NeutralPP, LHCb::ProtoParticleLocation::Neutrals); + } + + if(isVerbose()) m_pid=true; + + return StatusCode::SUCCESS ; +} +//============================================================================= +// Fill +//============================================================================= +StatusCode MCTupleToolReconstructed::fill( const LHCb::MCParticle* + , const LHCb::MCParticle* mcp + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(head); + + bool test = true; + int catted = -10 ; + int catible = -10 ; + + // pointer is ready, prepare the values: + if( 0!=mcp ) + { + catted = m_rected->reconstructed(mcp); + catible = m_recible->reconstructible(mcp); + } + + // fill the tuple: + test &= tuple->column( prefix+"_Reconstructible", catible ); + test &= tuple->column( prefix+"_Reconstructed", catted ); + std::vector PX, PY, PZ, Weights, dlle, dllmu, dllk, dllp, pchi2; + + if ( (0!=mcp) && m_associate && isStable(mcp)) + { + std::vector > ppv = getProtos(mcp); + for ( std::vector >::const_iterator ppp = ppv.begin() ; + ppp != ppv.end() ; ++ppp) + { + const LHCb::ProtoParticle* proto = ppp->first; + double w = ppp->second; + /// @todo There's plenty more that can be added here. Like PID for instance. + if (0!=proto->track()) + { + Gaudi::XYZVector mom = proto->track()->momentum(); + PX.push_back(mom.X()); + PY.push_back(mom.Y()); + PZ.push_back(mom.Z()); + pchi2.push_back(proto->track()->probChi2()); + } + Weights.push_back(w); + if (m_pid){ + dlle.push_back(proto->info( ProtoParticle::CombDLLe, -999.0 )); + dllmu.push_back(proto->info( ProtoParticle::CombDLLmu, -999.0 )); + dllk.push_back(proto->info( ProtoParticle::CombDLLk, -999.0 )); + dllp.push_back(proto->info( ProtoParticle::CombDLLp, -999.0 )); + } + } + } + const unsigned int maxPP = 20 ; + test &= tuple->farray( prefix+"_PP_PX", PX, prefix+"_ProtoParticles" , maxPP ); + test &= tuple->farray( prefix+"_PP_PY", PY, prefix+"_ProtoParticles" , maxPP ); + test &= tuple->farray( prefix+"_PP_PZ", PZ, prefix+"_ProtoParticles" , maxPP ); + test &= tuple->farray( prefix+"_PP_Weight", Weights, prefix+"_ProtoParticles" , maxPP ); + test &= tuple->farray( prefix+"_PP_tr_pchi2", pchi2, prefix+"_ProtoParticles" , maxPP ); + if (m_pid) + { + test &= tuple->farray( prefix+"_PP_DLLe", dlle, prefix+"_ProtoParticles" , maxPP ); + test &= tuple->farray( prefix+"_PP_DLLk", dllk, prefix+"_ProtoParticles" , maxPP ); + test &= tuple->farray( prefix+"_PP_DLLp", dllp, prefix+"_ProtoParticles" , maxPP ); + test &= tuple->farray( prefix+"_PP_DLLmu", dllmu, prefix+"_ProtoParticles" , maxPP ); + } + + + return StatusCode(test); +} + +//========================================================================= +/// Protoparticles list @todo return weight as well +//======================================================================== +std::vector > +MCTupleToolReconstructed::getProtos(const LHCb::MCParticle* mcp) const +{ + ProtoParticle2MCLinker* asct = (mcp->particleID().threeCharge()==0)?m_pNPPAsct:m_pCPPAsct; + if (0==asct) Exception("Null PP asociator"); + std::vector > ppv ; + double w=0; + const LHCb::ProtoParticle* pp = asct->firstP(mcp,w); + while( pp ) + { + ppv.push_back(std::pair(pp,w)); + pp = asct->nextP(w); + } + return ppv; +} diff --git a/first-analysis-steps/DecayTrees/MCTupleToolReconstructed.h b/first-analysis-steps/DecayTrees/MCTupleToolReconstructed.h new file mode 100644 index 00000000..b141cc1b --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolReconstructed.h @@ -0,0 +1,64 @@ +#ifndef MCTUPLETOOLMCRECONSTRUCTED_H +#define MCTUPLETOOLMCRECONSTRUCTED_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IMCParticleTupleTool.h" // Interface +#include "Kernel/Particle2MCLinker.h" +#include "Event/ProtoParticle.h" + +/** @class MCTupleToolReconstructed MCTupleToolReconstructed.h + * + * Fill MC Particle + * + * See the properties inline documentation to toggle on/off some of + * the columns + * + * - head_Reconstructible : IMCReconstructible category + * - head_Reconstructed : IMCReconstructed category + * - head_PP_PX,Y,Z : ProtoParticle PX, PY, PZ + * - head_PP_Weight : ProtoParticle association weight + * + * \sa MCDecayTreeTuple, IMCReconstructible, IMCReconstructed + * + * @author Patrick Koppenburg + * @date 2009-01-22 + */ +struct IMCReconstructible ; +struct IMCReconstructed ; + +class MCTupleToolReconstructed : public TupleToolBase, virtual public IMCParticleTupleTool { +public: + /// Standard constructor + MCTupleToolReconstructed( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + +public: + + StatusCode fill( const LHCb::MCParticle* + , const LHCb::MCParticle* + , const std::string& + , Tuples::Tuple& ) override; + + +private: + + std::vector > getProtos(const LHCb::MCParticle*) const; + +#include "DecayTreeTupleBase/isStable.h" + +private: + + IMCReconstructible* m_recible ; ///< Reconstructible tool + IMCReconstructed* m_rected ; ///< Reconstructed too + ProtoParticle2MCLinker* m_pCPPAsct ; ///< Charged protoparticle associator + ProtoParticle2MCLinker* m_pNPPAsct ; ///< Neutral protoparticle associator + bool m_associate ; ///< Do association + bool m_pid ; ///< Do PID + +}; +#endif // MCTUPLETOOLMCRECONSTRUCTED_H diff --git a/first-analysis-steps/DecayTrees/MCTupleToolRedecay.cpp b/first-analysis-steps/DecayTrees/MCTupleToolRedecay.cpp new file mode 100644 index 00000000..88325573 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolRedecay.cpp @@ -0,0 +1,67 @@ +// Include files + +// from Gaudi +#include "Event/MCHeader.h" +#include "Event/MCVertex.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +// local +#include "MCTupleToolRedecay.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : MCTupleToolRedecay +// +// 2017-1-26 : Dominik Muller +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( MCTupleToolRedecay ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +MCTupleToolRedecay::MCTupleToolRedecay(const std::string& type, + const std::string& name, + const IInterface* parent) + : TupleToolBase(type, name, parent) { + declareInterface(this); +} + +//============================================================================= +// Destructor +//============================================================================= +MCTupleToolRedecay::~MCTupleToolRedecay() {} + +//============================================================================= +StatusCode MCTupleToolRedecay::fill(Tuples::Tuple& tuple) { + const std::string prefix = fullName(); + + if (msgLevel(MSG::VERBOSE)) verbose() << "getting MCHeader" << endmsg; + if (!exist(LHCb::MCHeaderLocation::Default)) { + Warning("No MCHeader at " + LHCb::MCHeaderLocation::Default, + StatusCode::SUCCESS, 1); + return StatusCode::SUCCESS; + } + const LHCb::MCHeader* mch = + get(LHCb::MCHeaderLocation::Default); + auto time = mch->evtTime(); + // for ReDecay, the unused evtTime contains the cantor pairing of + // the original event run and event number. Decomposing it now + // following https://en.wikipedia.org/wiki/Pairing_function. + // Magic + + auto w = std::floor((sqrtl(8 * time + 1) - 1) / 2); + auto t = (w*w + w) / 2; + unsigned long long RD_org_runNumber = time - t; + unsigned long long RD_org_eventNumber = w - RD_org_runNumber; + unsigned int RD_i_event = mch->evtNumber() - RD_org_eventNumber; + + if (!(tuple->column(prefix + "RD_org_eventNumber", RD_org_eventNumber))) + return StatusCode::FAILURE; + if (!(tuple->column(prefix + "RD_org_runNumber", RD_org_runNumber))) + return StatusCode::FAILURE; + if (!(tuple->column(prefix + "RD_i_event", RD_i_event))) + return StatusCode::FAILURE; + + return StatusCode::SUCCESS; +} diff --git a/first-analysis-steps/DecayTrees/MCTupleToolRedecay.h b/first-analysis-steps/DecayTrees/MCTupleToolRedecay.h new file mode 100644 index 00000000..47b7fb84 --- /dev/null +++ b/first-analysis-steps/DecayTrees/MCTupleToolRedecay.h @@ -0,0 +1,34 @@ +// $Id: MCTupleToolRedecay.h,v 1.0 2017-01-26 15:39:26 dmuller Exp $ +#ifndef MCTUPLETOOLREDECAY_H +#define MCTUPLETOOLREDECAY_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface + +/** @class MCTupleToolRedecay MCTupleToolRedecay.h + * + * \brief Decodes evtTime to add redecay information to the ntuple. + * RD_org_eventNumber and RD_org_runNumber contain the event and run number + * of the original event to allow to group events stemming from the same + * original event. + * RD_i_event gives the index of the ReDecay event + * + * Tuple columns: + * - RD_org_eventNumber, RD_org_runNumber, RD_i_event + * + * @author Dominik Muller + * @date 2017-1-26 + */ +class MCTupleToolRedecay : public TupleToolBase, + virtual public IEventTupleTool { + public: + /// Standard constructor + MCTupleToolRedecay(const std::string& type, const std::string& name, + const IInterface* parent); + + virtual ~MCTupleToolRedecay(); ///< Destructor + StatusCode fill(Tuples::Tuple&) override; +}; +#endif // MCTUPLETOOLREDECAY_H diff --git a/first-analysis-steps/DecayTrees/TupleToolANNPID.cpp b/first-analysis-steps/DecayTrees/TupleToolANNPID.cpp new file mode 100644 index 00000000..5298d7a6 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolANNPID.cpp @@ -0,0 +1,125 @@ +// $Id: $ + +#include "TupleToolANNPID.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolANNPID +//----------------------------------------------------------------------------- + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolANNPID::TupleToolANNPID( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name, parent ) +{ + declareInterface(this); + declareProperty( "ANNPIDTunes", m_pidTunes = + { "MC12TuneV2","MC12TuneV3","MC12TuneV4","MC15TuneV1" + //,"MC15TuneDNNV1","MC15TuneFLAT4dV1","MC15TuneCatBoostV1" + } + ); + // PID types. Deuteron by default is not included at the moment. + declareProperty( "PIDTypes", m_pidTypes = + { "Electron","Muon","Pion","Kaon","Proton","Ghost" } ); +} + +//============================================================================= + +StatusCode TupleToolANNPID::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_pidTool = + tool( "ANNGlobalPID::ChargedProtoANNPIDTool", + "ChargedProtoANNPID" ); + + // by default all types are off + m_pidIsOn.fill(false); + // turn on as required + for ( const auto & p : m_pidTypes ) + { + if ( "Electron" == p ) { m_pidIsOn[El] = true; } + else if ( "Muon" == p ) { m_pidIsOn[Mu] = true; } + else if ( "Pion" == p ) { m_pidIsOn[Pi] = true; } + else if ( "Kaon" == p ) { m_pidIsOn[Ka] = true; } + else if ( "Proton" == p ) { m_pidIsOn[Pr] = true; } + else if ( "Deuteron" == p ) { m_pidIsOn[De] = true; } + else if ( "Ghost" == p ) { m_pidIsOn[Gh] = true; } + } + + return sc; +} + +//============================================================================= + +StatusCode TupleToolANNPID::fill( const LHCb::Particle* + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + StatusCode sc = StatusCode::SUCCESS; + + // Only run on charged stable particles + if ( !P || !P->proto() || !P->proto()->track() ) return sc; + + // get the prefix + const auto prefix = fullName(head); + + // Loop over PID tunes + for ( const auto& pidTune : m_pidTunes ) + { + // Fill the ANNPID variables for those that are defined + ANNGlobalPID::IChargedProtoANNPIDTool::RetType res; + // Electrons + if ( sc && m_pidIsOn[El] ) + { + res = m_pidTool->annPID(P->proto(),LHCb::ParticleID(11),pidTune); + if ( res.status ) { sc = tuple->column( prefix+"_"+pidTune+"_ProbNNe", res.value ); } + } + // Muons + if ( sc && m_pidIsOn[Mu] ) + { + res = m_pidTool->annPID(P->proto(),LHCb::ParticleID(13),pidTune); + if ( res.status ) { sc = tuple->column( prefix+"_"+pidTune+"_ProbNNmu", res.value ); } + } + // Pions + if ( sc && m_pidIsOn[Pi] ) + { + res = m_pidTool->annPID(P->proto(),LHCb::ParticleID(211),pidTune); + if ( res.status ) { sc = tuple->column( prefix+"_"+pidTune+"_ProbNNpi", res.value ); } + } + // Kaons + if ( sc && m_pidIsOn[Ka] ) + { + res = m_pidTool->annPID(P->proto(),LHCb::ParticleID(321),pidTune); + if ( res.status ) { sc = tuple->column( prefix+"_"+pidTune+"_ProbNNk", res.value ); } + } + // Protons + if ( sc && m_pidIsOn[Pr] ) + { + res = m_pidTool->annPID(P->proto(),LHCb::ParticleID(2212),pidTune); + if ( res.status ) { sc = tuple->column( prefix+"_"+pidTune+"_ProbNNp", res.value ); } + } + // Deuterons + if ( sc && m_pidIsOn[De] ) + { + res = m_pidTool->annPID(P->proto(),LHCb::ParticleID(1000010020),pidTune); + if ( res.status ) { sc = tuple->column( prefix+"_"+pidTune+"_ProbNNd", res.value ); } + } + // Ghosts + if ( sc && m_pidIsOn[Gh] ) + { + res = m_pidTool->annPID(P->proto(),LHCb::ParticleID(0),pidTune); + if ( res.status ) { sc = tuple->column( prefix+"_"+pidTune+"_ProbNNghost", res.value ); } + } + } + + // return + return sc; +} + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolANNPID ) diff --git a/first-analysis-steps/DecayTrees/TupleToolANNPID.h b/first-analysis-steps/DecayTrees/TupleToolANNPID.h new file mode 100644 index 00000000..dda618da --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolANNPID.h @@ -0,0 +1,62 @@ +#ifndef _TupleToolANNPID_H +#define _TupleToolANNPID_H 1 + +// STL +#include +#include + +// Base class +#include "DecayTreeTupleBase/TupleToolBase.h" + +// Interfaces +#include "Kernel/IParticleTupleTool.h" +#include "RecInterfaces/IChargedProtoANNPIDTool.h" + +//============================================================================ + +class TupleToolANNPID : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + // Standard constructor + TupleToolANNPID( const std::string& type, + const std::string& name, + const IInterface* parent); + + ~TupleToolANNPID() {} + + StatusCode initialize() override; ///< Initialise + +public: + + StatusCode fill( const LHCb::Particle*, + const LHCb::Particle*, + const std::string& , + Tuples::Tuple& ) override; + +private: + + // Local PID type enum + enum PID { El = 0, Mu, Pi, Ka, Pr, De, Gh }; + // total PID types possible + static const std::size_t NPIDs = 7; + +private: + + /// Activation flag for each type + std::array m_pidIsOn; + + /// Pointer to the ANNPID tool + const ANNGlobalPID::IChargedProtoANNPIDTool * m_pidTool = nullptr; + + /// The ANNPID tunes to fill + std::vector m_pidTunes; + + /// The PID types to fill + std::vector m_pidTypes; + +}; + +#endif // _TupleToolANNPID_H diff --git a/first-analysis-steps/DecayTrees/TupleToolANNPIDTraining.cpp b/first-analysis-steps/DecayTrees/TupleToolANNPIDTraining.cpp new file mode 100644 index 00000000..7d1943a9 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolANNPIDTraining.cpp @@ -0,0 +1,50 @@ +// $Id: $ + +#include "TupleToolANNPIDTraining.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolANNPIDTraining +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolANNPIDTraining ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolANNPIDTraining::TupleToolANNPIDTraining( const std::string& type, + const std::string& name, + const IInterface* parent ) +: TupleToolBase ( type, name, parent ), + m_tuple ( NULL ) +{ + declareInterface(this); +} + +//============================================================================= + +StatusCode TupleToolANNPIDTraining::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_tuple = + tool( "ANNGlobalPID::ChargedProtoANNPIDTupleTool", + "Tuple", this ); + + return sc; +} + +//============================================================================= + +StatusCode TupleToolANNPIDTraining::fill( const LHCb::Particle* + , const LHCb::Particle* P + , const std::string& /* head */ + , Tuples::Tuple& tuple ) +{ + //const std::string prefix = fullName(head); + + // Fill the ANNPID variables + // Note, prefix is not used here, so can only use this tool on a single particle at a time... + return m_tuple->fill( tuple, P ); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolANNPIDTraining.h b/first-analysis-steps/DecayTrees/TupleToolANNPIDTraining.h new file mode 100644 index 00000000..d17a9942 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolANNPIDTraining.h @@ -0,0 +1,42 @@ +#ifndef _TupleToolANNPIDTraining_H +#define _TupleToolANNPIDTraining_H 1 + +// Base class +#include "DecayTreeTupleBase/TupleToolBase.h" + +// Interfaces +#include "Kernel/IParticleTupleTool.h" +#include "RecInterfaces/IChargedProtoANNPIDTupleTool.h" + +//============================================================================ + +class TupleToolANNPIDTraining : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + // Standard constructor + TupleToolANNPIDTraining( const std::string& type, + const std::string& name, + const IInterface* parent); + + ~TupleToolANNPIDTraining() {} + + StatusCode initialize() override; ///< Initialise + +public: + + StatusCode fill(const LHCb::Particle*, + const LHCb::Particle*, + const std::string& , + Tuples::Tuple& ) override; + +private: + + /// Pointer to the ANNPID tuple tool + const ANNGlobalPID::IChargedProtoANNPIDTupleTool * m_tuple; + +}; + +#endif // _TupleToolANNPIDTraining_H diff --git a/first-analysis-steps/DecayTrees/TupleToolAllPhotons.cpp b/first-analysis-steps/DecayTrees/TupleToolAllPhotons.cpp new file mode 100644 index 00000000..e8287bf8 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolAllPhotons.cpp @@ -0,0 +1,188 @@ +// from Gaudi +#include "Event/Track.h" +#include "Event/RecSummary.h" +#include "Event/VertexBase.h" +#include "Event/RecVertex.h" +#include "Kernel/DefaultDVToolTypes.h" +#include "Event/VeloCluster.h" +#include "Event/Particle.h" +#include "TrackInterfaces/IVeloClusterPosition.h" +#include "TrackInterfaces/IVeloExpectation.h" +#include "TrackInterfaces/IMeasurementProvider.h" +// local +#include "TupleToolAllPhotons.h" +#include "TrackInterfaces/ITrackExtrapolator.h" +#include "TrackInterfaces/ITrackStateProvider.h" +#include "Kernel/IParticle2MCAssociator.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolAllPhotons +// +// 2017-05-25 : Dan Johnson, Victor Coco, Kazu Akiba +//----------------------------------------------------------------------------- + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolAllPhotons::TupleToolAllPhotons(const std::string& type, + const std::string& name, + const IInterface* parent) + : TupleToolBase(type, name, parent) { + declareInterface(this); +} + +StatusCode TupleToolAllPhotons::initialize() { + StatusCode sc = TupleToolBase::initialize(); + if (sc.isFailure()) return sc; + + info() << "Will fill all particles from " << m_location << " up to size " << m_max << endmsg; + + m_pvf = tool(DaVinci::DefaultTools::PVRelator, this); + if (!m_pvf) return Error("Couldn't get PVRelator"); + + m_dist = tool(DaVinci::DefaultTools::Distance, this); + if (!m_dist) { + return Error("Unable to retrieve the IDistanceCalculator tool"); + } + m_extrapolator = tool("TrackStateProvider", this); + + // MC associators + for ( const auto &iMCAss : m_p2mcAssocTypes ) { + m_p2mcAssocs.push_back(tool(iMCAss, this)); + } + + return sc; +} + +//============================================================================= +StatusCode TupleToolAllPhotons::fill(Tuples::Tuple& tup) { + const std::string prefix = fullName(); + + LHCb::Particle::Range parts; + if (exist(m_location)) { + parts = get(m_location); + } else + return Warning("Nothing found at " + m_location, StatusCode::SUCCESS, 1); + + // Fill the tuple + bool test = true; + + std::vector PX, PY, PZ, PE, CL, Prob; + std::vector ISMUON; + std::vector PID, TCAT, TPID; + std::vector vCaloTrMatch; + std::vector vCaloDepositID; + std::vector vShowerShape; + std::vector vClusterMass; + std::vector vCaloNeutralSpd; + std::vector vCaloNeutralPrs; + std::vector vCaloNeutralEcal; + std::vector vCaloNeutralHcal2Ecal; + std::vector vCaloNeutralE49; + std::vector vCaloNeutralID; + std::vector vPhotonID; + std::vector vIsPhoton; + + for (const auto& p : parts) { + if (PID.size() == m_max) { + Warning("Reached maximum size of array", StatusCode::SUCCESS).ignore(); + break; + } + PID.push_back(p->particleID().pid()); + TPID.push_back(TID(p)); + PX.push_back(p->momentum().x()); + PY.push_back(p->momentum().y()); + PZ.push_back(p->momentum().z()); + PE.push_back(p->momentum().T()); + const LHCb::ProtoParticle* pp = p->proto(); + if (pp) { + vCaloTrMatch.push_back(pp->info(LHCb::ProtoParticle::CaloTrMatch, -1000)); + vCaloDepositID.push_back( + pp->info(LHCb::ProtoParticle::CaloDepositID, -1000)); + vShowerShape.push_back(pp->info(LHCb::ProtoParticle::ShowerShape, -1000)); + vClusterMass.push_back(pp->info(LHCb::ProtoParticle::ClusterMass, -1000)); + vCaloNeutralSpd.push_back( + pp->info(LHCb::ProtoParticle::CaloNeutralSpd, -1000)); + vCaloNeutralPrs.push_back( + pp->info(LHCb::ProtoParticle::CaloNeutralPrs, -1000)); + vCaloNeutralEcal.push_back( + pp->info(LHCb::ProtoParticle::CaloNeutralEcal, -1000)); + vCaloNeutralHcal2Ecal.push_back( + pp->info(LHCb::ProtoParticle::CaloNeutralHcal2Ecal, -1000)); + vCaloNeutralE49.push_back( + pp->info(LHCb::ProtoParticle::CaloNeutralE49, -1000)); + vCaloNeutralID.push_back( + pp->info(LHCb::ProtoParticle::CaloNeutralID, -1000)); + vPhotonID.push_back(pp->info(LHCb::ProtoParticle::PhotonID, -1000)); + vIsPhoton.push_back(pp->info(LHCb::ProtoParticle::IsPhoton, -1000)); + } + } + unsigned int siz = PID.size(); + + test &= (PE.empty() || PE.size() == siz); // check + test &= (vIsPhoton.empty() || vIsPhoton.size() == siz); // check + if (!test) { + err() << "Inconsistent array sizes " << siz << " and " << PE.size() + << " and " << vIsPhoton.size() << endmsg; + return StatusCode(test); + } + + test &= tup->farray(prefix + "AllPhotons_PID", PID, prefix + "nParts", m_max); + test &= + tup->farray(prefix + "AllPhotons_TPID", TPID, prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_PX", PX, prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_PY", PY, prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_PZ", PZ, prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_PE", PE, prefix + "nParts", m_max); + + test &= tup->farray(prefix + "AllPhotons_CaloTrMatch", vCaloTrMatch, + prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_CaloDepositID", vCaloDepositID, + prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_ShowerShape", vShowerShape, + prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_ClusterMass", vClusterMass, + prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_CaloNeutralSpd", vCaloNeutralSpd, + prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_CaloNeutralPrs", vCaloNeutralPrs, + prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_CaloNeutralEcal", vCaloNeutralEcal, + prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_CaloNeutralHcal2Ecal", + vCaloNeutralHcal2Ecal, prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_CaloNeutralE49", vCaloNeutralE49, + prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_CaloNeutralID", vCaloNeutralID, + prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_PhotonID", vPhotonID, + prefix + "nParts", m_max); + test &= tup->farray(prefix + "AllPhotons_IsPhoton", vIsPhoton, + prefix + "nParts", m_max); + + return StatusCode(test); +} +//============================================================================ +int TupleToolAllPhotons::TID(const LHCb::Particle* P) { + Assert(!m_p2mcAssocs.empty(), + "The DaVinci smart associator(s) have not been initialized!"); + const LHCb::MCParticle* mcp(NULL); + if (P) { + // assignedPid = P->particleID().pid(); + if (msgLevel(MSG::VERBOSE)) + verbose() << "Getting related MCP to " << P << endmsg; + for (const auto& iMCAss : m_p2mcAssocs) { + mcp = iMCAss->relatedMCP(P); + if (mcp) break; + } + if (msgLevel(MSG::VERBOSE)) verbose() << "Got mcp " << mcp << endmsg; + } + // pointer is ready, prepare the values: + if (mcp) + return mcp->particleID().pid(); + else + return 0; +} + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolAllPhotons ) diff --git a/first-analysis-steps/DecayTrees/TupleToolAllPhotons.h b/first-analysis-steps/DecayTrees/TupleToolAllPhotons.h new file mode 100644 index 00000000..75b5cbea --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolAllPhotons.h @@ -0,0 +1,50 @@ +#ifndef TUPLETOOLALLTRACKS_H +#define TUPLETOOLALLTRACKS_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface +#include "Kernel/IRelatedPVFinder.h" +#include + +struct ITrackExtrapolator; +struct ITrackStateProvider; +class IParticle2MCAssociator; + +/** @class TupleToolAllPhotons TupleToolAllPhotons.h + * + * This tuple tool fills information about every calorimeter object in the StdLooseAllPhotons container. + * + * The primary target of this tool is analysis in a low multiplicity environment, particularly CEP studies. + * The default case is therefore to limit the stored information to 12 objects in the container, in order + * to minimise the impact on ntuple size. However, this limit is left configurable. + * + * @author Dan Johnson, Victor Coco, Kazu Akiba + * @date 2017-05-25 + */ +class TupleToolAllPhotons : public TupleToolBase, + virtual public IEventTupleTool { + public: + /// Standard constructor + TupleToolAllPhotons(const std::string& type, const std::string& name, + const IInterface* parent); + + /// Declare properties + Gaudi::Property< std::string > m_location{this, "Location", "/Event/Phys/StdLooseAllPhotons/Particles", "Location of particles"}; + Gaudi::Property< unsigned int > m_max {this, "Max" , 12 , "Maximum n photons to store information about"}; + Gaudi::Property< bool > m_allChi2 {this, "AllChi2" , false , "Fill all chi2?"}; + Gaudi::Property< std::vector > m_p2mcAssocTypes {this, "IP2MCPAssociatorTypes" , {"DaVinciSmartAssociator","MCMatchObjP2MCRelator"} , "MC associators to try, in order"}; + + virtual StatusCode fill(Tuples::Tuple&) override; ///< Fill tuple + StatusCode initialize() override; ///< init + + private: + int TID(const LHCb::Particle* p); + const IDistanceCalculator* m_dist=0; + IRelatedPVFinder* m_pvf=0; + const ITrackStateProvider* m_extrapolator=0; /// m_p2mcAssocs; +}; + +#endif // TUPLETOOLALLTRACKS_H diff --git a/first-analysis-steps/DecayTrees/TupleToolAllTracks.cpp b/first-analysis-steps/DecayTrees/TupleToolAllTracks.cpp new file mode 100644 index 00000000..54b13965 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolAllTracks.cpp @@ -0,0 +1,564 @@ +// Include files +// local +#include "TupleToolAllTracks.h" +// from Gaudi +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "GaudiKernel/Transform3DTypes.h" +// from Phys +#include "Kernel/GetIDVAlgorithm.h" +#include "Kernel/IDVAlgorithm.h" +#include "Kernel/IDistanceCalculator.h" +#include "Kernel/IVertexFit.h" +#include "Kernel/IPVReFitter.h" +#include "Kernel/IParticleDescendants.h" +// from LHCb +#include "Event/Particle.h" +//from LoKi +#include "LoKi/ParticleProperties.h" +//from boost +#include "boost/algorithm/string/replace.hpp" + +DECLARE_COMPONENT( TupleToolAllTracks ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolAllTracks::TupleToolAllTracks( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_dva(0) + , m_dist(0) + , m_pVertexFit(0) + , m_particleDescendants(0) +{ + declareInterface(this); + + declareProperty( "InputParticles" ,m_InputParticles = {"Phys/StdAllNoPIDsPions/Particles"}, "List of input Particles"); + declareProperty( "Target" ,m_TargetParticle = "Charm" , "Particle to add Particles to"); + declareProperty( "VertexMode" ,m_VModedummy = 0 , "Decay vertex to which the particle is added"); + declareProperty( "ANNPID" ,m_ANNPIDCut = -1.f , "Cut on ProbNN of added input particle type"); //NB: if -1, no cut is placed + declareProperty( "Theta" ,m_theta = -1.f , "Cut on theta angle of the added input particle"); //NB: if -1, no cut is placed + declareProperty( "DeltaPhi" ,m_deltaphi = -1.f , "Cut on the difference between phi angles of target and added particle"); //NB: if -1, no cut is placed + declareProperty( "GhostProb" ,m_GhostProb = 1.f , "Cut on the added input particle ghost probability"); //NB: if -1, no cut is placed + declareProperty( "DLLPID" ,m_DLLPIDCut = -9999.f , "Cut on DLL of added input particle type"); //NB: PIDPi == -PIDK! + declareProperty( "NewVertexChi2" ,m_VertexChi2Cut = -1.f , "Cut on Vertex chi2/ndof with added particle"); //NB: if -1, no cut is placed + declareProperty( "ImprovedVertex" ,m_improvedVertex = -1.f , "Cut on Vertex chi2/ndof w added particle - Vertex chi2/ndof w/o added particle"); //NB: if -1, no cut is placed + declareProperty( "IPchi2" ,m_ipchi2Cut = -1.f , "Cut on IPchi2 of added particle w.r.t. new vertex"); //NB: if -1, no cut is placed + declareProperty( "PVIPchi2" ,m_PVipchi2Cut = -1.f , "Cut on IPchi2 of added particle w.r.t. closest primary vertex"); //NB: if -1, no cut is placed + declareProperty( "MHi" ,m_HiMassCut = -1.f*Gaudi::Units::MeV , "Cut on invariant mass of Target+input particles"); //NB: if -1, no cut is placed + declareProperty( "AddMax" ,m_mult = 200 , "Maximal number of added particles"); + declareProperty( "WritePXPYPZ" ,m_addpxpypz = false , "Write PX, PY, PZ of added particle alone and target+particle combination"); + declareProperty( "CorrectedMass" ,m_addcorrm = false , "Write corrected mass and it's error of mother+added particle"); +} + +//============================================================================= + +StatusCode TupleToolAllTracks::initialize() { + if( ! TupleToolBase::initialize() ) return StatusCode::FAILURE; + + for(auto location = m_InputParticles.begin(); location != m_InputParticles.end() ; location++ ){ + info() << "Adding particles from " << *location << " to a " << m_TargetParticle << endmsg; + if (!exist(*location)){ + if (msgLevel(MSG::WARNING)) warning() << "No particles at " << *location << "! Skipping this TES location!" << endmsg; + m_InputParticles.erase(location); + } + } + if(m_InputParticles.empty())return StatusCode::FAILURE; + + //declareProperty can't deal with enums(?) + m_VertexMode = static_cast(m_VModedummy); + + if(m_addcorrm && m_VertexMode != VMode::ToMother && msgLevel(MSG::WARNING)) + warning() << "Writing the corrected mass is only implemented for VertexMode = 0.\n" + "No corrected mass output will be written to the tuple!" << endmsg; + + if(m_improvedVertex != -1 && m_VertexMode == VMode::NewVertex && msgLevel(MSG::WARNING)) + warning() << "Requested an improved vertex cut, but running in mode where a new vertex is made.\n" + "This cut will have no effect!" << endmsg; + + + //get tools + m_dva = Gaudi::Utils::getIDVAlgorithm ( contextSvc() ) ; + m_dist = tool("LoKi::DistanceCalculator",this); + m_pvReFitter = tool("LoKi::PVReFitter:PUBLIC", this ); + m_pVertexFit = m_dva->vertexFitter(); + m_particleDescendants = tool ( "ParticleDescendants"); + if( !m_dva ) return Error("Couldn't get parent DVAlgorithm", StatusCode::FAILURE); + if( !m_dist ) return Error("Unable to retrieve the IDistanceCalculator tool", StatusCode::FAILURE); + if( !m_pvReFitter ) return Error("Unable to retrieve the LoKi::PVReFitter", StatusCode::FAILURE); + if( !m_pVertexFit ) return Error("Unable to retrieve the IVertexFit tool", StatusCode::FAILURE); + if( !m_particleDescendants ) return Error("Unable to retrieve the ParticleDescendants tool", StatusCode::FAILURE); + + return StatusCode::SUCCESS; +} + +//============================================================================= + +StatusCode TupleToolAllTracks::fill( const Particle* mother + , const Particle* Mother + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix="Added"; + Assert( Mother && mother && m_dist + , "This should not happen, you are inside TupleToolAllTracks.cpp :(" ); + + // set test true. It will be the StatusCode that is returned + bool test = true; + const auto pion_mass = 139.57 *Gaudi::Units::MeV; + const auto kaon_mass = 493.68 *Gaudi::Units::MeV; + const auto proton_mass = 938.272*Gaudi::Units::MeV; + + //declare variables that will be written to the tuple + std::vector h_oldip, h_oldipchi2, h_newip, h_newipchi2, h_minipchi2; + std::vector h_opening, h_fdchi2_new, h_fdchi2_old, h_fd_new, h_fd_old; + std::vector h_vertexchi2_new, h_vertexchi2_old; + std::vector h_trackchi2, h_ghost; + std::vector h_tracktype; + std::vector h_PIDk, h_PIDe, h_PIDmu, h_PIDp, h_ProbNNp, h_ProbNNk, h_ProbNNe, h_ProbNNpi, h_ProbNNmu; + std::vector h_PT, h_ETA, h_PHI, h_THETA, h_DELPHI, h_PX, h_PY, h_PZ; + std::vector h_PID, h_ProbNNPID; + std::vector T_plus_h_M, M_h_CorrM, M_h_Delta_CorrM, T_plus_h_M_pion, M_h_CorrM_pion, M_h_Delta_CorrM_pion; + std::vector T_plus_h_M_proton, M_h_CorrM_proton, M_h_Delta_CorrM_proton, T_plus_h_M_kaon, M_h_CorrM_kaon, M_h_Delta_CorrM_kaon; + std::vector T_plus_h_PT, T_plus_h_ETA, T_plus_h_PHI, T_plus_h_PX, T_plus_h_PY, T_plus_h_PZ; + std::vector VRFS; + std::vector newvertex_x,newvertex_y,newvertex_z,newPVx,newPVy,newPVz; + std::vector vertexcov_new, pvcov_new; + + Particle *Target = nullptr; + + //check if mother is target + auto mother_is_target = !m_TargetParticle.compare("Mother") //==0 means strings are equal + || Mother->particleID().abspid() == (LoKi::Particles::pidFromName(m_TargetParticle)).abspid(); + if(mother_is_target){ + Target = const_cast(Mother); + } + else{ + for( auto tmpDaughter : Mother->daughtersVector()){ + //tmp daughter is charm meson or baryon + bool default_charm = ( (400 < tmpDaughter->particleID().abspid() && tmpDaughter->particleID().abspid() < 500) + | (4000 < tmpDaughter->particleID().abspid() && tmpDaughter->particleID().abspid() < 5000) ); + //declare particles in the decay chain as target + if(!m_TargetParticle.compare("Charm")){ + if(default_charm) + Target = const_cast(tmpDaughter); + else continue; + } + else if(tmpDaughter->particleID().abspid() == (LoKi::Particles::pidFromName(m_TargetParticle)).abspid()) + Target = const_cast(tmpDaughter); + else continue; + } + } + + //If no target was found, or the mother is a basic particle, go to the next event + if(Target == nullptr) return StatusCode(test); + if(Mother->isBasicParticle()) return StatusCode(test); + + //get the vertex from the decay described in the DecayDescriptor (old vertex) + //here we have 3 different scenarios: + // - the new particle should be added to the target's mother + // (e.g. Lb -> (Sc->Lc {pi}) mu nu, where Sc is strongly decaying to the target and a pion we want to add) + // - the new particle should be added directly to the target decay vertex + // (e.g. {psi(2S)?} -> (J/psi -> mu mu) {pi} {pi}, where the two pions are directly added to the dimuon vertex, because of the short J/psi lifetime) + // - the new particle and the target form a new vertex + // (e.g. {B?} -> D0 {pi}, where D0 is target, pi is added particle. Since the D0 decay vertex will be upstream of the B vertex due to it's lifetime, we need to make a new vertex) + // contrary to the first 2 scenarios, it makes no sense to compare vertices in this case, since the vertex didn't exist before. + Vertex v; + Particle::ConstVector parts2Vertex; + if(m_VertexMode == VMode::ToMother) + parts2Vertex = Mother->daughtersVector(); + else if(m_VertexMode == VMode::ToTarget) + parts2Vertex = Target->daughtersVector(); + else + parts2Vertex.push_back(Target); + if(m_VertexMode != VMode::NewVertex) + m_pVertexFit->fit(v,parts2Vertex); + + // for all input particle locations + for(auto location : m_InputParticles){ + // get particles parts + auto parts = get(location); + if (msgLevel(MSG::DEBUG)) debug() << "Getting particles from " << location << " with " << (parts).size() << " particles" << endmsg; + for(auto *part : parts){ + if (!part){ info() << "particle to be added not found" << endmsg;continue;} + + auto PID = part->particleID().pid(); + //is basic or not one of the other basic particles that don't have a prototrack... (is there a query if a particle has a protoparticle?) + bool proto_exits = part->isBasicParticle() && std::abs(PID) != 22 && std::abs(PID) != 111 && std::abs(PID) != 221; + + //cut on track types includes Velo, VeloR, Long, Upstream and Downstream tracks + //skip tracks if they are already in the decay chain + if(proto_exits && ((part->proto()->track()->type() < Track::Types::Velo || part->proto()->track()->type() > Track::Types::Downstream) + || isTrackInDecay(part,Mother)))continue; + + auto pidK = -999.f, pide = -999.f, pidmu = -999.f, pidP = -999.f; + auto probNNe = -1.f, probNNk = -1.f, probNNp = -1.f, probNNpi = -1.f, probNNmu = -1.f, ghprob = -1.f; + auto ProbNNPID = 0, sign_long = 0, tracktype = 0; + + if(proto_exits){ + tracktype = part->proto()->track()->type(); + pidK = part->proto()->info(ProtoParticle::CombDLLk,-999); + pide = part->proto()->info(ProtoParticle::CombDLLe,-999); + pidmu = part->proto()->info(ProtoParticle::CombDLLmu,-999); + pidP = part->proto()->info(ProtoParticle::CombDLLp,-999); + std::vector probNNs; + probNNpi = part->proto()->info(ProtoParticle::ProbNNpi,-1);probNNs.push_back(probNNpi); + probNNmu = part->proto()->info(ProtoParticle::ProbNNmu,-1);probNNs.push_back(probNNmu); + probNNk = part->proto()->info(ProtoParticle::ProbNNk,-1);probNNs.push_back(probNNk); + probNNp = part->proto()->info(ProtoParticle::ProbNNp,-1);probNNs.push_back(probNNp); + probNNe = part->proto()->info(ProtoParticle::ProbNNe,-1);probNNs.push_back(probNNe); + ghprob = part->proto()->track()->ghostProbability(); + //get PID according most probable ProbNN value of the track + auto itelPID = std::distance(probNNs.begin(),std::max_element(probNNs.begin(), probNNs.end())); + part->particleID().pid() < 0 ? sign_long = -1 : sign_long = 1; + auto PIDfromProbNN = [=] () { + if (itelPID == 0) return sign_long*211; + else if (itelPID == 1) return -sign_long*13; + else if (itelPID == 2) return sign_long*321; + else if (itelPID == 3) return sign_long*2212; + else if (itelPID == 4) return -sign_long*11; + else return -1; + }; + ProbNNPID = PIDfromProbNN(); + } + //Ghost Probability cut + if(ghprob > m_GhostProb) continue; + + //get PID variables for the input particle type and make the desired cut + auto PIDVariables_underPIDHypothesis = [=] () -> std::pair { + if (std::abs(PID)==211) return {probNNpi,-pidK}; + else if(std::abs(PID)==321) return {probNNk,pidK}; + else if(std::abs(PID)==2212)return {probNNp,pidP}; + else if(std::abs(PID)==13) return {probNNmu,pidmu}; + else if(std::abs(PID)==11) return {probNNe,pide}; + else return {1.f,100.f}; + }; + if(PIDVariables_underPIDHypothesis().first < m_ANNPIDCut || PIDVariables_underPIDHypothesis().second < m_DLLPIDCut) continue; + + //calculate the Target+particle mass and make the desired cut + const auto TH = Gaudi::LorentzVector(Target->momentum()+part->momentum()); + auto Th_mass = TH.M(); + if(m_HiMassCut != -1*Gaudi::Units::MeV && Th_mass > m_HiMassCut) continue; + //Theta angle + float theta_part = part->momentum().theta(); + if( theta_part < m_theta) continue; + + float Delta_phi = Target->momentum().phi() - part->momentum().phi(); + if(std::fabs(Delta_phi) < m_deltaphi)continue; + + //PV min ipchi2 + auto PVinfo = getminipchi(part); + if(m_PVipchi2Cut != -1 && PVinfo.first < m_PVipchi2Cut) continue; + + //Fit a vertex with the added particle + bool VertexRefit = true; + Vertex vtxWithExtraTrack; + Particle *tmp_part = new Particle(*part); + parts2Vertex.push_back(tmp_part); + VertexRefit &= m_pVertexFit->fit(vtxWithExtraTrack,parts2Vertex); + parts2Vertex.pop_back(); + delete tmp_part; + + double oldip = 0, oldipchi2 = 0, newip, newipchi2, oldfd = 0, oldfdchi2 = 0, newfd, newfdchi2; + //Vertex chi2's + auto newvertchi2 = vtxWithExtraTrack.chi2PerDoF(); + if(m_VertexChi2Cut != -1 && (newvertchi2 > m_VertexChi2Cut || newvertchi2 < 0)) continue; + auto oldvertchi2 = m_VertexMode != VMode::NewVertex ? v.chi2PerDoF() : 0.f; + if(m_improvedVertex != -1 && m_VertexMode != VMode::NewVertex && (newvertchi2 > oldvertchi2 + m_improvedVertex || newvertchi2 < 0)) continue; + //Vertex IP's + m_dist->distance( part,&vtxWithExtraTrack,newip,newipchi2 ); + if(newipchi2 < 0 || (m_ipchi2Cut != -1 && newipchi2 > m_ipchi2Cut)) continue; + if(m_VertexMode != VMode::NewVertex){ + m_dist->distance( part,&v,oldip,oldipchi2 ); + if(oldipchi2 < 0) continue; + } + + h_minipchi2.push_back(PVinfo.first); + + //FD's + m_dist->distance ( PVinfo.second.get(), &vtxWithExtraTrack, newfd, newfdchi2 ); + if(m_VertexMode != VMode::NewVertex) + m_dist->distance ( PVinfo.second.get(), &v, oldfd, oldfdchi2 ); + + //opening angle between added particle and mother + h_opening.push_back(Mother->momentum().Dot(part->momentum())/sqrt(Mother->momentum().mag2()*part->momentum().mag2())); + + //Masses and corrected masses + std::vector tmp_vec; + ROOT::Math::PxPyPzM4D Tg,h; + Tg.SetPxPyPzE(Target->momentum().px(),Target->momentum().py(),Target->momentum().pz(),Target->momentum().E()); + h.SetPxPyPzE(part->momentum().px(),part->momentum().py(),part->momentum().pz(),part->momentum().E()); + + T_plus_h_M.push_back(Th_mass); + if(m_addcorrm && m_VertexMode == VMode::ToMother){ + tmp_vec = getcorrm(PVinfo.second.get(),&vtxWithExtraTrack,(Mother->momentum() + part->momentum())); + M_h_CorrM.push_back(tmp_vec.at(0)); + M_h_Delta_CorrM.push_back(tmp_vec.at(1)); + } + + h.SetM(pion_mass); + T_plus_h_M_pion.push_back((static_cast(Tg)+static_cast(h)).M()); + if(m_addcorrm && m_VertexMode == VMode::ToMother){ + tmp_vec = getcorrm(PVinfo.second.get(),&vtxWithExtraTrack,(Mother->momentum() + static_cast(h))); + M_h_CorrM_pion.push_back(tmp_vec.at(0)); + M_h_Delta_CorrM_pion.push_back(tmp_vec.at(1)); + } + + h.SetM(kaon_mass); + T_plus_h_M_kaon.push_back((static_cast(Tg)+static_cast(h)).M()); + if(m_addcorrm && m_VertexMode == VMode::ToMother){ + tmp_vec = getcorrm(PVinfo.second.get(),&vtxWithExtraTrack,(Mother->momentum() + static_cast(h))); + M_h_CorrM_kaon.push_back(tmp_vec.at(0)); + M_h_Delta_CorrM_kaon.push_back(tmp_vec.at(1)); + } + + h.SetM(proton_mass); + T_plus_h_M_proton.push_back((static_cast(Tg)+static_cast(h)).M()); + if(m_addcorrm && m_VertexMode == VMode::ToMother){ + tmp_vec = getcorrm(PVinfo.second.get(),&vtxWithExtraTrack,(Mother->momentum() + static_cast(h))); + M_h_CorrM_proton.push_back(tmp_vec.at(0)); + M_h_Delta_CorrM_proton.push_back(tmp_vec.at(1)); + } + + T_plus_h_PT .push_back(TH.pt()); + T_plus_h_ETA .push_back(TH.eta()); + T_plus_h_PHI .push_back(TH.phi()); + if(m_addpxpypz){ + T_plus_h_PX .push_back(TH.px()); + T_plus_h_PY .push_back(TH.py()); + T_plus_h_PZ .push_back(TH.pz()); + h_PX .push_back(part->momentum().px()); + h_PY .push_back(part->momentum().py()); + h_PZ .push_back(part->momentum().pz()); + } + h_PT .push_back(part->momentum().pt()); + h_ETA .push_back(part->momentum().eta()); + h_PHI .push_back(part->momentum().phi()); + h_THETA .push_back(theta_part); + h_DELPHI .push_back(Delta_phi); + if(m_VertexMode != VMode::NewVertex){ + h_oldip .push_back((float)oldip); + h_oldipchi2 .push_back((float)oldipchi2); + h_fdchi2_old .push_back((float)oldfdchi2); + h_fd_old .push_back((float)oldfd); + h_vertexchi2_old.push_back(oldvertchi2); + } + h_newip .push_back((float)newip); + h_newipchi2 .push_back((float)newipchi2); + h_fdchi2_new .push_back((float)newfd); + h_fd_new .push_back((float)newfdchi2); + h_vertexchi2_new.push_back(newvertchi2); + if(proto_exits){ + h_PIDk .push_back(pidK); + h_PIDe .push_back(pide); + h_PIDp .push_back(pidP); + h_PIDmu .push_back(pidmu); + h_ProbNNpi .push_back(probNNpi); + h_ProbNNp .push_back(probNNp); + h_ProbNNe .push_back(probNNe); + h_ProbNNk .push_back(probNNk); + h_ProbNNmu .push_back(probNNmu); + h_ghost .push_back(ghprob); + h_trackchi2 .push_back(part->proto()->track()->chi2PerDoF()); + h_tracktype .push_back(tracktype); + h_ProbNNPID .push_back(ProbNNPID); + } + h_PID .push_back(PID); + VRFS .push_back(VertexRefit); + newvertex_x .push_back(vtxWithExtraTrack.position().X()); + newvertex_y .push_back(vtxWithExtraTrack.position().Y()); + newvertex_z .push_back(vtxWithExtraTrack.position().Z()); + newPVx .push_back(PVinfo.second->position().X()); + newPVy .push_back(PVinfo.second->position().Y()); + newPVz .push_back(PVinfo.second->position().Z()); + vertexcov_new .push_back(vtxWithExtraTrack.covMatrix()); + pvcov_new .push_back(PVinfo.second->covMatrix()); + } + } + + auto target_tup_name = m_TargetParticle; + boost::algorithm::replace_all(target_tup_name,"*","St"); + boost::algorithm::replace_all(target_tup_name,"-","m"); + boost::algorithm::replace_all(target_tup_name,"+","p"); + boost::algorithm::replace_all(target_tup_name,"~","bar"); + boost::algorithm::replace_all(target_tup_name,"'","prime"); + boost::algorithm::replace_all(target_tup_name,"(","_"); + boost::algorithm::replace_all(target_tup_name,")","_"); + + //If array is bigger than m_mult entries per mother, we are still safe with the StatusCode, because farray will only throw a warning and not a bad status code in this case + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_M" ,T_plus_h_M.begin(), T_plus_h_M.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_M_pion" ,T_plus_h_M_pion.begin(), T_plus_h_M_pion.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_M_kaon" ,T_plus_h_M_kaon.begin(), T_plus_h_M_kaon.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_M_proton" ,T_plus_h_M_proton.begin(), T_plus_h_M_proton.end() ,prefix+"_n_Particles",m_mult ); + if(m_addcorrm && m_VertexMode == VMode::ToMother){ + test &= tuple -> farray( fullName(head) + "_dauH_CorrM" ,M_h_CorrM.begin(), M_h_CorrM.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( fullName(head) + "_dauH_CorrM_pion" ,M_h_CorrM_pion.begin(), M_h_CorrM_pion.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( fullName(head) + "_dauH_CorrM_kaon" ,M_h_CorrM_kaon.begin(), M_h_CorrM_kaon.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( fullName(head) + "_dauH_CorrM_proton" ,M_h_CorrM_proton.begin(), M_h_CorrM_proton.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( fullName(head) + "_dauH_CorrMErr" ,M_h_Delta_CorrM.begin(), M_h_Delta_CorrM.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( fullName(head) + "_dauH_CorrMErr_pion" ,M_h_Delta_CorrM_pion.begin(), M_h_Delta_CorrM_pion.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( fullName(head) + "_dauH_CorrMErr_kaon" ,M_h_Delta_CorrM_kaon.begin(), M_h_Delta_CorrM_kaon.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( fullName(head) + "_dauH_CorrMErr_proton" ,M_h_Delta_CorrM_proton.begin(), M_h_Delta_CorrM_proton.end(),prefix+"_n_Particles",m_mult ); + } + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_PT" ,T_plus_h_PT.begin(), T_plus_h_PT.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_ETA" ,T_plus_h_ETA.begin(), T_plus_h_ETA.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_PHI" ,T_plus_h_PHI.begin(), T_plus_h_PHI.end() ,prefix+"_n_Particles",m_mult ); + if(m_addpxpypz){ + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_PX" ,T_plus_h_PX.begin(), T_plus_h_PX.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_PY" ,T_plus_h_PY.begin(), T_plus_h_PY.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_PZ" ,T_plus_h_PZ.begin(), T_plus_h_PZ.end() ,prefix+"_n_Particles",m_mult ); + } + if(m_VertexMode != VMode::NewVertex) + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_FDCHI2_OLD" ,h_fdchi2_old.begin(), h_fdchi2_old.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_FDCHI2_NEW" ,h_fdchi2_new.begin(), h_fdchi2_new.end() ,prefix+"_n_Particles",m_mult ); + if(m_VertexMode != VMode::NewVertex) + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_FD_OLD" ,h_fd_old.begin(), h_fd_old.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_FD_NEW" ,h_fd_new.begin(), h_fd_new.end() ,prefix+"_n_Particles",m_mult ); + if(m_VertexMode != VMode::NewVertex) + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_VERTEXCHI2_OLD" ,h_vertexchi2_old.begin(), h_vertexchi2_old.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_VERTEXCHI2_NEW" ,h_vertexchi2_new.begin(), h_vertexchi2_new.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_VERTEX_X_NEW" ,newvertex_x.begin(), newvertex_x.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_VERTEX_Y_NEW" ,newvertex_y.begin(), newvertex_y.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_VERTEX_Z_NEW" ,newvertex_z.begin(), newvertex_z.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_PV_X_NEW" ,newPVx.begin(), newPVx.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_PV_Y_NEW" ,newPVy.begin(), newPVy.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_PV_Z_NEW" ,newPVz.begin(), newPVz.end() ,prefix+"_n_Particles",m_mult ); + + //The following line doesn't work with that type, so write the individual components to the tuple + //test &= tuple -> put ( prefix + "_H_VERTEX_COV_NEW", const_cast*>(&h_vertexcov_new)); + std::vector xyz = {"X","Y","Z"}; + for(unsigned int i = 0; i < 3; i++){ + for(unsigned int j = i; j < 3; j++){ + std::vector tmp_cov_vec, tmp_pv_cov; + for(unsigned int k = 0; k < vertexcov_new.size(); k++){ + tmp_cov_vec.push_back(vertexcov_new.at(k).At(i,j)); + tmp_pv_cov .push_back(pvcov_new .at(k).At(i,j)); + } + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_VERTEX_COV_" + xyz.at(i) + xyz.at(j),tmp_cov_vec.begin(), tmp_cov_vec.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_PV_COV_" + xyz.at(i) + xyz.at(j),tmp_pv_cov.begin() , tmp_pv_cov.end() ,prefix+"_n_Particles",m_mult ); + } + } + + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_VertexRefitStatus",VRFS.begin(),VRFS.end() ,prefix+"_n_Particles",m_mult ); + if(m_VertexMode != VMode::NewVertex){ + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_IPCHI2_OLD" ,h_oldipchi2.begin(), h_oldipchi2.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_IP_OLD" ,h_oldip.begin(), h_oldip.end() ,prefix+"_n_Particles",m_mult ); + } + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_IPCHI2_NEW" ,h_newipchi2.begin(), h_newipchi2.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_IP_NEW" ,h_newip.begin(), h_newip.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_" + target_tup_name + "H_MINIPCHI2" ,h_minipchi2.begin(), h_minipchi2.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( fullName(head) + "_H_OPENING" ,h_opening.begin(), h_opening.end() ,prefix+"_n_Particles",m_mult ); + if(m_addpxpypz){ + test &= tuple -> farray( prefix + "_H_PX" ,h_PX.begin(), h_PX.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_H_PY" ,h_PY.begin(), h_PY.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_H_PZ" ,h_PZ.begin(), h_PZ.end() ,prefix+"_n_Particles",m_mult ); + } + test &= tuple -> farray( prefix + "_H_PT" ,h_PT.begin(), h_PT.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_H_ETA" ,h_ETA.begin(), h_ETA.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_H_PHI" ,h_PHI.begin(), h_PHI.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_H_THETA" ,h_THETA.begin(), h_THETA.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_H_DELTAPHI" ,h_DELPHI.begin(), h_DELPHI.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_H_PID" ,h_PID.begin(), h_PID.end() ,prefix+"_n_Particles",m_mult ); + test &= tuple -> farray( prefix + "_H_PROBNNPID" ,h_ProbNNPID.begin(), h_ProbNNPID.end() ,prefix+"_n_Tracks",m_mult ); + test &= tuple -> farray( prefix + "_H_GHOST" ,h_ghost.begin(), h_ghost.end() ,prefix+"_n_Tracks",m_mult ); + test &= tuple -> farray( prefix + "_H_TRACKCHI2" ,h_trackchi2.begin(), h_trackchi2.end() ,prefix+"_n_Tracks",m_mult ); + test &= tuple -> farray( prefix + "_H_TRACKTYPE" ,h_tracktype.begin(), h_tracktype.end() ,prefix+"_n_Tracks",m_mult ); + test &= tuple -> farray( prefix + "_H_PIDe" ,h_PIDe.begin(), h_PIDe.end() ,prefix+"_n_Tracks",m_mult ); + test &= tuple -> farray( prefix + "_H_PIDK" ,h_PIDk.begin(), h_PIDk.end() ,prefix+"_n_Tracks",m_mult ); + test &= tuple -> farray( prefix + "_H_PIDmu" ,h_PIDmu.begin(), h_PIDmu.end() ,prefix+"_n_Tracks",m_mult ); + test &= tuple -> farray( prefix + "_H_PIDp" ,h_PIDp.begin(), h_PIDp.end() ,prefix+"_n_Tracks",m_mult ); + test &= tuple -> farray( prefix + "_H_ProbNNpi" ,h_ProbNNpi.begin(), h_ProbNNpi.end() ,prefix+"_n_Tracks",m_mult ); + test &= tuple -> farray( prefix + "_H_ProbNNk" ,h_ProbNNk.begin(), h_ProbNNk.end() ,prefix+"_n_Tracks",m_mult ); + test &= tuple -> farray( prefix + "_H_ProbNNp" ,h_ProbNNp.begin(), h_ProbNNp.end() ,prefix+"_n_Tracks",m_mult ); + test &= tuple -> farray( prefix + "_H_ProbNNe" ,h_ProbNNe.begin(), h_ProbNNe.end() ,prefix+"_n_Tracks",m_mult ); + test &= tuple -> farray( prefix + "_H_ProbNNmu" ,h_ProbNNmu.begin(), h_ProbNNmu.end() ,prefix+"_n_Tracks",m_mult ); + + return StatusCode(test); +} + +//============================================================================= +// Check if the track is already in the decay +//============================================================================= +bool TupleToolAllTracks::isTrackInDecay(const Particle* particle, const Particle* mother){ + bool isInDecay = false; + //loop over daughters + auto stable_daughters = m_particleDescendants->finalStates(mother); + if(stable_daughters.empty())return isInDecay; + for(auto* it : stable_daughters){ + if(std::abs(it->particleID().pid()) != 22 && std::abs(it->particleID().pid()) != 111 && std::abs(it->particleID().pid()) != 221){ + if(it->proto()->track() == particle->proto()->track()){ + if ( msgLevel(MSG::DEBUG) ) debug() << "Track is in decay, skipping it" << endmsg; + isInDecay = true; + break; + } + } + } + return isInDecay; +} + +//============================================================================= +// MINIPCHI2 for a Particle | Thanks to Roel for correcting this part of code! +//============================================================================= +std::pair > TupleToolAllTracks::getminipchi(const Particle* particle){ + float minchi2 = -1.f ; + RecVertex *bestPV = nullptr; + auto PV = m_dva->primaryVertices(); + if ( PV.empty() )return {minchi2,nullptr}; + for ( auto pv : PV ){ + double ip, chi2; + m_dist->distance ( particle, pv, ip, chi2 ); + if( (chi2 < minchi2) || (minchi2 < 0.0) ){ + RecVertex* newPV = pv->clone(); + // remove particle refit vertex + m_pvReFitter->remove( particle, newPV ); + m_dist->distance( particle, newPV, ip, chi2 ); + minchi2 = chi2; + delete bestPV; + bestPV = newPV; + } + } + return {minchi2, std::unique_ptr(bestPV)}; +} + +//============================================================================= +// Corrected mass for mother + additional particle +//============================================================================= +std::vector TupleToolAllTracks::getcorrm(const RecVertex *PV, const Vertex *SV, const Gaudi::LorentzVector &new_mother){ + //Calculations taken from Lb -> p mu nu note: https://cds.cern.ch/record/1694339/files/LHCb-ANA-2014-048.pdf + auto dir = SV->position() - PV->position(); + auto mom = new_mother.Vect(); + auto dmag2 = dir.Mag2(); + auto longit_norm = 0.f; + if ( 0.f != dmag2 ) longit_norm = mom.Dot(dir)/dmag2; + auto ptprime = mom - dir*longit_norm; + float CorrM = (float)sqrt( pow(new_mother.M(),2) + ptprime.Mag2() ) + sqrt(ptprime.Mag2()); + + //calculate derivatives of longit_norm + auto dlon_dx = ( 2*dir.x()*mom.Dot(dir) - mom.x()*dmag2 )/(pow(dmag2,2)); + auto dlon_dy = ( 2*dir.y()*mom.Dot(dir) - mom.y()*dmag2 )/(pow(dmag2,2)); + auto dlon_dz = ( 2*dir.z()*mom.Dot(dir) - mom.z()*dmag2 )/(pow(dmag2,2)); + + //derivatives of pt (from Michael Kolpin) + std::vector pt_derivatives; + if(ptprime.Mag2() == 0.f)return {CorrM,-1.f}; + pt_derivatives.push_back( (longit_norm*ptprime.x() - dlon_dx*(ptprime.x() + ptprime.y() + ptprime.z()))/sqrt(ptprime.Mag2()) ); + pt_derivatives.push_back( (longit_norm*ptprime.y() - dlon_dy*(ptprime.x() + ptprime.y() + ptprime.z()))/sqrt(ptprime.Mag2()) ); + pt_derivatives.push_back( (longit_norm*ptprime.z() - dlon_dz*(ptprime.x() + ptprime.y() + ptprime.z()))/sqrt(ptprime.Mag2()) ); + + //uncertainty of pt + auto PV_cov = PV->covMatrix(); + auto SV_cov = SV->covMatrix(); + auto delta_ptprime2 = 0.f; + for(auto i = 0; i < 3; i++){ + for(auto j = 0; j < 3; j++){ + delta_ptprime2 += pt_derivatives.at(i)*pt_derivatives.at(j)*( PV_cov.At(i,j) + SV_cov.At(i,j) ); + if(i != j) delta_ptprime2 *= 2; + } + } + //uncertainty on m_corr + float delta_Corr_M = (float)( sqrt(ptprime.Mag2())/sqrt(pow(new_mother.M(),2) + ptprime.Mag2()) + 1.0 ) * sqrt(delta_ptprime2); + + return {CorrM,delta_Corr_M}; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolAllTracks.h b/first-analysis-steps/DecayTrees/TupleToolAllTracks.h new file mode 100644 index 00000000..3c22e3b4 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolAllTracks.h @@ -0,0 +1,129 @@ +#ifndef TUPLETOOLAllTracks_H +#define TUPLETOOLAllTracks_H + +// from Gaudi +#include "Kernel/IParticleTupleTool.h" +#include "TrackInterfaces/ITrackVertexer.h" +//from LHCb +#include "Event/Vertex.h"//includes Gaudi::LorentzVector +//from Analysis +#include "DecayTreeTupleBase/TupleToolBase.h" + + +/** + + @class TupleToolAllTracks TupleToolAllTracks.h + @brief Isolation tool based on TupleToolVtxIsoln by Mitesh Patel, Patrick Koppenburg, using ideas from TupleToolSLTools + The idea is to add particles, passing a selection that is set by configurable parameters, + from given TES location(s) to a (configurable) target particle in the decay chain + and provide information that can be used to isolate the specific decay, + or to simply provide the information needed to study a new exclusive decay chain. + + In a pyton options-file, use e.g.: + @code + from Configurables import TupleToolAllTracks + AllTracks=TupleToolAllTracks("AllTracks") + locations = [] + loations.append('Phys/StdAllNoPIDsPions/Particles') + locations.append("Phys/StdLoosePi02gg/Particles") + locations.append("Phys/StdLooseAllPhotons/Particles") + AllTracks.VertexMode = 0 + AllTracks.ANNPIDCut = 0.3 #ProbNNPID cut on input particle of type PID + AllTracks.GhostProb = 0.5 + AllTracks.Theta = 0.012 #Cut on theta angle (less than) of the added input particle + AllTracks.DeltaPhi = 0.005 #Cut on the difference between phi angles (abs value less than) of target and added particle + AllTracks.NewVertexChi2 = 6 + AllTracks.MHi = 7000 + AllTracks.ImprovedVertex = 4 #new vertex chi^2 / ndof should not be worse than 4 + AllTracks.PVIPchi2 = 25 + AllTracks.CorrectedMass = True + AllTracks.InputParticles = locations + AllTracks.Target = Lambda_c+ #has to be defined in decay descriptor + @endcode + then add the tool to the head(!) of your chain. + If a cut is not explicitly given in the config file, no cut will be made. + + The VertexMode option takes values 0,1,2 describing the following scenarios: + - the new particle should be added to the target's mother (e.g. Lb -> (Sc->Lc {pi}) mu nu, where Sc is strongly decaying to the target and a pion we want to add) + - the new particle should be added directly to the target decay vertex (e.g. {psi(2S)?} -> (J/psi -> mu mu) {pi} {pi}, where the two pions are directly added to the dimuon vertex, because of the short J/psi lifetime) + - the new particle and the target form a new vertex (e.g. {B?} -> D0 {pi}, where D0 is target, pi is added particle. Since the D0 decay vertex will be upstream of the B vertex due to it's lifetime, we need to make a new vertex) + + For a preselection of the added particles, one can use e.g. a FilterDesktop: + @code + pionFilter = FilterDesktop("PionFilter") + pionFilter.Code = "(P > 2.*GeV) & (P < 200.*GeV)" \ + "& (PT < 10.*GeV)" \ + "& (TRCHI2DOF < 3)" + SelStdNoPIDsPions = DataOnDemand(Location='Phys/StdAllNoPIDsPions/Particles') + + PifromB = Selection("SelPifromB", + Algorithm = pionFilter, + RequiredSelections = [SelStdNoPIDsPions]) + SeqPifromB = SelectionSequence("SeqPifromB", TopSelection = PifromB) + @endcode + and pass the outputlocation to the tool (if locations is your list of TES locations) + @code + locations.append(SeqPifromB.outputLocation()) + @endcode + + @note + The calculation of the corrected mass and it's error has not been cross-checked with existing algorithms yet. Use at own risk! + + @date 2015-10-08 + @version v1r1 2016-06-08 : implemented VertexMode & possibility to add particles to head + @author Greg Ciezarek, Marco Fiore, Marian Stahl + +**/ + +struct IDVAlgorithm; +struct IDistanceCalculator; +struct IVertexFit; +struct IPVReFitter; +struct IParticleDescendants; + +using namespace LHCb; + +class TupleToolAllTracks : public TupleToolBase, virtual public IParticleTupleTool { +public: + // Standard constructor + TupleToolAllTracks( const std::string& type, const std::string& name, const IInterface* parent); + virtual ~TupleToolAllTracks( ){} + StatusCode initialize() override; + StatusCode fill(const Particle* , const Particle* , const std::string& , Tuples::Tuple& ) override; + +private: + + //Tools + IDVAlgorithm *m_dva; + IDistanceCalculator *m_dist; + const IVertexFit *m_pVertexFit; + IPVReFitter *m_pvReFitter; + std::string m_typeVertexFit; + IParticleDescendants *m_particleDescendants; + + //functions + bool isTrackInDecay(const Particle *particle, const Particle *mother); + std::pair > getminipchi (const Particle *particle); + std::vector getcorrm (const RecVertex *PV, const Vertex *SV, const Gaudi::LorentzVector &new_mother); + + //member variables + std::vector m_InputParticles; + std::string m_TargetParticle; + int m_VModedummy; + enum class VMode{ToMother = 0, ToTarget, NewVertex}; + VMode m_VertexMode; + float m_ANNPIDCut; + float m_theta; + float m_deltaphi; + float m_GhostProb; + float m_DLLPIDCut; + float m_VertexChi2Cut; + float m_ipchi2Cut; + float m_PVipchi2Cut; + float m_improvedVertex; + float m_HiMassCut; + unsigned long m_mult; + bool m_addpxpypz; + bool m_addcorrm; +}; +#endif // TUPLETOOLAllTracks_H diff --git a/first-analysis-steps/DecayTrees/TupleToolAllVeloTracks.cpp b/first-analysis-steps/DecayTrees/TupleToolAllVeloTracks.cpp new file mode 100644 index 00000000..99bfefd0 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolAllVeloTracks.cpp @@ -0,0 +1,93 @@ +// from Gaudi +#include "Event/Track.h" +#include "Event/RecSummary.h" +#include "Event/VertexBase.h" +#include "Event/RecVertex.h" +#include "Kernel/DefaultDVToolTypes.h" +#include "Event/VeloCluster.h" +#include "Event/Particle.h" +#include "TrackInterfaces/IVeloClusterPosition.h" +#include "TrackInterfaces/IVeloExpectation.h" +#include "TrackInterfaces/IMeasurementProvider.h" +// local +#include "TupleToolAllVeloTracks.h" +#include "TrackInterfaces/ITrackExtrapolator.h" +#include "TrackInterfaces/ITrackStateProvider.h" +#include "Kernel/IParticle2MCAssociator.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolAllVeloTracks +// +// 2017-05-25 : Dan Johnson, Victor Coco, Kazu Akiba +//----------------------------------------------------------------------------- + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolAllVeloTracks::TupleToolAllVeloTracks(const std::string& type, + const std::string& name, + const IInterface* parent) + : TupleToolBase(type, name, parent) { + declareInterface(this); +} + +StatusCode TupleToolAllVeloTracks::initialize() { + StatusCode sc = TupleToolBase::initialize(); + if (sc.isFailure()) return sc; + + return sc; +} + +//============================================================================= +StatusCode TupleToolAllVeloTracks::fill(Tuples::Tuple& tup) { + const std::string prefix = fullName(); + bool test = true; + + std::vector vSlopeX; + std::vector vSlopeY; + std::vector vPointX; + std::vector vPointY; + std::vector vPointZ; + std::vector vChi2pDOF; + std::vector vType; + std::vector vKey; + + const LHCb::Tracks* tracks = get(m_location); + if (!tracks || tracks->empty()) return StatusCode::FAILURE; + for (const auto& tr : (*tracks)) { + // Only save tracks with a velo segment (long, velo or upstream) + if (tr->type() != LHCb::Track::Types::Velo && + tr->type() != LHCb::Track::Types::Upstream && tr->type() != LHCb::Track::Types::Long) + continue; + Gaudi::XYZPoint pos = tr->position(); + Gaudi::XYZVector slop = tr->slopes(); + vSlopeX.push_back(slop.X()); + vSlopeY.push_back(slop.Y()); + vPointX.push_back(pos.X()); + vPointY.push_back(pos.Y()); + vPointZ.push_back(pos.Z()); + vType.push_back(tr->type()); + vKey.push_back(tr->key()); + vChi2pDOF.push_back(tr->chi2PerDoF()); + } // tracks + test &= tup->farray(prefix + "VeloSegTr_slopeX", vSlopeX, + prefix + "nVeloSegTracks", m_max); + test &= tup->farray(prefix + "VeloSegTr_slopeY", vSlopeY, + prefix + "nVeloSegTracks", m_max); + test &= tup->farray(prefix + "VeloSegTr_pointX", vPointX, + prefix + "nVeloSegTracks", m_max); + test &= tup->farray(prefix + "VeloSegTr_pointY", vPointY, + prefix + "nVeloSegTracks", m_max); + test &= tup->farray(prefix + "VeloSegTr_pointZ", vPointZ, + prefix + "nVeloSegTracks", m_max); + test &= tup->farray(prefix + "VeloSegTr_chi2pdof", vChi2pDOF, + prefix + "nVeloSegTracks", m_max); + test &= tup->farray(prefix + "VeloSegTr_type", vType, + prefix + "nVeloSegTracks", m_max); + test &= tup->farray(prefix + "VeloSegTr_key", vKey, prefix + "nVeloSegTracks", + m_max); + return StatusCode(test); +} + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolAllVeloTracks ) diff --git a/first-analysis-steps/DecayTrees/TupleToolAllVeloTracks.h b/first-analysis-steps/DecayTrees/TupleToolAllVeloTracks.h new file mode 100644 index 00000000..4072ee35 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolAllVeloTracks.h @@ -0,0 +1,42 @@ +#ifndef TUPLETOOLALLTRACKS_H +#define TUPLETOOLALLTRACKS_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface +#include "Kernel/IRelatedPVFinder.h" +#include + +struct ITrackExtrapolator; +struct ITrackStateProvider; +class IParticle2MCAssociator; + +/** @class TupleToolAllVeloTracks TupleToolAllVeloTracks.h + * + * This tuple tool fills information about every VELO track best-tracks container. + * + * The primary target of this tool is analysis in a low multiplicity environment, particularly CEP studies. + * The default case is therefore to limit the stored information to 50 tracks in the container, in order + * to minimise the impact on ntuple size. However, this limit is left configurable. + * + * @author Dan Johnson, Victor Coco, Kazu Akiba + * @date 2017-05-25 + */ +class TupleToolAllVeloTracks : public TupleToolBase, + virtual public IEventTupleTool { + public: + /// Standard constructor + TupleToolAllVeloTracks(const std::string& type, const std::string& name, + const IInterface* parent); + + /// Declare properties + Gaudi::Property< std::string > m_location{this, "Location", LHCb::TrackLocation::Default, "Location of particles"}; + Gaudi::Property< unsigned int > m_max {this, "Max" , 50 , "Maximum n photons to store information about"}; + + virtual StatusCode fill(Tuples::Tuple&) override; ///< Fill tuple + StatusCode initialize() override; ///< init + +}; + +#endif // TUPLETOOLALLTRACKS_H diff --git a/first-analysis-steps/DecayTrees/TupleToolAngles.cpp b/first-analysis-steps/DecayTrees/TupleToolAngles.cpp new file mode 100644 index 00000000..3c364469 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolAngles.cpp @@ -0,0 +1,96 @@ +// $Id: TupleToolAngles.cpp,v 1.5 2010-01-26 15:39:26 rlambert Exp $ +// Include files +#include "gsl/gsl_sys.h" + +// from Gaudi +#include "GaudiKernel/PhysicalConstants.h" +#include "GaudiKernel/Vector3DTypes.h" + +// local +#include "TupleToolAngles.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" + +using namespace LHCb; +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolAngles +// +// 2009-01-19 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolAngles ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolAngles::TupleToolAngles( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ), + m_wrtMother(0) +{ + declareInterface(this); + declareProperty("WRTMother",m_wrtMother=true, + "Turn false to fill angles with respect to top of tree"); +} + +//============================================================================= +// Destructor +//============================================================================= +TupleToolAngles::~TupleToolAngles() {} + +//============================================================================= +// Fill +//============================================================================= +StatusCode TupleToolAngles::fill( const LHCb::Particle* top + , const LHCb::Particle* part + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(head); + + bool test = true; + const LHCb::Particle* mother=top; + if(m_wrtMother) mother=findMother(top,part); + if ( 0==part || 0==mother || part==mother ) return StatusCode::SUCCESS ; + double cosT = cosTheta(mother->momentum(), part->momentum() ); + // fill the tuple: + test &= tuple->column( prefix+"_CosTheta", cosT ); + if(isVerbose()) test &= tuple->column( prefix+"_Theta", acos(cosT) ); + if ( msgLevel(MSG::DEBUG)) debug() << mother->particleID().pid() << " " << mother->momentum() << " " + << part->particleID().pid() << " " << part->momentum() << endmsg ; + return StatusCode(test) ; + +} +//============================================================================= +// Fill +//============================================================================= + +const LHCb::Particle* TupleToolAngles::findMother( const LHCb::Particle* top + , const Particle* P ) const +{ + if( top == P || top->isBasicParticle() ) return 0; + + const SmartRefVector< LHCb::Particle >& dau = top->daughters (); + if( dau.empty() ) return 0; + + SmartRefVector< LHCb::Particle >::const_iterator it; + for( it = dau.begin(); dau.end()!=it; ++it ){ + if( P == *it ){ // I found the daughter + return top; + } + } + + // vertex not yet found, get deeper in the decay: + for( it = dau.begin(); dau.end()!=it; ++it ){ + if( P != *it && !(*it)->isBasicParticle() ){ + const LHCb::Particle* tm = findMother( *it, P ); + if( tm ) return tm; + } + } + return 0; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolAngles.h b/first-analysis-steps/DecayTrees/TupleToolAngles.h new file mode 100644 index 00000000..63ad85f2 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolAngles.h @@ -0,0 +1,71 @@ +// $Id: TupleToolAngles.h,v 1.5 2010-01-26 15:39:26 rlambert Exp $ +#ifndef TUPLETOOLANGLES_H +#define TUPLETOOLANGLES_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "Math/Boost.h" +#include "GaudiKernel/Vector4DTypes.h" + + +/** @class TupleToolAngles TupleToolAngles.h + * + * Fill MC Particle with decay angle in mother frame + * + * - head_CosTheta : angle in mother's frame + * - if WRTMother is false, will calculate angle in frame of top of tree + * + * \sa MCTupleToolAngles, DecayTreeTuple, MCDecayTreeTuple + * + * @author Patrick Koppenburg + * @date 2009-01-21 + * @author R. Lambert + * @date 2009-09-04 + */ + +class TupleToolAngles : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolAngles( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolAngles( ); ///< Destructor + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + inline double cosTheta( const Gaudi::LorentzVector& mother, + const Gaudi::LorentzVector& mcp ) + { + ROOT::Math::Boost boost( mother.BoostToCM() ); + const Gaudi::XYZVector boostedParticle = (boost( mcp )).Vect().unit(); + const Gaudi::XYZVector boostedMother = mother.Vect().unit(); + double cosT = boostedParticle.Dot(boostedMother) ; + if (msgLevel(MSG::VERBOSE)) verbose() << mother << " " + << mcp << " " << boostedMother + << " " << boostedParticle + << " " << cosT << endmsg ; + return cosT; + } + + const LHCb::Particle* findMother( const LHCb::Particle* top + , const LHCb::Particle* P ) const; + +private: + + bool m_wrtMother; + +}; + +#endif // TUPLETOOLANGLES_H diff --git a/first-analysis-steps/DecayTrees/TupleToolBeamSpot.cpp b/first-analysis-steps/DecayTrees/TupleToolBeamSpot.cpp new file mode 100644 index 00000000..7a2b2da8 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolBeamSpot.cpp @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// Implementation for class: TupleToolBeamSpot +// +// 2015-07-10 : TupleToolBeamSpot +//----------------------------------------------------------------------------- + +#include "TupleToolBeamSpot.h" + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( TupleToolBeamSpot ) + +TupleToolBeamSpot::TupleToolBeamSpot( const std::string& type, const std::string& name, const IInterface* parent ) + : TupleToolBase(type, name, parent) +{ + declareInterface(this); + + declareProperty("Bound", m_bound = 10., "Bound to pass to beamspot constructor"); +} + +TupleToolBeamSpot::~TupleToolBeamSpot() { } + +StatusCode TupleToolBeamSpot::initialize() +{ + StatusCode sc = TupleToolBase::initialize(); + if ( ! sc.isSuccess() ) { return sc; } + + if (msgLevel(MSG::DEBUG)) { debug() << "=> Initialize" << endmsg; } + + svc("LoKiSvc", true); + + m_beamspot = std::unique_ptr{new LoKi::BeamSpot(m_bound)}; + if ( ! m_beamspot ) { + return Error("Could not get the beamspot"); + } + + return StatusCode::SUCCESS; +} + +StatusCode TupleToolBeamSpot::finalize() +{ + if (msgLevel(MSG::DEBUG)) { debug() << "=> Finalize" << endmsg; } + + m_beamspot.reset(); + + return TupleToolBase::finalize(); +} + +StatusCode TupleToolBeamSpot::fill( Tuples::Tuple& tuple ) +{ + std::string prefix = fullName(); + + tuple->column(prefix+"BeamX", m_beamspot->x()); + tuple->column(prefix+"BeamY", m_beamspot->y()); + + return StatusCode::SUCCESS; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolBeamSpot.h b/first-analysis-steps/DecayTrees/TupleToolBeamSpot.h new file mode 100644 index 00000000..3e53bf89 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolBeamSpot.h @@ -0,0 +1,39 @@ +// Include files + +// from LHCb +#include "Kernel/IEventTupleTool.h" +#include "DecayTreeTupleBase/TupleToolBase.h" + +#include "LoKi/BeamSpot.h" + +/** @class TupleToolBeamSpot DecayTreeTuple/TupleToolBeamSpot.cpp +* +* Add beamspot position (from the Velo resolver position) +* +* Tuple columns: +* - BeamX +* - BeamY +* +* @see LoKi::BeamSpot +* +* @author Pieter David +* @date 2015-07-10 +*/ +class TupleToolBeamSpot : public TupleToolBase, virtual public IEventTupleTool +{ +public: + /// Standard constructor + TupleToolBeamSpot ( const std::string& type, const std::string& name, const IInterface* parent ); + + virtual ~TupleToolBeamSpot(); ///< Destructor + + StatusCode initialize() override; + StatusCode finalize() override; + + // Interface methods + StatusCode fill( Tuples::Tuple& tuple ) override; + +private: + double m_bound; + std::unique_ptr m_beamspot; +}; diff --git a/first-analysis-steps/DecayTrees/TupleToolBremInfo.cpp b/first-analysis-steps/DecayTrees/TupleToolBremInfo.cpp new file mode 100644 index 00000000..28eb7653 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolBremInfo.cpp @@ -0,0 +1,147 @@ +// $Id: TupleToolBremInfo.cpp +// Include files + +// local +#include "TupleToolBremInfo.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "Event/Particle.h" +#include "GaudiKernel/IRegistry.h" // +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" +#include "CaloUtils/CaloMomentum.h" +#include +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolBremInfo +// +// +//----------------------------------------------------------------------------- + +using namespace Gaudi; +using namespace LHCb; + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolBremInfo::TupleToolBremInfo( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ), + m_parts(), + m_pids() +{ + declareInterface(this); + declareProperty("Particle",m_parts); + declareProperty("fullDST",m_dst=true);// to switch off/on information not available on microDST + m_parts.push_back("e+"); + m_parts.push_back("gamma"); // for gamma->e+e- +} + +StatusCode TupleToolBremInfo::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_adder = tool("BremAdder","BremAdder" ,this ); + + m_ppsvc = svc("LHCb::ParticlePropertySvc",true) ; + if ( !m_parts.empty() ){ + for ( std::vector::const_iterator p = m_parts.begin();m_parts.end() != p; ++p ){ + const LHCb::ParticleProperty* pp = m_ppsvc->find( *p ); + if (pp) { m_pids.push_back( pp->pdgID().abspid() ); } + } + } + + return sc; +} + +//============================================================================= +StatusCode TupleToolBremInfo::fill(const Particle*, + const Particle* P, + const std::string& head, + Tuples::Tuple& tuple ) +{ + if( !P ) return StatusCode::SUCCESS; + + const std::string prefix = fullName(head); + + bool ok=false; + for ( std::vector::const_iterator pid = m_pids.begin(); + m_pids.end() != pid; ++pid ) { + if ( P->particleID().abspid() == *pid ) { ok=true; break; } + } + if ( !ok ) return StatusCode::SUCCESS; + + + + bool filltuple = true; + if( P->isBasicParticle() && P->proto() != NULL && P->proto()->track() != NULL ){ + LHCb::CaloMomentum brem =m_adder->bremMomentum( P, Gaudi::Utils::toString(P->particleID().pid()) ); + if ( msgLevel(MSG::VERBOSE) ){ // https://savannah.cern.ch/bugs/?92524 + verbose() << "Multi : " << brem.multiplicity() << endmsg ; + verbose() << " Brem P : " << brem.momentum() << endmsg ; + verbose() << " Origin : " << brem.referencePoint() << endmsg ; + } + + //brem info from the particle (from creation) + filltuple &= tuple->column( prefix+"_HasBremAdded" , P->info(LHCb::Particle::HasBremAdded,0.)> 0 ) ; + filltuple &= tuple->column( prefix+"_BremMultiplicity", P->info(LHCb::Particle::HasBremAdded,0.)); // replace the multiplicity() method that need fullDST + //brem info from rerunning the BremAdder, looking at the photons + //This is not correct when running on an mDST - you look at a subset of the total photons in the event. + if((int) P->info(LHCb::Particle::HasBremAdded,0.) != (int)brem.multiplicity() && m_dst) + Warning("TupleToolBremInfo requires fullDST - BremP and BremOrigin might not be reliable (Multiplicity is OK)",StatusCode::SUCCESS,5); + if(m_dst)filltuple &= tuple->column( prefix+"_BremP" , brem.momentum()); // need fullDST + if(m_dst)filltuple &= tuple->column( prefix+"_BremOrigin" , brem.referencePoint()); // need fullDST + + }else{ + // e.g. diElectron + LHCb::Particle::ConstVector daughters = P->daughtersVector(); + if( daughters.size() != 2)return StatusCode(filltuple); + + const LHCb::Particle* p1 = NULL; + const LHCb::Particle* p2 = NULL; + int k=0; + for( LHCb::Particle::ConstVector::const_iterator itmp = daughters.begin(); itmp!=daughters.end(); itmp++){ + const LHCb::Particle* p= *itmp; + if( p1 == NULL)p1=p; + else p2=p; + for ( std::vector::const_iterator pid = m_pids.begin();m_pids.end() != pid; ++pid ) { + if ( p->particleID().abspid() == *pid ) { k++;break;} + } + } + if( k!=2 || p1 == NULL || p2 == NULL)return StatusCode(filltuple); + // OK let's evaluate the brem for (p1,p2) system + + double mult = p1->info(LHCb::Particle::HasBremAdded,0.) + p2->info(LHCb::Particle::HasBremAdded,0.); + const std::pair brems=m_adder->bremMomenta(p1,p2); + LHCb::CaloMomentum b1 = brems.first; + LHCb::CaloMomentum b2 = brems.second; + filltuple &= tuple->column( prefix+"_DiEBremMultiplicity", mult ); + if(m_dst)filltuple &= tuple->column( prefix+"_DiEBremP", b1.momentum()+b2.momentum() ); + std::string name1 = property( p1->particleID())->name() ; + std::string name2 = property( p2->particleID())->name() ; + boost::replace_all(name1,"+","plus"); + boost::replace_all(name1,"-","minus"); + boost::replace_all(name2,"+","plus"); + boost::replace_all(name2,"-","minus"); + filltuple &= tuple->column( prefix+"_"+name1+"_DiEBremMultiplicity", p1->info(LHCb::Particle::HasBremAdded,0.) ); + if(m_dst)filltuple &= tuple->column( prefix+"_"+name1+"_DiEBremP", b1.momentum() ); + filltuple &= tuple->column( prefix+"_"+name2+"_DiEBremMultiplicity", p2->info(LHCb::Particle::HasBremAdded,0.) ); + if(m_dst)filltuple &= tuple->column( prefix+"_"+name2+"_DiEBremP", b2.momentum() ); + + // standalone evaluation + if( m_dst ){ + LHCb::CaloMomentum sb1=m_adder->bremMomentum(p1); + LHCb::CaloMomentum sb2=m_adder->bremMomentum(p2); + filltuple &= tuple->column( prefix+"_"+name1+"_StandaloneBremMultiplicity", sb1.multiplicity() ); + filltuple &= tuple->column( prefix+"_"+name2+"_StandaloneBremMultiplicity", sb2.multiplicity() ); + } + + } + + + return StatusCode(filltuple); +} + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolBremInfo ) diff --git a/first-analysis-steps/DecayTrees/TupleToolBremInfo.h b/first-analysis-steps/DecayTrees/TupleToolBremInfo.h new file mode 100644 index 00000000..67e42053 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolBremInfo.h @@ -0,0 +1,43 @@ +// $Id: TupleToolBremInfo.h +#ifndef _TUPLETOOLBREMINFO_H +#define _TUPLETOOLBREMINFO_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +// Interfaces +#include "Kernel/IParticleTupleTool.h" +#include "Kernel/IBremAdder.h" +#include +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" + + +//============================================================================ +class TupleToolBremInfo : public TupleToolBase, virtual public IParticleTupleTool { + //========================================================================== + +public: + + // Standard constructor + TupleToolBremInfo( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + virtual ~TupleToolBremInfo( ) {}; ///< Destructor + + StatusCode fill( const LHCb::Particle*, + const LHCb::Particle*, + const std::string&, + Tuples::Tuple& ) override; +private : + const LHCb::ParticleProperty* property(const LHCb::ParticleID pid){return (m_ppsvc) ? m_ppsvc->find( pid ) : NULL;}; + LHCb::IParticlePropertySvc* m_ppsvc; + IBremAdder* m_adder; + std::vector m_parts; + std::vector m_pids; + bool m_dst; +}; + +#endif // _TUPLETOOLBREMINFO_H diff --git a/first-analysis-steps/DecayTrees/TupleToolCPU.cpp b/first-analysis-steps/DecayTrees/TupleToolCPU.cpp new file mode 100755 index 00000000..ab36f1a6 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolCPU.cpp @@ -0,0 +1,56 @@ +#include "TupleToolCPU.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/ITupleTool.h" +#include "GaudiKernel/Memory.h" +#include "GaudiAlg/ISequencerTimerTool.h" + +#include "GaudiKernel/IRegistry.h" // IOpaqueAddress + +//----------------------------------------------------------------------------- +// Implementation file for class : CPUTupleTool +// +// 2010-08-19 Patrick Koppenburg +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolCPU ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolCPU::TupleToolCPU( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_timerTool(0) + , m_timer(0) +{ + declareInterface(this); +} +//============================================================================= + +StatusCode TupleToolCPU::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + m_timerTool = tool( "SequencerTimerTool" ); //global tool + m_timer = m_timerTool->addTimer( name() ); + m_timerTool->start(m_timer) ; /// start it now + return sc ; +} + +//============================================================================= + +StatusCode TupleToolCPU::fill( Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(); + + double t = m_timerTool->stop(m_timer) ; /// stop + if (msgLevel(MSG::DEBUG)) debug() << "Time is " << t << endmsg ; + m_timerTool->start(m_timer) ; /// start again + + bool test = true; + test &= tuple->column( prefix+"Memory", (double)System::virtualMemory()); + test &= tuple->column( prefix+"CPUTime", t); + return StatusCode(test); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolCPU.h b/first-analysis-steps/DecayTrees/TupleToolCPU.h new file mode 100755 index 00000000..9ac84f61 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolCPU.h @@ -0,0 +1,41 @@ +// $Id: TupleToolCPU.h,v 1.1 2010-08-19 13:50:45 pkoppenb Exp $ +#ifndef JBOREL_TUPLETOOLCPU_H +#define JBOREL_TUPLETOOLCPU_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface + +class ITupleTool; +class ISequencerTimerTool ; + +/** @class TupleToolCPU TupleToolCPU.h jborel/TupleToolCPU.h + * + * \brief Event and Run number for DecayTreeTuple + * + * Tuple columns: + * - CPU of event + * - Memory used + + * \sa DecayTreeTuple + * @author Patrick Koppenburg + * @date 2010-08-19 + */ +class TupleToolCPU : public TupleToolBase, virtual public IEventTupleTool { +public: + /// Standard constructor + TupleToolCPU( const std::string& type, + const std::string& name, + const IInterface* parent); + + ~TupleToolCPU( ){}; ///< Destructor + + StatusCode fill( Tuples::Tuple& ) override; + StatusCode initialize( ) override; + +private : + ISequencerTimerTool* m_timerTool ; ///< timer tool + int m_timer ; ///< timer index +}; +#endif // JBOREL_TUPLETOOLCPU_H diff --git a/first-analysis-steps/DecayTrees/TupleToolCaloDigits.cpp b/first-analysis-steps/DecayTrees/TupleToolCaloDigits.cpp new file mode 100755 index 00000000..1a94dac8 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolCaloDigits.cpp @@ -0,0 +1,113 @@ +// $Id: TupleToolCaloDigits.cpp,v 0.1 2015-08-05 13:50:45 bursche $ +// Include files + +// local +#include "TupleToolCaloDigits.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/ITupleTool.h" + +#include "Event/CaloDigit.h" + +#include "GaudiKernel/IRegistry.h" // IOpaqueAddress + +#include "CaloDet/DeCalorimeter.h" + + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolCaloDigits +// +// 2015-08-05 Albert Bursche +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolCaloDigits ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolCaloDigits::TupleToolCaloDigits( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); + declareProperty( "DigitLocation" , m_DigitLocation); + declareProperty( "CaloName" , m_CaloName); + declareProperty( "CaloLocation", m_CaloLocation); + declareProperty( "MaxDigits", m_maxSize); + declareProperty( "AutoConfigure", m_auto_configure); + if (m_auto_configure) + { + if (m_CaloName == "Spd") + { + m_CaloLocation = DeCalorimeterLocation::Spd; + m_DigitLocation = LHCb::CaloDigitLocation::Spd; + } + if (m_CaloName == "Prs") + { + m_CaloLocation =DeCalorimeterLocation::Prs; + m_DigitLocation = LHCb::CaloDigitLocation::Prs; + } + if (m_CaloName == "Ecal") + { + m_CaloLocation = DeCalorimeterLocation::Ecal; + m_DigitLocation = LHCb::CaloDigitLocation::Ecal; + } + if (m_CaloName == "Hcal") + { + m_CaloLocation = DeCalorimeterLocation::Hcal; + m_DigitLocation = LHCb::CaloDigitLocation::Hcal; + } + // Feel free to add more locations from Event/CaloDigit.h + fatal() << "Invalid CaloName. Mus be one of Spd,Prs,Ecal,Hcal if AutoConfigure is used (i.e. true)" <(m_DigitLocation); + if (!digits) return StatusCode::SUCCESS; + DeCalorimeter* calo = getDet( m_CaloLocation ); + for( const auto& digit : *digits ) { + const LHCb::CaloCellID cellID = digit->cellID(); + m_index.push_back( cellID.index() ); + m_calo.push_back( cellID.calo() ); + m_area.push_back( cellID.area() ); + m_row.push_back( cellID.row() ); + m_column.push_back( cellID.col() ); + + auto p = calo->cellCenter(cellID); + m_xs.push_back(p.X()); + m_ys.push_back(p.Y()); + m_zs.push_back(p.Z()); + m_es.push_back( digit->e() ); + + if ( msgLevel(MSG::DEBUG) ) debug() << cellID.toString() << " has an energy of " << m_es.back() << " \n"; + } + if ( msgLevel(MSG::DEBUG) ) debug() << " saved " << m_index.size() <<" digits to n tuple "+m_CaloName + "Digit." << endmsg; + tuple->farray( m_extraName + m_CaloName + "DigitIndex" ,std::begin(m_index), std::end(m_index), m_extraName + m_CaloName + "DigitNi",m_maxSize); + m_index.clear(); + tuple->farray( m_extraName + m_CaloName + "DigitCalo" ,std::begin(m_calo), std::end(m_calo), m_extraName + m_CaloName + "DigitNc",m_maxSize); + m_calo.clear(); + tuple->farray( m_extraName + m_CaloName + "DigitArea" ,std::begin(m_area), std::end(m_area), m_extraName + m_CaloName + "DigitNa",m_maxSize); + m_area.clear(); + tuple->farray( m_extraName + m_CaloName + "DigitRow" ,std::begin(m_row), std::end(m_row), m_extraName + m_CaloName + "DigitNr",m_maxSize); + m_row.clear(); + tuple->farray( m_extraName + m_CaloName + "DigitColumn" ,std::begin(m_column),std::end(m_column),m_extraName + m_CaloName + "DigitNco",m_maxSize); + m_column.clear(); + tuple->farray( m_extraName + m_CaloName + "Digit_X" ,std::begin(m_xs), std::end(m_xs), m_extraName + m_CaloName + "DigitNx",m_maxSize); + m_xs.clear(); + tuple->farray( m_extraName + m_CaloName + "Digit_Y" ,std::begin(m_ys), std::end(m_ys), m_extraName + m_CaloName + "DigitNy",m_maxSize); + m_ys.clear(); + tuple->farray( m_extraName + m_CaloName + "Digit_Z" ,std::begin(m_zs), std::end(m_zs), m_extraName + m_CaloName + "DigitNz",m_maxSize); + m_zs.clear(); + tuple->farray( m_extraName + m_CaloName + "DigitEnergy" ,std::begin(m_es), std::end(m_es), m_extraName + m_CaloName + "DigitNe",m_maxSize); + m_es.clear(); + + return StatusCode::SUCCESS; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolCaloDigits.h b/first-analysis-steps/DecayTrees/TupleToolCaloDigits.h new file mode 100755 index 00000000..2bb0b81f --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolCaloDigits.h @@ -0,0 +1,54 @@ +// $Id: TupleToolCaloDigits.h,v 0.1 2015-08-05 bursche $ +#ifndef TUPLETOOLCALODIGITS_H +#define TUPLETOOLCALODIGITS_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface +#include "CaloDet/DeCalorimeter.h" +#include "TupleToolCaloDigits.h" +class ITupleTool; + +/** @class TupleToolCaloDigits TupleToolCaloDigits.h + * + * \brief Add Calorimter digits to DecayTreeTuple + * + * Tuple columns: + * - Digit energy + * - Cell ID + * - Cell area, column and row + * \sa DecayTreeTuple + * @author Albert Bursche + * @date 2015-08-05 + */ +class TupleToolCaloDigits : public TupleToolBase, virtual public IEventTupleTool { +public: + /// Standard constructor + TupleToolCaloDigits( const std::string& type, + const std::string& name, + const IInterface* parent); + + ~TupleToolCaloDigits( ) override = default; ///< Destructor + + StatusCode fill( Tuples::Tuple& ) override; + +private : + std::string m_DigitLocation = LHCb::CaloDigitLocation::Spd; + std::string m_CaloName = "Spd"; + std::string m_CaloLocation = DeCalorimeterLocation::Spd ; + + std::vector m_index; + std::vector m_calo; + std::vector m_area; + std::vector m_row; + std::vector m_column; + std::vector m_xs; + std::vector m_ys; + std::vector m_zs; + std::vector m_es; + + unsigned long m_maxSize = 4096; + bool m_auto_configure = false; +}; +#endif // diff --git a/first-analysis-steps/DecayTrees/TupleToolCaloHypo.cpp b/first-analysis-steps/DecayTrees/TupleToolCaloHypo.cpp new file mode 100644 index 00000000..22bbabea --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolCaloHypo.cpp @@ -0,0 +1,218 @@ +// $Id: TupleToolCaloHypo.cpp,v 1.1 2010-05-21 17:03:11 odescham Exp $ +// Include files + +// local +#include "TupleToolCaloHypo.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "Event/Particle.h" +#include "GaudiKernel/IRegistry.h" // + +#include "CaloUtils/CaloAlgUtils.h" +#include "CaloUtils/CaloMomentum.h" +#include "CaloUtils/Calo2Track.h" +#include "Relations/IRelationWeighted2D.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolCaloHypo +// +// 2008-10-31 :(Happy Halloween) +// Yasmine Amhis +//----------------------------------------------------------------------------- + +using namespace Gaudi; +using namespace LHCb; + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolCaloHypo ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolCaloHypo::TupleToolCaloHypo( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ){ + declareInterface(this); + declareProperty("DataList",m_dataList); + declareProperty("AllowBremHypo",m_brem = false); + declareProperty("AllowChargedHypo",m_charged=false); + declareProperty("AllowDaughtersHypo",m_daugh=false); // SplitPhotons from merged + m_dataList.push_back( "All" ); + } + + + +StatusCode TupleToolCaloHypo::initialize() { + if( ! TupleToolBase::initialize() ) return StatusCode::FAILURE; + + m_estimator = tool("CaloHypoEstimator","CaloHypoEstimator",this); + m_tables = tool("CaloRelationsGetter","CaloRelationsGetter",this); + m_caloElectron = tool("CaloElectron", this); + m_pileup = tool("CaloDigitFilterTool","FilterTool"); + + info() << "Caution : this TupleTool may trigger part of Calo reconstruction - ONLY WORK ON DST" << endmsg; + + return StatusCode::SUCCESS; +} + +//============================================================================= +StatusCode TupleToolCaloHypo::fill(const Particle* , const Particle* P + ,const std::string& head + ,Tuples::Tuple& tuple ){ + + const std::string prefix=fullName(head); + + + if( NULL == P )return StatusCode::SUCCESS; + if( NULL == P->proto() )return StatusCode::SUCCESS; + if( 0 != P->charge() && !m_charged)return StatusCode::SUCCESS; + + bool filltuple = true; + const SmartRefVector& hypos = P->proto()->calo(); + bool hasCalo = true; + bool hasBremCalo = false; + if( 0 == hypos.size() )hasCalo = false; + if( 1 < hypos.size() )hasBremCalo = true; + filltuple &= tuple->column( prefix+"_hasCaloHypo", (int) hasCalo ); + if( !isPureNeutralCalo( P ) && m_brem ) + filltuple &= tuple->column( prefix+"_hasBremCaloHypo", (int) hasBremCalo ); + + + + using namespace CaloDataType; + // select hypos + const LHCb::CaloHypo* hypo = NULL; + const LHCb::CaloHypo* hypo2 = NULL; + for( SmartRefVector::const_iterator ih = hypos.begin() ; hypos.end() != ih ; ++ih){ + if( !isPureNeutralCalo( P ) ){ + if( (*ih)->hypothesis() == LHCb::CaloHypo::EmCharged)hypo = *ih; + else hypo2 = *ih; + }else hypo = *ih; + } + + //info() << "coucou 0 " << P->pid() << endmsg; + const LHCb::CaloHypo* daugh1 = NULL; + const LHCb::CaloHypo* daugh2 = NULL; + if( hypo != NULL && hypo->hypothesis() == LHCb::CaloHypo::Pi0Merged && m_daugh){ + // == extract SplitPhotons hypos + const SmartRefVector& hypos = hypo->hypos(); + daugh1 = *(hypos.begin() ); + daugh2 = *(hypos.begin()+1 ); + } + //info() << "coucou 1 " << hypo << " " << hypo2 << " " << daugh1 << " " << daugh2 << endmsg; + + double he =0.; + double hx =0.; + double hy =0.; + double hz =0.; + double dT =-1.; + + if(hypo != NULL ){ + const LHCb::CaloPosition* position=hypo->position(); + if( position != NULL){ + he = position->e() ; + hx = position->x() ; + hy = position->y() ; + hz = position->z() ; + double th1 = incidence( hypo ) ; + double th2 = incidence(hypo, true); + if(th1 != -1. && th2 != -1)dT = th1-th2; + + } + //info() << "coucou 2 " << hypo->hypothesis() << endmsg; + } + filltuple &= tuple->column( prefix+"_CaloHypo_E", he ); + filltuple &= tuple->column( prefix+"_CaloHypo_X", hx ); + filltuple &= tuple->column( prefix+"_CaloHypo_Y", hy ); + filltuple &= tuple->column( prefix+"_CaloHypo_Z", hz ); + + + + if( m_charged )filltuple &= tuple->column( prefix+"_CaloHypo_DeltaTheta", dT ); + if( hypo != NULL && hypo->hypothesis() == LHCb::CaloHypo::Pi0Merged && m_daugh && daugh1 != NULL && daugh2 != NULL){ + const LHCb::CaloPosition* pos1=daugh1->position(); + const LHCb::CaloPosition* pos2=daugh2->position(); + if( pos1 != NULL && pos2 != NULL){ + filltuple &= tuple->column( prefix+"_CaloHypoDaugh0_E", pos1->e() ); + filltuple &= tuple->column( prefix+"_CaloHypoDaugh0_X", pos1->x() ); + filltuple &= tuple->column( prefix+"_CaloHypoDaugh0_Y", pos1->y() ); + filltuple &= tuple->column( prefix+"_CaloHypoDaugh0_Z", pos1->z() ); + filltuple &= tuple->column( prefix+"_CaloHypoDaugh1_E", pos2->e() ); + filltuple &= tuple->column( prefix+"_CaloHypoDaugh1_X", pos2->x() ); + filltuple &= tuple->column( prefix+"_CaloHypoDaugh1_Y", pos2->y() ); + filltuple &= tuple->column( prefix+"_CaloHypoDaugh1_Z", pos2->z() ); + } + } + + // PileUp subtracted energy + const LHCb::CaloCluster* cl = LHCb::CaloAlgUtils::ClusterFromHypo(hypo, false); + const LHCb::CaloCellID seed = (cl !=NULL) ? cl->seed() : LHCb::CaloCellID(); + double offset = (cl != NULL) ? m_pileup->offset( seed , 0 ) : -1.; + filltuple &= tuple->column(prefix+"_CaloHypoPileUpEnergy", offset); + + //fill tuple + for( int id = 0 ; id < Last ; ++id){ + int mask = ( P->charge() == 0 ) ? 0x1 : 0x2; + if( useData( id , mask ) ){ + double val = (NULL != hypo && hasCalo) ? m_estimator->data(hypo, (DataType) id ,0.) : 0.; + //info() << "coucou loop 1 " << Name[id] << " " << val << endmsg; + filltuple &= tuple->column( prefix+"_CaloHypo_"+Name[id], val ); + } + if( P->charge() != 0 && m_brem && useData( id , 0x1 ) ){ + double bval = (NULL != hypo2 && hasBremCalo) ? m_estimator->data(hypo2,(DataType) id ,0.) : 0.; + //info() << "coucou loop 2 " << Name[id] << " " << bval << endmsg; + filltuple &= tuple->column( prefix+"_BremCaloHypo_"+Name[id], bval ); + } + if( hypo != NULL && hypo->hypothesis() == LHCb::CaloHypo::Pi0Merged && m_daugh && useData(id,0x1) ){ + double val0 =( NULL != daugh1 ) ? m_estimator->data(daugh1,(DataType) id, 0.) : 0.; + double val1 =( NULL != daugh2 ) ? m_estimator->data(daugh2,(DataType) id, 0.) : 0.; + //info() << "coucou loop 3 " << Name[id] << " " << val0 << " " << val1 << endmsg; + filltuple &= tuple->column( prefix+"_CaloHypoDaugh0_"+Name[id], val0 ); + filltuple &= tuple->column( prefix+"_CaloHypoDaugh1_"+Name[id], val1 ); + } + } + return StatusCode(filltuple); +} + +bool TupleToolCaloHypo::useData( int id , int mask){ + using namespace CaloDataType; + std::string name = Name[id]; + int type = TypeMask[id]; + for(std::vector::iterator i = m_dataList.begin() ; m_dataList.end() !=i ; ++i){ + if( *i == "All" && (type & mask) !=0 )return true; + if( *i == name )return true; + } + return false; +} + +double TupleToolCaloHypo::incidence(const LHCb::CaloHypo* hypo, bool straight)const { + + const LHCb::CaloCluster* cluster = LHCb::CaloAlgUtils::ClusterFromHypo(hypo,true) ; + std::string m_cmLoc= LHCb::CaloAlgUtils::CaloIdLocation("ClusterMatch", context()); + + double incidence = -1; + if( LHCb::CaloHypo::EmCharged == hypo->hypothesis() && !straight ){ + // for electron hypothesis : get the matching track + if (exist (m_cmLoc)) { + LHCb::Calo2Track::IClusTrTable* ctable = m_tables->getClusTrTable( m_cmLoc ); + const LHCb::Calo2Track::IClusTrTable::Range range = ctable -> relations(cluster); + if ( !range.empty() ){ + const LHCb::Track* ctrack = range.front(); + // temporary protoParticle + LHCb::ProtoParticle* proto = new LHCb::ProtoParticle(); + proto->setTrack( ctrack ); + proto->addToCalo( hypo ); + if( m_caloElectron->set(proto))incidence = m_caloElectron->caloState().momentum().Theta(); + delete proto; + } + } + }else{ + // for neutrals : + LHCb::CaloMomentum cMomentum = LHCb::CaloMomentum( hypo ); + incidence = cMomentum.momentum().Theta(); + } + return incidence; +} + + diff --git a/first-analysis-steps/DecayTrees/TupleToolCaloHypo.h b/first-analysis-steps/DecayTrees/TupleToolCaloHypo.h new file mode 100644 index 00000000..25fb36ba --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolCaloHypo.h @@ -0,0 +1,43 @@ +// $Id: TupleToolCalohypo.h,v 1.1 2010-05-21 17:03:11 odescham Exp $ +#ifndef _TUPLETOOLECALOHYPO_H +#define _TUPLETOOLECALOHYPO_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +// Interface +#include "Kernel/IParticleTupleTool.h" +#include "CaloUtils/ICaloElectron.h" +#include "Relations/IRelationWeighted2D.h" +#include "CaloInterfaces/ICaloRelationsGetter.h" +#include "Event/Track.h" +#include "CaloDAQ/ICaloDigitFilterTool.h" + +#include "CaloInterfaces/ICaloHypoEstimator.h" + +//============================================================================ +class TupleToolCaloHypo : public TupleToolBase, virtual public IParticleTupleTool { + //========================================================================== +public: + // Standard constructor + TupleToolCaloHypo( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + virtual ~TupleToolCaloHypo(){}; + StatusCode fill(const LHCb::Particle*, const LHCb::Particle* + , const std::string& ,Tuples::Tuple& ) override; +private: + double incidence(const LHCb::CaloHypo* hypo,bool straight=false) const; + std::vector m_dataList; + bool useData( int id , int mask = 0x3); + ICaloHypoEstimator* m_estimator; + bool m_brem; + bool m_charged; + bool m_daugh; + ICaloRelationsGetter* m_tables; + ICaloElectron* m_caloElectron; + ICaloDigitFilterTool* m_pileup; +}; +#endif // _TUPLETOOLECALOHYPO_H diff --git a/first-analysis-steps/DecayTrees/TupleToolConeIsolation.cpp b/first-analysis-steps/DecayTrees/TupleToolConeIsolation.cpp new file mode 100644 index 00000000..e5a1c325 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolConeIsolation.cpp @@ -0,0 +1,899 @@ +// Include files +#include "Event/Particle.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "GaudiKernel/PhysicalConstants.h" +#include +// local +#include "TupleToolConeIsolation.h" +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolConeIsolation +// +// 2015-02-19 : Simone Bifani, Michel De Cian +// 2016-03-10 : Adlene Hicheur +//----------------------------------------------------------------------------- +#define MAXNPIZEROS 1000 +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( TupleToolConeIsolation ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolConeIsolation::TupleToolConeIsolation( const std::string &type, + const std::string &name, + const IInterface *parent ) +: TupleToolBase ( type, name, parent ) +{ + + declareInterface( this ); + + declareProperty( "MinConeSize", m_minConeSize = 0.4, + "Set the minimum cone size (default = 0.4)" ); + declareProperty( "MaxConeSize", m_maxConeSize = 0.6, + "Set the maximum cone size (default = 0.6)" ); + declareProperty( "SizeStep", m_sizeStep = 0.1, + "Set the cone size step between two iterations (default = 0.1)" ); + declareProperty( "MinhPi0Mass", m_MinhPi0Mass = 0*Gaudi::Units::MeV, "Set the lower seed-Pi0 invariant mass cut (default = 0 MeV)" ); + declareProperty( "MaxhPi0Mass", m_MaxhPi0Mass = 5000*Gaudi::Units::MeV, "Set the upper seed-Pi0 invariant mass cut (default = 5000 MeV)" ); + declareProperty( "FillCharged", m_fillCharged = true, + "Flag to fill the charged cone (default = true)" ); + declareProperty( "ExtraParticlesLocation", m_extraParticlesLocation = "Phys/StdAllNoPIDsMuons/Particles", + "Set the type of particles that are considered in the charged cone (default = Phys/StdAllNoPIDsMuons/Particles)" ); + declareProperty( "TrackType", m_trackType = 3, + "Set the type of tracks that are considered in the cone (default = 3)" ); + + declareProperty( "FillNeutral", m_fillNeutral = true, + "Flag to fill the neutral cone (default = true)" ); + declareProperty( "ExtraPhotonsLocation", m_extraPhotonsLocation = "Phys/StdLooseAllPhotons/Particles", + "Set the type of particles that are considered in the neutral cone (default = Phys/StdLooseAllPhotons/Particles)" ); + declareProperty( "FillPi0Info", m_fillPi0Info = false, + "Flag to fill the pi0 info (default = false)" ); + declareProperty( "FillMergedPi0Info", m_fillMergedPi0Info = false, + "Flag to fill the merged pi0 info (default = true)" ); + declareProperty( "PizerosLocation", m_PizerosLocation = "Phys/StdLoosePi02gg/Particles", "Set the type of pi0s that are considered (default = Phys/StdLoosePi02gg/Particles)" ); + declareProperty( "MergedPizerosLocation", m_MergedPizerosLocation = "Phys/StdLooseMergedPi0/Particles", "Set the type of merged pi0s that are considered (default = Phys/StdLooseMergedPi0/Particles)" ); + declareProperty( "FillAsymmetry", m_fillAsymmetry = false, + "Flag to fill the asymmetry variables (default = false)" ); + declareProperty( "FillDeltas", m_fillDeltas = false, + "Flag to fill the delta variables (default = false)" ); + declareProperty( "FillIsolation", m_fillIsolation = true, + "Flag to fill the isolation variables (default = true)" ); + declareProperty( "FillMaxPt", m_fillMaxPt = true, + "Flag to fill the momentum of the max-pT object in the cone (default = true)" ); + declareProperty( "MaxPtParticlesLocation", m_maxPtParticleLocation = "Phys/StdAllLooseMuons/Particles", + "Set the type of max-pT particles that are considered in the charged cone (default = Phys/StdAllLooseMuons/Particles)" ); + + declareProperty( "FillComponents", m_fillComponents = false, + "Flag to fill the components of all relevant variables (default = false)" ); + +} +//============================================================================= +// Destructor +//============================================================================= +TupleToolConeIsolation::~TupleToolConeIsolation() {} +//============================================================================= +// Initialization +//============================================================================= +StatusCode TupleToolConeIsolation::initialize() { + + StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) + return sc; + + if ( !m_fillCharged && !m_fillNeutral ) { + if ( msgLevel( MSG::FATAL ) ) + fatal() << "No cone to fill" << endmsg; + return StatusCode::FAILURE; + } + + if ( m_minConeSize > m_maxConeSize) { + if ( msgLevel( MSG::FATAL ) ) + fatal() << "Max conesize smaller than min conesize" << endmsg; + return StatusCode::FAILURE; + } + + if ( msgLevel( MSG::DEBUG ) ) + debug() << "==> Initialize" << endmsg; + + if ( isVerbose() ) { + m_fillCharged = true; + m_fillNeutral = true; + m_fillAsymmetry = true; + m_fillDeltas = true; + m_fillIsolation = true; + m_fillMaxPt = true; + } + + return StatusCode::SUCCESS; + +} +//============================================================================= +// Fill the tuple +//============================================================================= +StatusCode TupleToolConeIsolation::fill( const LHCb::Particle *top, + const LHCb::Particle *seed, + const std::string &head, + Tuples::Tuple &tuple ) { + + const std::string prefix = fullName( head ); + + if ( msgLevel( MSG::DEBUG ) ) + debug() << "==> Fill" << endmsg; + + // -- The vector m_decayParticles contains all the particles that belong to the given decay according to the decay descriptor. + + // -- Clear the vector with the particles in the specific decay + m_decayParticles.clear(); + + // -- Add the mother (prefix of the decay chain) to the vector + if ( msgLevel( MSG::DEBUG ) ) + debug() << "Filling particle with ID " << top->particleID().pid() << endmsg; + m_decayParticles.push_back( top ); + + // -- Save all particles that belong to the given decay in the vector m_decayParticles + saveDecayParticles( top ); + + // -- Check particle containers + const LHCb::Particles *parts = get( m_extraParticlesLocation ); + if ( m_fillCharged ) + if ( parts->size() == 0 ) + if ( msgLevel( MSG::WARNING ) ) + warning() << "Could not retrieve extra-particles... Skipping" << endmsg; + const LHCb::Particles *maxPts = get( m_maxPtParticleLocation ); + if ( m_fillMaxPt ) + if ( maxPts->size() == 0 ) + if ( msgLevel( MSG::WARNING ) ) + warning() << "Could not retrieve maxPt-particle... Skipping" << endmsg; + const LHCb::Particles *photons = NULL; +if(exist( m_extraPhotonsLocation )){ + photons = get( m_extraPhotonsLocation ); + if ( m_fillNeutral ) + if ( photons->size() == 0 ) + if ( msgLevel( MSG::WARNING ) ) + warning() << "Could not retrieve extra-photons... Skipping" << endmsg; +}else{ + +warning()<< m_extraPhotonsLocation << " Not available"<( m_PizerosLocation )) { + pizeros = get( m_PizerosLocation ); + if ( m_fillPi0Info ) + if ( pizeros->size() == 0 ) + if ( msgLevel( MSG::WARNING ) ) + warning() << "Could not retrieve pi0s... Skipping" << endmsg; +}else{ + +warning()<< m_PizerosLocation << " Not available"<( m_MergedPizerosLocation )) { + mergedpizeros = get( m_MergedPizerosLocation ); + if ( m_fillMergedPi0Info ) + if ( mergedpizeros->size() == 0 ) + if ( msgLevel( MSG::WARNING ) ) + warning() << "Could not retrieve merged pi0s... Skipping" << endmsg; +}else{ + +warning()<< m_MergedPizerosLocation << " Not available"<size() != 0 ) { + int ccMultiplicity = 0; + double ccScalarPt = 0.; + std::vector ccMomentum; + std::vector ccMaxPt; + + StatusCode ccSc = ChargedCone( seed, parts, maxPts, coneSize, ccMultiplicity, ccScalarPt, ccMomentum, ccMaxPt ); + if ( ccSc.isFailure() ) + ccMultiplicity = -1; + + ccP.SetX( ccMomentum[0] ); + ccP.SetY( ccMomentum[1] ); + ccP.SetZ( ccMomentum[2] ); + + double ccDeltaEta = seed->momentum().Eta() - ccP.Eta(); + double ccDeltaPhi = fabs( seed->momentum().Phi() - ccP.Phi() ); + if ( ccDeltaPhi > M_PI ) + ccDeltaPhi = 2 * M_PI - ccDeltaPhi; + + // -- Fill the tuple with the variables + test &= tuple->column( prefix + "_" + conesize + "_cc_mult", ccMultiplicity ); + test &= tuple->column( prefix + "_" + conesize + "_cc_sPT", ccScalarPt ); + test &= tuple->column( prefix + "_" + conesize + "_cc_vPT", sqrt( ccP.Perp2() ) ); + + if ( m_fillComponents ) { + test &= tuple->column( prefix + "_" + conesize + "_cc_PX", ccP.X() ); + test &= tuple->column( prefix + "_" + conesize + "_cc_PY", ccP.Y() ); + test &= tuple->column( prefix + "_" + conesize + "_cc_PZ", ccP.Z() ); + } + + if ( m_fillAsymmetry ) { + test &= tuple->column( prefix + "_" + conesize + "_cc_asy_P", ( seed->p() - sqrt( ccP.Mag2() ) ) / (seed->p() + sqrt( ccP.Mag2() ) ) ); + test &= tuple->column( prefix + "_" + conesize + "_cc_asy_PT", ( seed->pt() - sqrt( ccP.Perp2() ) ) / (seed->pt() + sqrt( ccP.Perp2() ) ) ); + if ( m_fillComponents ) { + test &= tuple->column( prefix + "_" + conesize + "_cc_asy_PX", ( seed->momentum().Px() - ccP.X() ) / (seed->momentum().Px() + ccP.X()) ); + test &= tuple->column( prefix + "_" + conesize + "_cc_asy_PY", ( seed->momentum().Py() - ccP.Y() ) / (seed->momentum().Py() + ccP.Y()) ); + test &= tuple->column( prefix + "_" + conesize + "_cc_asy_PZ", ( seed->momentum().Pz() - ccP.Z() ) / (seed->momentum().Pz() + ccP.Z()) ); + } + } + + if ( m_fillDeltas ) { + test &= tuple->column( prefix + "_" + conesize + "_cc_deltaEta", ccDeltaEta ); + test &= tuple->column( prefix + "_" + conesize + "_cc_deltaPhi", ccDeltaPhi ); + } + + if ( m_fillIsolation ) + test &= tuple->column( prefix + "_" + conesize + "_cc_IT", seed->pt() / sqrt( pow(seed->momentum().Px() + ccP.X(), 2) + pow(seed->momentum().Py() + ccP.Y(), 2) ) ); + + if ( m_fillMaxPt ) { + test &= tuple->column( prefix + "_" + conesize + "_cc_maxPt_Q", (int) ccMaxPt[4] ); + test &= tuple->column( prefix + "_" + conesize + "_cc_maxPt_PT", sqrt( pow(ccMaxPt[0], 2) + pow(ccMaxPt[1], 2) ) ); + if ( m_fillComponents ) { + test &= tuple->column( prefix + "_" + conesize + "_cc_maxPt_PX", ccMaxPt[0] ); + test &= tuple->column( prefix + "_" + conesize + "_cc_maxPt_PY", ccMaxPt[1] ); + test &= tuple->column( prefix + "_" + conesize + "_cc_maxPt_PZ", ccMaxPt[2] ); + test &= tuple->column( prefix + "_" + conesize + "_cc_maxPt_PE", ccMaxPt[3] ); + } + } + } + else { + test &= tuple->column( prefix + "_" + conesize + "_cc_mult", 0 ); + test &= tuple->column( prefix + "_" + conesize + "_cc_sPT", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_cc_vPT", 0. ); + + if ( m_fillComponents ) { + test &= tuple->column( prefix + "_" + conesize + "_cc_PX", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_cc_PY", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_cc_PZ", 0. ); + } + + if ( m_fillAsymmetry ) { + test &= tuple->column( prefix + "_" + conesize + "_cc_asy_P", 1. ); + test &= tuple->column( prefix + "_" + conesize + "_cc_asy_PT", 1. ); + if ( m_fillComponents ) { + test &= tuple->column( prefix + "_" + conesize + "_cc_asy_PX", 1. ); + test &= tuple->column( prefix + "_" + conesize + "_cc_asy_PY", 1. ); + test &= tuple->column( prefix + "_" + conesize + "_cc_asy_PZ", 1. ); + } + } + + if ( m_fillDeltas ) { + test &= tuple->column( prefix + "_" + conesize + "_cc_deltaEta", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_cc_deltaPhi", 0. ); + } + + if ( m_fillIsolation ) + test &= tuple->column( prefix + "_" + conesize + "_cc_IT", 1. ); + + if ( m_fillMaxPt ) { + test &= tuple->column( prefix + "_" + conesize + "_cc_maxPt_Q", 0 ); + test &= tuple->column( prefix + "_" + conesize + "_cc_maxPt_PT", 0. ); + if ( m_fillComponents ) { + test &= tuple->column( prefix + "_" + conesize + "_cc_maxPt_PX", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_cc_maxPt_PY", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_cc_maxPt_PZ", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_cc_maxPt_PE", 0. ); + } + } + } + } + + // -- Neutral cone + Gaudi::XYZVector ncP; + if ( m_fillNeutral ) { + if ( photons->size() != 0 ) { + int ncMultiplicity = 0; + double ncScalarPt = 0.; + std::vector ncMomentum; + std::vector ncMaxPt; + double LegH1, LegH2, LegH3, LegH4; + double avConfLevel, maxConfLevel; + StatusCode ncSc = NeutralCone( seed, photons, coneSize, ncMultiplicity, ncScalarPt, ncMomentum, ncMaxPt , avConfLevel, maxConfLevel, LegH1, LegH2, LegH3, LegH4); + if ( ncSc.isFailure() ) + ncMultiplicity = -1; + + ncP.SetX( ncMomentum[0] ); + ncP.SetY( ncMomentum[1] ); + ncP.SetZ( ncMomentum[2] ); + + double ncDeltaEta = seed->momentum().Eta() - ncP.Eta(); + double ncDeltaPhi = fabs( seed->momentum().Phi() - ncP.Phi() ); + if ( ncDeltaPhi > M_PI ) + ncDeltaPhi = 2 * M_PI - ncDeltaPhi; + + // -- Fill the tuple with the variables + test &= tuple->column( prefix + "_" + conesize + "_nc_mult", ncMultiplicity); + test &= tuple->column( prefix + "_" + conesize + "_nc_sPT", ncScalarPt ); + test &= tuple->column( prefix + "_" + conesize + "_nc_vPT", sqrt( ncP.Perp2() ) ); + + if ( m_fillComponents ) { + test &= tuple->column( prefix + "_" + conesize + "_nc_PX", ncP.X() ); + test &= tuple->column( prefix + "_" + conesize + "_nc_PY", ncP.Y() ); + test &= tuple->column( prefix + "_" + conesize + "_nc_PZ", ncP.Z() ); + test &= tuple->column( prefix + "_" + conesize + "_nc_avCL", avConfLevel); + test &= tuple->column( prefix + "_" + conesize + "_nc_maxCL", maxConfLevel); + } + + if ( m_fillAsymmetry ) { + test &= tuple->column( prefix + "_" + conesize + "_nc_asy_P", ( seed->p() - sqrt( ncP.Mag2() ) ) / (seed->p() + sqrt( ncP.Mag2() ) ) ); + test &= tuple->column( prefix + "_" + conesize + "_nc_asy_PT", ( seed->pt() - sqrt( ncP.Perp2() ) ) / (seed->pt() + sqrt( ncP.Perp2() ) ) ); + if ( m_fillComponents ) { + test &= tuple->column( prefix + "_" + conesize + "_nc_asy_PX", ( seed->momentum().Px() - ncP.X() ) / (seed->momentum().Px() + ncP.X()) ); + test &= tuple->column( prefix + "_" + conesize + "_nc_asy_PY", ( seed->momentum().Py() - ncP.Y() ) / (seed->momentum().Py() + ncP.Y()) ); + test &= tuple->column( prefix + "_" + conesize + "_nc_asy_PZ", ( seed->momentum().Pz() - ncP.Z() ) / (seed->momentum().Pz() + ncP.Z()) ); + } + } + + if ( m_fillDeltas ) { + test &= tuple->column( prefix + "_" + conesize + "_nc_deltaEta", ncDeltaEta ); + test &= tuple->column( prefix + "_" + conesize + "_nc_deltaPhi", ncDeltaPhi ); + } + + if ( m_fillIsolation ) + test &= tuple->column( prefix + "_" + conesize + "_nc_IT", seed->pt() / sqrt( pow(seed->momentum().Px() + ncP.X(), 2) + pow(seed->momentum().Py() + ncP.Y(), 2) ) ); + + if ( m_fillMaxPt ) { + test &= tuple->column( prefix + "_" + conesize + "_nc_maxPt_PT", sqrt( pow(ncMaxPt[0], 2) + pow(ncMaxPt[1], 2) ) ); + if ( m_fillComponents ) { + test &= tuple->column( prefix + "_" + conesize + "_nc_maxPt_PX", ncMaxPt[0] ); + test &= tuple->column( prefix + "_" + conesize + "_nc_maxPt_PY", ncMaxPt[1] ); + test &= tuple->column( prefix + "_" + conesize + "_nc_maxPt_PZ", ncMaxPt[2] ); + test &= tuple->column(prefix + "_" + conesize + "_nc_H1",LegH1); + test &= tuple->column(prefix + "_" + conesize + "_nc_H2",LegH2); + test &= tuple->column(prefix + "_" + conesize + "_nc_H3",LegH3); + test &= tuple->column(prefix + "_" + conesize + "_nc_H4",LegH4); + // test &= tuple->column(prefix + "_" + conesize + "_nc_Mass",TheMass); + } + } + } + else { + test &= tuple->column( prefix + "_" + conesize + "_nc_mult", 0 ); + test &= tuple->column( prefix + "_" + conesize + "_nc_sPT", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_nc_vPT", 0. ); + + if ( m_fillComponents ) { + test &= tuple->column( prefix + "_" + conesize + "_nc_PX", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_nc_PY", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_nc_PZ", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_nc_avCL", 0.); + test &= tuple->column( prefix + "_" + conesize + "_nc_maxCL", 0.); + } + + if ( m_fillAsymmetry ) { + test &= tuple->column( prefix + "_" + conesize + "_nc_asy_P", 1. ); + test &= tuple->column( prefix + "_" + conesize + "_nc_asy_PT", 1. ); + if ( m_fillComponents ) { + test &= tuple->column( prefix + "_" + conesize + "_nc_asy_PX", 1. ); + test &= tuple->column( prefix + "_" + conesize + "_nc_asy_PY", 1. ); + test &= tuple->column( prefix + "_" + conesize + "_nc_asy_PZ", 1. ); + } + } + + if ( m_fillDeltas ) { + test &= tuple->column( prefix + "_" + conesize + "_nc_deltaEta", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_nc_deltaPhi", 0. ); + } + + if ( m_fillIsolation ) + test &= tuple->column( prefix + "_" + conesize + "_nc_IT", 1. ); + + if ( m_fillMaxPt ) { + test &= tuple->column( prefix + "_" + conesize + "_nc_maxPt_PT", 0. ); + if ( m_fillComponents ) { + test &= tuple->column( prefix + "_" + conesize + "_nc_maxPt_PX", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_nc_maxPt_PY", 0. ); + test &= tuple->column( prefix + "_" + conesize + "_nc_maxPt_PZ", 0. ); + test &= tuple->column(prefix + "_" + conesize + "_nc_H1",-1.); + test &= tuple->column(prefix + "_" + conesize + "_nc_H2",-1.); + test &= tuple->column(prefix + "_" + conesize + "_nc_H3",-1.); + test &= tuple->column(prefix + "_" + conesize + "_nc_H4",-1.); + // test &= tuple->column(prefix + "_" + conesize + "_nc_Mass",-1.); + } + } + } + } + + if ( m_fillIsolation ) { + if ( m_fillCharged && m_fillNeutral ) { + if ( ( parts->size() != 0 ) && ( photons->size() != 0 ) ) + test &= tuple->column( prefix + "_" + conesize + "_IT", seed->momentum().Pt() / sqrt( pow(seed->momentum().Px() + ccP.X() + ncP.X(), 2) + pow(seed->momentum().Py() + ccP.Y() + ncP.Y(), 2) ) ); + else + test &= tuple->column( prefix + "_" + conesize + "_IT", 1. ); + } + } + + // -- Increase the counter with the stepsize + coneSize += m_sizeStep; + } + + if ( m_fillPi0Info ) { + if ( pizeros->size() != 0 ) { + int Pi0Multiplicity = 0; + std::vector MassWithPi0,Pi0MomX,Pi0MomY,Pi0MomZ,Pi0MomE,Pi0MomM,Pi0DeltaR,Pi0Ph1CL,Pi0Ph2CL; + StatusCode pizSc = pi0Comb( seed, pizeros, Pi0Multiplicity,MassWithPi0,Pi0MomX,Pi0MomY,Pi0MomZ,Pi0MomE,Pi0MomM,Pi0DeltaR,Pi0Ph1CL,Pi0Ph2CL); + // -- Fill the tuple with the variables + test &= tuple->column( prefix + "_pi0_mult", Pi0Multiplicity ); + test &= tuple->farray( prefix+"_MasshPi0", MassWithPi0.begin(), MassWithPi0.end(), prefix+"_Pi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_Pi0_PX", Pi0MomX.begin(), Pi0MomX.end(), prefix+"_Pi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_Pi0_PY", Pi0MomY.begin(), Pi0MomY.end(), prefix+"_Pi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_Pi0_PZ", Pi0MomZ.begin(), Pi0MomZ.end(), prefix+"_Pi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_Pi0_E", Pi0MomE.begin(), Pi0MomE.end(), prefix+"_Pi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_Pi0_M", Pi0MomM.begin(), Pi0MomM.end(), prefix+"_Pi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_Pi0_DeltaR", Pi0DeltaR.begin(), Pi0DeltaR.end(), prefix+"_Pi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_Pi0Ph1_CL", Pi0Ph1CL.begin(), Pi0Ph1CL.end(), prefix+"_Pi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_Pi0Ph2_CL", Pi0Ph2CL.begin(), Pi0Ph2CL.end(), prefix+"_Pi0_ArrayLength", MAXNPIZEROS); + } else { + std::vector MassWithPi0 = {-1}; + std::vector Pi0MomX = {-1e6}; + std::vector Pi0MomY = {-1e6}; + std::vector Pi0MomZ = {-1e6}; + std::vector Pi0MomE = {-1e6}; + std::vector Pi0MomM = {-1e6}; + std::vector Pi0DeltaR = {-1e6}; + std::vector Pi0Ph1CL = {-1e6}; + std::vector Pi0Ph2CL = {-1e6}; + + test &= tuple->column( prefix + "_pi0_mult",0); + test &= tuple->farray( prefix+"_MasshPi0",MassWithPi0.begin(), MassWithPi0.end(), prefix+"_Pi0_ArrayLength",0); + test &= tuple->farray( prefix+"_Pi0_PX", Pi0MomX.begin(), Pi0MomX.end(), prefix+"_Pi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_Pi0_PY", Pi0MomY.begin(), Pi0MomY.end(), prefix+"_Pi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_Pi0_PZ", Pi0MomZ.begin(), Pi0MomZ.end(), prefix+"_Pi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_Pi0_E", Pi0MomE.begin(), Pi0MomE.end(), prefix+"_Pi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_Pi0_M", Pi0MomM.begin(), Pi0MomM.end(), prefix+"_Pi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_Pi0_DeltaR", Pi0MomE.begin(), Pi0MomE.end(), prefix+"_Pi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_Pi0Ph1_CL", Pi0Ph1CL.begin(), Pi0Ph1CL.end(), prefix+"_Pi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_Pi0Ph2_CL", Pi0Ph2CL.begin(), Pi0Ph2CL.end(), prefix+"_Pi0_ArrayLength", 0); + } + } + + if ( m_fillMergedPi0Info ) { + if ( mergedpizeros->size() != 0 ) { + // warning() << "Non-empty merged pi0 list" << endmsg; + int MergPi0Multiplicity = 0; + + std::vector MassWithMergPi0,Pi0MomX,Pi0MomY,Pi0MomZ,Pi0MomE,Pi0MomM,Pi0DeltaR,Pi0Ph1CL,Pi0Ph2CL; + StatusCode mpizSc = pi0Comb( seed, mergedpizeros, MergPi0Multiplicity,MassWithMergPi0,Pi0MomX,Pi0MomY,Pi0MomZ,Pi0MomE,Pi0MomM,Pi0DeltaR,Pi0Ph1CL,Pi0Ph2CL); + // -- Fill the tuple with the variables + test &= tuple->column( prefix + "_mergpi0_mult", MergPi0Multiplicity ); + test &= tuple->farray( prefix+"_MasshMergPi0", MassWithMergPi0.begin(), MassWithMergPi0.end(), prefix+"_MergPi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_MergPi0_PX", Pi0MomX.begin(), Pi0MomX.end(), prefix+"_MergPi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_MergPi0_PY", Pi0MomY.begin(), Pi0MomY.end(), prefix+"_MergPi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_MergPi0_PZ", Pi0MomZ.begin(), Pi0MomZ.end(), prefix+"_MergPi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_MergPi0_E", Pi0MomE.begin(), Pi0MomE.end(), prefix+"_MergPi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_MergPi0_M", Pi0MomM.begin(), Pi0MomM.end(), prefix+"_MergPi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_MergPi0_DeltaR", Pi0DeltaR.begin(), Pi0DeltaR.end(), prefix+"_MergPi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_MergPi0Ph1_CL", Pi0Ph1CL.begin(), Pi0Ph1CL.end(), prefix+"_MergPi0_ArrayLength", MAXNPIZEROS); + test &= tuple->farray( prefix+"_MergPi0Ph2_CL", Pi0Ph2CL.begin(), Pi0Ph2CL.end(), prefix+"_MergPi0_ArrayLength", MAXNPIZEROS); + } else { + std::vector MassWithMergPi0 = {-1}; + std::vector Pi0MomX = {-1e6}; + std::vector Pi0MomY = {-1e6}; + std::vector Pi0MomZ = {-1e6}; + std::vector Pi0MomE = {-1e6}; + std::vector Pi0MomM = {-1e6}; + std::vector Pi0DeltaR = {-1e6}; + std::vector Pi0Ph1CL = {-1e6}; + std::vector Pi0Ph2CL = {-1e6}; + + test &= tuple->column( prefix + "_mergpi0_mult",0); + test &= tuple->farray( prefix+"_MasshMergPi0",MassWithMergPi0.begin(), MassWithMergPi0.end(), prefix+"_MergPi0_ArrayLength",0); + test &= tuple->farray( prefix+"_MergPi0_PX", Pi0MomX.begin(), Pi0MomX.end(), prefix+"_MergPi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_MergPi0_PY", Pi0MomY.begin(), Pi0MomY.end(), prefix+"_MergPi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_MergPi0_PZ", Pi0MomZ.begin(), Pi0MomZ.end(), prefix+"_MergPi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_MergPi0_E", Pi0MomE.begin(), Pi0MomE.end(), prefix+"_MergPi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_MergPi0_M", Pi0MomM.begin(), Pi0MomM.end(), prefix+"_MergPi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_MergPi0_DeltaR", Pi0MomE.begin(), Pi0MomE.end(), prefix+"_MergPi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_MergPi0Ph1_CL", Pi0Ph1CL.begin(), Pi0Ph1CL.end(), prefix+"_MergPi0_ArrayLength", 0); + test &= tuple->farray( prefix+"_MergPi0Ph2_CL", Pi0Ph2CL.begin(), Pi0Ph2CL.end(), prefix+"_MergPi0_ArrayLength", 0); + } + } + + + } + else { + if ( msgLevel( MSG::WARNING ) ) + warning() << "The seed particle is not valid. Skipping" << endmsg; + + return StatusCode::FAILURE; + } + + if ( msgLevel( MSG::VERBOSE ) ) + verbose() << "Stop looping through different conesizes" << endmsg; + + return StatusCode( test ); + +} +//============================================================================= +// Save the particles in the decay chain (recursive function) +//============================================================================= +void TupleToolConeIsolation::saveDecayParticles( const LHCb::Particle *top ) { + + // -- Get the daughters of the top particle + const SmartRefVector< LHCb::Particle > daughters = top->daughters(); + + // -- Fill all the daugthers in m_decayParticles + for ( SmartRefVector< LHCb::Particle >::const_iterator ip = daughters.begin(); ip != daughters.end(); ++ip ) { + + // -- If the particle is stable, save it in the vector, or... + if ( (*ip)->isBasicParticle() ) { + if ( msgLevel(MSG::DEBUG) ) + debug() << "Filling particle with ID " << (*ip)->particleID().pid() << endmsg; + m_decayParticles.push_back( (*ip) ); + } + else { + // -- if it is not stable, call the function recursively + m_decayParticles.push_back( (*ip) ); + if ( msgLevel(MSG::DEBUG) ) + debug() << "Filling particle with ID " << (*ip)->particleID().pid() << endmsg; + saveDecayParticles( (*ip) ); + } + } + + return; + +} +//============================================================================= +// Loop over all the tracks in the cone which do not belong to the desired decay +//============================================================================= +StatusCode TupleToolConeIsolation::ChargedCone( const LHCb::Particle *seed, + const LHCb::Particles *parts, + const LHCb::Particles *maxPts, + const double rcut, + int &multiplicity, + double &scalarPt, + std::vector &momentum, + std::vector &maxPt ) { + + // -- Initialize values + multiplicity = 0; + scalarPt = 0; + double conePx = 0; + double conePy = 0; + double conePz = 0; + double maxPtPx = 0; + double maxPtPy = 0; + double maxPtPz = 0; + double maxPtPe = 0; + double maxPtQ = 0; + + // -- Get the momentum of the seed particle + Gaudi::XYZVector seedMomentum = seed->momentum().Vect(); + + for ( LHCb::Particles::const_iterator ip = parts->begin(); ip != parts->end(); ++ip ) { + const LHCb::Particle *particle = (*ip); + + const LHCb::ProtoParticle *proto = particle->proto(); + if ( proto ) { + + const LHCb::Track *track = proto->track(); + if ( track ) { + + // -- Check if the track belongs to the decay itself + bool isInDecay = isTrackInDecay( track ); + if ( isInDecay ) + continue; + + Gaudi::XYZVector trackMomentum = track->momentum(); + + // -- Calculate the difference in Eta and Phi between the seed particle and a track + double deltaPhi = fabs( seedMomentum.Phi() - trackMomentum.Phi() ); + if ( deltaPhi > M_PI ) + deltaPhi = 2 * M_PI - deltaPhi; + double deltaEta = seedMomentum.Eta() - trackMomentum.Eta(); + double deltaR = sqrt( pow(deltaPhi, 2) + pow(deltaEta, 2) ); + + if ( ( rcut == 0 ) || ( deltaR < rcut ) ) { + if ( track->type() == m_trackType ) { + + multiplicity++; + + // -- Calculate scalar information + scalarPt += track->pt(); + + // -- Calculate vector information + conePx += trackMomentum.X(); + conePy += trackMomentum.Y(); + conePz += trackMomentum.Z(); + + // -- Find max-pT particle + if ( maxPts->size() != 0 ) { + if ( track->pt() > sqrt( pow(maxPtPx, 2) + pow(maxPtPy, 2) ) ) { + + for ( LHCb::Particles::const_iterator iPt = maxPts->begin(); iPt != maxPts->end(); ++iPt ) { + const LHCb::Particle *particlePt = (*iPt); + + const LHCb::ProtoParticle *protoPt = particlePt->proto(); + if ( protoPt ) { + + if ( protoPt == proto ) { + + const LHCb::Track *trackPt = protoPt->track(); + if ( trackPt ) { + maxPtPx = trackPt->momentum().X(); + maxPtPy = trackPt->momentum().Y(); + maxPtPz = trackPt->momentum().Z(); + maxPtPe = particlePt->momentum().E(); + maxPtQ = trackPt->charge(); + } + + break; + } + } + } + } + } + else { + maxPtPx = 0.; + maxPtPy = 0.; + maxPtPz = 0.; + maxPtPe = 0.; + maxPtQ = 0; + } + } + } + } + } + } + + momentum.push_back( conePx ); + momentum.push_back( conePy ); + momentum.push_back( conePz ); + + maxPt.push_back( maxPtPx ); + maxPt.push_back( maxPtPy ); + maxPt.push_back( maxPtPz ); + maxPt.push_back( maxPtPe ); + maxPt.push_back( maxPtQ ); + + return StatusCode::SUCCESS; + +} +//============================================================================= +// Loop over all the photons in the cone +//============================================================================= +StatusCode TupleToolConeIsolation::NeutralCone( const LHCb::Particle *seed, + const LHCb::Particles *photons, + const double rcut, + int &multiplicity, + double &scalarPt, + std::vector &momentum, + std::vector &maxPt, + double& AvConfLevel, + double& MaxConfLevel, + double &LegendreRat1, + double &LegendreRat2, + double &LegendreRat3, + double &LegendreRat4) { + + // -- Initialize values + multiplicity = 0; + scalarPt = 0; + double conePx = 0; + double conePy = 0; + double conePz = 0; + double maxPtPx = 0; + double maxPtPy = 0; + double maxPtPz = 0; + double numLeg1 = 0; + double numLeg2 = 0; + double numLeg3 = 0; + double numLeg4 = 0; + double coneE = 0; + double maxP = 0; + double maxCL = 0; + double avCL = 0; + + // -- Get the momentum of the seed particle + Gaudi::XYZVector seedMomentum = seed->momentum().Vect(); + + + for ( LHCb::Particles::const_iterator ip = photons->begin(); ip != photons->end(); ++ip ) { + const LHCb::Particle *photon = (*ip); + + double photCL = photon->confLevel(); + + // -- Get the momentum of the photon + Gaudi::XYZVector photonMomentum = photon->momentum().Vect(); + // -- Calculate the difference in Eta and Phi between the seed particle and a photons + double deltaPhi = fabs( seedMomentum.Phi() - photonMomentum.Phi() ); + if ( deltaPhi > M_PI ) + deltaPhi = 2 * M_PI - deltaPhi; + double deltaEta = seedMomentum.Eta() - photonMomentum.Eta(); + double deltaR = sqrt( pow(deltaPhi, 2) + pow(deltaEta, 2) ); + + if ( ( rcut == 0 ) || ( deltaR < rcut ) ) { + multiplicity++; + + // -- Calculate scalar information + scalarPt += sqrt( photonMomentum.Perp2() ); + + // -- Calculate vector information + conePx += photonMomentum.X(); + conePy += photonMomentum.Y(); + conePz += photonMomentum.Z(); + + //Calculate sum for Legendre ratio + Double_t cosAng = (seedMomentum.unit()).Dot(photonMomentum.unit()); + if(cosAng > +1.0) + { + cosAng = +1.0; + counter("Forced cos > 1 to 1")++; + } + if(cosAng < -1.0) + { + cosAng = -1.0; + counter("Forced cos < -1 to -1")++; + } + + coneE += std::sqrt(photonMomentum.Mag2()); + numLeg1 += std::sqrt(photonMomentum.Mag2())*gsl_sf_legendre_Pl(1,cosAng); + numLeg2 += std::sqrt(photonMomentum.Mag2())*gsl_sf_legendre_Pl(2,cosAng); + numLeg3 += std::sqrt(photonMomentum.Mag2())*gsl_sf_legendre_Pl(3,cosAng); + numLeg4 += std::sqrt(photonMomentum.Mag2())*gsl_sf_legendre_Pl(4,cosAng); + // Extra Photon + if ( sqrt( photonMomentum.Perp2() ) > sqrt( pow(maxPtPx, 2) + pow(maxPtPy, 2) ) ) { + maxPtPx = photonMomentum.X(); + maxPtPy = photonMomentum.Y(); + maxPtPz = photonMomentum.Z(); + } + + //average CL and search for max CL + avCL += photCL; + if(maxCLmaxP) { + maxP = std::sqrt(photonMomentum.Mag2()); + } + } + + momentum.push_back( conePx ); + momentum.push_back( conePy ); + momentum.push_back( conePz ); + + maxPt.push_back( maxPtPx ); + maxPt.push_back( maxPtPy ); + maxPt.push_back( maxPtPz ); + + AvConfLevel = avCL/multiplicity; + MaxConfLevel = maxCL; + + LegendreRat1 = numLeg1/coneE; + LegendreRat2 = numLeg2/coneE; + LegendreRat3 = numLeg3/coneE; + LegendreRat4 = numLeg4/coneE; + return StatusCode::SUCCESS; + +} +//============================================================================= +// Check if the track is already in the decay +//============================================================================= +bool TupleToolConeIsolation::isTrackInDecay( const LHCb::Track *track ) { + + bool isInDecay = false; + + for ( std::vector::iterator ip = m_decayParticles.begin(); ip != m_decayParticles.end(); ++ip ) { + const LHCb::ProtoParticle *proto = (*ip)->proto(); + if ( proto ) { + + const LHCb::Track *myTrack = proto->track(); + if ( myTrack ) { + + if ( myTrack == track ) { + if ( msgLevel( MSG::DEBUG ) ) + debug() << "Track is in decay, skipping it" << endmsg; + isInDecay = true; + } + + } + } + } + + return isInDecay; + +} + + +//============================================================================= +// Loop over all the pi0 in the cone +//============================================================================= +StatusCode TupleToolConeIsolation::pi0Comb( const LHCb::Particle *seed, + const LHCb::Particles *pi0s, + int &multiplicity, + std::vector &InvMass, + std::vector &Pi0PX, + std::vector &Pi0PY, + std::vector &Pi0PZ, + std::vector &Pi0E, + std::vector &Pi0M, + std::vector &Pi0DeltaR, + std::vector &Pi0Photon1CL, + std::vector &Pi0Photon2CL) { + + // -- Initialize values + + // -- Get the momentum of the seed particle + Gaudi::XYZVector seedMomentum = seed->momentum().Vect(); + Gaudi::LorentzVector seed4Momentum = seed->momentum(); + + for ( LHCb::Particles::const_iterator ip = pi0s->begin(); ip != pi0s->end(); ++ip ) { + const LHCb::Particle *pion0 = (*ip); + + // -- Get the momentum of the pion0 + Gaudi::XYZVector pion0Momentum = pion0->momentum().Vect(); + Gaudi::LorentzVector pion04Momentum = pion0->momentum(); + double masshPi0 = (pion04Momentum+seed4Momentum).M(); + if(masshPi0 < m_MaxhPi0Mass && masshPi0 > m_MinhPi0Mass) { + multiplicity++; + InvMass.push_back(masshPi0); + Pi0PX.push_back(pion0Momentum.X()); + Pi0PY.push_back(pion0Momentum.Y()); + Pi0PZ.push_back(pion0Momentum.Z()); + Pi0E.push_back(pion04Momentum.E()); + Pi0M.push_back(pion04Momentum.M()); + + + // -- Calculate the difference in Eta and Phi between the seed particle and the pi0 + double deltaPhi = fabs( seedMomentum.Phi() - pion0Momentum.Phi() ); + if ( deltaPhi > M_PI ) + deltaPhi = 2 * M_PI - deltaPhi; + double deltaEta = seedMomentum.Eta() - pion0Momentum.Eta(); + double deltaR = sqrt( pow(deltaPhi, 2) + pow(deltaEta, 2) ); + Pi0DeltaR.push_back(deltaR); + + // Get photon info: + if ( !(pion0->isBasicParticle()) ) { + + const SmartRefVector< LHCb::Particle > photons = pion0->daughters(); + + // -- Fill all the daugthers in m_decayParticles + Int_t nph = 0; + + for ( SmartRefVector< LHCb::Particle >::const_iterator iph = photons.begin(); iph != photons.end(); ++iph ) { + double photonCL = (*iph)->confLevel(); + if(nph==0) Pi0Photon1CL.push_back(photonCL); + if(nph==1) Pi0Photon2CL.push_back(photonCL); + nph++; + } + + } else { + Pi0Photon1CL.push_back(-999); + Pi0Photon2CL.push_back(-999); + } + + } + + } + + + return StatusCode::SUCCESS; + +} diff --git a/first-analysis-steps/DecayTrees/TupleToolConeIsolation.h b/first-analysis-steps/DecayTrees/TupleToolConeIsolation.h new file mode 100644 index 00000000..749ba9a9 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolConeIsolation.h @@ -0,0 +1,175 @@ +#ifndef TUPLETOOLCONEISOLATION_H +#define TUPLETOOLCONEISOLATION_H 1 + +// Include files +#include "Kernel/IParticleTupleTool.h" +#include "DecayTreeTupleBase/TupleToolBase.h" + +/** @class TupleToolConeIsolation TupleToolConeIsolation.h + * + * \brief Fill track isolation for DecayTreeTuple. + * Open an eta-phi cone around the head, exclude all tracks that are in the decay descriptor (i.e. that belong to the decay you are looking for), and build variables with the remaining tracks + * + * Options: + * + * - MinConeSize: set the minimum cone size (default = 0.4) + * - MaxConeSize: set the maximum cone size (default = 0.6) + * - SizeStep: set the cone size step between two iterations (default = 0.1) + * - FillCharged: flag to fill the charged cone (default = true) + * - ExtraParticlesLocation: set the type of particles that are considered in the charged cone (default = "Phys/StdAllNoPIDsMuons/Particles") + * - TrackType: set the type of tracks that are considered in the charged cone (default = 3) + * - FillNeutral: flag to fill the neutral cone (default = true) + * - ExtraPhotonsLocation: set the type of particles that are considered in the neutral cone (default = "Phys/StdLooseAllPhotons/Particles") + * - FillAsymmetry: flag to fill the asymmetry variables (default = false) + * - FillDeltas: flag to fill the delta variables (default = false) + * - FillIsolation: flag to fill the isolation variables (default = true) + * - FillMaxPt: flag to fill the momentum of the max-pT object in the cone (default = true) + * - MaxPtParticleLocation: set the type of max-pT particles that are considered in the charged cone (default = "Phys/StdAllLooseMuons/Particles") + * - FillComponents: flag to fill the components of all variables (default = false) + * - FillPi0Info: flag to fill the resolved pi0 info (default = false) + * - FillMergedPi0Info: flag to fill the merged pi0 info (default = false) + * - PizerosLocation: set the resolved pi0 type considered for combination with the seed (default = Phys/StdLoosePi02gg/Particles) + * - MergedPizerosLocation: set the merged pi0 type considered for combination with the seed (default = Phys/StdLooseMergedPi0/Particles) + * - MinhPi0Mass: Set the lower seed-Pi0 invariant mass cut (default = 0 MeV) + * - MaxhPi0Mass: Set the upper seed-Pi0 invariant mass cut (default = 5000 MeV) + * + * If Verbose, all options are set to true + * + * Cone prefix: + * + * - head_cc: charged cone + * - head_nc: neutral cone + * + * The pi0 variables are not dependent on the cone size + * + * Variables (XX = cc or nc): + * + * - head_XX_mult : number of objects inside the cone + * - head_XX_sPT : scalar-summed pT of the objects inside the cone + * - head_XX_vPT : vector-summed pT of the objects inside the cone + * - head_XX_P : x, y and z components of the cone momentum + * + * - head_XX_asy_P : momentum asymmetry between the head and the cone defined as (head_P - head_XX_P) / (head_P + head_XX_P) + * - head_XX_asy_P : x, y, z and transverse components of the momentum asymmetry + * + * - head_XX_deltaEta : difference in eta between the head and the cone + * - head_XX_deltaPhi : difference in phi between the head and the cone + * + * - head_XX_IT : transverse isolation of the head in the cone, defined as head_PT / (head_P + head_XX_P)_T + * - head_IT : transverse isolation of the head in the charged and neutral cones, defined as head_PT / (head_P + head_cc_P + head_nc_P)_T + * + * - head_cc_maxPt_Q : charge of the max-pT object in the charged cone + * - head_XX_maxPt_P : x, y, z (and e) components of the max-pT object momentum in the cone + * - head_MasshPi0: invariant mass of the seed-Pi0 combinations + * - head_Pi0_DeltaR: DeltaR between the seed and the pi0 directions + * - head_Pi0_E, head_Pi0_PX, head_Pi0_PY, head_Pi0_PZ: four momentum of the pi0 + * - head_Pi0_M: invariant mass of the pi0 + * - head_Pi0Ph1_CL, head_Pi0Ph2_CL: confidence levels of the (photon) pi0 daughters + * - For the merged pi0, the names of the variables are labelled replacing Pi0 by MergPi0 + * + * \sa DecayTreeTuple, TupleToolTrackIsolation + * + * @author Simone Bifani, Michel De Cian, Adlene Hicheur + * @date 2016-03-10 + * + */ + + +class TupleToolConeIsolation : public TupleToolBase, virtual public IParticleTupleTool { + +public: + + /// Standard constructor + TupleToolConeIsolation( const std::string &type, + const std::string &name, + const IInterface *parent ); + + virtual ~TupleToolConeIsolation(); ///< Destructor + + StatusCode initialize() override; ///< Algorithm initialization + + /// Loop over different cone sizes and fill the variables into the tuple + StatusCode fill( const LHCb::Particle*, + const LHCb::Particle*, + const std::string&, + Tuples::Tuple& ) override; + +protected: + +private: + + double m_minConeSize; + double m_maxConeSize; + double m_sizeStep; + double m_MinhPi0Mass; + double m_MaxhPi0Mass; + + std::string m_extraParticlesLocation; + std::string m_maxPtParticleLocation; + std::string m_extraPhotonsLocation; + std::string m_PizerosLocation; + std::string m_MergedPizerosLocation; + + int m_trackType; + + bool m_fillCharged; + bool m_fillNeutral; + bool m_fillPi0Info; + bool m_fillMergedPi0Info; + bool m_fillAsymmetry; + bool m_fillDeltas; + bool m_fillIsolation; + bool m_fillMaxPt; + + bool m_fillComponents; + + std::vector m_decayParticles; + + /// Save all the particles in the decay descriptor in a vector + void saveDecayParticles( const LHCb::Particle *top ); + + /// Calculate properties of the charged cone + StatusCode ChargedCone( const LHCb::Particle *seed, + const LHCb::Particles *parts, + const LHCb::Particles *maxPts, + const double rcut, + int &multiplicity, + double &scalarPt, + std::vector &momentum, + std::vector &maxPt ); + + /// Calculate properties of the neutral cone + StatusCode NeutralCone( const LHCb::Particle *seed, + const LHCb::Particles *photons, + const double rcut, + int &multiplicity, + double &scalarPt, + std::vector &momentum, + std::vector &maxPt, + double &AvConfLevel, + double &MaxConfLevel, + double &LR1, + double &LR2, + double &LR3, + double &LR4); + + /// Check if a track belongs to the decay + bool isTrackInDecay( const LHCb::Track *track ); + + //fill pi0-track mass info + StatusCode pi0Comb( const LHCb::Particle *seed, + const LHCb::Particles *pi0s, + int &multiplicity, + std::vector &InvMass, + std::vector &Pi0PX, + std::vector &Pi0PY, + std::vector &Pi0PZ, + std::vector &Pi0E, + std::vector &Pi0M, + std::vector &Pi0DeltaR, + std::vector &Pi0Photon1CL, + std::vector &Pi0Photon2CL); + +}; + +#endif // TUPLETOOLCONEISOLATION_H diff --git a/first-analysis-steps/DecayTrees/TupleToolCorrectedMass.cpp b/first-analysis-steps/DecayTrees/TupleToolCorrectedMass.cpp new file mode 100644 index 00000000..91bfd021 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolCorrectedMass.cpp @@ -0,0 +1,232 @@ +// Include files +// from Gaudi +//#include "GaudiKernel/ToolFactory.h" +// local +#include "TupleToolCorrectedMass.h" +#include +#include +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "Event/Particle.h" + +using namespace LHCb; +using namespace Gaudi::Units; +using namespace ROOT::Math; + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolCorrectedMass +// @author Michel De Cian +// @date 2018-03-21 +//----------------------------------------------------------------------------- +DECLARE_COMPONENT( TupleToolCorrectedMass ) +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolCorrectedMass::TupleToolCorrectedMass( const std::string& type, + const std::string& name, + const IInterface* parent ) +: TupleToolBase ( type, name , parent ), + m_dva(nullptr) +{ + declareInterface(this); +} +//============================================================================= +// -- Initialize +//============================================================================= +StatusCode TupleToolCorrectedMass::initialize(){ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_dva = Gaudi::Utils::getIDVAlgorithm ( contextSvc(), this ) ; + if (!m_dva) return Error("Couldn't get parent DVAlgorithm", + StatusCode::FAILURE); + + return sc; +} +//============================================================================= +// -- The main method +//============================================================================= +StatusCode TupleToolCorrectedMass::fill( const Particle* mother + , const Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) { + + const std::string prefix=fullName(head); + Assert( P && mother + , "This should not happen, you are inside TupleToolCorrectedMass.cpp :(" ); + if( !P ) return StatusCode::FAILURE; + if( !( P->particleID().hasBottom() )) return StatusCode::SUCCESS; + + // -------------------------------------------------- + const LHCb::Vertex* BEndVertex = P->endVertex(); + const LHCb::VertexBase* primaryVertex = m_dva->bestVertex ( P ); + + const Gaudi::LorentzVector pMother = P->momentum(); + + const TVector3 PV(primaryVertex->position().X(),primaryVertex->position().Y(), primaryVertex->position().Z()); + const TVector3 SV(BEndVertex->position().X(),BEndVertex->position().Y(), BEndVertex->position().Z()); + const TVector3 flightDir = (SV - PV).Unit(); + + const double MCorr = mCorr(pMother, flightDir); + const std::pair MCorrErrors = mCorrErrors(SV, PV, pMother, P->covMatrix(), primaryVertex->covMatrix()); + + bool test=true; + test &= tuple->column( prefix + "_MCORR", MCorr); + test &= tuple->column( prefix + "_MCORRERR", MCorrErrors.second); + test &= tuple->column( prefix + "_MCORRVERTEXERR", MCorrErrors.first); // only errors on vertices + + return StatusCode(test); +} +//========================================================================= +// -- Calculate the corrected mass: m_corr = sqrt( m_vis² + pT² ) + pT +//========================================================================= +double TupleToolCorrectedMass::mCorr(const Gaudi::LorentzVector p, const TVector3 flightDir) const { + const TVector3 pVec(p.Px(), p.Py(), p.Pz()); + const double PT = pVec.Perp(flightDir); + return std::sqrt(p.M2() + PT * PT) + PT; +} +//========================================================================= +// -- Helper calculation for mCorrErrors +//========================================================================= +double TupleToolCorrectedMass::dPTdx(const double dAdx, const double dBdx, const double PT, const double A, const double B) const { + + return 1/PT * -0.5 * (2*A*B*dAdx - A*A*dBdx)/(B*B); + +} +//========================================================================= +// -- Calculate the corrected mass error +//========================================================================= +std::pair TupleToolCorrectedMass::mCorrErrors(const TVector3 sv, const TVector3 pv, const Gaudi::LorentzVector p, + const Gaudi::SymMatrix7x7 covP, const Gaudi::SymMatrix3x3 covPV ) const { + // -- + // -- m_corr = sqrt( m_vis² + pT² ) + pT + // -- + // -- To transform the errors on the vertices and the momentum to the corrected mass, one essentially needs to do + // -- mcorr_err² = Sum_i,j( d(m_corr)/dx_i d(m_corr)/dx_j M_ij )_PV + Sum_n,m( d(m_corr)/dx_n d(m_corr)/dx_m M_nm )_SV + // -- where M_ij is the covariance matrix of the PV, and M_nm the covariance matrix of the SV, including uncertainties of the momenta + // -- of the particles that formed the SV. + // -- + // -- For the vertex coordinates: + // -- d(m_corr) / dx = d(m_corr)/dpT * dpT/dx + // -- d(m_corr)/dpT = 1/2 * 1/std::sqrt( m_vis² + pT² ) * 2 * pT + 1; + // -- pT = sqrt( (p_vec - (x_SV_vec - x_PV_vec) * A/B)² ) + // -- with A = px(x_SV - x_PV) + py(y_SV - y_PV) + pz(z_SV - z_PV) + // -- and B = (x_SV - x_PV)² + (y_SV - y_PV)² + (z_SV - z_PV)², or the magnitude squared of x_SV_vec - x_PV_vec + // -- + // -- For the momentum coordinates: + // -- m_vis² = E² - (px² + py² + pz²) + // -- d(m_corr) / dpx = 1/2 * 1 / sqrt( m_vis² + pT²) * ( -2A/B(x_SV-x_PV) ) + 1/pT * ( px - 2A/B(x_SV - x_PV) ) + // -- d(m_corr) / dE = 1/2 * / sqrt( m_vis² + pT²) * 2E + + const double x_SV = sv.Px(); //SV + const double y_SV = sv.Py(); //SV + const double z_SV = sv.Pz(); //SV + const double x_PV = pv.Px(); //PV + const double y_PV = pv.Py(); //PV + const double z_PV = pv.Pz(); //PV + const double px = p.Px(); + const double py = p.Py(); + const double pz = p.Pz(); + const double E = p.E(); + + const TVector3 pVec(p.Px(), p.Py(), p.Pz()); + const double PT = pVec.Perp((sv - pv)); + const double A = px*(x_SV - x_PV) + py*(y_SV - y_PV) + pz*(z_SV - z_PV); + const double B = (sv-pv).Mag2(); + + const double invSqrtMassPT = 1/std::sqrt( p.M2() + PT*PT ); + const double dMcorrdPT = 0.5 * invSqrtMassPT * 2 * PT + 1; + + // -- First let's calculate the derivates of 'A' and 'B' + // -- A + const double dAdx_SV = px; + const double dAdy_SV = py; + const double dAdz_SV = pz; + + const double dAdx_PV = -px; + const double dAdy_PV = -py; + const double dAdz_PV = -pz; + + const double dAdpx = x_SV - x_PV; + const double dAdpy = y_SV - y_PV; + const double dAdpz = z_SV - z_PV; + + // -- B + const double dBdx_SV = 2*(x_SV - x_PV); + const double dBdy_SV = 2*(y_SV - y_PV); + const double dBdz_SV = 2*(z_SV - z_PV); + + const double dBdx_PV = -2*(x_SV - x_PV); + const double dBdy_PV = -2*(y_SV - y_PV); + const double dBdz_PV = -2*(z_SV - z_PV); + + + // -- the vertices + const double dMcdx_SV = dMcorrdPT * dPTdx( dAdx_SV, dBdx_SV, PT, A, B); + const double dMcdy_SV = dMcorrdPT * dPTdx( dAdy_SV, dBdy_SV, PT, A, B ); + const double dMcdz_SV = dMcorrdPT * dPTdx( dAdz_SV, dBdz_SV, PT, A, B ); + + const double dMcdx_PV = dMcorrdPT * dPTdx( dAdx_PV, dBdx_PV, PT, A, B ); + const double dMcdy_PV = dMcorrdPT * dPTdx( dAdy_PV, dBdy_PV, PT, A, B ); + const double dMcdz_PV = dMcorrdPT * dPTdx( dAdz_PV, dBdz_PV, PT, A, B ); + + + // -- the momentum + const double dMcdpx = -1 * invSqrtMassPT * A/B*dAdpx + 1/PT * (px - A/B*dAdpx); + const double dMcdpy = -1 * invSqrtMassPT * A/B*dAdpy + 1/PT * (py - A/B*dAdpy); + const double dMcdpz = -1 * invSqrtMassPT * A/B*dAdpz + 1/PT * (pz - A/B*dAdpz); + const double dMcdE = invSqrtMassPT * E; + + + // -- the errors on the vertices + const double errsqVertex = + // -- the diagonal for SV + covP(0,0) * dMcdx_SV * dMcdx_SV + + covP(1,1) * dMcdy_SV * dMcdy_SV + + covP(2,2) * dMcdz_SV * dMcdz_SV + + // -- the diagonal for PV + covPV(0,0) * dMcdx_PV * dMcdx_PV + + covPV(1,1) * dMcdy_PV * dMcdy_PV + + covPV(2,2) * dMcdz_PV * dMcdz_PV + + // -- the cross terms for SV + covP(0,1) * 2. * dMcdx_SV * dMcdy_SV + + covP(0,2) * 2. * dMcdx_SV * dMcdz_SV + + covP(1,2) * 2. * dMcdy_SV * dMcdz_SV + + // -- the cross terms for PV + covPV(0,1) * 2. * dMcdx_PV * dMcdy_PV + + covPV(0,2) * 2. * dMcdx_PV * dMcdz_PV + + covPV(1,2) * 2. * dMcdy_PV * dMcdz_PV ; + + + // -- the errors on the momentum x vertex + const double errsqMom = + // -- the diagonal for the momentum + covP(3,3) * dMcdpx * dMcdpx + + covP(4,4) * dMcdpy * dMcdpy + + covP(5,5) * dMcdpz * dMcdpz + + covP(6,6) * dMcdE * dMcdE + + // -- momentum x momomentum cross terms + covP(3,4) * 2. * dMcdpx * dMcdpy + + covP(3,5) * 2. * dMcdpx * dMcdpz + + covP(3,6) * 2. * dMcdpx * dMcdE + + covP(4,5) * 2. * dMcdpy * dMcdpz + + covP(4,6) * 2. * dMcdpy * dMcdE + + covP(5,6) * 2. * dMcdpz * dMcdE + + // -- momentum x position terms + covP(0,3) * 2. * dMcdx_SV * dMcdpx + + covP(1,3) * 2. * dMcdy_SV * dMcdpx + + covP(2,3) * 2. * dMcdz_SV * dMcdpx + + covP(0,4) * 2. * dMcdx_SV * dMcdpy + + covP(1,4) * 2. * dMcdy_SV * dMcdpy + + covP(2,4) * 2. * dMcdz_SV * dMcdpy + + covP(0,5) * 2. * dMcdx_SV * dMcdpz + + covP(1,5) * 2. * dMcdy_SV * dMcdpz + + covP(2,5) * 2. * dMcdz_SV * dMcdpz + + covP(0,6) * 2. * dMcdx_SV * dMcdE + + covP(1,6) * 2. * dMcdy_SV * dMcdE + + covP(2,6) * 2. * dMcdz_SV * dMcdE; + + return std::make_pair( std::sqrt( errsqVertex ), std::sqrt( errsqVertex + errsqMom ) ); + +} + diff --git a/first-analysis-steps/DecayTrees/TupleToolCorrectedMass.h b/first-analysis-steps/DecayTrees/TupleToolCorrectedMass.h new file mode 100644 index 00000000..ebf83cfe --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolCorrectedMass.h @@ -0,0 +1,53 @@ +#ifndef TUPLETOOLCORRECTEDMASS_H +#define TUPLETOOLCORRECTEDMASS_H + +// Include files +// from Gaudi +#include +#include +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "TVector3.h" + +/** @class TupleToolCorrectedMass TupleToolCorrectedMass.h + * + * \brief Fill corrected mass (m_corr = sqrt( m_vis² + pT² ) + pT) and error on corrected mass + * + * - head_MCORR: corrected mass + * - head_MCORRERR : error on corrected mass + * - head_MCORRVERTEXERR: error on corrected mass, only taking the uncertainties on the vertices into account + * + * \sa DecayTreeTuple + * + * @author Michel De Cian (based on Will Sutcliffe's version) + * @date 2018-03-21 + */ + +class TupleToolCorrectedMass : public TupleToolBase, virtual public IParticleTupleTool { + + public: + + /// Standard constructor + TupleToolCorrectedMass( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual StatusCode initialize() override; + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + + private: + + double mCorr(const Gaudi::LorentzVector p, const TVector3 flightDir) const; + double dPTdx(const double dAdx, const double dBdx, const double PT, const double A, const double B) const; + std::pair mCorrErrors(const TVector3 sv, const TVector3 pv, const Gaudi::LorentzVector p, + const Gaudi::SymMatrix7x7 covP, const Gaudi::SymMatrix3x3 covPV ) const; + + IDVAlgorithm* m_dva; + +}; + +#endif diff --git a/first-analysis-steps/DecayTrees/TupleToolDEDX.cpp b/first-analysis-steps/DecayTrees/TupleToolDEDX.cpp new file mode 100755 index 00000000..c7392449 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolDEDX.cpp @@ -0,0 +1,392 @@ +#include "TupleToolDEDX.h" +#include "map" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" +#define MAXCLUSTERS 45 +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolDEDX +// +// 2009-06-09 : Rob Lambert +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolDEDX ) + +namespace { + using std::pow; + using std::sqrt; +} +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolDEDX::TupleToolDEDX( const std::string& type, + const std::string& name, + const IInterface* parent ) + : GaudiTool ( type, name , parent ) +{ + declareInterface(this); + declareProperty("absCharge", m_abs=false); +} + +//============================================================================= + +StatusCode TupleToolDEDX::fill( const LHCb::Particle* + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ){ + //fill some information about the particle here! + bool test = true; + if( P ){ + //fill some information here! + //std::cout<<"INSIDE TUPLETOOL HERE!!!!!!" << std::endl; + if(m_abs) test &= tuple->column( head+"_Q", std::abs(P->charge()) ).isSuccess(); + else test &= tuple->column( head+"_Q", P->charge() ).isSuccess(); + test &= tuple->column( head+"_eta", P->momentum().Rapidity() ).isSuccess(); + + if ( !exist( LHCb::VeloClusterLocation::Default ) ) { + debug() << "No VeloClusters container found for this event !" << endmsg; + return StatusCode::FAILURE; + } + else { + m_clusters = get( LHCb::VeloClusterLocation::Default ); + debug() << " -> number of clusters found in TES: " + << m_clusters->size() <size(); + //int nProtoParticles = protoParticles->size(); + int TrackCounter=0; + int ClusterCounter=0; + //int PID=0; + std::string dirName; + + const LHCb::ProtoParticle* proto = P->proto(); + if(!proto) return StatusCode::SUCCESS; + const LHCb::Track* track = proto->track(); + if(!track) return StatusCode::SUCCESS; + //Skip the tracks without VELO(Velo, VeloR, Upstream and Long)hits + if ( !track->hasVelo() ) { + debug() <<"Track has no VELO hits, continuing with next track."<< endmsg; + // continue; + } + + //Get track IDs: + const std::vector< LHCb::LHCbID > & trackID = track->lhcbIDs() ; + // int nClusters=trackID.size(); + + //Get track angle vector: + Gaudi::XYZVector slope= track->slopes(); + Gaudi::XYZVector momentum = track->momentum(); + debug() <<"Starting linker" << endmsg; + + int trackType = track->type(); + double theta = slope.Theta(); + //double phi = slope.Phi(); + // double trackp = sqrt(momentum.Mag2() )/Gaudi::Units::GeV; + double trackpt = momentum.rho(); + double trackpx = momentum.x(); + double trackpy = momentum.y(); + double trackpz = momentum.z(); + double prap = track->pseudoRapidity(); + double trackChi2 = track->chi2(); + int trackKey = track->key(); + int trackVeloKey = -10 ; + const SmartRefVector& ancestors = track->ancestors(); + for (SmartRefVector::const_iterator it4 = ancestors.begin(); it4 != ancestors.end(); ++it4){ + if((*it4)->type() == 1) trackVeloKey = (*it4)->key(); + //else trackVeloKey = -1; + } + + double trackProbChi2 = track->probChi2(); + double trackLikelihood = track->likelihood(); + double trackGhostProb = track->ghostProbability(); + double trackChi2PerDoF = track->chi2PerDoF(); + int tracknDoF = track->nDoF(); + + //Muon PID: + double protoMuLL(-999); + double protoMuBkgLL(-999); + if(proto->hasInfo(200) ){ + const LHCb::MuonPID* protoMuPID = proto->muonPID(); + protoMuLL= protoMuPID->MuonLLMu(); + debug() << "Muon LL: " << protoMuLL << endmsg; + protoMuBkgLL = protoMuPID->MuonLLBg(); + } + + //Rich PID: + float protoRichDLLe(-999); + float protoRichDLLmu(-999); + float protoRichDLLpi(-999); + float protoRichDLLk(-999); + float protoRichDLLp(-999); + int protoRichBestPID(-1); + if(proto->hasInfo(100) ) protoRichDLLe = proto->richPID()->particleDeltaLL( (Rich::Electron) ); + if(proto->hasInfo(101) ) protoRichDLLmu = proto->richPID()->particleDeltaLL((Rich::Muon) ); + if(proto->hasInfo(102) ) protoRichDLLpi = proto->richPID()->particleDeltaLL((Rich::Pion) ); + if(proto->hasInfo(103) ) protoRichDLLk = proto->richPID()->particleDeltaLL((Rich::Kaon) ); + if(proto->hasInfo(104) ) protoRichDLLp = proto->richPID()->particleDeltaLL((Rich::Proton) ); + + if(proto->richPID() ) { + protoRichBestPID = proto->richPID()->bestParticleID(); + } + + //Try to find Calo PID: + const SmartRefVector &caloVec = proto->calo(); + std::vector protoCaloHypothesis; + std::vector protoCaloLh; + SmartRefVector< LHCb::CaloHypo >::const_iterator iCalo; + for (iCalo=caloVec.begin(); iCalo!= caloVec.end(); iCalo++){ + const LHCb::CaloHypo* protoCaloData = iCalo->target(); + if(protoCaloData){ + protoCaloHypothesis.push_back(protoCaloData->hypothesis()); + protoCaloLh.push_back(protoCaloData->lh()); + } + } + //tracks travel at an angle relative to sensors, so have a factor to account for + // the excess material traversed. This will need to be refined later... + // dE/dx = constant \times ADC counts/ path. path = 300 um /cos(theta); + // dE/dx = constant' \times cos(theta) + double AngleFactor=1; + //if(m_AngleCorrection){ + if(cos(theta) !=0)AngleFactor = cos(theta); + //} + std::vector::const_iterator iID; + std::vector ADCValues; + std::vector CorrectedADCValues; + std::list listOfADCValues; + debug()<<"==> Begin loop over track IDs: " << trackID.size() << " clusters" <( LHCb::VeloClusterLocation::Default ); + debug() << " -> number of clusters found in TES: " + << m_clusters->size() <object( vcID ); + if(!cluster) return StatusCode::SUCCESS; + + debug() << "After cluster " << TrackCounter << endmsg; + + if ( 0 == cluster ) { + error() << "Missing cluster with ID " << vcID << endmsg; + continue; + } + LHCb::VeloChannelID idfilter = cluster->channelID(); + + //Separate info for R and Phi sensors... + if(idfilter.isRType()){ + //Can do something here... + } + else if (idfilter.isPhiType() ){ + // do something with the phis. + } + double adc = cluster->totalCharge(); + if(ClusterCountertotalCharge()*AngleFactor; + if(ClusterCounter=2){ + //Median: + debug()<<"==> Calculating Median " << endmsg; + if( ClusterCounter%2!=0){ + MPV_Corrected_Median=(float)CorrectedClusterArray[ClusterCounter/2]; + MPV_Median=(float)ClusterArray[ClusterCounter/2]; + } + else{ + MPV_Corrected_Median = 0.5*((float)CorrectedClusterArray[ClusterCounter/2] + + (float)CorrectedClusterArray[(ClusterCounter/2) -1]); + MPV_Median = 0.5*((float)ClusterArray[ClusterCounter/2] + + (float)ClusterArray[(ClusterCounter/2) -1]); + } + + debug()<<"==> Calculating Mean " << endmsg; + tempMean=0.0; + for(int i=0; i Calculating Truncated Mean " << endmsg; + if(ClusterCounter<5) MPV_Trunc20=MPV_Median; + else{ + nToInclude20 = (int)round(0.8*ClusterCounter); + tempMean=0.0; + for(int i=0; i Calculating Generalized Mean " << endmsg; + tempMean=0.0; + + float PowerK = -2.; + for(int i=0; icolumn("EventNumber", m_event); + //tuple->column("TrackNumber",TrackCounter ); + //tuple->column("phi", phi); + //tuple->column("TrackID", PID); + tuple->column(head+"_DEDX_theta", theta); + //tuple->column("momentum", trackp); + //tuple->column("momentumTRUE", trackpTRUE/GeV); + tuple->column( head+"_DEDX_pt", trackpt); + tuple->column( head+"_DEDX_px", trackpx); + tuple->column( head+"_DEDX_py", trackpy); + tuple->column( head+"_DEDX_pz", trackpz); + tuple->column( head+"_DEDX_pseudoRapidity", prap); + tuple->column( head+"_DEDX_trackType", trackType); + tuple->column( head+"_DEDX_trackKey", trackKey); + tuple->column( head+"_DEDX_trackVeloKey", trackVeloKey); + tuple->column( head+"_DEDX_trackChi2", trackChi2); + tuple->column( head+"_DEDX_trackProbChi2", trackProbChi2); + tuple->column( head+"_DEDX_trackLikelihood", trackLikelihood); + tuple->column( head+"_DEDX_trackGhostProb", trackGhostProb); + tuple->column( head+"_DEDX_trackChi2PerDoF", trackChi2PerDoF); + tuple->column( head+"_DEDX_tracknDoF", tracknDoF); + //PID: + tuple->column( head+"_DEDX_protoMuBkgLL", protoMuBkgLL); + tuple->column( head+"_DEDX_protoMuLL", protoMuLL); + tuple->column( head+"_DEDX_protoRichDLLe", protoRichDLLe); + tuple->column( head+"_DEDX_protoRichDLLmu", protoRichDLLmu); + tuple->column( head+"_DEDX_protoRichDLLpi", protoRichDLLpi); + tuple->column( head+"_DEDX_protoRichDLLk", protoRichDLLk); + tuple->column( head+"_DEDX_protoRichDLLp", protoRichDLLp); + tuple->column( head+"_DEDX_protoRichBestPID", protoRichBestPID); + tuple->farray( head+"_DEDX_protoCaloHypothesis", protoCaloHypothesis.begin(), protoCaloHypothesis.end(), "CaloHypoLength", 100); + tuple->farray( head+"_DEDX_protoCaloLh", protoCaloLh.begin(), protoCaloLh.end(), "CaloHypoLength", 100); + tuple->column( head+"_DEDX_MPV_Mean", MPV_Mean); + tuple->column( head+"_DEDX_MPV_Median", MPV_Median); + tuple->column( head+"_DEDX_MPV_Corrected_Median", MPV_Corrected_Median); + tuple->column( head+"_DEDX_MPV_Trunc20", MPV_Trunc20); + tuple->column( head+"_DEDX_MPV_Trunc40", MPV_Trunc40); + tuple->column( head+"_DEDX_MPV_GenMean_2", MPV_GenMean_2); + tuple->column( head+"_DEDX_MPV_GenMean_4", MPV_GenMean_4); + tuple->column( head+"_DEDX_MPV_GenMean_6", MPV_GenMean_6); + tuple->column( head+"_DEDX_MPV_GenMean_0_5", MPV_GenMean_0_5); + tuple->column( head+"_DEDX_nClustersPerTrack", ClusterCounter); + tuple->farray( head+"_DEDX_ADCValues", ADCValues.begin(), ADCValues.end(), head+"_DEDX_ArrayLength", MAXCLUSTERS); + tuple->farray( head+"_DEDX_CorrectedADCValues", CorrectedADCValues.begin(), + CorrectedADCValues.end(), + head+"_DEDX_ArrayLength", MAXCLUSTERS); + + }else + { + return StatusCode::FAILURE; + } + return StatusCode(test); +} + +//============================================================================ +// QuickSort, for finding median... +//============================================================================ +void TupleToolDEDX::quickSort(double arr[], int left, int right) +{ + int i = left, j = right; + double tmp; + double pivot = arr[(left + right) / 2]; + /* partition */ + while (i <= j) { + while (arr[i] < pivot) + i++; + while (arr[j] > pivot) + j--; + if (i <= j) { + tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + i++; + j--; + } + }; + /* recursion */ + if (left < j) + quickSort(arr, left, j); + if (i < right) + quickSort(arr, i, right); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolDEDX.h b/first-analysis-steps/DecayTrees/TupleToolDEDX.h new file mode 100755 index 00000000..77efc301 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolDEDX.h @@ -0,0 +1,95 @@ +// $Id: TupleToolDEDX_Solution.h,v 1.1 2009/06/11 16:22:29 rlambert Exp $ +#ifndef TUPLETOOLDEDX_H +#define TUPLETOOLDEDX_H 1 + +//Include from VELOPID: +//#include "Velo/VeloMonitorBase.h" +#include "Event/VeloCluster.h" +#include "Event/Track.h" +#include "Event/Particle.h" +#include "TrackInterfaces/IVeloClusterPosition.h" +#include "TrackInterfaces/IVeloExpectation.h" +#include "TrackInterfaces/IMeasurementProvider.h" +#include "GaudiAlg/GaudiTupleAlg.h" +//#include "GaudiAlg/GaudiTool.h" +#include "GaudiAlg/TupleObj.h" +#include "Event/MCHit.h" + +//Linkers, track2mc +#include "Linker/LinkedTo.h" +#include "Linker/LinkerWithKey.h" +#include "Linker/LinkerTool.h" +#include "Linker/LinkedFrom.h" +#include "Kernel/Track2MC.h" +//tuple: +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include +//End VeloPID + + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +#include "Kernel/IParticleTupleTool.h" // Interface + +/** @class TupleToolDEDX TupleToolDEDX.h jborel/TupleToolDEDX.h + * + * \brief Skeleton for DaVinci Tutorial 7 + * + * + * + * \sa DecayTreeTuple + * + * @author Rob Lambert + * @date 2009-06-09 + */ +class TupleToolDEDX : public GaudiTool, virtual public IParticleTupleTool { + public: +//Start VeloPID: + LHCb::Tracks* tracks; + LHCb::VeloClusters* m_clusters; + LHCb::MCParticles* m_MCParticles; + LHCb::MCHits* m_MCHits; + LHCb::ProtoParticles* protoParticles; + unsigned long m_event; +// // std::string asctName(); +// //From Tomasz: +// typedef LinkerTool AsctTool; +// typedef AsctTool::DirectType Table; +// typedef Table::Range Range; +// typedef Table::iterator iterator; + std::string m_asctLocation; +// IMCParticleSelector* m_mcSelector; /// MC selector +// virtual StatusCode loopOnTracks(); +// StatusCode plotCluster(LHCb::VeloCluster* cluster,std::string ClusterType, double theta=-400.,double prap = -400.); + void quickSort(double arr[], int left, int right); + StatusCode plotSensorsADC(double& adc,std::string corr,std::string& ClusterType,int sensor_num = -400); + bool m_MC; + bool m_AngleCorrection; + std::string m_clusterCont; + std::string m_trackCont; + std::string m_MCCont; + std::string m_track2MC; + std::string m_MCHitsCont; + std::string m_protoParticlesCont; + + //End VELOPID + + TupleToolDEDX( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolDEDX(){}; ///< Destructor + + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; +private: + bool m_abs; + +}; + +#endif // TUPLETOOLDEDX_H diff --git a/first-analysis-steps/DecayTrees/TupleToolDalitz.cpp b/first-analysis-steps/DecayTrees/TupleToolDalitz.cpp new file mode 100644 index 00000000..92141dd5 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolDalitz.cpp @@ -0,0 +1,56 @@ +#include "Event/Particle.h" + +#include "TupleToolDalitz.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolDalitz +// +// 2009-02-17 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolDalitz ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolDalitz::TupleToolDalitz( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_ppSvc(0) +{ + declareInterface(this); + +} +//============================================================================= +// Destructor +//============================================================================= +TupleToolDalitz::~TupleToolDalitz() {} + +//============================================================================= +//============================================================================= +// Fill +//============================================================================= +StatusCode TupleToolDalitz::fill( const LHCb::Particle* mother + , const LHCb::Particle* part + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(head); + + if (msgLevel(MSG::VERBOSE)) verbose() << "Dalitz fill " << prefix << " " << mother + << " " << part << endmsg ; + if (0==part) return StatusCode::FAILURE ; + const LHCb::Particle::ConstVector& dauts = part->daughtersVector() ; + if ( 2 >= dauts.size() ){ + debug() << "Will not fill Dalitz of two body decay " << prefix << endmsg; + return StatusCode::SUCCESS; + } + if (part->particleID().abspid()==98){ + debug() << "Will not fill Dalitz for particle type CELLjet " << endmsg; + return StatusCode::SUCCESS; + } + + return fill(dauts,head,tuple,(part->particleID().pid()<0)) ; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolDalitz.h b/first-analysis-steps/DecayTrees/TupleToolDalitz.h new file mode 100644 index 00000000..cdfce777 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolDalitz.h @@ -0,0 +1,56 @@ +// $Id: TupleToolDalitz.h,v 1.3 2010-01-26 15:39:26 rlambert Exp $ +#ifndef TUPLETOOLDALITZ_H +#define TUPLETOOLDALITZ_H 1 + +// Include files +// from Gaudi +#include "Kernel/IParticleTupleTool.h" +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/Escape.h" +#include "Event/Particle.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" +// Boost +#include + + + + + + +/** @class TupleToolDalitz TupleToolDalitz.h + * + * Fills square masses of all combinations of direct daughters + * + * @author Patrick Koppenburg + * @date 2009-02-17 + */ +class TupleToolDalitz : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolDalitz( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolDalitz( ); ///< Destructor + + /// The filling method + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + // Horrid way of sharing code. Should use inheritance instead ... +#include "TupleToolDalitz.icpp" + +}; + +#endif // TUPLETOOLDALITZ_H diff --git a/first-analysis-steps/DecayTrees/TupleToolDalitz.icpp b/first-analysis-steps/DecayTrees/TupleToolDalitz.icpp new file mode 100644 index 00000000..f9f63629 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolDalitz.icpp @@ -0,0 +1,85 @@ + +private: + +//============================================================================= +// The templated method filling the tuple for Particles and MCParticles +//============================================================================= +/// The templated method that does it all +template StatusCode fill( const std::vector& dauts /// daughters + , const std::string& head /// header + , Tuples::Tuple& tuple /// tuple + , bool revert ) /// revert all PID (because mother is antiparticle) +{ + + const std::string prefix = fullName(head); + bool test = true; + // sort out daughters vector + std::vector daughters(dauts); // local copies to sort + const LHCb::IParticlePropertySvc* pp=ppSvc() ; + std::stable_sort(daughters.begin(), daughters.end(), [revert,pp](const TYPE* c1, const TYPE* c2){ + int sign=(revert) ? -1 : 1; + int p1 = ( pp->find( c1->particleID())->selfcc() ) ? c1->particleID().pid() : sign*c1->particleID().pid(); + int p2 = ( pp->find( c2->particleID())->selfcc() ) ? c2->particleID().pid() : sign*c2->particleID().pid(); + bool comp=std::make_pair(p1,c1->key()) > std::make_pair(p2,c2->key()); + return comp; + }); + std::map used; + + for ( typename std::vector::const_iterator i = daughters.begin();i != daughters.end(); ++i ) { + const std::string n1 = particleName( (*i)->particleID(), revert ); + const Gaudi::LorentzVector& p1 = (*i)->momentum() ; + for ( typename std::vector::const_iterator j = daughters.begin();i != j; ++j ) { + const std::string n2 = particleName( (*j)->particleID(), revert ); + const Gaudi::LorentzVector p = p1 + (*j)->momentum(); + const std::string basename = prefix+"_Dalitz_"+n1+"_"+n2+"_M2"; + std::string name = basename; + if(used.find(basename) != used.end() ){ + unsigned int add=used[basename]; + name = basename+"_"+boost::lexical_cast(add); + used[basename]=add+1; + Info("Renaming duplicate to "+name,StatusCode::SUCCESS,1); + }else{ + used[basename]=1; + } + test &= tuple->column( name, p .M2() ); + } + } + return StatusCode(test); +} + +/// get name of particle or anti-particle +std::string particleName( const LHCb::ParticleID& id, bool revert ) const +{ + const LHCb::ParticleProperty* ppp = ppSvc()->find( id ); + if ( !ppp ) + { + std::ostringstream mess; + mess << "Unknown ParticleID " << id; + Exception( mess.str() ); + } + return Decays::escape( ( revert ? + ppp->antiParticle()->particle() : + ppp->particle() ) ) ; +} + +/// get particle property serivce +const LHCb::IParticlePropertySvc* ppSvc() const +{ + return m_ppSvc; +} + +public: + +StatusCode initialize() override +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isSuccess() ) + { + m_ppSvc = svc("LHCb::ParticlePropertySvc", true ); + } + return sc; +} + +private: + +LHCb::IParticlePropertySvc* m_ppSvc ; diff --git a/first-analysis-steps/DecayTrees/TupleToolDecayTreeFitter.cpp b/first-analysis-steps/DecayTrees/TupleToolDecayTreeFitter.cpp new file mode 100644 index 00000000..b2461020 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolDecayTreeFitter.cpp @@ -0,0 +1,692 @@ + +// local +#include "TupleToolDecayTreeFitter.h" + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolDecayTreeFitter +// Yasmine Amhis, Matt Needham, Patrick Koppenburg +// 30-10-2010, 01-04-2011 +//----------------------------------------------------------------------------- + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolDecayTreeFitter::TupleToolDecayTreeFitter( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name, parent ) +{ + declareProperty( "daughtersToConstrain", m_massConstraints, + "List of particles to contrain to mass"); + declareProperty( "constrainToOriginVertex", m_constrainToOriginVertex = false, + "Do a refit constraining to Origin Vertex (could be PV)"); + declareProperty( "Substitutions", m_map, + "PID-substitutions : { ' decay-component' : 'new-pid' }" ) ; + declareProperty( "StoreRefittedPVsTwice" ,m_storeAnyway = false, + "Store PV even if a refitted version is already the best PV (i.e store twice)." ) ; + declareProperty( "UpdateDaughters" ,m_updateDaughters = false, + "Store updated momenta of tracks in the decay tree." ) ; + declareProperty( "StateProvider", m_stateprovider ) ; + declareProperty( "VetoPIDs", m_vetoPIDs, + "An optional list of PDG particle codes to skip when filling the tuple." ); + declareProperty( "UseFullTreeInName", m_useFullTreeInName = false, + "Use an improved branch naming scheme that includes a full history of the " + "parents and grand-parents for each particle. Makes it easier to identify " + "cases where the same particle type appears at different levels in the decay tree." ); + declareInterface(this); +} + +//============================================================================= +StatusCode TupleToolDecayTreeFitter::initialize() +{ + StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + // convert the list of names to a list of pids + m_ppSvc = svc("LHCb::ParticlePropertySvc",true) ; + for ( const auto & S : m_massConstraints ) + { + const auto prop = m_ppSvc->find( S ); + if (!prop) Exception("Unknown PID"); + m_massConstraintsPids.push_back(prop->pdgID()); + } + + m_dva = Gaudi::Utils::getIDVAlgorithm ( contextSvc(), this ) ; + if ( !m_dva ) return Error("Couldn't get parent IDVAlgorithm", StatusCode::FAILURE); + + m_particleDescendants = tool ( "ParticleDescendants"); + + if ( !m_stateprovider.empty() ) + { + sc = m_stateprovider.retrieve() ; + if ( sc.isFailure() ) return sc ; + } + + if ( m_extraName.empty() ) + { + const auto en = name() ; // use tool name as prepended name + const auto d = en.find_last_of("."); + m_extraName = en.substr(d+1,en.size()-1); // from d to end + if ( "TupleToolDecayTreeFitter" == m_extraName ) m_extraName = ""; // user has not chanegd instance name + info() << "All fields will be prepended with ``" << m_extraName << "''" <("SubstitutePIDTool",this); + sc = m_substitute->decodeCode( m_map ); + } + + if ( !m_vetoPIDs.empty() ) + { + info() << "Will veto PIDs " << m_vetoPIDs << " from filling" << endmsg; + } + + if ( m_useFullTreeInName ) + { + info() << "Will use the full decay tree as part of branch names" << endmsg; + } + + return sc; +} + +StatusCode TupleToolDecayTreeFitter::finalize() +{ + StatusCode sc = StatusCode::SUCCESS; + if ( !m_stateprovider.empty() ) { sc = m_stateprovider.release(); } + return StatusCode{ TupleToolBase::finalize() && sc }; +} + +//============================================================================= +// The fill method implementation +//============================================================================= +StatusCode TupleToolDecayTreeFitter::fill( const LHCb::Particle* mother + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + if( !P ) return StatusCode::FAILURE; + if ( P->isBasicParticle() ) + { + return Error("Do not call TupleToolDecayTreeFitter for basic particles. Use Branches. See doxygen."); + } + const std::string prefix = fullName(head); + if (msgLevel(MSG::DEBUG)) debug() << "head ''" << head << "'' prefix ''" << prefix + << "'' extraname ''" << m_extraName << "''" < originVtx; + TupleMap tMap ; // the temporary data map + + if (m_constrainToOriginVertex) + { + if (msgLevel(MSG::DEBUG)) { + debug() << "Constrain the origin vertex" << endmsg; + } + // check for origin vertex + originVtx = originVertex( mother, P ); + if( originVtx.empty() ){return Error("Can't get an origin vertex");} + if (msgLevel(MSG::DEBUG)) debug() << "PVs: " << originVtx.size() << endmsg; + for ( const auto & v : originVtx ) + { + if (msgLevel(MSG::DEBUG)) debug() << "Creating DecayTreeFitter on " + << tree.head() << " " << v << endmsg; + DecayTreeFitter::Fitter fitter(*(tree.head()), *v, stateprovider ) ; + if (msgLevel(MSG::DEBUG)) debug() << "Created DecayTreeFitter" << endmsg; + if (!fit(fitter, tree.head(), v, prefix, tMap)) return StatusCode::FAILURE ; + } + } + else + { + if (msgLevel(MSG::DEBUG)) debug() << "Do not constrain the origin vertex" << endmsg; + // Get the fitter + DecayTreeFitter::Fitter fitter(*(tree.head()), stateprovider ) ; + if (!fit(fitter, tree.head(), 0, prefix, tMap)) return StatusCode::FAILURE; + } + + return fillTuple(tMap,tuple,prefix); // the actual filling +} +//============================================================================= +// do filling for a given vertex +//============================================================================= +StatusCode TupleToolDecayTreeFitter::fit(DecayTreeFitter::Fitter& fitter, + const LHCb::Particle* P, + const LHCb::VertexBase* pv, + const std::string& prefix, + TupleMap& tMap) const +{ + if (msgLevel(MSG::VERBOSE)) verbose() << "fit " << P << " " << pv << " " << prefix << endmsg ; + bool test = true ; + //add mass contraints + if ( !m_massConstraintsPids.empty() ) + { + for ( const auto & C : m_massConstraintsPids ) + { + fitter.setMassConstraint(C); + } + } + // fit + if (msgLevel(MSG::VERBOSE)) verbose() << "calling Fit" << endmsg ; + fitter.fit(); + if (msgLevel(MSG::VERBOSE)) verbose() << "called Fit" << endmsg ; + // fill the fit result + fillDecay(fitter,prefix,tMap ); + fillMomentum(fitter,P,prefix,tMap ); + if (m_constrainToOriginVertex) + { + test &= fillPV(pv,prefix,tMap); + test &= fillLT(fitter,P,prefix,tMap ); + } + if ( isVerbose() ) + { + test &= fillDaughters( fitter,P,prefix,tMap ); + } + if ( m_updateDaughters ) + { + test &= fillStableDaughters( fitter,P,prefix,tMap ); + } + + return StatusCode(test); +} +//============================================================================= +// Fill standard stuff +//============================================================================= +StatusCode TupleToolDecayTreeFitter::fillPV(const LHCb::VertexBase* pv, + const std::string& prefix, + TupleMap& tMap ) const +{ + bool test = true; + if (msgLevel(MSG::VERBOSE)) verbose() << "FillPV " << prefix << endmsg ; + if (!pv) Exception("Null PVs cannot happen with ConstrainToOriginVertex!"); + test &= insert( prefix+"_PV_key", pv->key(), tMap ); + if ( isVerbose() ) + { + test &= insert( prefix+"_PV_X", pv->position().X(), tMap ); + test &= insert( prefix+"_PV_Y", pv->position().Y(), tMap ); + test &= insert( prefix+"_PV_Z", pv->position().Z(), tMap ); + } + return StatusCode(test); +} +//============================================================================= +// Fill standard stuff +//============================================================================= +StatusCode TupleToolDecayTreeFitter::fillDecay(const DecayTreeFitter::Fitter& fitter, + const std::string& prefix, + TupleMap& tMap ) const +{ + bool test = true; + if (msgLevel(MSG::VERBOSE)) verbose() << "FillDecay " << prefix << endmsg ; + + test &= insert( prefix+"_status", fitter.status(), tMap ); + test &= insert( prefix+"_nDOF", fitter.nDof(), tMap ); + test &= insert( prefix+"_chi2", fitter.chiSquare(), tMap ); + test &= insert( prefix+"_nIter", fitter.nIter(), tMap ); + + return StatusCode(test); +} +//============================================================================= +// Fill momentum and mass information +//============================================================================= +StatusCode TupleToolDecayTreeFitter::fillMomentum(const DecayTreeFitter::Fitter& fitter, + const Particle* P, + const std::string& prefix, + TupleMap& tMap ) const +{ + bool test = true; + + if ( isVetoed(P->particleID().pid()) ) { return StatusCode(test); } + + if (msgLevel(MSG::VERBOSE)) verbose() << "FillMomentum " << prefix << endmsg ; + //Get the fit parameters + const auto params = fitter.fitParams(P) ; + const auto& momentum = params->momentum() ; + + test &= insert( prefix+"_M", momentum.m().value(), tMap ); + test &= insert( prefix+"_MERR", momentum.m().error(), tMap ); + test &= insert( prefix+"_P", momentum.p().value(), tMap ); + test &= insert( prefix+"_PERR", momentum.p().error(), tMap ) ;//MeV + + return StatusCode(test); +} +//============================================================================= +// Fill lifetime information +//============================================================================= +StatusCode TupleToolDecayTreeFitter::fillLT(const DecayTreeFitter::Fitter& fitter, + const Particle* P, + const std::string& prefix, + TupleMap& tMap ) const +{ + bool test = true; + + if ( isVetoed(P->particleID().pid()) ) { return StatusCode(test); } + + if (msgLevel(MSG::VERBOSE)) verbose() << "FillLT " << prefix << endmsg ; + const auto tParams = fitter.fitParams(P); + const auto& decayLength = tParams->decayLength(); + const auto& ctau = tParams->ctau(); + test &= insert( prefix+"_ctau", ctau.value(), tMap ); + test &= insert( prefix+"_ctauErr", ctau.error(), tMap ); + test &= insert( prefix+"_decayLength", decayLength.value(), tMap ); + test &= insert( prefix+"_decayLengthErr", decayLength.error(), tMap ); + + return StatusCode(test); +} +//============================================================================= +// Fill lifetime information for non stable daughters +//============================================================================= +StatusCode TupleToolDecayTreeFitter::fillDaughters( const DecayTreeFitter::Fitter& fitter + ,const LHCb::Particle* P + ,const std::string& prefix + ,TupleMap& tMap ) const +{ + bool test = true; + + if (msgLevel(MSG::VERBOSE)) verbose() << "FillDaughters " << prefix << endmsg ; + const auto & daughters = ( m_useFullTreeInName ? + P->daughtersVector() : + m_particleDescendants->descendants(P) ); + if (msgLevel(MSG::DEBUG)) debug() << "for id " << P->particleID().pid() + << " daughter size is " << daughters.size() << endmsg; + if ( daughters.empty() ) return StatusCode(test); + std::set usedNames; + unsigned int add = 0; + for ( const auto& particle : daughters ) + { + if ( particle->isBasicParticle() ) continue ; + const auto pid = abs(particle->particleID().pid()); + const auto pidName = getName(pid) ; + auto name = prefix+"_"+pidName ; + bool renamed = false; + while ( usedNames.find(name) != usedNames.end() ) + { // fix to bug 88702 + renamed = true; + if (msgLevel(MSG::VERBOSE)) verbose() << "Found already name " << name + << " trying next " << endmsg; + name = prefix + "_" + pidName + "_" + boost::lexical_cast(add); + ++add; + } + if ( renamed ) Info("Renaming duplicate to "+name,StatusCode::SUCCESS,1); + usedNames.insert(name); + test &= fillMomentum( fitter,particle,name,tMap ); + test &= fillLT( fitter,particle,name,tMap); + if ( m_useFullTreeInName ) { fillDaughters(fitter,particle,name,tMap); } + } + return StatusCode(test); +} +//============================================================================= +// Fill lifetime information for stable daughters +//============================================================================= +StatusCode +TupleToolDecayTreeFitter::fillStableDaughters( const DecayTreeFitter::Fitter& fitter, + const LHCb::Particle* P, + const std::string& prefix, + TupleMap& tMap ) const +{ + bool test = true; + + if (msgLevel(MSG::VERBOSE)) verbose() << "FillStableDaughters " << prefix << endmsg ; + const LHCb::Particle::ConstVector& daughters = P->daughtersVector(); + if (msgLevel(MSG::DEBUG)) debug() << "for id " << P->particleID().pid() + << " daughter size is " << daughters.size() << endmsg; + if ( daughters.empty() ) return StatusCode(test); + std::set usedNames; + unsigned int add = 0; + for ( const auto& particle : daughters ) + { + if ( !particle->isBasicParticle() ) + { + const auto pid = abs(particle->particleID().pid()); + const auto pidName = getName(pid) ; + auto name = prefix+"_"+pidName ; + bool renamed = false; + while ( usedNames.find(name) != usedNames.end() ) + { // fix to bug 88702 + if (msgLevel(MSG::VERBOSE)) verbose() << "Found already name " << name + << " trying next " << endmsg ; + renamed = true; + name = prefix+"_"+pidName+boost::lexical_cast(add); + ++add; + } + if ( renamed ) Info("Renaming duplicate to "+name,StatusCode::SUCCESS,1); + usedNames.insert(name); + test &= fillStableDaughters( fitter, particle, name, tMap ); + } + else + { + // const int pid = particle->particleID().pid(); + const auto pid = abs(particle->particleID().pid()); + const auto pidName = getName(pid) ; + auto name = prefix+"_"+pidName; + bool renamed = false; + while ( usedNames.find(name) != usedNames.end() ) + { // fix to bug 88702 + if (msgLevel(MSG::VERBOSE)) verbose() << "Found already name " << name + << " trying next " << endmsg ; + renamed = true; + name = prefix+"_"+pidName+"_"+boost::lexical_cast(add); + ++add; + } + if ( renamed ) Info("Renaming duplicate to "+name,StatusCode::SUCCESS,1); + usedNames.insert(name); + test &= fillTracksMomentum( fitter, particle, name, tMap ); + } + } + return StatusCode(test); +} + +//============================================================================= +// Fill updated tracks momentum +//============================================================================= +StatusCode +TupleToolDecayTreeFitter::fillTracksMomentum( const DecayTreeFitter::Fitter& fitter, + const Particle* P, + const std::string& prefix, + TupleMap& tMap ) const +{ + bool test = true; + + if ( isVetoed(P->particleID().pid()) ) { return StatusCode(test); } + + if (msgLevel(MSG::VERBOSE)) verbose() << "FillTracksMomentum " << prefix << endmsg ; + + // Get the fit parameters + const auto params = fitter.fitParams(P) ; + const auto& momentum = params->momentum() ; + + test &= insert( prefix+"_ID", P->particleID().pid(), tMap ); + test &= insert( prefix+"_PX", momentum.Px(), tMap ); + test &= insert( prefix+"_PY", momentum.Py(), tMap ); + test &= insert( prefix+"_PZ", momentum.Pz(), tMap ); + test &= insert( prefix+"_PE", momentum.E() , tMap );//MeV + + return StatusCode(test); +} + +//============================================================================= +// append data to TupleMap +//============================================================================= +StatusCode TupleToolDecayTreeFitter::insert( const std::string& leaf, + const double val, + TupleMap& tMap ) const +{ + auto l = tMap.find(leaf); + if ( l == tMap.end() ) + { /// first time this is seen. Create + std::vector vals; + vals.push_back(val); + tMap.insert( std::make_pair(leaf,vals) ); + } + else + { + l->second.push_back(val); /// append a to vector + } + if (msgLevel(MSG::VERBOSE)) + verbose() << "insert " << leaf << " " << val + << " size " << l->second.size() << endmsg ; + return StatusCode::SUCCESS ; +} + +//============================================================================= +// actual filling of the Tuple +//============================================================================= +StatusCode +TupleToolDecayTreeFitter::fillTuple( TupleMap& tMap, + Tuples::Tuple& tuple, + const std::string& prefix ) +{ + bool test = true ; + + if ( UNLIKELY(m_firstTupleFill) ) + { + // Save the list of keys in the given order for future comparisons + m_firstTupleKeys.clear(); + m_firstTupleKeys.reserve( tMap.size() ); + for ( const auto& i : tMap ) { m_firstTupleKeys.emplace_back(i.first); } + // flag having saved the keys + m_firstTupleFill = false; + } + else + { + // test against the first set of keys + test = checkTupleKeys( tMap ); + } + + // if OK, save and continue + if ( test ) + { + for ( const auto& t : tMap ) + { + const auto& leaf = t.first; + const auto& data = t.second; + if (msgLevel(MSG::DEBUG)) + debug() << "Filling leaf ``" << leaf << "'' with vector of size " + << data.size() << endmsg ; + if ( m_maxPV < data.size() ) + Exception("Seeing data with too many PVs. Have you set MaxPVs?"); + test &= tuple->farray( leaf, data, prefix+"_nPV", m_maxPV); + } + } + + return StatusCode(test); +} + +//============================================================================= +// Sort Tracks +//============================================================================= +std::set +TupleToolDecayTreeFitter::sortedTracks(const LHCb::VertexBase* vb) const +{ + const LHCb::RecVertex* pv = dynamic_cast(vb); + if (!pv) Exception("Failed to cast PV"); + std::set st ; + for ( const auto& t : pv->tracks() ) { st.insert(t); } + return st ; +} + +//============================================================================= +// Compare PVs, check that one PV's tracks is a subset of the other +//============================================================================= +bool TupleToolDecayTreeFitter::samePV( const LHCb::VertexBase* vb1, + const LHCb::VertexBase* vb2 ) const +{ + // exception checking. See bug https://savannah.cern.ch/bugs/?100933 + if ( !vb1 && !vb2 ) + { + Warning("samePV method called with 2 NULL PVs. " + "The answer is obviously true, but you may want to check the meaning of the question.", + StatusCode::SUCCESS,1); + return true ; + } + else if ( !vb1 || !vb2 ) + { + Warning("samePV method called with 1 NULL PV. " + "The answer is obviously false, but you may want to check the meaning of the question.", + StatusCode::SUCCESS,1); + return false ; + } + + if ( !(vb1->isPrimary()) || !(vb2->isPrimary()) ) + { + Warning("Non PV VertexBase is being used as PV", StatusCode::SUCCESS, 1).ignore(); + return false ; + } + + const auto st1 = sortedTracks(vb1); + const auto st2 = sortedTracks(vb2); + + const bool inc = std::includes(st1.begin(),st1.end(),st2.begin(),st2.end()); + if ( msgLevel(MSG::VERBOSE)) + { + verbose() << "PV 2 of size " << st2.size() << " is "; + if (!inc) verbose() << "not "; + verbose() << "included in PV 1 of size " << st1.size() << endmsg ; + } + return inc; +} + +//============================================================================= +// get origin vertex +//============================================================================= +std::vector +TupleToolDecayTreeFitter::originVertex( const Particle* mother, const Particle* P ) const +{ + std::vector oriVx; + if ( mother == P ) + {// the origin vertex is the primary. + const auto bpv = m_dva->bestVertex( P ); + if ( bpv ) + { + oriVx.push_back(bpv); + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "Pushed back bpv " << bpv << " from " + << tesLocation(bpv) << " at " + << bpv->position() << endmsg ; + } + else if ( m_constrainToOriginVertex) + { + Warning( "NULL bestPV while constraining to origin vertex. Fit will be ignored.", + StatusCode::SUCCESS, 0 ).ignore(); + } + // all the other ones + /// @todo : keep only the related ones + for ( const auto & pv : m_dva->primaryVertices() ) + { + if ( m_storeAnyway || !samePV(pv,bpv) ) + { + oriVx.push_back(pv); + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "Pushed back pv " << pv << " from " + << tesLocation(pv) << " at " + << pv->position() << endmsg ; + } + if ( oriVx.size() >= m_maxPV ) + { + Warning("Truncated number of PVs", StatusCode::FAILURE, 0).ignore(); + break ; + } + } + } + else + { + const auto & dau = mother->daughters (); + if ( dau.empty() ) return oriVx ; + + for ( const auto& d : dau ) + { + if ( P == d ) + { + oriVx.push_back(mother->endVertex()); + return oriVx ; + } + } + + // vertex not yet found, get deeper in the decay: + for ( const auto& d : dau ) + { + if ( P != d && !d->isBasicParticle() ) + { + oriVx = originVertex( d, P ); + if( !oriVx.empty() ) + { + return oriVx ; // found + } + } + } + } + return oriVx; +} + +//============================================================================= +// Convert pid number in names +//============================================================================= +std::string TupleToolDecayTreeFitter::getName(const int id) const +{ + const auto * prop = m_ppSvc->find( LHCb::ParticleID(id) ); + if (!prop) Exception("Unknown PID"); + //if (msgLevel(MSG::VERBOSE)) verbose() << "ID " << id << " gets name " + // << Decays::escape(prop->name()) << endmsg ; + return Decays::escape(prop->name()); +} + +//============================================================================= +// Substitute +//============================================================================= +StatusCode TupleToolDecayTreeFitter::substitute(LHCb::DecayTree& tree) +{ + if (msgLevel(MSG::DEBUG)) debug() << "Calling substitute" << endmsg ; + const auto substituted = m_substitute->substitute ( tree.head() ) ; + // debugging + if ( msgLevel(MSG::VERBOSE) || 0 == substituted ) + { + const auto mp = tree.cloneMap(); + for ( const auto & i : mp ) + { + if ( i.first->particleID().pid() == i.second->particleID().pid() ) + { + info() << "A " << getName(i.first->particleID().pid()) << " remains unchanged" << endmsg ; + } + else + { + info() << "A " << getName(i.first->particleID().pid()) << " is substituted by a " + << getName(i.second->particleID().pid()) << endmsg ; + } + } + + } + if ( 0 == substituted ) + { + return Error( "No particles have been substituted. Check your substitution options." ); + } + return StatusCode::SUCCESS ; +} + +//============================================================================= +// Check Mass Constraints +//============================================================================= +StatusCode TupleToolDecayTreeFitter::checkMassConstraints(const LHCb::DecayTree& tree) +{ + if (!m_first) return StatusCode::SUCCESS ; // do that only once + m_first = false ; + const auto mp = tree.cloneMap(); + for ( const auto & m : m_massConstraintsPids ) + { + bool found = false ; + for ( const auto & i : mp ) + { + if ( m.abspid() == i.second->particleID().abspid() ) + { + found = true ; + break ; + } + } + if ( found && msgLevel(MSG::VERBOSE) ) + verbose() << "Constraint " << getName(m.pid()) << " was found in tree" << endmsg ; + if ( !found ) + { + std::ostringstream mess; + mess << "Constraint " << getName(m.pid()) + << " was not found in tree. Check your options. Maybe also the substitution options."; + return Error( mess.str() ) ; + } + } + return StatusCode::SUCCESS ; + +} + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolDecayTreeFitter ) diff --git a/first-analysis-steps/DecayTrees/TupleToolDecayTreeFitter.h b/first-analysis-steps/DecayTrees/TupleToolDecayTreeFitter.h new file mode 100644 index 00000000..9cf255e7 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolDecayTreeFitter.h @@ -0,0 +1,311 @@ +#pragma once + +/**@class TupleToolDecayTreeFitter + * - History : this tool was written during the study of the b->JpsiX lifetimes. It was not very generic. + * This re-implmentation is hopefully more generic, although it requires several instances of the tool + * to achive the same result. + * - Advice : Most of the output of this code could be saved via the LoKi style lines. + + * - Usage : One can plug this Tool in DecayTreeTuple. It is advised to give it to a branch and not to try to run + * it on all the tree. To get full functionality use several instances. + * Always give it an instance name which will be used as prefix. See example. + * - Configuration : + @code + constrainToOriginVertex = False # save a fit to compute the lifetime. + particlesToConstrain = ["J/psi(1S)"] # chose the particles to mass to constrain. + ExtraName = "" # Additional Prefix (will replace instance name) (inherited from TupleToolBase) + Verbose = False # Fill Lifetime for daughters. (inherited from TupleToolBase) + @endcode + * + * - Outputs: for each fit is saved: + - The status, the chi2, the number of degres of freedom of the fit. + - The fitted mass, mass error for example : Lambda_b0_massConAllDaughters_M ... + - The fitted lifetime, and error : Lambda_b0_taufit_ctau (ctau is given in mm). + * + * - Example: + @code + decay = "B0 -> (^J/psi(1S) -> ^mu+ ^mu-) (^KS0 -> ^pi+ ^pi-)" + bh = 'B0' + tuple.Decay = decay + tuple = DecayTreeTuple("MyTuple") + tuple.ToolList += ["TupleToolGeometry", "TupleToolKinematic", "TupleToolPrimaries", "TupleToolEventInfo" ] + tuple.Branches = { "B" : "["+bh+"]cc : "+decay.replace("^","") } + from Configurables import TupleToolDecayTreeFitter + tuple.B.ToolList += [ "TupleToolDecayTreeFitter/Fit", # just a refit + "TupleToolDecayTreeFitter/MassFit", # fit with J/psi mass constraint + "TupleToolDecayTreeFitter/PVFit" ] # fit with all constraints I can think of + + tuple.B.addTool(TupleToolDecayTreeFitter("MassFit")) + tuple.B.MassFit.constrainToOriginVertex = False + tuple.B.MassFit.daughtersToConstrain = [ "J/psi(1S)" ] + + tuple.B.addTool(TupleToolDecayTreeFitter("PVFit")) + tuple.B.PVFit.Verbose = True + tuple.B.PVFit.constrainToOriginVertex = True + tuple.B.PVFit.daughtersToConstrain = [ "J/psi(1S)", "KS0" ] + + # now two that check for reflections + tuple.B.ToolList += ["TupleToolDecayTreeFitter/SubLambda", "TupleToolDecayTreeFitter/SubLambdabar" ] + subDTF = TupleToolDecayTreeFitter("SubLambda", Verbose=True, + daughtersToConstrain = [ "J/psi(1S)" ], + constrainToOriginVertex=True, + Substitutions={ 'Beauty -> Meson (Strange -> ^pi+ pi-)': 'p+' }) + tuple.B.addTool(subDTF) + tuple.B.addTool(subDTF.clone("SubLambdabar",Substitutions={ 'Beauty -> Meson (Strange -> pi+ ^pi-)': 'p-' })) + + @endcode + * + * - This will produce the following columns for the B (from this tool): + * - B_Fit_status B_Fit_nDOF B_Fit_chi2_B B_Fit_nIter B_Fit_M B_Fit_MERR B_Fit_P B_Fit_PERR + * - B_MassFit_status B_MassFit_nDOF B_MassFit_chi2_B B_MassFit_nIter B_MassFit_M B_MassFit_MERR B_MassFit_P + * B_MassFit_PERR B_PVFit_status B_PVFit_nDOF B_PVFit_chi2_B B_PVFit_nIter B_PVFit_M B_PVFit_MERR B_PVFit_P + * - B_PVFit_PERR B_PVFit_ctau B_PVFit_ctauErr B_PVFit_decayLength B_PVFit_decayLengthErr B_PVFit_J_psi_1S_ctau + * B_PVFit_J_psi_1S_ctauErr B_PVFit_J_psi_1S_decayLength B_PVFit_J_psi_1S_decayLengthErr B_PVFit_KS0_ctau + * B_PVFit_KS0_ctauErr B_PVFit_KS0_decayLength B_PVFit_KS0_decayLengthErr + * + * - One can also hange the PID of some particles in the chain, using the same syntax as SubstitutePID + * + * \sa SubstitutePID + * + * \sa DecayTreeTuple + * + * @author Yasmine Amhis, Matt Needham (original authors), Patrick Koppenburg (re-implementation) + * @date 2010-10-30, 2011-04-01 + * + **/ + +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +#include "GaudiKernel/ToolHandle.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "DecayTreeTupleBase/TupleToolBase.h" + +#include "Kernel/IParticleTupleTool.h" +#include "Kernel/ISubstitutePID.h" +#include "Kernel/GetIDVAlgorithm.h" +#include "Kernel/IDVAlgorithm.h" +#include "Kernel/ParticleProperty.h" +#include "Kernel/IParticleDescendants.h" +#include "Kernel/Escape.h" +#include "Kernel/IParticlePropertySvc.h" + +#include "TrackInterfaces/ITrackStateProvider.h" + +#include "DecayTreeFitter/Fitter.h" + +#include "Event/RecVertex.h" +#include "Event/Particle.h" + +#include "LoKi/ParticleProperties.h" + +// boost +#include +#include + +// STL +#include +#include +#include +#include + +struct IParticleDescendants; + +namespace LHCb +{ + class ParticleID; + class IParticlePropertySvc; + class VertexBase; + class Particle; + class RecVertex ; + class DecayTree ; +} +namespace DecayTreeFitter +{ + class Fitter; +} + +struct IDVAlgorithm; +/** @class TupleToolDecayTreeFitter TupleToolDecayTreeFitter.h + * + * Yasmine Amhis and Matt Needham + * 30-10-10 + */ +class TupleToolDecayTreeFitter : public TupleToolBase, virtual public IParticleTupleTool +{ + +private: + + typedef std::map SubstitutionMap ; + typedef std::map< std::string, std::vector > TupleMap ; ///< temporary storage of tuple data + +public: + + /// Standard constructor + TupleToolDecayTreeFitter( const std::string& type, + const std::string& name, + const IInterface* parent); + + ~TupleToolDecayTreeFitter( ) = default; ///< Destructor + + StatusCode initialize() override; + + StatusCode finalize() override; + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + /// Fill inforation for a given origin vertex + StatusCode fit(DecayTreeFitter::Fitter& fitter, + const LHCb::Particle* P, + const LHCb::VertexBase* pv, + const std::string& prefix, + TupleMap& tMap) const; + + /// Fill lifetime information + /// Fill fit inforation for top decay + StatusCode fillDecay(const DecayTreeFitter::Fitter& fitter, + const std::string& prefix, + TupleMap& tMap) const; + + /// Fill lifetime information + StatusCode fillLT(const DecayTreeFitter::Fitter& fitter, + const LHCb::Particle* P, + const std::string& prefix, + TupleMap& tMap) const; + + /// Fill momentum and mass information + StatusCode fillMomentum(const DecayTreeFitter::Fitter& fitter, + const LHCb::Particle* P, + const std::string& prefix, + TupleMap& tMap) const; + + /// Fill PV information + StatusCode fillPV(const LHCb::VertexBase* pv, + const std::string& prefix, + TupleMap& tMap) const; + + /// Fill lifetime information for non stable daughters + StatusCode fillDaughters( const DecayTreeFitter::Fitter& fitter, + const LHCb::Particle* P, + const std::string& prefix, + TupleMap& tMap )const; + + /// Fill lifetime information for non stable daughters + StatusCode fillStableDaughters( const DecayTreeFitter::Fitter& fitter, + const LHCb::Particle* P, + const std::string& prefix, + TupleMap& tMap )const; + + /// Fill updated tracks momentum + StatusCode fillTracksMomentum(const DecayTreeFitter::Fitter& fitter, + const LHCb::Particle* P, + const std::string& prefix, + TupleMap& tMap) const; + + /// actual filling of tuple + StatusCode fillTuple(TupleMap& tMap, + Tuples::Tuple& tuple, + const std::string& prefix ) ; + + /// insert helper method + StatusCode insert( const std::string& leaf, + const double val, + TupleMap& tMap ) const ; + + std::string getName(const int id) const; ///< name of particle + + /// origin vertex + std::vector originVertex( const LHCb::Particle*, + const LHCb::Particle* ) const; + + /// same PV? + bool samePV(const LHCb::VertexBase*, const LHCb::VertexBase*) const ; + + /// sort tracks into a set + std::set sortedTracks(const LHCb::VertexBase*) const ; + + /// substitutions + StatusCode substitute( LHCb::DecayTree& tree); + + /// checkMassConstraints + StatusCode checkMassConstraints(const LHCb::DecayTree& tree); + + /// Get the TES location for a data object + template + inline std::string tesLocation( const TYPE * obj ) const + { + return ( obj && obj->parent() && obj->parent()->registry() ? + obj->parent()->registry()->identifier() : "NotInTES" ); + } + + /// Test if a given PID code is veto'ed + inline bool isVetoed( const int id ) const + { + return ( !m_vetoPIDs.empty() && + std::find( m_vetoPIDs.begin(), m_vetoPIDs.end(), id ) != m_vetoPIDs.end() ); + } + + /// Compare two maps + inline bool checkTupleKeys( const TupleMap& r ) + { + bool OK = true; + if ( UNLIKELY( m_firstTupleKeys.size() != r.size() ) ) + { + Error( "Maps have different sizes" ).ignore(); + OK = false; + } + auto i = m_firstTupleKeys.begin(); + auto j = r.begin(); + for ( ; j != r.end(); ++i, ++j ) + { + // compare key names + if ( UNLIKELY( *i != j->first ) ) + { + std::ostringstream mess; + mess << "Tuple entry error : " << *i << " != " << j->first; + Error( mess.str() ).ignore(); + OK = false; + } + } + return OK; + } + +private: + + std::string m_pvLocation ; ///< PV location to be used. If empty, take context-dependent default + + IDVAlgorithm* m_dva = nullptr; + + std::vector m_massConstraints; + std::vector m_massConstraintsPids; + + bool m_constrainToOriginVertex; ///< Constrain to Origin Vertex for lifetime + + LHCb::IParticlePropertySvc* m_ppSvc = nullptr; + IParticleDescendants* m_particleDescendants = nullptr; + + /// mapping : { 'decay-component' : "new-pid" } (property) + ISubstitutePID::SubstitutionMap m_map ; // mapping : { 'decay-component' : "new-pid" } + /// Substitute Tool + ISubstitutePID* m_substitute = nullptr; + bool m_storeAnyway ;///< Store PV even if a refitted version is already the best PV (i.e store twice) + bool m_updateDaughters; ///< Store updated momenta of tracks in the decay tree + ToolHandle m_stateprovider{ "TrackStateProvider" }; + bool m_first{true} ; ///< This is the first candidate + bool m_firstTupleFill{true}; ///< Flag for the first tuple filling + + std::vector m_firstTupleKeys; ///< cache the keys for the first tuple map + + /// List of PID codes to veto filling for + std::vector m_vetoPIDs; + + /// Use full decay tree in branch names + bool m_useFullTreeInName; + +}; diff --git a/first-analysis-steps/DecayTrees/TupleToolDira.cpp b/first-analysis-steps/DecayTrees/TupleToolDira.cpp new file mode 100755 index 00000000..7cc657b8 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolDira.cpp @@ -0,0 +1,176 @@ +// Include files + +// local +#include "TupleToolDira.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : DiraTupleTool +// +// 2010-09-06 : Fatima Soomro +//----------------------------------------------------------------------------- + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolDira::TupleToolDira( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + +{ + declareInterface(this); +} + +//============================================================================= + +StatusCode TupleToolDira::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_context = Gaudi::Utils::getIDVAlgorithm ( contextSvc(), this ) ; + if ( !m_context ) return Error("Could not get parent DVAlgorithm", + StatusCode::FAILURE); + + return sc; +} + +//============================================================================= + +StatusCode TupleToolDira::fill( const Particle* mother + , const Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + Assert( P && mother && m_context + , "This should not happen, you are inside TupleToolDira.cpp :(" ); + + if ( isPureNeutralCalo(P) ) + return Warning( "Will not fill geometry tuple for calo neutrals. No worry.", + StatusCode::SUCCESS, 10 ); + if ( mother != P || P->isBasicParticle() ) return StatusCode::SUCCESS; + + const VertexBase* motherPV = m_context->bestVertex ( mother ); + if ( !motherPV ) + { + return Warning( "Could not find related PV" ); + } + + return fillDIRAError( motherPV, mother, head, tuple ); +} + +//========================================================================= +// fill vertex stuff +//========================================================================= +StatusCode TupleToolDira::fillDIRAError( const VertexBase* primVtx + ,const Particle* P + , const std::string head + , Tuples::Tuple& tuple ) const +{ + + const VertexBase* evtx = P->endVertex(); + + if( !evtx ) + { + return Error( "Cannot retrieve the end vertex for " + head ); + } + + + double diraerr(0), dira(0); + calculateDIRAError( P ,primVtx , dira, diraerr ); + + bool test = true; + test &= tuple->column( head + "_DiraAngleError", diraerr/(std::sqrt(1-dira*dira))) ; + test &= tuple->column( head + "_DiraCosError", diraerr ); + test &= tuple->column( head + "_DiraAngle", std::acos(dira)) ; + test &= tuple->column( head + "_DiraCos", dira ); + + return StatusCode(test); +} + +//========================================================================= + +void TupleToolDira::calculateDIRAError( const Particle* P, + const VertexBase* primVtx, + double & dira, + double & diraerr ) const +{ + + + const Gaudi::SymMatrix7x7 & covMother = P->covMatrix (); + const Gaudi::SymMatrix3x3 & covPrim= primVtx->covMatrix (); + SymMatrix10x10 Cov; + + for(int i=0; i<7; ++i) + { + for(int j=0; j<7; ++j) + { + Cov(i,j) = covMother(i,j); + } + } + + for(int i=7; i<10; ++i) + { + for(int j=7; j<10; ++j) + { + Cov(i,j) = covPrim(i-7,j-7); + } + } + + for(int i=7; i<10; ++i) + { + for(int j=0; j<7; ++j) + { + Cov(i,j) = 0.0; + Cov(j,i) = 0.0; + } + } + + const Gaudi::XYZVector vectord = P->endVertex()->position() - primVtx->position(); + const Gaudi::XYZVector& vectorp = P->momentum().Vect() ; + + double vecd[3] = { vectord.x(), vectord.y(), vectord.z()}; + double vecp[3] = { vectorp.x(), vectorp.y(), vectorp.z()}; + + const double magd = std::sqrt( vectord.Mag2() ) ; + const double magp = std::sqrt( vectorp.Mag2() ); + + ROOT::Math::SMatrix gradVec; + gradVec(6,0) = 0.0; + + for ( int i = 0; i < 3; ++i ) + { + double gp = vecd[i]*magp*magp; + double gd = vecp[i]*magd*magd; + + for ( int j = 0; j < 3; ++j ) + { + gp -= vecd[j]*vecp[j]*vecp[i]; + gd -= vecp[j]*vecd[j]*vecd[i]; + } + gradVec(i+3,0) = gp/(magd*magp*magp*magp); + gradVec(i,0) = gd/(magp*magd*magd*magd); + gradVec(i+7,0) = -gd/(magp*magd*magd*magd); + } + + const Gaudi::SymMatrix1x1 diraErrSq = + ROOT::Math::SimilarityT(gradVec, Cov); + + diraerr = std::sqrt(diraErrSq(0,0)); + + dira = (vectord.Dot(vectorp))/ (magp*magd); + + return; +} + +//========================================================================= + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolDira ) + +//========================================================================= diff --git a/first-analysis-steps/DecayTrees/TupleToolDira.h b/first-analysis-steps/DecayTrees/TupleToolDira.h new file mode 100755 index 00000000..0fbfb546 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolDira.h @@ -0,0 +1,53 @@ +#ifndef FSOOMRO_TUPLETOOLDIRA_H +#define FSOOMRO_TUPLETOOLDIRA_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "Math/SMatrix.h" + +#include +#include +#include + +#include "Event/Vertex.h" +#include "Event/RecVertex.h" +#include "Event/Particle.h" + +class TupleToolDira : public TupleToolBase, + virtual public IParticleTupleTool +{ + +private: + + typedef ROOT::Math::SMatrix > SymMatrix10x10; + +public: + + /// Standard constructor + TupleToolDira( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolDira( ){}; ///< Destructor + + StatusCode initialize() override; + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + StatusCode fillDIRAError( const LHCb::VertexBase* primVtx ,const LHCb::Particle* P , + const std::string head, Tuples::Tuple& tuple ) const ; + void calculateDIRAError( const LHCb::Particle*, const LHCb::VertexBase*, double&, double&) const ; + + // IContextTool* m_context; + IDVAlgorithm* m_context; + +}; + +#endif // FSOOMRO_TUPLETOOLDIRA_H diff --git a/first-analysis-steps/DecayTrees/TupleToolEventInfo.cpp b/first-analysis-steps/DecayTrees/TupleToolEventInfo.cpp new file mode 100755 index 00000000..70bb3b01 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolEventInfo.cpp @@ -0,0 +1,143 @@ +// Include files + +#include "Kernel/ILHCbMagnetSvc.h" + +// local +#include "TupleToolEventInfo.h" + +#include "Event/ODIN.h" // event & run number +#include "Event/L0DUReport.h" +#include "Event/HltDecReports.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/ITupleTool.h" +#include "Event/RecVertex.h" +#include "Event/VertexBase.h" +#include "Event/Track.h" + +#include "GaudiKernel/IRegistry.h" // IOpaqueAddress + +//----------------------------------------------------------------------------- +// Implementation file for class : EventInfoTupleTool +// +// 2007-11-07 : Jeremie Borel +//----------------------------------------------------------------------------- + +using namespace Gaudi; +using namespace LHCb; + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolEventInfo ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolEventInfo::TupleToolEventInfo( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); + declareProperty("InputLocation", + m_pvLocation = LHCb::RecVertexLocation::Primary, + "PV location to be used. If empty, take default"); + declareProperty("Mu", m_mu); +} + +//============================================================================= + +StatusCode TupleToolEventInfo::initialize( ) +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + m_magSvc = svc( "MagneticFieldSvc", true ); + return sc; +} + +//============================================================================= +StatusCode TupleToolEventInfo::fill( Tuples::Tuple& tuple ) +{ + const std::string prefix = fullName(); + + // Load the ODIN + const LHCb::ODIN* odin = getIfExists(evtSvc(),LHCb::ODINLocation::Default); + if ( !odin ) { odin = getIfExists(evtSvc(),LHCb::ODINLocation::Default,false); } + if ( !odin ) + { + // should always be available ... + return Error( "Cannot load the ODIN data object", StatusCode::SUCCESS ); + } + + LHCb::L0DUReport* report = + getIfExists(evtSvc(),LHCb::L0DUReportLocation::Default); + if ( !report ) + { + report = + getIfExists(evtSvc(),LHCb::L0DUReportLocation::Default,false); + } + if ( !report ) + { + Warning( "Can't get LHCb::L0DUReportLocation::Default (" + + LHCb::L0DUReportLocation::Default + ")" ).ignore(); + } + + LHCb::HltDecReports* decreport_hlt1 = + getIfExists(evtSvc(),LHCb::HltDecReportsLocation::Hlt1Default); + if ( !decreport_hlt1 ) + { + decreport_hlt1 = + getIfExists(evtSvc(),LHCb::HltDecReportsLocation::Hlt1Default,false); + } + if ( !decreport_hlt1 ) + { + Warning( "Can't get LHCb::HltDecReportsLocation::DefaultHlt1 (" + + LHCb::HltDecReportsLocation::Hlt1Default + ")" ).ignore(); + } + + LHCb::HltDecReports* decreport_hlt2 = + getIfExists(evtSvc(),LHCb::HltDecReportsLocation::Hlt2Default); + if ( !decreport_hlt2 ) + { + decreport_hlt2 = + getIfExists(evtSvc(),LHCb::HltDecReportsLocation::Hlt2Default,false); + } + + if ( !decreport_hlt2 ) + { + Warning( "Can't get LHCb::HltDecReportsLocation::DefaultHlt2 (" + + LHCb::HltDecReportsLocation::Hlt2Default + ")" ).ignore(); + } + + bool test = true; + + // Fill the tuple + + if (!m_mu.empty()) test &= tuple->column( prefix+"Mu", m_mu[odin->runNumber()] ); + + test &= tuple->column( prefix+"runNumber", odin->runNumber() ); + test &= tuple->column( prefix+"eventNumber", odin->eventNumber() ); + test &= tuple->column( prefix+"BCID", odin->bunchId() ); + test &= tuple->column( prefix+"BCType", odin->bunchCrossingType() ); + test &= tuple->column( prefix+"OdinTCK", odin->triggerConfigurationKey() ); + test &= tuple->column( prefix+"L0DUTCK", report ? report->tck() : 0 ); + test &= tuple->column( prefix+"HLT1TCK", decreport_hlt1 ? decreport_hlt1->configuredTCK() : 0 ); + test &= tuple->column( prefix+"HLT2TCK", decreport_hlt2 ? decreport_hlt2->configuredTCK() : 0 ); + test &= tuple->column( prefix+"GpsTime", odin->gpsTime() ); + + if ( isVerbose() ) + { + const Gaudi::Time gtime = odin->eventTime(); + test &= tuple->column( prefix+"GpsYear", gtime.year(false) ); + test &= tuple->column( prefix+"GpsMonth", gtime.month(false) ); + test &= tuple->column( prefix+"GpsDay", gtime.day(false) ); + test &= tuple->column( prefix+"GpsHour", gtime.hour(false) ); + test &= tuple->column( prefix+"GpsMinute", gtime.minute(false) ); + test &= tuple->column( prefix+"GpsSecond", gtime.second(false) + (gtime.nsecond()/1e9) ); + test &= tuple->column( prefix+"TriggerType", odin->triggerType() ); + } + + test &= tuple->column( prefix+"Polarity", (short)(m_magSvc->isDown()?-1:1) ); + + if( msgLevel( MSG::VERBOSE ) ) verbose() << "Returns " << test << endmsg; + return StatusCode(test); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolEventInfo.h b/first-analysis-steps/DecayTrees/TupleToolEventInfo.h new file mode 100755 index 00000000..f1ed5391 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolEventInfo.h @@ -0,0 +1,55 @@ +// $Id: TupleToolEventInfo.h,v 1.5 2010-06-02 12:01:44 pkoppenb Exp $ +#ifndef JBOREL_TUPLETOOLEVENTINFO_H +#define JBOREL_TUPLETOOLEVENTINFO_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface + +class ITupleTool; +struct ILHCbMagnetSvc; + +/** @class TupleToolEventInfo TupleToolEventInfo.h jborel/TupleToolEventInfo.h + * + * \brief Event and Run number for DecayTreeTuple + * + * Tuple columns: + * - runNumber: well, the run number + * - eventNumber: + * - BCID and BC type + * - Odin, L0 and Hlt TCKs + * - GPS time + * - If the property Mu is given it will fill the Mu of the run. A working dictionary + * can be found at https://twiki.cern.ch/twiki/bin/view/LHCb/NuMuPileUp + * - if Verbose is on, also gps time in year,month,day,hour,min,second + * Note that months are numbered [0-11]. That's a convention. Sorry. + * + * \sa DecayTreeTuple + * @author Jeremie Borel + * @date 2007-11-07 + */ +class TupleToolEventInfo : public TupleToolBase, + virtual public IEventTupleTool +{ + +public: + + /// Standard constructor + TupleToolEventInfo( const std::string& type, + const std::string& name, + const IInterface* parent); + + ~TupleToolEventInfo( ){}; ///< Destructor + + StatusCode initialize() override; + StatusCode fill( Tuples::Tuple& ) override; + +private : + + std::string m_pvLocation ; + std::map m_mu ; + ILHCbMagnetSvc* m_magSvc ; + +}; +#endif // JBOREL_TUPLETOOLEVENTINFO_H diff --git a/first-analysis-steps/DecayTrees/TupleToolFillingScheme.cpp b/first-analysis-steps/DecayTrees/TupleToolFillingScheme.cpp new file mode 100644 index 00000000..c2f74faf --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolFillingScheme.cpp @@ -0,0 +1,221 @@ +// from Gaudi +#include "GaudiAlg/GaudiAlgorithm.h" +// local +#include "TupleToolFillingScheme.h" +#include "Event/ODIN.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolFillingScheme +// +// 2015-08-15 : Albert Bursche +// 2018-04-23 : Bartek Rachwal +//----------------------------------------------------------------------------- + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolFillingScheme::TupleToolFillingScheme( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name, parent ) + ,m_lhc("Conditions/Online/LHC") + ,m_lhcFS("Conditions/Online/LHCb/LHCFillingScheme") +{ + declareInterface(this); + declareProperty( "BXOffset" , m_BXOffset = 0 ); + } + +//============================================================================= +StatusCode TupleToolFillingScheme::initialize() { + StatusCode sc = TupleToolBase::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error printed already by GaudiAlgorithm + m_condFilling = new Condition(); + if (this->existDet(m_lhcFS)) + registerCondition(m_lhcFS, m_condFilling, &TupleToolFillingScheme::i_cacheFillingData); + else + warning() << "Could not find Filling Scheme in DB!" << endmsg; + + // Check if the LHC information is available in the conditions database. + m_condLHC = new Condition(); + if (this->existDet(m_lhc)) { + registerCondition(m_lhc, m_condLHC, &TupleToolFillingScheme::cacheFill); + // First update. + sc = updMgrSvc()->update(this); + if (sc.isFailure()) return Error("Cannot retrieve fill number.", sc); + + } else { + warning() << "Cannot find " << m_lhc << " in database" << endmsg; + } + + return StatusCode::SUCCESS; +} + +//============================================================================= +// Destructor +//============================================================================= +TupleToolFillingScheme::~TupleToolFillingScheme() {} + +//============================================================================= +StatusCode TupleToolFillingScheme::fill( Tuples::Tuple& tup ) +{ + const std::string prefix = fullName(); + bool test = true; + //Get bunch crossing ID from ODIN + LHCb::ODIN* odin = getIfExists(LHCb::ODINLocation::Default); + + // should remain flagged as an error and stop the run + if(!odin) + return Error("ODIN cannot be loaded", StatusCode::FAILURE); + + long bxid = odin->bunchId(); + int m_type = odin->bunchCrossingType(); + + if ( msgLevel(MSG::DEBUG) ) + debug() << "ODIN BCID: " << bxid << endmsg; + + test &= tup->column( prefix+"fill", m_fillNumber); + + //logic from FilterFillingScheme::processDB + const int max_buckets = m_B1FillingScheme.size(); + assert(static_cast(max_buckets) == m_B2FillingScheme.size()); + if ( msgLevel(MSG::DEBUG) ) + debug() << "max_buckets: " << max_buckets << endmsg; + if (max_buckets){ + + // ODIN starts counting at 1 - so we have to subtract 1 always to index into the string + unsigned int index = (m_BXOffset + bxid + max_buckets - 1) % max_buckets; + unsigned int indexPrev1 = (index - 1 ) % max_buckets; + unsigned int indexPrev2 = (index - 2 ) % max_buckets; + unsigned int indexNext1 = (index + 1 ) % max_buckets; + unsigned int indexNext2 = (index + 2 ) % max_buckets; + + int firstBB, firstEE, firstBE, firstEB; + int lastBB, lastEE, lastBE, lastEB; + + lastBB = lastBE = lastEB = lastEE = firstEE = firstBB = firstBE = firstEB = -1; + bool isBeamBeam = (m_B1FillingScheme[index] == '1') && (m_B2FillingScheme[index] == '1'); + for(int i=1; ( lastBB==-1||lastBE==-1||lastEB==-1||firstBB==-1||firstEE==-1||lastEE==-1||firstBE==-1||firstEB==-1 ) && icolumn( prefix+"CrossingsAfterToEE" ,(int)firstEE ); + test &= tup->column( prefix+"CrossingsAfterToBB" ,(int)firstBB ); + test &= tup->column( prefix+"CrossingsAfterToBE" ,(int)firstBE ); + test &= tup->column( prefix+"CrossingsAfterToEB" ,(int)firstEB ); + test &= tup->column( prefix+"CrossingsBeforeToEE" ,(int)lastEE ); + test &= tup->column( prefix+"CrossingsBeforeToBB" ,(int)lastBB ); + test &= tup->column( prefix+"CrossingsBeforeToBE",(int)lastBE ); + test &= tup->column( prefix+"CrossingsBeforeToEB",(int)lastEB ); + test &= tup->column( prefix+"IsBeamBeam", isBeamBeam); + test &= tup->column( prefix+"Prev1" , tmptypePrev1 ); + test &= tup->column( prefix+"Prev2" , tmptypePrev2 ); + test &= tup->column( prefix+"Next1" , tmptypeNext1 ); + test &= tup->column( prefix+"Next2" , tmptypeNext2 ); + int isSpillOver = 0; + int isEmpty = 0; + int isPreSpill = 0; + if( m_type == 0 && tmptypePrev1 == 3 && tmptypeNext1 == 0 && tmptypeNext2 == 0 ) isSpillOver = 1; + if( m_type == 0 && tmptypePrev2 == 0 && tmptypePrev1 == 0 && tmptypeNext1 == 0 && tmptypeNext2 == 0 ) isEmpty = 1; + if( m_type == 0 && tmptypePrev2 == 0 && tmptypePrev1 == 0 && tmptypeNext1 == 3 ) isPreSpill = 1; + test &= tup->column( prefix+"isSpillOver",isSpillOver); + test &= tup->column( prefix+"isEmpty",isEmpty); + test &= tup->column( prefix+"isPreSpill",isPreSpill); + } + else + { + test &= tup->column( prefix+"CrossingsAfterToEE" ,(int) -1); + test &= tup->column( prefix+"CrossingsAfterToEB" ,(int) -1); + test &= tup->column( prefix+"CrossingsAfterToBE" ,(int) -1); + test &= tup->column( prefix+"CrossingsAfterToBB" ,(int) -1); + test &= tup->column( prefix+"CrossingsBeforeToEE" ,(int) -1); + test &= tup->column( prefix+"CrossingsBeforeToBB" ,(int) -1); + test &= tup->column( prefix+"CrossingsBeforeToBE" ,(int) -1); + test &= tup->column( prefix+"CrossingsBeforeToEB" ,(int) -1); + test &= tup->column( prefix+"IsBeamBeam", false); + test &= tup->column( prefix+"Prev1" , -1. ); + test &= tup->column( prefix+"Prev2" , -1. ); + test &= tup->column( prefix+"Next1" , -1. ); + test &= tup->column( prefix+"Next2" , -1. ); + test &= tup->column( prefix+"isSpillOver", -1.); + test &= tup->column( prefix+"isEmpty", -1.); + test &= tup->column( prefix+"isPreSpill", -1.); + } + + + return StatusCode(test); +} + +//========================================================================= +// Extract data from Filling scheme +//========================================================================= +StatusCode TupleToolFillingScheme::i_cacheFillingData() { + // data from /Conditions/Online/LHCb/LHCFillingScheme + //if ( msgLevel(MSG::DEBUG) ) debug() << "callback Filling:" << endmsg; + m_B1FillingScheme = (std::string) m_condFilling->param("B1FillingScheme"); + m_B2FillingScheme = (std::string) m_condFilling->param("B2FillingScheme"); + if ( msgLevel(MSG::DEBUG) ) + debug() << "B1FillingScheme: " << m_B1FillingScheme + << "\nB2FillingScheme: " << m_B2FillingScheme << endmsg; + + return StatusCode::SUCCESS; +} + +//============================================================================= +// Call-back function for retrieving fill number from conditions database. +//============================================================================= +StatusCode TupleToolFillingScheme::cacheFill(){ + m_fillNumber = m_condLHC->param("FillNumber"); + return StatusCode::SUCCESS; +} + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolFillingScheme ) diff --git a/first-analysis-steps/DecayTrees/TupleToolFillingScheme.h b/first-analysis-steps/DecayTrees/TupleToolFillingScheme.h new file mode 100644 index 00000000..b56b380c --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolFillingScheme.h @@ -0,0 +1,50 @@ +#ifndef TUPLETOOLFILLINGSCHEME_H +#define TUPLETOOLFILLINGSCHEME_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface + +#include "Event/Track.h" + +// CondDB +#include "DetDesc/Condition.h" +#include "GaudiKernel/IDetDataSvc.h" + + +/** @class TupleToolFillingScheme TupleToolFillingScheme.h + * + * Fills LHC filling scheme info + * + * @author Albert Bursche, Bartlomiej Rachwal + * @date 2015-08-15 + */ +class TupleToolFillingScheme : public TupleToolBase, + virtual public IEventTupleTool +{ + +public: + /// Standard constructor + TupleToolFillingScheme( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolFillingScheme( ); ///< Destructor + StatusCode fill( Tuples::Tuple& ) override;///< Fill tuple + StatusCode initialize() override; + +private: + Condition * m_condFilling = nullptr; + Condition * m_condLHC = nullptr; + StatusCode cacheFill(); + StatusCode i_cacheFillingData(); + std::string m_lhc; + std::string m_lhcFS; + std::string m_B1FillingScheme; + std::string m_B2FillingScheme; + int m_BXOffset; + int m_fillNumber = 0; +}; + +#endif // TUPLETOOLFILLINGSCHEME_H diff --git a/first-analysis-steps/DecayTrees/TupleToolGeneration.cpp b/first-analysis-steps/DecayTrees/TupleToolGeneration.cpp new file mode 100755 index 00000000..fa70cce2 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolGeneration.cpp @@ -0,0 +1,108 @@ +// Include files + +// local +#include "TupleToolGeneration.h" + +#include "Event/GenHeader.h" +#include "Kernel/ParticleID.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/ITupleTool.h" + +#include "GaudiKernel/IRegistry.h" // IOpaqueAddress + +//----------------------------------------------------------------------------- +// Implementation file for class : GenerationTupleTool +// +// 2008-07-01 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolGeneration::TupleToolGeneration( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); +} + +//============================================================================= + +StatusCode TupleToolGeneration::fill( Tuples::Tuple& tuple ) +{ + + const std::string prefix = fullName(); + + if (msgLevel(MSG::DEBUG)) debug() << "TupleToolGeneration" << endmsg ; + + LHCb::GenHeader * mch = getIfExists(LHCb::GenHeaderLocation::Default); + if ( !mch ) + { + return Warning("NoGenHeader. You probably don't need this tool.", StatusCode::SUCCESS, 1); + } + if (msgLevel(MSG::DEBUG)) debug() << mch->numOfCollisions() << " collisions" << endmsg ; + + std::vector heaviestQuark ; + std::vector processType ; + unsigned int hqEvent = 0 ; + + // quarks + processType.reserve( mch->collisions().size() ); + for ( SmartRefVector::const_iterator ic = mch->collisions().begin(); + ic != mch->collisions().end(); ++ic ) + { + if ( 0 == *ic ) { Exception("NULL LHCb::GenCollision pointer"); } + const LHCb::HepMCEvent * gene = (*ic)->event() ; + if ( !gene ) + { + Warning("NULL LHCb::HepMCEvent pointer -> This tool cannot work on this MC data", + StatusCode::SUCCESS).ignore(); + continue; + } + + processType.push_back( (*ic)->processType() ); + unsigned int hq = 2 ; + for ( HepMC::GenEvent::particle_const_iterator p = gene->pGenEvt()->particles_begin(); + p != gene->pGenEvt()->particles_end(); ++p ) + { + const LHCb::ParticleID pid( (*p)->pdg_id() ) ; + if (msgLevel(MSG::VERBOSE)) verbose() << "Gen particle " << (*p)->pdg_id() << " " + << pid.hasQuark(LHCb::ParticleID::bottom) + << " " << pid.hasQuark(LHCb::ParticleID::charm) + << endmsg ; + if ( (hq hqEvent ) hqEvent = hq ; + if (msgLevel(MSG::VERBOSE)) + verbose() << "Process type is " << (*ic)->processType() << ". Heaviest quark " << hq + << endmsg ; + } + + bool test = true; + test &= tuple->farray( prefix+"ProcessType" , processType , prefix+"Collisions" , 20 ); + test &= tuple->farray( prefix+"HeaviestQuark", heaviestQuark, prefix+"Collisions" , 20 ); + test &= tuple->column( prefix+"HeaviestQuarkInEvent" , hqEvent ); + + return StatusCode(test); +} + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolGeneration ) diff --git a/first-analysis-steps/DecayTrees/TupleToolGeneration.h b/first-analysis-steps/DecayTrees/TupleToolGeneration.h new file mode 100755 index 00000000..ce90437b --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolGeneration.h @@ -0,0 +1,44 @@ +// $Id: TupleToolGeneration.h,v 1.3 2010-01-26 15:39:26 rlambert Exp $ +#ifndef JBOREL_TUPLETOOLGENERATION_H +#define JBOREL_TUPLETOOLGENERATION_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface + +class ITupleTool; + +/** @class TupleToolGeneration TupleToolGeneration.h jborel/TupleToolGeneration.h + * + * \brief b quark content and number of pp interactions for DecayTreeTuple + * + * Tuple columns: + * - Collisions + * - HeaviestQuark in collision + * - ProcessType in collision + * - HeaviestQuarkInEvent + * + * Only data that can be extracted without accessing Sm/MCParticles to be added here + * + * \sa DecayTreeTuple + * @author P. Koppenburg + * @date 2008-07-01 + */ +class TupleToolGeneration : public TupleToolBase, + virtual public IEventTupleTool +{ + +public: + + /// Standard constructor + TupleToolGeneration( const std::string& type, + const std::string& name, + const IInterface* parent); + + ~TupleToolGeneration( ){}; ///< Destructor + + StatusCode fill( Tuples::Tuple& ) override; + +}; +#endif // JBOREL_TUPLETOOLGENERATION_H diff --git a/first-analysis-steps/DecayTrees/TupleToolGeometry.cpp b/first-analysis-steps/DecayTrees/TupleToolGeometry.cpp new file mode 100755 index 00000000..3b795c0f --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolGeometry.cpp @@ -0,0 +1,503 @@ +// $Id: TupleToolGeometry.cpp,v 1.17 2010-05-12 20:01:40 jpalac Exp $ +// Include files + +// local +#include "TupleToolGeometry.h" + +#include "Kernel/IDVAlgorithm.h" +#include +#include +#include "Kernel/IPVReFitter.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : GeometryTupleTool +// +// 2007-11-07 : Jeremie Borel +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolGeometry ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolGeometry::TupleToolGeometry( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); + declareProperty("RefitPVs",m_refitPVs=false, + "Refit PVs when doing next best PV checks"); + declareProperty("PVReFitter", m_pvReFitterName = "LoKi::PVReFitter:PUBLIC", + "PV refitter algorithm name (':PUBLIC' at end of algo name makes sure a public instance is used)" ); + declareProperty("FillMultiPV",m_fillMultiPV=false, + "Fill Multi PV arrays"); + + //declareProperty("FillMother",m_fillMother=true, + // "Turn false if the mother is expected to be NULL, will not fill mother PV info"); + // replaced by Verbose + + //setProperty( "OutputLevel", 1 ); + +} + +//============================================================================= + +StatusCode TupleToolGeometry::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_dva = Gaudi::Utils::getIDVAlgorithm ( contextSvc(), this ) ; + if (!m_dva) return Error("Couldn't get parent DVAlgorithm"); + + m_dist = m_dva->distanceCalculator(); + if ( !m_dist ) + { + return Error("Unable to retrieve the IDistanceCalculator tool"); + } + + m_pvReFitter = tool( m_pvReFitterName, this ); + if ( !m_pvReFitter ) + { + return Error( "Unable to retrieve IPVReFitter instance" ); + } + + return sc; +} + +//============================================================================= +StatusCode TupleToolGeometry::fill( const Particle* mother + , const Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const auto prefix = fullName(head); + + StatusCode sc = StatusCode::SUCCESS; + + Assert( P && m_dist && m_dva + , "No mother or particle, or tools misconfigured." ); + + if ( isPureNeutralCalo(P) ) + return Warning( "Will not fill geometry tuple for neutral Calo particles. No worry", + StatusCode::SUCCESS, 10); + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolGeometry::fill " << mother << " " << P << " " << prefix + << endmsg ; + + //fill min IP + if ( isVerbose() || m_fillMultiPV ) + { + sc = fillMinIP(P,prefix,tuple); + if ( sc.isFailure() ) + { + return Warning("Could not fill minimum IP", StatusCode::FAILURE, 1); + } + } + //========================================================================= + //fill end vertex info + //========================================================================= + if( P->isBasicParticle() ) + { + if (msgLevel(MSG::VERBOSE)) + verbose() << "No need to look for endVertex of " << prefix << endmsg ; + } + else + { + //========================================================================= + if ( msgLevel(MSG::VERBOSE) && P->endVertex() ) + { // https://savannah.cern.ch/bugs/?92524 + verbose() << "Before cast : " << P->endVertex() << endmsg ; + verbose() << "Container " << P->endVertex()->parent()->registry()->identifier() + << " key " << P->endVertex()->key() << endmsg ; + } + + const auto evtx = P->endVertex(); + if ( !evtx ) + { + fatal() << "Can't retrieve the end vertex for " << prefix + << ". TupleToolGeometry cannot act on such a particle. Define a branch" << endmsg ; + fatal() << "See https://twiki.cern.ch/twiki/bin/view/LHCb/DaVinciTutorial7#Branches" << endmsg ; + return StatusCode::FAILURE ; + } + + if ( msgLevel(MSG::VERBOSE) ) + { // https://savannah.cern.ch/bugs/?92524 + verbose() << "End Vertex : " << *evtx << endmsg ; + verbose() << "Container " << evtx->parent()->registry()->identifier() + << " key " << evtx->key() << endmsg ; + } + // end vertex + sc = fillVertex(evtx,prefix+"_ENDVERTEX",tuple); + if ( sc.isFailure() ) + { + return Warning("Could not fill Endvertex "+prefix, sc, 1); + } + } + + const VertexBase* aPV = nullptr; + + //========================================================================= + // fill IP for Particles's Own BPV.. if it isn't the mother! + //========================================================================= + if ( true ) + { + aPV = m_dva->bestVertex ( P ); + if ( aPV && msgLevel(MSG::VERBOSE) ) + verbose() << "Got best PV of particle : " << *aPV << endmsg ; + sc = fillVertexFull(aPV,P,prefix,"_OWNPV",tuple); + if ( sc.isFailure() ) + { + return Warning("Could not fill best PV", sc, 1); + } + } + //========================================================================= + // fill IP for head of chain's own BPV + //========================================================================= + if ( mother && isVerbose() ) + { + aPV = m_dva->bestVertex ( mother ); + if ( aPV && msgLevel(MSG::VERBOSE)) + verbose() << "Got best PV of mother : " << *aPV << endmsg ; + sc = fillVertexFull(aPV,P,prefix,"_TOPPV",tuple); + if ( sc.isFailure() ) + { + return Warning("Could not fill TOP PV", sc, 1); + } + } + //========================================================================= + // fill IP wrt Mother's decay vertex, if it isn't the mother! + //========================================================================= + if ( mother && mother != P) + { + aPV = originVertex( mother, P ); + if(aPV && msgLevel(MSG::VERBOSE)) + verbose() << "Got originVertex of mother : " << *aPV << endmsg ; + if ( isVerbose() ) + { + sc = fillVertexFull(aPV,P,prefix,"_ORIVX",tuple); + if ( sc.isFailure() ) + { + return Warning("Could not fill VertexFull "+prefix, sc, 1); + } + } + else + { + sc = fillVertex(aPV,prefix+"_ORIVX",tuple); + if ( sc.isFailure() ) + { + return Warning("Could not fill ORIVX", sc, 1); + } + if( !P->isBasicParticle() ) sc = fillFlight(aPV,P,prefix,tuple,"_ORIVX"); + if ( sc.isFailure() ) + { + return Warning("Could not fill Flight", sc, 1); + } + + } + + if ( sc.isFailure() ) return sc; + } + //========================================================================= + + return sc ; +} + +//========================================================================= +// Fill Everything for this vertex for related PV +//========================================================================= +StatusCode TupleToolGeometry::fillVertexFull(const LHCb::VertexBase* vtx, + const LHCb::Particle* P, + const std::string& prefix, + const std::string& vtx_name, + Tuples::Tuple& tuple) const +{ + if ( !vtx ) ++counter("Can't retrieve the " +vtx_name+ " vertex for " + prefix ); + auto sc = fillVertex(vtx,prefix+vtx_name,tuple); + if ( sc.isFailure() ) + { + return Warning("Could not fill Endvertex "+prefix, sc, 1); + } + sc = fillBPV(vtx,P,prefix,tuple,vtx_name); + if ( sc.isFailure() ) + { + return Warning("Could not fillBPV "+prefix, sc, 1); + } + if( !P->isBasicParticle() ) + { + sc = fillFlight(vtx,P,prefix,tuple,vtx_name); + if ( sc.isFailure() ) Warning("Error in fillFlight "+prefix, StatusCode::SUCCESS, 1).ignore(); + } + return sc; +} + +//========================================================================= +// Fill PV for related PV +//========================================================================= +StatusCode TupleToolGeometry::fillBPV( const VertexBase* primVtx + , const Particle* P + , const std::string& prefix + , Tuples::Tuple& tuple + , const std::string& trail) const { + bool test = true ; + + double ip{-999}, chi2{-999}; + + if ( !primVtx ) + { + ++counter("No BPV for "+prefix); + } + else + { + test &= m_dist->distance ( P, primVtx, ip, chi2 ); + if ( !test ) { ip = chi2 = -1; } + } + + test &= tuple->column( prefix + "_IP"+trail, ip ); + test &= tuple->column( prefix + "_IPCHI2"+trail, chi2 ); + + if (!test) Warning("Error in fillBPV "+prefix, StatusCode::SUCCESS, 1).ignore(); + return StatusCode(test) ; +} +//========================================================================= +// Fill PV for all PV +//========================================================================= +StatusCode TupleToolGeometry::fillMinIP( const Particle* P, + const std::string& prefix, + Tuples::Tuple& tuple ) const +{ + bool test = true ; + // minimum IP + double ipmin = -1; + double minchi2 = -1 ; + + double ipminnextbest = -1; + double minchi2nextbest = -1; + + if(msgLevel(MSG::VERBOSE)) verbose() << "Looking for Min IP" << endmsg ; + const auto PVS = m_dva->primaryVertices(); + if(msgLevel(MSG::VERBOSE)) verbose() << "PV size: " << PVS.size() << endmsg ; + + std::vector ips, ipchi2s, diras; + if ( !PVS.empty() ) + { + if(msgLevel(MSG::VERBOSE)) verbose() << "Filling IP " << prefix + "_MINIP : " + << P << " PVs:" << PVS.size() << endmsg ; + + for ( const auto& pv : PVS ) + { + RecVertex newPV(*pv); + if (m_refitPVs) + { + + StatusCode scfit = m_pvReFitter->remove(P, &newPV); + if(!scfit) { Warning("ReFitter fails!",StatusCode::SUCCESS,10).ignore(); continue; } + } + + double ip{0}, chi2{0}; + //StatusCode test2 = m_dist->distance ( P, *pv, ip, chi2 ); + + auto newPVPtr = (LHCb::VertexBase*)&newPV; + const auto test2 = m_dist->distance ( P, newPVPtr, ip, chi2 ); + ips.push_back(ip); + ipchi2s.push_back(chi2); + if ( P->endVertex()) { diras.push_back(dira(newPVPtr,P)); } + if ( test2 && isVerbose() ) + { + if ( ipcolumn( prefix + "_MINIP", ipmin ); + test &= tuple->column( prefix + "_MINIPCHI2", minchi2 ); + + test &= tuple->column( prefix + "_MINIPNEXTBEST", ipminnextbest ); + test &= tuple->column( prefix + "_MINIPCHI2NEXTBEST", minchi2nextbest ); + } + if (m_fillMultiPV) + { + test &= tuple->farray( prefix + "_AllIP", ips, "nPV", m_maxPV ); + test &= tuple->farray( prefix + "_AllIPchi2", ipchi2s, "nPV", m_maxPV ); + if (!diras.empty()) test &= tuple->farray( prefix + "_AllDIRA", diras, "nPV", m_maxPV ); + // -------------------------------------------------- + } + + if(msgLevel(MSG::VERBOSE)) + verbose() << "Return from fillMinIP: " << prefix << " " << test << endmsg; + if (!test) Warning("Error in fillMinIP", StatusCode::FAILURE, 1); + return StatusCode(test) ; +} +//========================================================================= +// fill vertex stuff +//========================================================================= +StatusCode TupleToolGeometry::fillVertex( const LHCb::VertexBase* vtx, + const std::string& vtx_name, + Tuples::Tuple& tuple ) const +{ + bool test = true ; + + // decay vertex information: + if ( !vtx ) + { + Gaudi::XYZPoint pt(-999.,-999.,-999.) ; // arbitrary point + test &= tuple->column( vtx_name+"_", pt ); + test &= tuple->column( vtx_name + "_XERR", -999. ); + test &= tuple->column( vtx_name + "_YERR", -999. ); + test &= tuple->column( vtx_name + "_ZERR", -999. ); + test &= tuple->column( vtx_name + "_CHI2", -999. ); + test &= tuple->column( vtx_name + "_NDOF", -1 ); + test &= tuple->matrix( vtx_name + "_COV_", Gaudi::SymMatrix3x3() ); + } + else + { + const auto & m = vtx->covMatrix (); + test &= tuple->column( vtx_name+"_", vtx->position() ); + test &= tuple->column( vtx_name + "_XERR", std::sqrt( m(0,0) ) ); + test &= tuple->column( vtx_name + "_YERR", std::sqrt( m(1,1) ) ); + test &= tuple->column( vtx_name + "_ZERR", std::sqrt( m(2,2) ) ); + test &= tuple->column( vtx_name + "_CHI2", vtx->chi2() ); + test &= tuple->column( vtx_name + "_NDOF", vtx->nDoF() ); + test &= tuple->matrix( vtx_name + "_COV_", m ); + } + + // -------------------------------------------------- + if (!test) Warning("Error in fillVertex "+vtx_name, StatusCode::SUCCESS, 1).ignore(); + return StatusCode(test) ; + +} +//========================================================================= +// fill flight distance, angle... +//========================================================================= +StatusCode TupleToolGeometry::fillFlight( const VertexBase* oriVtx, + const Particle* P, + const std::string& prefix, + Tuples::Tuple& tuple, + const std::string& trail ) const +{ + bool test = true ; + // -------------------------------------------------- + if ( !oriVtx ) + { + test &= tuple->column( prefix + "_FD"+trail, -999. ); + test &= tuple->column( prefix + "_FDCHI2"+trail, -999. ); + test &= tuple->column( prefix + "_DIRA"+trail, -999.); + } + else + { + + // flight distance + double dist{0}, chi2{0}; + const StatusCode sc = m_dist->distance( oriVtx, P->endVertex(), dist, chi2 ); + + // always fill variables to make sure branches do not change ... + test &= tuple->column( prefix + "_FD"+trail, sc ? dist : -999 ); + test &= tuple->column( prefix + "_FDCHI2"+trail, sc ? chi2 : -999 ); + // -------------------------------------------------- + // cosine of (flight distance) dot (momentum): + // find the origin vertex. Either the primary or the origin in the + // decay + test &= tuple->column( prefix + "_DIRA"+trail, sc ? dira(oriVtx,P) : -999 ); + + if ( sc.isFailure() ) return sc ; + } + + if (!test) Warning("Error in fillFlight "+prefix, StatusCode::SUCCESS, 1).ignore(); + return StatusCode(test); +} +// ===================================================== +// find origin vertex in the decay chain +// ===================================================== +const VertexBase* TupleToolGeometry::originVertex( const Particle* top, + const Particle* P ) const +{ + //this used to pass back zero if P was a basic particle. + //I don't think that's necessary. R Lambert 2009-08-14 + if ( top == P || top->isBasicParticle() ) return nullptr; + + const auto & dau = top->daughters(); + if ( dau.empty() ) return nullptr; + + for ( const auto d : dau ) + { + if( P == d ) + { // I found the daughter + if(msgLevel(MSG::VERBOSE)) + verbose() << "It's a daughter, retrning mother's endvertex : " + << endmsg; + return top->endVertex(); + } + } + + // vertex not yet found, get deeper in the decay: + for ( const auto d : dau ) + { + if ( P != d && !d->isBasicParticle() ) + { + const auto vv = originVertex( d, P ); + if ( msgLevel(MSG::VERBOSE) ) verbose() << "Went up : " << vv << endmsg ; + if ( vv ) return vv; + } + } + return nullptr; +} + +double TupleToolGeometry::dira( const LHCb::VertexBase* oriVtx, + const LHCb::Particle* P ) const +{ + if ( !P || !oriVtx ) + { + Exception("Wrong use of dira"); + return -1501. ; + } + const auto evtx = P->endVertex(); + if ( !evtx ) + { + Warning("Cannot find end vertex",StatusCode::SUCCESS,1).ignore(); + return -999.; + } + const auto A = P->momentum().Vect(); + const auto B = evtx->position() - oriVtx->position(); + return A.Dot( B ) / std::sqrt( A.Mag2()*B.Mag2() ); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolGeometry.h b/first-analysis-steps/DecayTrees/TupleToolGeometry.h new file mode 100755 index 00000000..042f9eb6 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolGeometry.h @@ -0,0 +1,146 @@ +#ifndef JBOREL_TUPLETOOLGEOMETRY_H +#define JBOREL_TUPLETOOLGEOMETRY_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface + +struct IDistanceCalculator; +struct IDVAlgorithm; +struct IPVReFitter; + +namespace LHCb +{ + class Particle; + class VertexBase; +} + + +/** @class TupleToolGeometry TupleToolGeometry.h jborel/TupleToolGeometry.h + * + * \brief Fill geometry related information for DecayTreeTuple + * + * - head_MINIP : minimum impact parameter on any PV + * - head_MINIPCHI2 : minimum chi2 IP on all PVs + * - head_ENDVERTEX_[X|Y|Z] : decay vertex position for composite particles + * - head_ENDVERTEX_[X|Y|Z]ERR : decay vertex position error estimate for composite particles + * - head_ENDVERTEX_CHI2 : decay vertex chi2 + * - head_ENDVERTEX_NDOF : decay vertex nDoF + * - head_OWNPV_[X|Y|Z] : related primary vertex position + * - head_OWNPV_[X|Y|Z]ERR : related primary vertex position error estimate for composite particles + * - head_OWNPV_CHI2 : related primary vertex chi2 + * - head_OWNPV_NDOF : related primary vertex nDoF + * - head_IP_OWNPV : impact parameter with respect to the PhysDesktop::relatedVertex() considered particle + * - head_IPCHI2_OWNPV : impact parameter chi2 with respect to the relatedVertex() considered particle + * - head_FD_OWNPV : flight distance of composite particle wrt. the relatedVertex() considered particle + * - head_FDCHI2_OWNPV : flight distance significance in units of chi2 wrt. the relatedVertex() considered particle + * - head_DIRA_OWNPV : direction angle wrt. the PhysDesktop::relatedVertex() considered particle + * + * If Verbose is true: + * + * - head_TOPPV_[X|Y|Z] : PhysDesktop::relatedVertex() of the top of decay chain position + * - head_TOPPV_[X|Y|Z]ERR : PhysDesktop::relatedVertex() of the top of decay chain position error estimate + * - head_TOPPV_CHI2 : PhysDesktop::relatedVertex() of the top of decay chain chi2 + * - head_TOPPV_NDOF : PhysDesktop::relatedVertex() of the top of decay chain nDoF + * - head_IP_TOPPV : impact parameter with respect to the PhysDesktop::relatedVertex() of the top of decay chain + * - head_IPCHI2_TOPPV : impact parameter chi2 with respect to the relatedVertex() of the top of decay chain + * - head_FD_TOPPV : flight distance of composite particle wrt. the relatedVertex() of the top of decay chain + * - head_FDCHI2_TOPPV : flight distance significance in units of chi2 wrt. + * the PhysDesktop::relatedVertex() of the top of decay chain + * - head_DIRA_TOPPV : direction angle wrt. the relatedVertex() of the top of decay chain + * + * - head_ORIVX_[X|Y|Z] : ancestor's related primary vertex position (when applicable) + * - head_ORIVX_[X|Y|Z]ERR : ancestor's related primary vertex position error estimate (when applicable) + * - head_ORIVX_CHI2 : ancestor's related primary vertex chi2 (when applicable) + * - head_ORIVX_NDOF : ancestor's related primary vertex nDoF (when applicable) + * - head_IP_ORIVX : impact parameter with respect to the ancestor's vertex (when applicable) + * - head_IPCHI2_ORIVX : impact parameter chi2 with respect to the ancestor's vertex (when applicable) + * - head_FD_ORIVX : flight distance of composite particle wrt. the ancestor's vertex (when applicable) + * - head_FDCHI2_ORIVX : flight distance significance in units of chi2 wrt. ancestor's vertex (when applicable) + * - head_DIRA_ORIVX : direction angle wrt. ancestor's vertex (when applicable) + * + * Finally some arrays with FillMultiPV + * - head_AllIP : IP wrt to all PVs + * - head_AllIPchi2 : IPchi2 wrt to all Vs + * - head_AllDIRA : DIRA wrt to all PVs + * + * \sa DecayTreeTuple + * + * @author Jeremie Borel + * @date 2007-11-07 + */ +class TupleToolGeometry : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolGeometry( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + /// fill end vertex stuff + StatusCode fillVertexFull(const LHCb::VertexBase* vtx, + const LHCb::Particle* P, + const std::string& head, + const std::string& vtx_name, + Tuples::Tuple&) const ; + + /// origin vertex + const LHCb::VertexBase* originVertex( const LHCb::Particle* top, + const LHCb::Particle* P ) const; + /// fill related pV stuff + StatusCode fillBPV( const LHCb::VertexBase* primVtx, + const LHCb::Particle* P, + const std::string& prefix, + Tuples::Tuple& tuple, + const std::string& trail = "") const ; + + /// fill min IP + StatusCode fillMinIP(const LHCb::Particle* P, + const std::string& prefix, + Tuples::Tuple& tuple) const ; + + /// fill end vertex stuff + StatusCode fillVertex(const LHCb::VertexBase* vtx, + const std::string& vtx_name, + Tuples::Tuple&) const ; + + /// fill flight + StatusCode fillFlight(const LHCb::VertexBase* oriVtx, + const LHCb::Particle* P, + const std::string& prefix, + Tuples::Tuple& tuple, + const std::string& trail = "" ) const ; + + /// Compute DIRA + double dira(const LHCb::VertexBase* oriVtx, const LHCb::Particle* P) const; + +private: + + const IDistanceCalculator* m_dist = nullptr; + + bool m_refitPVs; + bool m_fillMultiPV ; ///< fill multiPV variables + + //bool m_fillMother; + + IDVAlgorithm* m_dva = nullptr; + + IPVReFitter* m_pvReFitter = nullptr; + std::string m_pvReFitterName; + +}; + +#endif // JBOREL_TUPLETOOLGEOMETRY_H diff --git a/first-analysis-steps/DecayTrees/TupleToolHOP.cpp b/first-analysis-steps/DecayTrees/TupleToolHOP.cpp new file mode 100644 index 00000000..76034ea0 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolHOP.cpp @@ -0,0 +1,448 @@ +// $Id: TupleToolHOP.cpp,v 0.1 2016-05-20 20:01:40 jpalac Exp $ +// Include files + +// local +#include "TupleToolHOP.h" + +//#include +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" +#include "Kernel/IDVAlgorithm.h" +#include + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : HOPTupleTool +// +// 2016-05-20 : Carla Marin Benito, Vinicius Franco Lima +// +// +//This Tool Implements the variables described in LHCb Note: LHCb-INT-2015-037 +//see https://cds.cern.ch/record/2102345 +// +//The HOP variables are conceived to exploit the kinematic characteristics of B +//decays into final states involving electrons. +// +//The general idea is to use the fact that the decay particles should have total +//pt with respect to the B flight direction of 0. Using this fact we can re-weight +//the electron momentum using the non-electron parts of the decay. +// +//It is important to note the way this tool works: It applies the momentum +//correction to the electrons in the decay and calculates the HOP mass from there, +//not correcting intermediate state momenta, but final state particles. +//We do, however take into account the intermediate ressonance momentum measurement +//in order to calculate the HOP correction itself. +// +//This tool is comprised of 3 methods: +// +// TupleTooHOP::ClassifyParticles: gets the top particle and two particle containers as +//input and loops over the decay chain classifying basic children in electron and non-electron +//type. When all the children of a composite particle belong to the same type, the composite +//particle receives the same type and it is itself – instead of each children – stored in the +//appropiate container. This is done in order not to loose presicion, since when the children +//are afterwards combined to obtain the mother’s corrected mass no fit but a simple addition +//of momenta is used. +// +// TupleToolHOP::HOPProjectMomentum: takes two particles as input, the first one is assumed +//to be the top of the decay. The direction of flight of this particle is obtained taking the best +//interaction vertex associated to it and its decay vertex. Then the transverse momentum of +//the second particle with respect to this direction is computed and returned. +// +// TupleToolHOP::fill: gets the top particle, the particles for which the variables should be +//computed, a string with the head name that will be used for the names of the variables that +//will be written to the ntuple and the ntuple itself as input. It first checks that the particle +//for which the variables should be computed is the same as the top of the chain. Since our +//algorithm is recursive on all the decay chain we only need to run it once from the top of it. +//Then the daughters are classified using the TupleToolHOP::ClassifyParticles function +//and their transverse momentum with respect to the direction of flight of the top particle +//obtained with the TupleToolHOP::HOPProjectMomentum. The transverse momentum for +//all electron and non-electron particles are added up separately and the HOP ratio is +//computed. This value is stored in the ntuple in the variable head HOP. Afterwards, it is +//used to correct the 4-momentum of each particle in the electron container. Finally, all the +//4-momenta of the electron particles are sumed together and added to the 4-momentum +//of the non-electron particles. The mother’s corrected mass is obtained from this total +//corrected 4-momentum and stored in the ntuple with the name head HOP MASS. The +//electron corrected mass is also obtained from the corrected 4-momentum of all the electron +//particles added together and is saved as head HOP ELECTRON MASS. +// + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolHOP ) + + +//============================================================================= + +StatusCode TupleToolHOP::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_dva = Gaudi::Utils::getIDVAlgorithm ( contextSvc(), this ) ; + if ( !m_dva ) + return Error("Couldn't get parent DVAlgorithm"); + + m_ppSvc = svc( "LHCb::ParticlePropertySvc", true ); + if ( !m_ppSvc ) + return Error("Couldn't get ParticlePropertySvc"); + m_electronMassSquared = std::pow( m_ppSvc->find("e+")->mass()/Gaudi::Units::MeV, 2); + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::initialize " << "Done" << endmsg ; + + return sc; +} + +//============================================================================= +StatusCode TupleToolHOP::fill( const Particle* mother + , const Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + StatusCode sc = StatusCode::SUCCESS; + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::fill " << endmsg ; + + if (mother == P) + { + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::fill " << ": " << "particle is mother, let's run " << endmsg ; + + bool test = true; + const std::string prefix = fullName(head); + + SmartRefVector electronContainer; + SmartRefVector nonElectronContainer; + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::fill " << ": " << "start ClassifyParticles " << endmsg ; + + ClassifyParticles(*P, electronContainer, nonElectronContainer); + + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::fill " << ": " << "electrons found: " << electronContainer << endmsg ; + verbose() << "TupleToolHOP::fill " << ": " << "non-electrons found: " << nonElectronContainer << endmsg ; + } + + //Get pt wrt mother direction of flight + float total_pt_e =0, total_pt_non_e=0; + Gaudi::LorentzVector total_4p_e = Gaudi::LorentzVector(0,0,0,0); + Gaudi::LorentzVector total_4p_non_e = Gaudi::LorentzVector(0,0,0,0); + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::fill " << ": " << "loop on electrons " << endmsg ; + for (auto& e: electronContainer) + { + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::fill " << ": " << "electron is " << e << endmsg ; + verbose() << "TupleToolHOP::fill " << ": " << "start HOPProjectMomentum " << endmsg ; + } + total_4p_e += e->momentum(); + total_pt_e = HOPProjectMomentum(P, &total_4p_e); + } + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::fill " << ": " << "loop on non-electrons " << endmsg ; + + for (auto& noE: nonElectronContainer) + { + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::fill " << ": " << "non-electron is " << noE << endmsg ; + verbose() << "TupleToolHOP::fill " << ": " << "start HOPProjectMomentum " << endmsg ; + } + total_4p_non_e += noE->momentum(); + total_pt_non_e = HOPProjectMomentum(P, &total_4p_non_e); + } + + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::fill " << ": " << "Total ptElectron: "<< total_pt_e << endmsg ; + verbose() << "TupleToolHOP::fill " << ": " << "Total pt non-Electron: "<< total_pt_non_e << endmsg ; + verbose() << "TupleToolHOP::fill " << ": " << "Total 4p non-Electron: "<< total_4p_non_e << endmsg ; + } + + //Compute HOP correction + double hop = 0; + if (total_pt_e != 0) + hop = total_pt_non_e/total_pt_e; + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::fill " << ": " << "hop: " << hop << endmsg ; + + //Fill tuple with HOP correction + test &= tuple->column( prefix + "_HOP", hop); + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::fill " << ": " << "hop written to ntuple" << endmsg ; + + // Correct elec momenta with HOP value + Gaudi::LorentzVector sumCorrected=Gaudi::LorentzVector(0,0,0,0); + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::fill " << ": " << "Electron mass squared in MeV^2 : " << m_electronMassSquared << endmsg ; + + for (auto& e2: electronContainer) + { + if(e2->isBasicParticle()) // directly correct elec momenta + { + Gaudi::LorentzVector correctedMomentum = Gaudi::LorentzVector((e2->momentum().Px())*hop, + (e2->momentum().Py())*hop, + (e2->momentum().Pz())*hop, + sqrt((std::pow(e2->momentum().Px(),2) + + std::pow(e2->momentum().Py(),2) + + std::pow(e2->momentum().Pz(),2) ) *std::pow(hop,2) + + std::pow( m_ppSvc->find(e2->particleID())->mass() / + Gaudi::Units::MeV, 2))); + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::fill " << ": " << "Electron PX: " << e2->momentum().Px() << ", Corrected PX: "<< e2->momentum().Px()*hop << endmsg ; + verbose() << "TupleToolHOP::fill " << ": " << "Electron PY: " << e2->momentum().Py() << ", Corrected PY: "<< e2->momentum().Py()*hop << endmsg ; + verbose() << "TupleToolHOP::fill " << ": " << "Electron PZ: " << e2->momentum().Pz() << ", Corrected PZ: "<< e2->momentum().Pz()*hop << endmsg ; + verbose() << "TupleToolHOP::fill " << ": " << "Electron E: " << e2->momentum().E() << ", Corrected E: "<< sqrt((std::pow(e2->momentum().Px(),2)+ std::pow(e2->momentum().Py(),2)+ std::pow(e2->momentum().Pz(),2))*std::pow(hop,2) + std::pow( m_ppSvc->find(e2->particleID())->mass()/Gaudi::Units::MeV ,2)) << endmsg ; + } + sumCorrected += correctedMomentum; + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::fill " << ": " << "Electron Corrected mass: " << correctedMomentum.M() << endmsg ; + } + + else // correct momenta of each children separately and add them up. Is this what we want?? + { + const auto& dau = e2->daughters(); + for(const auto& idaughter3 :dau) + { + Gaudi::LorentzVector correctedMomentum = Gaudi::LorentzVector((idaughter3->momentum().Px())*hop, + (idaughter3->momentum().Py())*hop, + (idaughter3->momentum().Pz())*hop, + sqrt((std::pow(idaughter3->momentum().Px(),2)+ + std::pow(idaughter3->momentum().Py(),2)+ + std::pow(idaughter3->momentum().Pz(),2))*std::pow(hop,2) + + std::pow( m_ppSvc->find(idaughter3->particleID())->mass() / + Gaudi::Units::MeV ,2))); + sumCorrected += correctedMomentum; + } + } + } + + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::fill " << ": " << "Total Electron Corrected mass: " << (sumCorrected).M() << endmsg ; + verbose() << "TupleToolHOP::fill " << ": " << "Non Electron mass: " << (total_4p_non_e).M() << endmsg ; + verbose() << "TupleToolHOP::fill " << ": " << "hop mass: " << (total_4p_non_e+sumCorrected).M() << endmsg ; + verbose() << "TupleToolHOP::fill " << ": " << "hop mass calculated: " << sqrt(pow((total_4p_non_e+sumCorrected).E(),2) + - pow((total_4p_non_e+sumCorrected).P(),2)) + << endmsg ; + } + + // Fill HOP_MASS and HOP_ELECTRON_MASS + test &= tuple->column( prefix + "_HOP_MASS", (total_4p_non_e+sumCorrected).M()); + test &= tuple->column( prefix + "_HOP_ELECTRON_MASS", (sumCorrected).M()); + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::fill " << ": " << "hop mass written to ntuple" << endmsg ; + + return StatusCode(test); + } + + return sc ; +} + +// ===================================================== +// Classify particles in electron type and others +// ===================================================== +int TupleToolHOP::ClassifyParticles( + const LHCb::Particle& top, + SmartRefVector& electronContainer, + SmartRefVector& nonElectronContainer) const +{ + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::ClassifyParticles " << endmsg ; + + // Base case: basic particle + if (top.isBasicParticle()) + { + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::ClassifyParticles: " << top.particleID().pid() << " is basic" << endmsg ; + + int p_isElectron = (top.particleID().abspid() == 11) ? 1 : 0 ; + int p_hasSameChildren = 2; // has no children since it is basic + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::ClassifyParticles: " << top.particleID().pid() << " is electron: " << p_isElectron << endmsg ; + + return encodeTuple(p_isElectron, p_hasSameChildren); + } + // Complex Case ( Intermediate particles in the decay, need to figure out how to correctly classify them) + else + { + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::ClassifyParticles: " << top.particleID().pid() << " is NOT basic" << endmsg ; + verbose() << "TupleToolHOP::ClassifyParticles: " << "start loop on daughters" << endmsg ; + } + + const auto& dau = top.daughters(); + + std::vector t_list; + int dau_type = 3; // means only first children beeing checked + bool are_equal = true; + for(const auto& idaughter :dau) + { + int dt = ClassifyParticles(*idaughter, + electronContainer, + nonElectronContainer); + t_list.push_back(dt); + // check if all daughters are of same type + if (dau_type == 3) // first children, get only its type + dau_type = isElectron(dt); + else // other childrens, compare to previous + { + if (dau_type != isElectron(dt)) + are_equal = false; + } + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::ClassifyParticles: " << idaughter->particleID().pid() << " electron: " << isElectron(dt) << endmsg; + verbose() << "TupleToolHOP::ClassifyParticles: " << idaughter->particleID().pid() << " same child: " << hasSameChildren(dt) << endmsg; + } + } + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::ClassifyParticles: " << top.particleID().pid() << " daughters: " << dau << endmsg; + //verbose() << "TupleToolHOP::ClassifyParticles: " << top.particleID().pid() << " t_list: " << t_list << endmsg; + verbose() << "TupleToolHOP::ClassifyParticles: " << top.particleID().pid() << " equal dau: " << are_equal << endmsg; + } + + int t = ClassifyParticles_Merge(dau, t_list, + are_equal, + electronContainer, + nonElectronContainer); + + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::ClassifyParticles: " << top.particleID().pid() << " electron: " << isElectron(t) << endmsg; + verbose() << "TupleToolHOP::ClassifyParticles: " << top.particleID().pid() << " same child: " << hasSameChildren(t) << endmsg; + } + + return t; + } +} + +// ===================================================== +// Merge function for ClassifyParticles +// ===================================================== +int TupleToolHOP::ClassifyParticles_Merge( + const SmartRefVector& dau, + std::vector& t_list, + bool are_equal, + SmartRefVector& electronContainer, + SmartRefVector& nonElectronContainer) const{ + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::ClassifyParticlesMerge " << endmsg ; + + int t_mother_isElectron = 0; + int t_mother_hasSameChildren = 0; + if (are_equal) + { + t_mother_hasSameChildren = 1; + t_mother_isElectron = isElectron(t_list[0]); // inherits children type + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::ClassifyParticlesMerge: " << "equal dau" << endmsg ; + verbose() << "TupleToolHOP::ClassifyParticlesMerge: " << "don't save children" << endmsg ; + } + } + + else + { + t_mother_hasSameChildren = 0; + t_mother_isElectron = 2; // mother has "no type" + + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::ClassifyParticlesMerge: " << "diff dau" << endmsg ; + verbose() << "TupleToolHOP::ClassifyParticlesMerge: " << "save children if not yet done" << endmsg ; + } + + //SmartRefVector::const_iterator it = t_list.begin(); + int i = 0; + for(const auto& idaughter: dau) + { + int it = t_list[i]; + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::ClassifyParticlesMerge: " << idaughter->particleID().pid() << " same child: " << hasSameChildren(it) << endmsg ; + + if (hasSameChildren(it)==1 || hasSameChildren(it)==2) + { + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::ClassifyParticlesMerge: " << idaughter->particleID().pid() << " has same or no children" << endmsg; + verbose() << "TupleToolHOP::ClassifyParticlesMerge: " << idaughter->particleID().pid() << " will be saved" << endmsg; + verbose() << "TupleToolHOP::ClassifyParticlesMerge: " << idaughter->particleID().pid() << " is e: " << isElectron(it) << endmsg; + } + + if (isElectron(it)==1) + { + electronContainer.push_back(idaughter); + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::ClassifyParticlesMerge: " << idaughter->particleID().pid() << " saved as electron" << endmsg; + } + + else + { + nonElectronContainer.push_back(idaughter); + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::ClassifyParticlesMerge: " << idaughter->particleID().pid() << " saved as no electron" << endmsg; + } + } + i++; + } + } + + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::ClassifyParticlesMerge: " << "mother is e: " << t_mother_isElectron << endmsg; + verbose() << "TupleToolHOP::ClassifyParticlesMerge: " << "mother has equal childs: " << t_mother_hasSameChildren << endmsg; + } + + return encodeTuple(t_mother_isElectron, t_mother_hasSameChildren); +} + +// ===================================================== +// PT recalculation +// ===================================================== +float TupleToolHOP::HOPProjectMomentum(const LHCb::Particle* top, + const Gaudi::LorentzVector* part_four_mom) const{ + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "TupleToolHOP::HOPProjectMomentum" << ": " << endmsg ; + + const LHCb::VertexBase* PV; + const LHCb::VertexBase* SV; + ROOT::Math::DisplacementVector3D> bFlightVector, bFlightVectorUnit; + PV = m_dva->bestVertex (top); + SV = top->endVertex(); + bFlightVector = SV->position() - PV->position(); + + bFlightVectorUnit = (SV->position() - PV->position()).Unit(); + double pInBFlightDir = (part_four_mom->Px()*bFlightVectorUnit.X() + + part_four_mom->Py()*bFlightVectorUnit.Y() + + part_four_mom->Pz()*bFlightVectorUnit.Z()) ; + double cosAngle = pInBFlightDir/part_four_mom->P(); + double ptInBFlightDir = part_four_mom->P()*sqrt(1-std::pow(cosAngle,2)); + + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "TupleToolHOP::HOPProjectMomentum" << ": " << " PV: "<< PV->position() << endmsg ; + verbose() << "TupleToolHOP::HOPProjectMomentum" << ": " << " SV: "<< SV->position() << endmsg ; + verbose() << "TupleToolHOP::HOPProjectMomentum" << ": " << " b Flight vector: "<< bFlightVector << endmsg ; + verbose() << "TupleToolHOP::HOPProjectMomentum" << ": " << " particle 4-momentum: "<< part_four_mom << endmsg ; + verbose() << "TupleToolHOP::HOPProjectMomentum" << ": " << " Momentum Magnitude in bFlight direction: "<< pInBFlightDir << endmsg ; + verbose() << "TupleToolHOP::HOPProjectMomentum" << ": " << " Cosine of angle: "<< cosAngle << endmsg ; + verbose() << "TupleToolHOP::HOPProjectMomentum" << ": " << " Pt wrt B flight direction: "<< ptInBFlightDir << endmsg ; + } + return ptInBFlightDir; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolHOP.h b/first-analysis-steps/DecayTrees/TupleToolHOP.h new file mode 100644 index 00000000..5b075f87 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolHOP.h @@ -0,0 +1,79 @@ +#ifndef TUPLETOOLHOP_H +#define TUPLETOOLHOP_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" + +struct IDVAlgorithm; + +namespace LHCb +{ + class Particle; + class VertexBase; +} + + +/** @class TupleToolHOP TupleToolHOP.h + * + * \brief Fill geometry related information for DecayTreeTuple + * + * - mother_HOP : HOP correction, the ratio between the Pt (with respecto to the mothers direction of flight) of electrons and non-electrons + * - mother_HOP_MASS : Mother mass obtained by scalling the electrons P by the hop factor + * - mother_ELECTRON_MASS : Mass obtained by summing the four-momenta of all electrons + * + * + * + * \sa DecayTreeTuple + * + * @author Vinicius Franco, Carla Marin Benito + * @date 2016-29-06 + */ + + +class TupleToolHOP : public extends +{ + +public: + + /// Standard constructor + using base_class::base_class; + + StatusCode initialize() override; + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + float HOPProjectMomentum(const LHCb::Particle* top, + const Gaudi::LorentzVector* part_four_mom) const; + + int encodeTuple(int isElectron, int hasSameChildren) const { return (isElectron << 2) | hasSameChildren; } + int isElectron(int tuple) const { return tuple >> 2 ; } ; + int hasSameChildren(int tuple) const { return tuple & 3 ; } ; + + + int ClassifyParticles( + const LHCb::Particle& top, + SmartRefVector& electronContainer, + SmartRefVector& nonElectronContainer) const; + + int ClassifyParticles_Merge( + const SmartRefVector& dau, + std::vector& t_list, + bool are_equal, + SmartRefVector& electronContainer, + SmartRefVector& nonElectronContainer) const; + +private: + //bool m_fillMother; + IDVAlgorithm* m_dva = nullptr; + LHCb::IParticlePropertySvc * m_ppSvc = nullptr; + float m_electronMassSquared = 0.0; +}; +#endif // TUPLETOOLHOP_H diff --git a/first-analysis-steps/DecayTrees/TupleToolHerschel.cpp b/first-analysis-steps/DecayTrees/TupleToolHerschel.cpp new file mode 100644 index 00000000..a6aff896 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolHerschel.cpp @@ -0,0 +1,334 @@ +// Include files + +// from Gaudi +#include "Event/ODIN.h" +#include "Event/HCDigit.h" +// from LHCb +#include "DetDesc/Condition.h" + +// local +#include "TupleToolHerschel.h" + +DECLARE_COMPONENT( TupleToolHerschel ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolHerschel::TupleToolHerschel( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name, parent ), + m_cond(nullptr) +{ + declareInterface(this); +} + +StatusCode TupleToolHerschel::initialize() { + StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + // Set up the mapping + m_channels.resize(5); + m_masked.resize(5); + // Check if the mapping is available in the conditions database. + const std::string location = "Conditions/ReadoutConf/HC/Mapping"; + if (existDet(location)) { + registerCondition(location, m_cond, &TupleToolHerschel::cacheMapping); + // First update. + sc = updMgrSvc()->update(this); + if (sc.isFailure()) { + return Error("Cannot update mapping.", StatusCode::FAILURE); + } + } else { + warning() << "Cannot find " << location << " in database" << endmsg; + mapChannels(m_channelsB0, m_sparesB0, m_masksB0, 0, true); + mapChannels(m_channelsB1, m_sparesB1, m_masksB1, 1, true); + mapChannels(m_channelsB2, m_sparesB2, m_masksB2, 2, true); + mapChannels(m_channelsF1, m_sparesF1, m_masksF1, 1, false); + mapChannels(m_channelsF2, m_sparesF2, m_masksF2, 2, false); + } + printMapping(); + + // Check if the FOM parameters are available in the conditions database. + const std::string location_fom = "Conditions/Calibration/HC/FigureOfMerit_SimpleChi2"; + if (existDet(location_fom)) { + registerCondition(location_fom, m_condFOM, &TupleToolHerschel::cacheFOMParameters); + // First update. + sc = updMgrSvc()->update(this); + if (sc.isFailure()) { + return Error("Cannot update FOM constants."); + } + } else { + warning() << "Cannot find " << location_fom << " in database." << endmsg; + _makeFOM = false ; + warning() << "Cannot set FOM constants, will not create Herschel FOM in NTuple. Please fix FOM constants location in CondDB." << endmsg; + //} + } + + return sc ; +} + +//============================================================================= +// Update the channel map using the conditions database. +//============================================================================= +StatusCode TupleToolHerschel::cacheMapping() { + + m_crateB = m_cond->param("CrateB"); + m_crateF = m_cond->param("CrateF"); + + m_channelsB0 = m_cond->paramVect("ChannelsB0"); + m_channelsB1 = m_cond->paramVect("ChannelsB1"); + m_channelsB2 = m_cond->paramVect("ChannelsB2"); + m_channelsF1 = m_cond->paramVect("ChannelsF1"); + m_channelsF2 = m_cond->paramVect("ChannelsF2"); + + m_sparesB0 = m_cond->paramVect("ReferenceChannelsB0"); + m_sparesB1 = m_cond->paramVect("ReferenceChannelsB1"); + m_sparesB2 = m_cond->paramVect("ReferenceChannelsB2"); + m_sparesF1 = m_cond->paramVect("ReferenceChannelsF1"); + m_sparesF2 = m_cond->paramVect("ReferenceChannelsF2"); + + m_masksB0 = m_cond->paramVect("MasksB0"); + m_masksB1 = m_cond->paramVect("MasksB1"); + m_masksB2 = m_cond->paramVect("MasksB2"); + m_masksF1 = m_cond->paramVect("MasksF1"); + m_masksF2 = m_cond->paramVect("MasksF2"); + + mapChannels(m_channelsB0, m_sparesB0, m_masksB0, 0, true); + mapChannels(m_channelsB1, m_sparesB1, m_masksB1, 1, true); + mapChannels(m_channelsB2, m_sparesB2, m_masksB2, 2, true); + mapChannels(m_channelsF1, m_sparesF1, m_masksF1, 1, false); + mapChannels(m_channelsF2, m_sparesF2, m_masksF2, 2, false); + return StatusCode::SUCCESS; +} + +//============================================================================= +// Setup the channel map for a given station. +//============================================================================= +bool TupleToolHerschel::mapChannels(const std::vector& channels, + const std::vector& refs, + const std::vector& masks, + const unsigned int station, + const bool bwd) { + + const unsigned int offset = bwd ? 0 : 2; + // Check if the input is valid. + if (channels.size() != 4 || refs.size() != 4 || masks.size() != 4) { + std::string s = bwd ? "B" : "F"; + s += std::to_string(station); + warning() << "Invalid channel map for station " << s + << ". Masking all quadrants." << endmsg; + m_channels[station + offset].assign(4, 0); + m_masked[station + offset].assign(4, true); + return false; + } + + const unsigned int crate = bwd ? m_crateB : m_crateF; + m_channels[station + offset].resize(4); + m_masked[station + offset].resize(4); + for (unsigned int i = 0; i < 4; ++i) { + if (channels[i] < 0) { + std::string s = bwd ? "B" : "F"; + s += std::to_string(station); + warning() << "Invalid channel number " << channels[i] + << ". Masking quadrant " << s << i << endmsg; + m_masked[station + offset][i] = true; + continue; + } + m_channels[station + offset][i] = (crate << 6) | channels[i]; + m_masked[station + offset][i] = masks[i] != 0; + } + return true; +} + +//============================================================================= +// Print the channel map for information +//============================================================================= +void TupleToolHerschel::printMapping() const { + + info() << " Quadrant ID Ref. ID Comment" << endmsg; + const std::vector stations = {"B0", "B1", "B2", "F1", "F2"}; + const unsigned int nStations = stations.size(); + for (unsigned int i = 0; i < nStations; ++i) { + for (unsigned int j = 0; j < 4; ++j) { + const std::string comment = m_masked[i][j] ? "Masked" : ""; + info() << format(" %2s/%1d", stations[i].c_str(), j) + << format(" %4d", m_channels[i][j]) + << format(" %-10s", comment.c_str()) << endmsg; + } + } + +} + +//============================================================================= +// Retrieve the FOM parameters from the conditions database. +//============================================================================= +StatusCode TupleToolHerschel::cacheFOMParameters() +{ + info() << "Updating HRC figure of merit parameters." << endmsg; + m_hrcFomVnum = m_condFOM->param("FOMvNum"); + info() << "HRC FOM version number " << m_hrcFomVnum << endmsg; + + m_meanConfig.clear(); + m_rmsConfig.clear(); + const std::vector stations = {"B0", "B1", "B2", "F1", "F2"}; + for (const auto& st : stations) { + const auto meanEven = m_condFOM->paramVect("Mean" + st + "Even"); + const auto meanOdd = m_condFOM->paramVect("Mean" + st + "Odd"); + const auto rmsEven = m_condFOM->paramVect("RMS" + st + "Even"); + const auto rmsOdd = m_condFOM->paramVect("RMS" + st + "Odd"); + for (unsigned int i = 0; i < 4; ++i) { + m_meanConfig.push_back(meanEven[i]); + m_meanConfig.push_back(meanOdd[i]); + m_rmsConfig.push_back(rmsEven[i]); + m_rmsConfig.push_back(rmsOdd[i]); + } + } + return setFOMParameters(); +} + +//============================================================================= +// Update the calibration constants. +//============================================================================= +StatusCode TupleToolHerschel::setFOMParameters() { + + const unsigned int nStations = 5; + const unsigned int nQuadrants = 4; + // Check if the lists of calibration constants have the right size. + const unsigned int nExpectedSize = nStations * 4 * 2; + if (m_meanConfig.size() != nExpectedSize || + m_rmsConfig.size() != nExpectedSize ) { + return Error("List of FOM calibration constants has incorrect size."); + } + m_mean.resize(nStations); + m_rms.resize(nStations); + unsigned int index = 0; + for (unsigned int i = 0; i < nStations; ++i) { + m_mean[i].resize(nQuadrants); + m_rms[i].resize(nQuadrants); + for (unsigned int j = 0; j < nQuadrants; ++j) { + m_mean[i][j].resize(2); + m_rms[i][j].resize(2); + for (unsigned int k = 0; k < 2; ++k) { + m_mean[i][j][k] = m_meanConfig[index]; + m_rms[i][j][k] = m_rmsConfig[index]; + ++index; + } + } + } + return StatusCode::SUCCESS; + +} + +//============================================================================= +StatusCode TupleToolHerschel::fill( Tuples::Tuple& tup ) +{ + const std::string prefix = fullName(); + + // Get ODIN + const LHCb::ODIN* odin = getIfExists(evtSvc(),LHCb::ODINLocation::Default); + if ( !odin ) { odin = getIfExists(evtSvc(),LHCb::ODINLocation::Default,false); } + if ( !odin ) { + // should always be available ... + return Error( "Cannot load the ODIN data object", StatusCode::SUCCESS ); + } + const unsigned int bxid = odin->bunchId(); + const unsigned int parity = bxid % 2; + + // Get Herschel digits + LHCb::HCDigits* digits = getIfExists(m_DigitsLocation); + if ( !digits ) { + // should always be available ... + return Error( "Cannot load the HCDigits data object", StatusCode::SUCCESS ); + } + + + // Fill the Herschel information + double log_hrc_fom = -999 ; + double log_hrc_fom_B = -999 ; + double log_hrc_fom_F = -999 ; + double hrc_fom = 0. ; + double hrc_fom_B = 0. ; + double hrc_fom_F = 0. ; + + // Herschel FOM : log( sum( chi2 )) + bool test = true; + const std::vector stations = {"B0", "B1", "B2", "F1", "F2"}; + const unsigned int nStations = 5; + for (unsigned int i = 0; i < nStations; ++i) + { + for (unsigned int j = 0; j < 4; ++j) + { + // Build channel name + const std::string ch = stations[i] + std::to_string(j); + LHCb::HCCellID id(m_channels[i][j]); + const LHCb::HCDigit* digit = digits->object(id); + + // Create a value of ADC to write out every event, irrespective of whether a HCdigit is found + int adc = -999 ; + + // If a digit is found *and* the channel is not masked + if (digit && !m_masked[i][j] ) + { + adc = digit->adc(); + + // Make Herschel FOM + if (_makeFOM) { + // A counter is to be ignored if the width is set to <0: + if ( m_rms[i][j][parity] < 0.0 ) continue ; + + double quadrant_pull = ( adc - m_mean[i][j][parity] ) / m_rms[i][j][parity] ; + hrc_fom += quadrant_pull * quadrant_pull ; + + // Make Herschel FOM for B-side and F-side separately + if (i<3) + hrc_fom_B += quadrant_pull * quadrant_pull ; + else + hrc_fom_F += quadrant_pull * quadrant_pull ; + } + else { + hrc_fom = -999. ; + hrc_fom_B = -999. ; + hrc_fom_F = -999. ; + } + } + else if (!digit) + { + warning() << "Cannot retrieve digit for " << ch << endmsg; + } + else + { + warning() << "Channel " << ch << " is masked." << endmsg; + } + + // Always write out the ADC + test &= tup->column( prefix+ch, adc); + } + } + + if ( hrc_fom>0 ) log_hrc_fom = std::log(hrc_fom) ; + if ( hrc_fom_B>0 ) log_hrc_fom_B = std::log(hrc_fom_B) ; + if ( hrc_fom_F>0 ) log_hrc_fom_F = std::log(hrc_fom_F) ; + test &= tup->column( prefix+"log_hrc_fom" +"_v"+std::to_string(m_hrcFomVnum) , log_hrc_fom ) ; + test &= tup->column( prefix+"log_hrc_fom_B"+"_v"+std::to_string(m_hrcFomVnum) , log_hrc_fom_B ) ; + test &= tup->column( prefix+"log_hrc_fom_F"+"_v"+std::to_string(m_hrcFomVnum) , log_hrc_fom_F ) ; + + // Fill ADC vectors + std::vector adcB,adcF; + for (const LHCb::HCDigit* dig : *digits) { + const int cell = int(dig->cellID().cellID()); + const int crate = cell >> 6; + if (crate == 0) { + adcB.push_back((double)dig->adc()); + } else if (crate == 1) { + adcF.push_back((double) dig->adc()); + } else { + info() << "Crate = " << crate << ". We have a problem." << endmsg; + } + } + + // Fill tuple + test &= tup->farray( prefix+"adc_B", adcB.begin(), adcB.end(),prefix+"nchB",1000); + test &= tup->farray( prefix+"adc_F", adcF.begin(), adcF.end(),prefix+"nchF",1000); + + return StatusCode(test); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolHerschel.h b/first-analysis-steps/DecayTrees/TupleToolHerschel.h new file mode 100644 index 00000000..f4fe21d5 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolHerschel.h @@ -0,0 +1,86 @@ +#ifndef TUPLETOOLHERSCHEL_H +#define TUPLETOOLHERSCHEL_H 1 + +// Include files +// from Gaudi +#include "Kernel/IEventTupleTool.h" // Interface +#include "DecayTreeTupleBase/TupleToolBase.h" + +/** @class TupleToolHerschel TupleToolHerschel.h + * + * Fills Herschel information. + * + * @author Dan Johnson + * @date 2015-07-08 + */ +class TupleToolHerschel : public TupleToolBase, + virtual public IEventTupleTool +{ + +public: + + /// Standard constructor + TupleToolHerschel( const std::string& type, + const std::string& name, + const IInterface* parent); + StatusCode initialize() override;///< Algorithm initialization + StatusCode fill( Tuples::Tuple& ) override;///< Fill tuple + + Gaudi::Property m_DigitsLocation{this, "DigitsLocation", "Raw/HC/Digits" , "TES location of Herschel digits"}; + // Mappings (to be retrieved from conditions database). + Gaudi::Property m_crateB{this, "CrateB", 0 , "Number of B-side crate"}; + Gaudi::Property m_crateF{this, "CrateF", 1 , "Number of F-side crate"}; + + Gaudi::Property> m_masksB0{this, "MasksB0", {false, false, false, false}, "B0 masking"}; + Gaudi::Property> m_masksB1{this, "MasksB1", {false, false, false, false}, "B1 masking"}; + Gaudi::Property> m_masksB2{this, "MasksB2", {false, false, false, false}, "B2 masking"}; + Gaudi::Property> m_masksF1{this, "MasksF1", {false, false, false, false}, "F1 masking"}; + Gaudi::Property> m_masksF2{this, "MasksF2", {false, false, false, false}, "F2 masking"}; + + Gaudi::Property> m_channelsB0{this, "ChannelsB0", {}, "B0 channels"}; + Gaudi::Property> m_channelsB1{this, "ChannelsB1", {}, "B1 channels"}; + Gaudi::Property> m_channelsB2{this, "ChannelsB2", {}, "B2 channels"}; + Gaudi::Property> m_channelsF1{this, "ChannelsF1", {}, "F1 channels"}; + Gaudi::Property> m_channelsF2{this, "ChannelsF2", {}, "F2 channels"}; + + Gaudi::Property> m_sparesB0{this, "SpareChannelsB0", {}, "B0 spare channels"}; + Gaudi::Property> m_sparesB1{this, "SpareChannelsB1", {}, "B1 spare channels"}; + Gaudi::Property> m_sparesB2{this, "SpareChannelsB2", {}, "B2 spare channels"}; + Gaudi::Property> m_sparesF1{this, "SpareChannelsF1", {}, "F1 spare channels"}; + Gaudi::Property> m_sparesF2{this, "SpareChannelsF2", {}, "F2 spare channels"}; + +protected: + /// Conditions database information + Condition* m_cond; + Condition* m_condFOM = nullptr; + + /// Channel numbers for each quadrant + std::vector > m_channels; + /// Masked flags for each quadrant + std::vector > m_masked; + /// Retrieve the mapping from the conditions database. + StatusCode cacheMapping(); + /// Setup the mapping for a given station. + bool mapChannels(const std::vector& channels, + const std::vector& refs, + const std::vector& masks, + const unsigned int station, const bool bwd); + /// Print the channel mapping for information. + void printMapping() const; + + StatusCode cacheFOMParameters(); + StatusCode setFOMParameters(); + + /// FOM constants for each channel and parity + /// station (x5) ; quadrant (x4) ; parity (x2) + std::vector > > m_mean; + std::vector > > m_rms; + bool _makeFOM=true; + + // Input parameters from CondDB + std::vector m_meanConfig; + std::vector m_rmsConfig; + int m_hrcFomVnum; +}; + +#endif diff --git a/first-analysis-steps/DecayTrees/TupleToolIsolationTwoBody.cpp b/first-analysis-steps/DecayTrees/TupleToolIsolationTwoBody.cpp new file mode 100644 index 00000000..719ae287 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolIsolationTwoBody.cpp @@ -0,0 +1,717 @@ +// $Id: TupleToolIsolationTwoBody.cpp +// from Gaudi +#include "Kernel/Particle2MCLinker.h" +#include "Kernel/IParticle2MCAssociator.h" +#include "LoKi/LoKi.h" +#include "LoKi/PhysTypes.h" +#include "LoKi/Functor.h" +#include "LoKi/CoreCuts.h" +#include "LoKi/Combiner.h" +#include "Event/VertexBase.h" +#include "Event/RecVertex.h" +#include "Event/ProtoParticle.h" +#include "Event/Particle.h" +#include +#include +#include +#include +#include +#include "TMath.h" +// local +#include "TupleToolIsolationTwoBody.h" +#include "Kernel/IParticleCombiner.h" +// Include files +#include "Event/Particle.h" +// kernel +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "GaudiKernel/PhysicalConstants.h" +#include +#include "Kernel/IPVReFitter.h" +// MC stuff +#include "Event/GenHeader.h" +#include "Event/MCHeader.h" + + +using namespace LHCb ; +using namespace std; + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolIsolationTwoBody +// +// 2012-03-17 : Fatima Soomro, based on IsolationTwoBody (in DaVinciTools) by Giampiero Mancinelli +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolIsolationTwoBody ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolIsolationTwoBody::TupleToolIsolationTwoBody( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name, parent ) + , m_Geom(0) + , m_angle(0) + , m_fc(0) + , m_doca(0) + , m_ips(0) + , m_svdis(0) + , m_svdis_h(0) + , m_pvdis(0) + , m_pvdis_h(0) + , m_ghost(0) + , m_clone(0) + , m_trchi2(0) + , m_hltgood(0) + , m_tracktype(0) + , m_PVInputLocation(LHCb::RecVertexLocation::Primary) + , m_p2mcAssoc(0) + , m_dva(0) + , m_p2mcAssocType("DaVinciSmartAssociator") +{ + declareInterface(this); + declareProperty("ParticlePath", + m_ParticlePath="/Event/Phys/StdAllNoPIDsPions/Particles"); + declareProperty("angle" , m_angle = 0.27 ); // + declareProperty("fc" , m_fc = 0.60 ); // + declareProperty("doca" , m_doca = 0.13 ); // + declareProperty("ips" , m_ips = 3.0 ); // + declareProperty("svdis" , m_svdis = -0.15 ); // + declareProperty("svdis_h" , m_svdis_h = 30. ); // + declareProperty("pvdis" , m_pvdis = 0.5 ); // + declareProperty("pvdis_h" , m_pvdis_h = 40. ); // + declareProperty("ghost" , m_ghost = 1000000. ); // + declareProperty("clone" , m_clone = -1000000. ); // + declareProperty("trchi2" , m_trchi2 = 1000000. ); // + declareProperty("tracktype" , m_tracktype = 3 ); // + declareProperty("hltgood" , m_hltgood = -10 ); // + declareProperty("PVInputLocation",m_PVInputLocation); + declareProperty("MuChi2", m_MuChi2 = true); + declareProperty("isMC", m_isMC = false); + + declareProperty( "IP2MCPAssociatorType", m_p2mcAssocType); +} + +//============================================================================= +// Initialize +//============================================================================= +StatusCode TupleToolIsolationTwoBody::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_dva = Gaudi::Utils::getIDVAlgorithm ( contextSvc(), this ) ; + if ( !m_dva ) { return Error( "Couldn't get parent DVAlgorithm", + StatusCode::FAILURE ); } + + m_p2mcAssoc = tool( m_p2mcAssocType, this ); + m_combiner = m_dva->particleCombiner(); + m_Geom = m_dva->distanceCalculator(); + + return sc; +} + +//============================================================================= +// Fill +//============================================================================= +StatusCode TupleToolIsolationTwoBody::fill( const LHCb::Particle * /* top */, + const LHCb::Particle *part, + const std::string & head, + Tuples::Tuple & tuple ) +{ + + const std::string prefix=fullName(head); + + if ( msgLevel(MSG::DEBUG) ) + debug()<<"filling tuple for "<isBasicParticle() && m_MuChi2){ sc = MuChi2(part, prefix, tuple); } + + if( part->isBasicParticle() || part->daughtersVector().size()!=2 ){ + + if ( msgLevel(MSG::DEBUG) ) + debug()<<"not filling for "<< fullName(head)<daughtersVector(); + + for ( Particle::ConstVector::const_iterator ip_part = parts.begin(); ip_part != parts.end(); ip_part++) { + if( !((*ip_part)->isBasicParticle()) ) shdBeTrue=false; + if ( !shdBeTrue && msgLevel(MSG::DEBUG) ) + debug()<<"Found compositle particle "<< (*ip_part)->particleID().pid() + <<" in the daughters of"<< fullName(head)<bestPV(part); + // const LHCb::VertexBase* SV = part->endVertex(); + if ( msgLevel(MSG::DEBUG) ) debug()<<" calling getiso "<column( prefix+"_test", massiso[0]); + + return sc; +} + + +//============================================================================= +// F.Soomro, 9 March 12 +// Fill MuonChi2DOF for the track, for Walter +//============================================================================= +StatusCode TupleToolIsolationTwoBody::MuChi2( const LHCb::Particle* P + , const std::string& prefix + , Tuples::Tuple& tuple ){ + //const std::string prefix=fullName(head); + + bool test = true; + if( !P ) return StatusCode::FAILURE; + + //first just return if the particle isn't supposed to have a track + if( !P->isBasicParticle() ) return StatusCode::SUCCESS; + + const LHCb::ProtoParticle* protop = P->proto(); + if(!protop) return StatusCode::SUCCESS; + const LHCb::Track* track = protop->track(); + if(!track) return StatusCode::SUCCESS; + + // double muchi2 = track->info(LHCb::Track::AdditionalInfo::MuonChi2perDoF , -1); + // test += tuple->column( prefix+"_MuonChi2DOF", muchi2); + + double muchi2 = -1; + + if ( msgLevel(MSG::DEBUG) ) + debug()<<"checking for muonpids at "<(LHCb::MuonPIDLocation::Default)) pMuids=get(LHCb::MuonPIDLocation::Default); + if (!pMuids){ + error() << " Failed to get pMuids" << LHCb::MuonPIDLocation::Default << endmsg; + return StatusCode::FAILURE; + } + + if ( msgLevel(MSG::DEBUG) ) + debug()<<" found it, the size is "<size()<begin(); ip != pMuids->end() ; ip++){ + if ((*ip)->idTrack() == track){ + mutrack = (*ip)->muonTrack(); + if (!mutrack) continue; + if ( msgLevel(MSG::DEBUG) ) debug()<<"found a mutrack "<info(LHCb::Track::AdditionalInfo::MuonChi2perDoF , -1); + } + + else{ + if ( msgLevel(MSG::DEBUG) ) + debug()<<"didnt find any mutrack! "<column( prefix+"_MuonChi2DOF", muchi2).getCode(); + + // here test is always true!!! + return test ? StatusCode::SUCCESS : StatusCode::FAILURE; +} + +//============================================================================= +// End of Fill MuonChi2DOF +//============================================================================= + + +//============================================================================= +// get the Isolation +//============================================================================= + +StatusCode TupleToolIsolationTwoBody::getIso(const LHCb::Particle *P, + const std::string prefix, + Tuples::Tuple& tuple ) +{ + + if ( msgLevel(MSG::DEBUG) ) + debug() <<"Now get the Isolation level"<< endmsg; + StatusCode sc = StatusCode::SUCCESS; + + const LHCb::Particle::ConstVector & parts = P->daughtersVector(); + if ( msgLevel(MSG::DEBUG) ) debug() <<"daughters vector "<< endmsg; + float massiso[2]; + float chi2iso[2]; + //int iso[2]; + if ( msgLevel(MSG::DEBUG) ) debug() <<"the floats "<< endmsg; + const LHCb::VertexBase *PV = m_dva->bestVertex(P); + const LHCb::VertexBase *SV = P->endVertex(); + if ( msgLevel(MSG::DEBUG) ) debug() <<" PV and SV "<< endmsg; + + LHCb::Particles* allparts = get(m_ParticlePath); + if (!allparts) { + error() << " Failed to get particles container " + << m_ParticlePath << endmsg; + return StatusCode::SUCCESS; + } + + if ( msgLevel(MSG::DEBUG) ) + debug() <<" have all_parts with size "<< allparts->size()<< endmsg; + + Assert( m_p2mcAssoc + , "The DaVinci smart associator hasn't been initialized!"); + /* + Particle2MCLinker* m_linkLinks(0); + if (m_isMC){ + + m_linkLinks = new Particle2MCLinker( this, + //Particle2MCMethod::Chi2, + Particle2MCMethod::Links, + m_ParticlePath); + if( !m_linkLinks ) { + fatal() << "Unable to retrieve Link Associator tool"<position(); + const Gaudi::XYZPoint& PosSV = SV->position(); + if ( msgLevel(MSG::DEBUG) ) debug() <<" PV and SV position "<< endmsg; + + int i = 0; + ROOT::Math::SVector iso5; + iso5[0]=0; + iso5[1]=0; + ROOT::Math::SMatrix o_mu; + ROOT::Math::SMatrix p_mu; + ROOT::Math::SVector ptmu; + int storeCharge[2]; + //Loop over input particles, get their simple kinematics + Particle::ConstVector::const_iterator ip_part; + + if ( msgLevel(MSG::DEBUG) ) debug () <<"=========== 1"<< endmsg; + // IParticle2MCAssociator* m_p2mcAssoc; + Particle::ConstVector iso_parts_0; + Particle::ConstVector iso_parts_1; + //const MCParticle* mclink1 = 0; + //const MCParticle* mclink2 = 0; + + // thats where you decide which daughter is at [0] and [1] of the arrays + for ( ip_part = parts.begin(); ip_part != parts.end(); ip_part++) + { + const LHCb::Particle* part = *(ip_part); + //if (m_isMC) { + //if (i==0) mclink1 = m_p2mcAssoc->relatedMCP(part); + //if (i==1) mclink2 = m_p2mcAssoc->relatedMCP(part); + //} + + if (i==0) iso_parts_0.push_back(part) ; + if (i==1) iso_parts_1.push_back(part) ; + const LHCb::ProtoParticle * proto = (*ip_part)->proto(); + const LHCb::Track* track = proto->track(); + storeCharge[i] = part->charge(); + + o_mu(0,i) = track->position().x(); + o_mu(1,i) = track->position().y(); + o_mu(2,i) = track->position().z(); + p_mu(0,i) = track->momentum().x(); + p_mu(1,i) = track->momentum().y(); + p_mu(2,i) = track->momentum().z(); + ptmu[i] = std::sqrt(std::pow(p_mu(0,i),2)+std::pow(p_mu(1,i),2)); + ++i; + + }// ip_part + int j=0; + + float doca2[2]; + doca2[0]=10000.; + doca2[1]=10000.; + float bestdoca[2]; + bestdoca[0]=10000.; + bestdoca[1]=10000.; + LHCb::Particle* bestpart_0(0) ; + LHCb::Particle* bestpart_1(0) ; + + if ( msgLevel(MSG::DEBUG) ) debug () <<"=========== 2"<< endmsg; + //Loop over all particles + LHCb::Particles::const_iterator ip; + for ( ip = allparts->begin(); ip != allparts->end() ; ++ip) { + + if ( msgLevel(MSG::DEBUG) ) debug() <<" looping over all parts "<< endmsg; + j++; + const LHCb::ProtoParticle * proto = (*ip)->proto(); + const LHCb::Track* track = proto->track(); + LHCb::Particle* cand = (*ip); + Gaudi::XYZPoint o(track->position()); + Gaudi::XYZVector p(track->momentum()); + bool isInList = 0; + double pt = p.Rho(); + //double ptot = p.R(); + + // skip if other particle is in input list + if ( msgLevel(MSG::DEBUG) ) debug() <<" check isInList "<< endmsg; + if (ratio(pt, ptmu[0]) < 0.0001 || ratio(pt,ptmu[1]) <0.0001) { + isInList = 1; + if ( msgLevel(MSG::DEBUG) ) debug() <<"isInList is found to be "<relatedMCP(cand); + if(mclink) { + debug() <<"=========== 5"<< endmsg; + //fromB = ancestor(mclink)->particleID().hasBottom(); + //fromD = ancestor(mclink)->particleID().hasCharm(); + //MCID = mclink->particleID().pid(); + debug() <<"=========== 6"<< endmsg; + const MCParticle*mc_mom = mclink->mother(); + if(mc_mom) { + debug() <<"=========== 7"<< endmsg; + //MCmothID = mc_mom->particleID().pid(); + } + } + debug() <<"=========== 4b"<< endmsg; + } + } + + //Loop over input particles (2) + for ( i2 = 0; i2 < 2; i2++) { + + //bool isolating = false; + //if (m_isMC) { + // if (i2 == 0 && mclink && mclink1) isolating = ancestor(mclink)==ancestor(mclink1); + // if (i2 == 1 && mclink && mclink2) isolating = ancestor(mclink)==ancestor(mclink2); + //} + + int hltgood = -1; + double fc = 0.; + Gaudi::XYZPoint omu(o_mu(0,i2),o_mu(1,i2),o_mu(2,i2)); + Gaudi::XYZVector pmu(p_mu(0,i2),p_mu(1,i2),p_mu(2,i2)); + // find roadmap isolation (only long tracks) + IsHltGood(o, p, omu, pmu ,PosPV, hltgood, fc); + if ( msgLevel(MSG::DEBUG) ) debug() <<"=========== 8"<< endmsg; + + // find doca and angle between input and other tracks + Gaudi::XYZPoint vtx(0.,0.,0.); + double doca(-1.); + double angle(-1.); + InCone(omu,pmu, o, p, vtx, doca, angle); + // find impact parameters, distances from secondary and primary vertex + doca2[i2]=doca; + if (doca2[i2](m_PVInputLocation)){ + verts = get(m_PVInputLocation); + } + for ( iv = verts->begin(); iv != verts->end(); iv++) { + m_Geom->distance(&(*cand),(*iv),imp,impchi2); + if (impchi2track()->info(LHCb::Track::AdditionalInfo::CloneDist,100000); + float ghost = proto->track()->ghostProbability(); + double trchi2 = proto->track()->chi2()/proto->track()->nDoF(); + // non-isolating criteria #5 + if (angle m_ips && + svdis>m_svdis && svdism_pvdis && pvdism_clone && ghosttype()==m_tracktype + && trchi2m_hltgood) { + //is_iso5 = true; + if (i2==0) iso_parts_0.push_back(cand) ; + if (i2==1) iso_parts_1.push_back(cand) ; + iso5[i2] += 1; + if ( msgLevel(MSG::DEBUG) ) debug()<<"isiso "<< i2 << iso5[i2]<< endmsg; + } + + + }// i<2 + + } // (!isInList) + }// allparts + + massiso[0]=0.; + chi2iso[0]=-100.; + massiso[1]=0.; + chi2iso[1]=-100.; + + LHCb::Vertex vertex0 ; + LHCb::Particle mother0 ; + LHCb::Vertex vertex1 ; + LHCb::Particle mother1 ; + if ( msgLevel(MSG::DEBUG) ) debug() <<"=========== 11"<< endmsg; + + if (iso_parts_0.size()>1) { + + StatusCode sc0 = StatusCode::SUCCESS; + sc0 = m_combiner->combine(iso_parts_0,mother0,vertex0 ) ; + if(sc0==StatusCode::SUCCESS) { + massiso[0] = mother0.measuredMass(); + chi2iso[0] = mother0.endVertex()->chi2(); + chi2iso[0] = chi2iso[0]/mother0.endVertex()->nDoF(); + } + } + + else { + iso_parts_0.push_back(bestpart_0); + if ( msgLevel(MSG::DEBUG) ) debug()<<"trying to get to this stage "<combine(iso_parts_0,mother0,vertex0 ) ; + if(sc0a==StatusCode::SUCCESS) { + chi2iso[0] = mother0.endVertex()->chi2(); + chi2iso[0] = chi2iso[0]/mother0.endVertex()->nDoF(); + } + } + + + if (iso_parts_1.size()>1) { + StatusCode sc1 = StatusCode::SUCCESS; + sc1 = m_combiner->combine(iso_parts_1,mother1,vertex1 ) ; + if(sc1==StatusCode::SUCCESS) { + massiso[1] = mother1.measuredMass(); + chi2iso[1] = mother1.endVertex()->chi2(); + chi2iso[1] = chi2iso[1]/mother1.endVertex()->nDoF(); + } + } + + else { + iso_parts_1.push_back(bestpart_1); + StatusCode sc1a = StatusCode::SUCCESS; + sc1a = m_combiner->combine(iso_parts_1,mother1,vertex1 ) ; + if(sc1a==StatusCode::SUCCESS) { + chi2iso[1] = mother1.endVertex()->chi2(); + chi2iso[1] = chi2iso[1]/mother1.endVertex()->nDoF(); + } + } + + if ( msgLevel(MSG::DEBUG) ) debug()<<"NTRACKS "<column( prefix+"_P1_massiso", massiso[0]).isSuccess(); + test &= tuple->column( prefix+"_P2_massiso", massiso[1]); + + test &= tuple->column( prefix+"_P1_Q", storeCharge[0]); + test &= tuple->column( prefix+"_P2_Q", storeCharge[1]); + + test &= tuple->column( prefix+"_P1_chi2iso", chi2iso[0]); + test &= tuple->column( prefix+"_P2_chi2iso", chi2iso[1]); + + test &= tuple->column( prefix+"_P1_iso5", iso5[0]); + test &= tuple->column( prefix+"_P2_iso5", iso5[1]); + + if(test) return StatusCode::SUCCESS; + else return StatusCode::FAILURE; +} + +//============================================================================= +// +//============================================================================= +void TupleToolIsolationTwoBody::IsHltGood(Gaudi::XYZPoint o,Gaudi::XYZVector p, + Gaudi::XYZPoint o_mu,Gaudi::XYZVector + p_mu, Gaudi::XYZPoint PV, int& hltgood, + double& fc) const +{ + + Gaudi::XYZVector rv; + Gaudi::XYZPoint vtx; + Gaudi::XYZPoint close; + Gaudi::XYZPoint close_mu; + bool fail(false); + closest_point(o,p,o_mu,p_mu,close,close_mu,vtx,fail); + if (fail) { + fc = -1.; + hltgood = -1; + } + else { + double pete = p.Rho(); + rv = vtx - PV; + double DOCA_b = (close-close_mu).R(); + double ZZ = rv.z(); + fc = pointer(rv,p,p_mu); + if ((DOCA_b<0.2) && (ZZ>0.) && (ZZ<30.) && (fc<0.4) && (pete>2.)) hltgood = 1; + } +} + + +//============================================================================= +// +//============================================================================= +void TupleToolIsolationTwoBody::InCone(Gaudi::XYZPoint o1, + Gaudi::XYZVector p1,Gaudi::XYZPoint o2, + Gaudi::XYZVector p2, + Gaudi::XYZPoint& vtx, double& + doca, double& angle) const +{ + Gaudi::XYZPoint rv; + Gaudi::XYZPoint close; + Gaudi::XYZPoint close_mu; + bool fail(false); + closest_point(o1,p1,o2,p2,close,close_mu,vtx, fail); + if (fail) { + doca =-1.; + angle=-1.; + } + else { + doca = (close-close_mu).R(); + angle = arcosine(p1,p2); + } +} + +//============================================================================= +// +//============================================================================= +double TupleToolIsolationTwoBody::pointer (Gaudi::XYZVector vertex, + Gaudi::XYZVector p, Gaudi::XYZVector + p_mu) const +{ + double pt=p.Rho()+p_mu.Rho(); + Gaudi::XYZVector ptot(p+p_mu); + double num=ptot.R()*sin(arcosine(vertex,ptot)); + double den=(num+pt); + double fc = num/den; + return fc; +} + +//============================================================================= +// +//============================================================================= +double TupleToolIsolationTwoBody::ratio( double p1, double p2) const +{ + return TMath::Abs(p1 -p2)*(1./TMath::Abs(p1+p2)); +} + +//============================================================================= +// +//============================================================================= + +double TupleToolIsolationTwoBody::arcosine(Gaudi::XYZVector p1, + Gaudi::XYZVector p2) const +{ + + double num=(p1.Cross(p2)).R(); + double den=p1.R()*p2.R(); + double seno = num/den; + double coseno = p1.Dot(p2)/den; + double alpha = asin(fabs(seno)); + if (coseno < 0 ) { + alpha = ROOT::Math::Pi() - alpha; + } + return alpha; +} + +//============================================================================= +// +//============================================================================= +void TupleToolIsolationTwoBody::closest_point(Gaudi::XYZPoint o,Gaudi::XYZVector p, + Gaudi::XYZPoint o_mu,Gaudi::XYZVector + p_mu, Gaudi::XYZPoint& close1, + Gaudi::XYZPoint& close2, + Gaudi::XYZPoint& vertex, bool& + fail) const +{ + Gaudi::XYZVector v0(o - o_mu); + Gaudi::XYZVector v1(p.unit()); + Gaudi::XYZVector v2(p_mu.unit()); + Gaudi::XYZPoint temp1(0.,0.,0.); + Gaudi::XYZPoint temp2(0.,0.,0.); + fail = false; + + double d02 = v0.Dot(v2); + double d21 = v2.Dot(v1); + double d01 = v0.Dot(v1); + double d22 = v2.Dot(v2); + double d11 = v1.Dot(v1); + double denom = d11 * d22 - d21 * d21; + if (fabs(denom) <= 0.) { + close1 = temp1; + close2 = temp2; + fail = true; + } + else { + double numer = d02 * d21 - d01 * d22; + double mu1 = numer / denom; + double mu2 = (d02 + d21 * mu1) / d22; + close1 = o+v1*mu1; + close2 = o_mu+v2*mu2; + } + vertex = (close1+(close2-close1)*0.5); +} + + +//============================================================================= +// +//============================================================================= +const LHCb::MCParticle* TupleToolIsolationTwoBody::ancestor(const LHCb::MCParticle*imc) const { + if (imc->mother()) { + const LHCb::MCParticle*mc_mom = imc->mother(); + if ( msgLevel(MSG::DEBUG) ) + { + debug()<<"iso c "<< mc_mom << endmsg; + debug()<<"iso c "<< mc_mom->momentum() << endmsg; + debug()<<"iso c "<< mc_mom->particleID() << endmsg; + debug()<<"iso c "<< mc_mom->mother() << endmsg; + } + return ancestor(mc_mom); + } + else { + return imc; + } +} + +//============================================================================= +// Destructor +//============================================================================= +TupleToolIsolationTwoBody::~TupleToolIsolationTwoBody() { +} + +//============================================================================= diff --git a/first-analysis-steps/DecayTrees/TupleToolIsolationTwoBody.h b/first-analysis-steps/DecayTrees/TupleToolIsolationTwoBody.h new file mode 100644 index 00000000..a256be39 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolIsolationTwoBody.h @@ -0,0 +1,186 @@ +#ifndef TUPLETOOLISOLATIONTWOBODY_H +#define TUPLETOOLISOLATIONTWOBODY_H 1 + +#include "Kernel/IDistanceCalculator.h" +#include "Kernel/IParticleTupleTool.h" +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IRelatedPVFinder.h" +#include "Event/RecVertex.h" + +#include "MuonDet/MuonBasicGeometry.h" +#include "MuonDet/DeMuonDetector.h" + +class IParticle2MCAssociator; +struct IParticleCombiner; +struct IDVAlgorithm; + + +//#include "IIsolation.h" // Interface + +//using namespace LHCb; + +/** @class TupleToolIsolationTwoBody TupleToolIsolationTwoBody.h + * Implementation for a "Particle Isolation" tool for particles from + * twobody decays. + * It return the degree of isolation of two particles with a common mother. + * + * Currently it returns the numbers of non-isolating particles associated + * with each of the input particles. + * + * @author Fatima Soomro, based on the code by Giampiero Mancinelli giampi@cppm.in2p3.fr in DaVinciTools + * @date 2012-03-17 + */ +class TupleToolIsolationTwoBody : public TupleToolBase, + public virtual IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolIsolationTwoBody(const std::string& type, + const std::string& name, + const IInterface* parent ); + + /// Standard initialization + StatusCode initialize() override; + + virtual ~TupleToolIsolationTwoBody( ); ///< Destructor + +public: + + StatusCode fill( const LHCb::Particle*, const LHCb::Particle*, + const std::string & head, Tuples::Tuple& tuple ) override; + +private: + + /** The method for the evaluation of the degree of isolation ("number + * of non-isolating tracks") of the input set of particles. + * + * @code + * + * // get the tool + * const IParticleIsolation* tool = ...; + * Particle::ConstVector vdaugh = ... ; + * int iso[2] = ... ; + * --> for new (#5) definition (see LHCb-INT-2010-011) + * --> other criteria defined in the same note are not yet implemented + * float massiso[2] = invariant mass of non-isolating particles + * float chi2iso[2] = chi2 of particle made with non-isolating particles + * const RecVertex* PV = ...; + * const RecVertex* SV = ...; + * + * // use the tool to evaluate the degrees of isolation + * StatusCode sc = tool ->getIso(vdaugh,iso,massiso,chi2iso,PV,SV); + * + * @endcode + * + * @param vdaugh (input) pointer to the input set particles (2 particles) + * @param iso (output) number(s) of non-isolating particles (2 isolations) + * @param massiso (output) invariant mass of non-isolating particles + * @param chi2iso (output) chi2 of particle made with non-isolating particles + * @param PV (input) (optional) primary vertex + * @param SV (input) (optional) secondary vertex (of mother) + * + * @return status code + */ + /* virtual StatusCode getIso(LHCb::Particle::ConstVector parts, */ + /* int* iso, float* massiso, float* chi2iso, */ + /* const LHCb::VertexBase* PV, */ + /* const LHCb::VertexBase* SV) const ; */ + + virtual StatusCode getIso(const LHCb::Particle*, std::string, Tuples::Tuple& ); + + StatusCode MuChi2( const LHCb::Particle* P, const std::string& head, Tuples::Tuple& tuple); + + /** Defines whether or not a particle is not isolating according to the + BsMuMu Roadmap, using an Hlt criterium + */ + void IsHltGood(Gaudi::XYZPoint o, + Gaudi::XYZVector p, + Gaudi::XYZPoint o_mu, + Gaudi::XYZVector + p_mu, Gaudi::XYZPoint PV, int& + hltgood, double& fc) const; + /** given two tracks returns the closest point, the doca and the angle + between the tracks + */ + void InCone(Gaudi::XYZPoint o1, + Gaudi::XYZVector p1, + Gaudi::XYZPoint o2, + Gaudi::XYZVector p2, + Gaudi::XYZPoint& vtx, double& + doca, double& angle) const; + /** given two particles and the vector between the PV and vertex defined + * by them, it returns : + * fc=\frac{\left|\vec{P_{\mu}}+\vec{P_{tr}}\right|\cdot\alpha^{\mu+tr,PV}} + * {\left|\vec{P_{\mu}}+\vec{P_{tr}}\right|\cdot\alpha^{\mu+tr,PV}+P_{T\mu} + * +P_{Ttr}} + * where $P_{T\mu}$ and $P_{Ttr}$ are the transverse momenta (with respect + * to the beam line) of the two tracks. + */ + double pointer (Gaudi::XYZVector vtx, + Gaudi::XYZVector P_tr, + Gaudi::XYZVector P_mu) const; + + /// return the arcosine between two vectors + double arcosine(Gaudi::XYZVector p1, + Gaudi::XYZVector p2) const; + + /** given two vectors and two application points finds for the two relevant + * straight lines the closest points along the lines and the middle one + * between the such points + */ + void closest_point(Gaudi::XYZPoint o, + Gaudi::XYZVector p, + Gaudi::XYZPoint o_mu, + Gaudi::XYZVector + p_mu, Gaudi::XYZPoint& close1, + Gaudi::XYZPoint& close2, + Gaudi::XYZPoint& vertex, bool& + fail) const; + + const LHCb::MCParticle* ancestor(const LHCb::MCParticle*) const; + +private: + + const IDistanceCalculator* m_Geom; + std::string m_ParticlePath; + + bool m_MuChi2; + /// cut on opening angle between tracks + double m_angle; + /// cut on pointing (hlt) (see LHCb-INT-2010-011) + double m_fc; + /// cut on distance of closest approach of tracks + double m_doca; + /// cut on particles minimum impact parameter with respect to PV + double m_ips; + /// cut on distance (low) between two track vertex and and the mother SV + double m_svdis; + /// cut on distance (high) between two track vertex and and the mother SV + double m_svdis_h; + /// cut on distance (low) between two track vertex and and the mother PV + double m_pvdis; + /// cut on distance (high) between two track vertex and and the mother PV + double m_pvdis_h; + /// cut on ghost probability + double m_ghost; + /// cut on clone probability + double m_clone; + /// cut on trk chi2 + double m_trchi2; + /// cut on hltgood + double m_hltgood; + int m_tracktype; + std::string m_PVInputLocation; + double ratio( double p1, double p2) const; + + // bool m_tuple; + bool m_isMC; + IParticle2MCAssociator* m_p2mcAssoc; + const IParticleCombiner* m_combiner; + IDVAlgorithm* m_dva; + + std::string m_p2mcAssocType; +}; +#endif // TUPLETOOLISOLATIONTWOBODY_H diff --git a/first-analysis-steps/DecayTrees/TupleToolJetRelations.cpp b/first-analysis-steps/DecayTrees/TupleToolJetRelations.cpp new file mode 100644 index 00000000..7b714c4c --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolJetRelations.cpp @@ -0,0 +1,165 @@ +#include "TupleToolJetRelations.h" +#include +#include +#include "boost/lexical_cast.hpp" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolJetRelations +// Autor: Albert Bursche +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolJetRelations ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolJetRelations::TupleToolJetRelations( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolJetsBase ( type, name , parent ) + +{ + declareInterface(this); + declareProperty( "RelationsContainer",m_RelationsContainer = "", + "Where to find the table to get information from." ); + declareProperty( "InvertTable",m_Invert = false, + "Invert relation table" ); + declareProperty( "ReverseMatching",m_Reverse = false, + "Does best matching correspond to highes or lowest weight?" ); + declareProperty( "MaxMatches",m_MaxMatches=1, + "How many matches in the tuple?" ); + declareProperty( "ExtraWeights",m_ExtraTableLocations=std::map(), + "Write the 'weight' parameter of these tables in the tuple. Uses the value of 'InvertTable'." ); +} + +//============================================================================= + +StatusCode TupleToolJetRelations::fill( const LHCb::Particle* /* top */, + const LHCb::Particle* p, + const std::string& head , + Tuples::Tuple& tuple ) +{ + m_tuple = &tuple; + bool test = true; + m_p = p; + m_head = m_extraName+head; + // if(exist(m_RelationsContainer)) + for ( std::map::const_iterator it = m_ExtraTableLocations.begin(); + it != m_ExtraTableLocations.end();++it) + { + IJets2Jets::Table * tab = 0; + getTable(it->second,tab); + m_ExtraTables[it->first] = tab; + } + if (m_ExtraTables.size()!=m_ExtraTableLocations.size()) + return StatusCode::FAILURE; + if (getTable(m_RelationsContainer,m_Table)==StatusCode::SUCCESS) + { + IJets2Jets::Table::Range r = m_Table->i_relations(p); + (*m_tuple)->column( m_head+"_numMatches",r.size()); + unsigned int numMatches = 0; + if (r.size()) + { + if(m_Reverse) + { + IJets2Jets::Table::Range::reverse_iterator it = r.rbegin(); + for (;numMatches::iterator it = m_ExtraTables.begin(); + it != m_ExtraTables.end();++it) + if (it->second) + { + delete it->second; + it->second = 0; + } + } + } + return StatusCode(test); +} + +double TupleToolJetRelations::DeltaR(const LHCb::Particle& jet,const LHCb::Particle& jet2) +{ //Delta R + double dphi = jet.momentum().Phi()- jet2.momentum().Phi(); + while (fabs(dphi)>M_PI) + dphi+=(dphi>0)?-2*M_PI:2*M_PI; + return sqrt(pow(jet.momentum().Eta()- jet2.momentum().Eta(),2)+pow(dphi,2)); +} +#define SAVEPOINT(POINT,FUN) \ + (POINT?POINT->FUN:-1.0) +bool TupleToolJetRelations::fill(unsigned int i,const IJets2Jets::Table::Entry *e) +{ + bool test = true; + std::string I = boost::lexical_cast(i); + if ( msgLevel(MSG::DEBUG) ) + debug() << "Tuple: "<< m_tuple << "\t"+ I +" \tRelation" << e << endmsg; + + test &=(*m_tuple)->column(m_head+"Relation"+I+"weight",SAVEPOINT(e,weight())); + test &=(*m_tuple)->column(m_head+"Relation"+I+"DeltaR",e==0?-1:DeltaR((*e->from()),*(e->to()))); + if (e&&e->to()) + WriteJetToTuple(e->to(),m_head+"Relation"+I+"Jet"); + else + WriteJetToTuple(0 ,m_head+"Relation"+I+"Jet"); + for (std::map::const_iterator it = m_ExtraTables.begin(); + it != m_ExtraTables.end();++it) + if (it->second)//this should be true for either all or no events + { + bool found = false; + // IJets2Jets::Table::Range FromRes = it->second->i_relations (e->from()); + if(e&&e->to()&&e->from()) + { + IJets2Jets::Table::Range FromRes = it->second->i_relations (e->from()); + for (IJets2Jets::Table::Range::iterator jt = FromRes.begin(); jt!=FromRes.end();++jt ) + if (jt->to()==e->to()) + { + if (found) + Error("Table corrupted!"); + debug() << "Writing value in " << m_head+"Relation"+I+it->first << endmsg; + test &=(*m_tuple)->column(m_head+"Relation"+I+it->first,jt->weight()); + found = true; + } + } + if (!found) + { + debug() << "Writing dummy in " << m_head+"Relation"+I+it->first << endmsg; + test &=(*m_tuple)->column(m_head+"Relation"+I+it->first,(double)-1); + } + } + return test; +} +StatusCode TupleToolJetRelations::getTable(std::string loc,IJets2Jets::Table*&tab) +{ + if(exist(loc)) + { + tab = get(loc); + if (m_Invert) + tab = new IJets2Jets::Table(*tab,1); + debug() << "Retrieved table from :" << loc << endmsg; + return StatusCode::SUCCESS; + } + else + { + tab = 0; + return StatusCode::FAILURE; + } +} diff --git a/first-analysis-steps/DecayTrees/TupleToolJetRelations.h b/first-analysis-steps/DecayTrees/TupleToolJetRelations.h new file mode 100644 index 00000000..1e8b05ad --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolJetRelations.h @@ -0,0 +1,45 @@ +#ifndef TUPLETOOLJETRELATIONS_H +#define TUPLETOOLJETRELATIONS_H 1 + +#include "TupleToolJetsBase.h" +#include "Kernel/IParticleTupleTool.h" +#include + +//autor: Albert Bursche +class TupleToolJetRelations : public TupleToolJetsBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolJetRelations( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolJetRelations(){} ///< Destructor + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; +private: + + std::string m_RelationsContainer; + bool m_Invert; // invert relation table + bool m_Reverse;// reverse order in relation table (true highest weight is closest) + IJets2Jets::Table * m_Table; + const LHCb::Particle * m_p; + // Tuples::Tuple* m_tuple; + unsigned int m_MaxMatches; + std::string m_head; + static double DeltaR(const LHCb::Particle&,const LHCb::Particle&); //can be made virtual to allow using the same code with different distance measure + bool furtherAway (LHCb::Particle& a,LHCb::Particle& b) + {return DeltaR(*m_p,a)>DeltaR(*m_p,b);} + bool fill(unsigned int i,const IJets2Jets::Table::Entry *e); + std::map m_ExtraTableLocations; + std::map m_ExtraTables; + StatusCode getTable(std::string loc,IJets2Jets::Table*&tab); +}; + +#endif // TUPLETOOLJETRELATIONS_H diff --git a/first-analysis-steps/DecayTrees/TupleToolJetTag.cpp b/first-analysis-steps/DecayTrees/TupleToolJetTag.cpp new file mode 100644 index 00000000..3875b2fd --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolJetTag.cpp @@ -0,0 +1,137 @@ +//----------------------------------------------------------------------------- +// +// Implementation file for class TupleToolJetTag +// +// Runs one jet tagging algorithm and writes the value out to the tuple +// +//----------------------------------------------------------------------------- + +//============================================================================= +// Setup +#include "Event/Particle.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "Kernel/IJets2Jets.h" + +#include "TupleToolJetTag.h" + +DECLARE_COMPONENT( TupleToolJetTag ) + + //============================================================================= + // Constructor +TupleToolJetTag::TupleToolJetTag(const std::string& type, + const std::string& name, + const IInterface* parent) + : TupleToolJetsBase(type, name , parent) + , m_TagTool(NULL) +{ + declareInterface(this); + + declareProperty("tagToolName", + m_tagToolName, + "name of jet tagger"); + + declareProperty("tagToolLabel", + m_tagToolLabel, + "label of jet tagger for tuple"); + + declareProperty( "VerboseTag", m_verboseTag=false ); + + +} + + +//============================================================================= +// Initalise +StatusCode TupleToolJetTag::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_TagTool = tool(m_tagToolName,m_tagToolName, this); + + return sc; +} + + +//============================================================================= +// Execute +StatusCode TupleToolJetTag::fill(const LHCb::Particle*, + const LHCb::Particle* jet, + const std::string& head, + Tuples::Tuple& tuple) +{ + bool result = true; + if ( jet ) + { + const std::string prefix = fullName(head); + + // Run jet tag tool + std::map property; + m_TagTool->calculateJetProperty(jet, property); + if(property.empty()) + if(msgLevel(MSG::ERROR)) debug() << "Write tag to ntuple --- not found "<< endmsg; + if(m_tagToolName!="LoKi::BDTTag"){ + for( std::map::iterator it = property.begin(); + it != property.end(); ++it ) + { + + result &= (tuple)->column(prefix + "_" + m_tagToolLabel +"_" + (it->first) , (it->second)); + + } + }else{ + //spacial case for BDTTag. + std::vector fdrMin,ptSvrJet,nTrk,nTrkJet,drSvrJet; + std::vector absQSum,m,mCor,fdChi2,ipChi2Sum; + std::vectorbdt0,bdt1,pass,tau,z,pt,backwards; + for (int idx = 0;idx!=(int) property.size()+1;idx++){ + + std::stringstream pre; pre << "Tag" << idx << "_"; + + fdrMin.push_back(property[pre.str()+"fdrMin"]); + ptSvrJet.push_back(property[pre.str()+"ptSvrJet"]); + nTrk.push_back(property[pre.str()+"nTrk"]); + nTrkJet.push_back(property[pre.str()+"nTrkJet"]); + drSvrJet.push_back(property[pre.str()+"drSvrJet"]); + absQSum.push_back(property[pre.str()+"absQSum"]); + m.push_back(property[pre.str()+"m"]); + mCor.push_back(property[pre.str()+"mCor"]); + fdChi2.push_back(property[pre.str()+"fdChi2"]); + ipChi2Sum.push_back(property[pre.str()+"ipChi2Sum"]); + bdt0.push_back(property[pre.str()+"bdt0"]); + bdt1.push_back(property[pre.str()+"bdt1"]); + pass.push_back(property[pre.str()+"pass"]); + tau.push_back(property[pre.str()+"tau"]); + z.push_back(property[pre.str()+"z"]); + pt.push_back(property[pre.str()+"pt"]); + backwards.push_back(property[pre.str()+"backwards"]); + int idx2 = idx +1; + std::stringstream pre2; pre2 << "Tag" << idx2 << "_"; + if(property.find(pre2.str()+"fdrMin") == property.end()) + break; + } + + result &= (tuple)->column(prefix + "_" + m_tagToolLabel +"_Tag" , property["Tag"]); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_fdrMin" , fdrMin.begin(), fdrMin.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_ptSvrJet" , ptSvrJet.begin(), ptSvrJet.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_nTrk" , nTrk.begin(), nTrk.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_nTrkJet" , nTrkJet.begin(), nTrkJet.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_drSvrJet" , drSvrJet.begin(), drSvrJet.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_absQSum", absQSum.begin(), absQSum.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_m", m.begin(), m.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_mCor", mCor.begin(), mCor.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_fdChi2", fdChi2.begin(), fdChi2.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_ipChi2Sum", ipChi2Sum.begin(), ipChi2Sum.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_bdt0", bdt0.begin(), bdt0.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_bdt1", bdt1.begin(), bdt1.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_pass", pass.begin(), pass.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_tau", tau.begin(), tau.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_z", z.begin(), z.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_pt", pt.begin(), pt.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + result &= (tuple)->farray(prefix + "_" + m_tagToolLabel +"_backwards", backwards.begin(), backwards.end(), prefix + "_" + m_tagToolLabel +"_NbTag", 20); + + } + } + + return StatusCode(result); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolJetTag.h b/first-analysis-steps/DecayTrees/TupleToolJetTag.h new file mode 100644 index 00000000..c21a00c4 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolJetTag.h @@ -0,0 +1,43 @@ +// $Id: TupleToolJetTagTag.h,v 1.1 2011-05-16 14:14:14 aphan Exp $ +#ifndef TUPLETOOLJETTAG_H +#define TUPLETOOLJETTAG_H 1 + +#include "Kernel/IJetTagTool.h" +#include "Kernel/IParticleTupleTool.h" +#include "TupleToolJetsBase.h" + +class TupleToolJetTag : public TupleToolJetsBase, + virtual public IParticleTupleTool +{ + +public: + + TupleToolJetTag(const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolJetTag(){}; + + StatusCode initialize() override; + + StatusCode fill(const LHCb::Particle*, + const LHCb::Particle*, + const std::string&, + Tuples::Tuple&) override; + +private: + + // label for ntuple + std::string m_tagToolLabel; + + // name to retrieve tool + std::string m_tagToolName; + +protected: + + IJetTagTool* m_TagTool; + bool m_verboseTag; ///< get details on Tag + +}; + +#endif // TUPLETOOLJET_H diff --git a/first-analysis-steps/DecayTrees/TupleToolJets.cpp b/first-analysis-steps/DecayTrees/TupleToolJets.cpp new file mode 100644 index 00000000..c38aee79 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolJets.cpp @@ -0,0 +1,39 @@ +#include "TupleToolJets.h" +#include +#include +#include "boost/lexical_cast.hpp" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolJets +// Autor: Albert Bursche +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolJets ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolJets::TupleToolJets( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolJetsBase ( type, name , parent ) + +{ + declareInterface(this); +} + +//============================================================================= + +StatusCode TupleToolJets::fill( const LHCb::Particle* /* top */, + const LHCb::Particle* p, + const std::string& head , + Tuples::Tuple& tuple ) +{ + m_tuple = &tuple; + bool test = true; + m_p = p; + m_head = m_extraName+head; + test &= WriteJetToTuple(p,m_head); + return StatusCode(test); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolJets.h b/first-analysis-steps/DecayTrees/TupleToolJets.h new file mode 100644 index 00000000..82991db8 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolJets.h @@ -0,0 +1,33 @@ +#ifndef TUPLETOOLJETS_H +#define TUPLETOOLJETS_H 1 + +#include "TupleToolJetsBase.h" +#include "Kernel/IParticleTupleTool.h" + +//autor: Albert Bursche +class TupleToolJets : public TupleToolJetsBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolJets( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolJets(){} ///< Destructor + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + const LHCb::Particle * m_p; + std::string m_head; + +}; + +#endif // TUPLETOOLJETS_H diff --git a/first-analysis-steps/DecayTrees/TupleToolJetsBase.cpp b/first-analysis-steps/DecayTrees/TupleToolJetsBase.cpp new file mode 100644 index 00000000..1678d138 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolJetsBase.cpp @@ -0,0 +1,212 @@ +#include "TupleToolJetsBase.h" +#include "LoKi/ParticleCuts.h" +#include "LoKi/AParticleCuts.h" + +TupleToolJetsBase::TupleToolJetsBase( const std::string& type, + const std::string& name, + const IInterface* parent) +: TupleToolBase ( type, name , parent ), + charge(LoKi::Cuts::ONE), + positiveParticles(LoKi::Cuts::ONE ), + negativeParticles(LoKi::Cuts::ONE ), + neutralParticles(LoKi::Cuts::ONE ), + maxPT(LoKi::Cuts::ONE ), + m_M(LoKi::Cuts::ONE ), + m_MM(LoKi::Cuts::ONE ) +{} +#define SAVEPOINT(POINT,FUN) \ + (POINT?POINT->FUN:-1.0) +bool TupleToolJetsBase::WriteJetToTuple(const LHCb::Particle*jet,std::string prefix) +{ + //filter plus and minus signs out to the prefix + std::map replacements ; + replacements["+"]="plus"; + replacements["-"]="minus"; + for (std::map::iterator it = replacements.begin();it != replacements.end();++it) + { + size_t point = 0; + while((point = prefix.find(it->first))!=std::string::npos) + prefix = prefix.replace(point,it->second.size(),it->second); + } + + if ( msgLevel(MSG::DEBUG) ) debug() << (jet?"Filling jet object ":"Filling dummy jet object ") << jet << " " << prefix << " in tuple at address "<column( prefix+"_PX", (double)( SAVEPOINT(jet,momentum().Px()))); + result &= (*m_tuple)->column( prefix+"_PY", (double)( SAVEPOINT(jet,momentum().Py()))); + result &= (*m_tuple)->column( prefix+"_PZ", (double)( SAVEPOINT(jet,momentum().Pz()))); + result &= (*m_tuple)->column( prefix+"_PE", (double)( SAVEPOINT(jet,momentum().e()))); + result &= (*m_tuple)->column( prefix+"_PT", (double)( SAVEPOINT(jet,momentum().Pt()))); + result &= (*m_tuple)->column( prefix+"_P", (double)( SAVEPOINT(jet,momentum().P()))); + result &= (*m_tuple)->column( prefix+"_Eta", (double)( SAVEPOINT(jet,momentum().Eta()))); + result &= (*m_tuple)->column( prefix+"_Phi", (double)( SAVEPOINT(jet,momentum().Phi()))); + result &= (*m_tuple)->column( prefix+"_M", (double)( SAVEPOINT(jet,momentum().mass()))); + + result &= (*m_tuple)->column( prefix+"_MLoKi", (double)(jet?m_M(jet):-99.0)); + result &= (*m_tuple)->column( prefix+"_MMLoKi", (double)( jet?m_MM(jet):-99.0)); + result &= (*m_tuple)->column( prefix+"_NTrk", (double)( jet->info(LHCb::JetIDInfo::Ntracks,-999.9))); + result &= (*m_tuple)->column( prefix+"_N90", (double)( jet->info(LHCb::JetIDInfo::N90,-999.9))); + result &= (*m_tuple)->column( prefix+"_MTF", (double)( jet->info(LHCb::JetIDInfo::MTF,-999.9))); + result &= (*m_tuple)->column( prefix+"_NSatCells", (double)( jet->info(LHCb::JetIDInfo::NSatCalo,-999.9))); + result &= (*m_tuple)->column( prefix+"_NHasPVInfo", (double)( jet->info(LHCb::JetIDInfo::NHasPV,-999.9))); + result &= (*m_tuple)->column( prefix+"_JEC_Cor", (double)( jet->info(LHCb::JECInfo::JEC,-999.9))); + result &= (*m_tuple)->column( prefix+"_JEC_PV", (double)( jet->info(LHCb::JECInfo::NPVsForJEC,-999.9))); + result &= (*m_tuple)->column( prefix+"_JEC_Error", (double)( jet->info(LHCb::JECInfo::JECError,-999.9))); + + + + double weigth = 1.0; + double myPT = (SAVEPOINT(jet,momentum().Pt())); + + + if(myPT < 20000) + weigth = 1 - ((20000-myPT)/16000); + + //weigth for 5GeV jet: + + + result &= (*m_tuple)->column( prefix+"_w", (double)( weigth)); + result &= (*m_tuple)->column( prefix+"_CPF", (double)( jet->info(LHCb::JetIDInfo::CPF,-999.9))); + result &= (*m_tuple)->column( prefix+"_JetWidth", (double)( jet->info(LHCb::JetIDInfo::JetWidth,-999.9))); + result &= (*m_tuple)->column( prefix+"_NSatECAL", (double)( jet->info(LHCb::JetIDInfo::NSatECAL,-999.9))); + result &= (*m_tuple)->column( prefix+"_NSatHCAL", (double)( jet->info(LHCb::JetIDInfo::NSatHCAL,-999.9))); + result &= (*m_tuple)->column( prefix+"_NIPChi2Inf4", (double)( jet->info(LHCb::JetIDInfo::NIPChi2Inf4,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfCharged", (double)( jet->info(LHCb::JetEnergyFractionInfo::Charged,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfChargedHadron", (double)( jet->info(LHCb::JetEnergyFractionInfo::ChargedHadron,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfMuon", (double)( jet->info(LHCb::JetEnergyFractionInfo::Muon,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfElectron", (double)( jet->info(LHCb::JetEnergyFractionInfo::Electron,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfNeutral", (double)( jet->info(LHCb::JetEnergyFractionInfo::Neutral,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfPhoton", (double)( jet->info(LHCb::JetEnergyFractionInfo::Photon,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfPi0", (double)( jet->info(LHCb::JetEnergyFractionInfo::Pi0,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfMPi0", (double)( jet->info(LHCb::JetEnergyFractionInfo::MergedPi0,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfRPi0", (double)( jet->info(LHCb::JetEnergyFractionInfo::ResolvedPi0,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfNHad", (double)( jet->info(LHCb::JetEnergyFractionInfo::NeutralHadron,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfNReco", (double)( jet->info(LHCb::JetEnergyFractionInfo::NeutralRecovery,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfCompo", (double)( jet->info(LHCb::JetEnergyFractionInfo::Composite,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfV0", (double)( jet->info(LHCb::JetEnergyFractionInfo::V0,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfD", (double)( jet->info(LHCb::JetEnergyFractionInfo::D,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfB", (double)( jet->info(LHCb::JetEnergyFractionInfo::B,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfBadParticle", (double)( jet->info(LHCb::JetEnergyFractionInfo::BadParticle,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfCharged0Momentum", (double)( jet->info(LHCb::JetEnergyFractionInfo::Charged0Momentum,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfChargedInfMomentum", (double)( jet->info(LHCb::JetEnergyFractionInfo::ChargedInfMomentum,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfBadPhotonMatchingT", (double)( jet->info(LHCb::JetEnergyFractionInfo::BadPhotonMatchingT,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfBadPhoton", (double)( jet->info(LHCb::JetEnergyFractionInfo::BadPhoton,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfIsolatedPhoton", (double)( jet->info(LHCb::JetEnergyFractionInfo::IsolatedPhoton,-999.9))); + result &= (*m_tuple)->column( prefix+"_NLongTrk", (double)( jet->info(LHCb::JetEnergyFractionInfo::NLongTrk,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfLongTrk", (double)( jet->info(LHCb::JetEnergyFractionInfo::EfLongTrk,-999.9))); + result &= (*m_tuple)->column( prefix+"_NDownTrk", (double)( jet->info(LHCb::JetEnergyFractionInfo::NDownTrk,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfDownTrk", (double)( jet->info(LHCb::JetEnergyFractionInfo::EfDownTrk,-999.9))); + result &= (*m_tuple)->column( prefix+"_NUpTrk", (double)( jet->info(LHCb::JetEnergyFractionInfo::NUpTrk,-999.9))); + result &= (*m_tuple)->column( prefix+"_EfUpTrk", (double)( jet->info(LHCb::JetEnergyFractionInfo::EfUpTrk,-999.9))); + + result &= (*m_tuple)->column( prefix+"_PU_NPVs", (double)( jet->info(LHCb::JetPileUpInfo::PUnPVs,-999.9))); + result &= (*m_tuple)->column( prefix+"_PU_Cone06_SumPTLongTrk", (double)( jet->info(LHCb::JetPileUpInfo::PUSumPTLongTrkCone06,-999.9))); + result &= (*m_tuple)->column( prefix+"_PU_Cone06_SumELongTrk", (double)( jet->info(LHCb::JetPileUpInfo::PUSumELongTrkCone06,-999.9))); + result &= (*m_tuple)->column( prefix+"_PU_Cone06_NLongTrk", (double)( jet->info(LHCb::JetPileUpInfo::PUNLongTrkCone06,-999.9))); + result &= (*m_tuple)->column( prefix+"_PU_Cone06_NUpVeloTrk", (double)( jet->info(LHCb::JetPileUpInfo::PUNUpVeloTrkCone06,-999.9))); + result &= (*m_tuple)->column( prefix+"_PU_Cone10_SumPTLongTrk", (double)( jet->info(LHCb::JetPileUpInfo::PUSumPTLongTrkCone10,-999.9))); + result &= (*m_tuple)->column( prefix+"_PU_Cone10_SumELongTrk", (double)( jet->info(LHCb::JetPileUpInfo::PUSumELongTrkCone10,-999.9))); + result &= (*m_tuple)->column( prefix+"_PU_Cone10_NLongTrk", (double)( jet->info(LHCb::JetPileUpInfo::PUNLongTrkCone10,-999.9))); + result &= (*m_tuple)->column( prefix+"_PU_Cone10_NUpVeloTrk", (double)( jet->info(LHCb::JetPileUpInfo::PUNUpVeloTrkCone10,-999.9))); + result &= (*m_tuple)->column( prefix+"_PU_Cone15_SumPTLongTrk", (double)( jet->info(LHCb::JetPileUpInfo::PUSumPTLongTrkCone15,-999.9))); + result &= (*m_tuple)->column( prefix+"_PU_Cone15_SumELongTrk", (double)( jet->info(LHCb::JetPileUpInfo::PUSumELongTrkCone15,-999.9))); + result &= (*m_tuple)->column( prefix+"_PU_Cone15_NLongTrk", (double)( jet->info(LHCb::JetPileUpInfo::PUNLongTrkCone15,-999.9))); + result &= (*m_tuple)->column( prefix+"_PU_Cone15_NUpVeloTrk", (double)( jet->info(LHCb::JetPileUpInfo::PUNUpVeloTrkCone15,-999.9))); + + + + + + + + + + + + +/* + + + + + + + + + + + + + + + + + + + result &= (*m_tuple)->column( prefix+"_ParticleMultiplicity", (double)( SAVEPOINT(jet,daughters().size()))); + // result &= (*m_tuple)->column( prefix+"_Charge", (double)( jet?charge(jet):-1.0)); + result &= (*m_tuple)->column( prefix+"_positiveParticleMultiplicity", (double)( jet?positiveParticles(jet):-1.0)); + result &= (*m_tuple)->column( prefix+"_negativeParticleMultiplicity", (double)( jet?negativeParticles(jet):-1.0)); + result &= (*m_tuple)->column( prefix+"_neutralParticleMultiplicity", (double)( jet?neutralParticles(jet):-1.0)); + result &= (*m_tuple)->column( prefix+"_chargedParticleMultiplicity", (double)( jet?positiveParticles(jet)+negativeParticles(jet):-1.0)); + result &= (*m_tuple)->column( prefix+"_maxPT", (double)( jet?maxPT(jet):-1.0)); + SmartRefVector< LHCb::Particle > SortedDaughters; + //buffer to store intermediate result to speed things up a bit + result &= (*m_tuple)->column( prefix+"_PT1", (double)( jet?MaxSumNPart(jet,1, LoKi::Cuts::PT,&SortedDaughters):-1.0)); + result &= (*m_tuple)->column( prefix+"_PT2", (double)( jet?MaxSumNPart(jet,2, LoKi::Cuts::PT,&SortedDaughters):-1.0)); + result &= (*m_tuple)->column( prefix+"_PT3", (double)( jet?MaxSumNPart(jet,3, LoKi::Cuts::PT,&SortedDaughters):-1.0)); + result &= (*m_tuple)->column( prefix+"_PT4", (double)( jet?MaxSumNPart(jet,4, LoKi::Cuts::PT,&SortedDaughters):-1.0)); + result &= (*m_tuple)->column( prefix+"_PT5", (double)( jet?MaxSumNPart(jet,5, LoKi::Cuts::PT,&SortedDaughters):-1.0)); + result &= (*m_tuple)->column( prefix+"_PT10", (double)( jet?MaxSumNPart(jet,10,LoKi::Cuts::PT,&SortedDaughters):-1.0)); + result &= (*m_tuple)->column( prefix+"_PT15", (double)( jet?MaxSumNPart(jet,15,LoKi::Cuts::PT,&SortedDaughters):-1.0)); + result &= (*m_tuple)->column( prefix+"_PT25", (double)( jet?MaxSumNPart(jet,25,LoKi::Cuts::PT,&SortedDaughters):-1.0)); + +*/ + + + + + + + + + + + + + + return result; +} + +StatusCode TupleToolJetsBase::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + //get LoKi objects + //charge = LoKi::Cuts::SUMTREE (LoKi::Cuts::Q, LoKi::Cuts::ALL, 0.0 ) ; + positiveParticles = LoKi::Cuts::NINTREE ( LoKi::Cuts::Q > 0 ); + negativeParticles = LoKi::Cuts::NINTREE ( LoKi::Cuts::Q < 0 ); + neutralParticles = LoKi::Cuts::NINTREE ( LoKi::Cuts::Q == 0 ); + maxPT = LoKi::Cuts::MAXTREE(LoKi::Cuts::PT,LoKi::Cuts::BASIC,-1); + m_M = LoKi::Particles::Mass(); + m_MM = LoKi::Particles::MeasuredMass(); + return sc ; +} + +double TupleToolJetsBase::MaxSumNPart(const LHCb::Particle* jet, + unsigned int n, + const LoKi::Types::Fun& fun, + SmartRefVector< LHCb::Particle >* SortedDaughters) +{ + // fun == LoKi::Cuts::ONE; + // if (jet->daughters().size() <= n) + // return LoKi::Cuts::SUMTREE ( LoKi::Cuts::BASIC, fun)(jet); + if (SortedDaughters&&SortedDaughters->size()) // Vector given and filled + return LoKi::Cuts::ASUM (fun)(LHCb::Particle::ConstVector(SortedDaughters->begin(),SortedDaughters->begin()+n)); + SmartRefVector< LHCb::Particle > daughters; //empty vector to take address of in case SortedDaughters == NULL + if (!SortedDaughters) + SortedDaughters = &daughters; + SortedDaughters->assign(jet->daughters().begin(),jet->daughters().end()); + sort(SortedDaughters->begin(),SortedDaughters->end(),Comperator(fun)); + return LoKi::Cuts::ASUM (fun)(LHCb::Particle::ConstVector(SortedDaughters->begin(),SortedDaughters->begin()+n)); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolJetsBase.h b/first-analysis-steps/DecayTrees/TupleToolJetsBase.h new file mode 100644 index 00000000..8537b1cc --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolJetsBase.h @@ -0,0 +1,42 @@ +#ifndef TUPLETOOLJETSBASE_H +#define TUPLETOOLJETSBASE_H 1 + +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" +#include "LoKi/LoKi.h" +#include "Kernel/JetEnums.h" + +//autor: Albert Bursche +class TupleToolJetsBase : public TupleToolBase, virtual public IParticleTupleTool { +public: + TupleToolJetsBase( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; +protected: + Tuples::Tuple* m_tuple; + LoKi::Types::Fun charge; + LoKi::Types::Fun positiveParticles; + LoKi::Types::Fun negativeParticles; + LoKi::Types::Fun neutralParticles; + LoKi::Types::Fun maxPT; + LoKi::Types::Fun m_M; + LoKi::Types::Fun m_MM; + + bool WriteJetToTuple(const LHCb::Particle*jet,std::string prefix); + double MaxSumNPart(const LHCb::Particle* jet,unsigned int n,const LoKi::Types::Fun& fun,SmartRefVector< LHCb::Particle >* SortedDaughters); + template + class Comperator + { + const LoKi::Types::Fun & m_fun; + public: + Comperator(const LoKi::Types::Fun &fun) + :m_fun(fun) + {} + bool operator()(T1 t1,T2 t2) + {return m_fun(t1)>m_fun(t2);} + }; +}; + +#endif //TUPLETOOLJETSBASE_H diff --git a/first-analysis-steps/DecayTrees/TupleToolJetsForB.cpp b/first-analysis-steps/DecayTrees/TupleToolJetsForB.cpp new file mode 100644 index 00000000..1436dcc5 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolJetsForB.cpp @@ -0,0 +1,552 @@ +// Include files + +// local +#include "TupleToolJetsForB.h" + +// global +#include +#include +#include "Event/Particle.h" +#include "LoKi/ParticleCuts.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolJetsForB +// +// 2014-06-30 : Xabier Cid Vidal +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( TupleToolJetsForB ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolJetsForB::TupleToolJetsForB( const std::string& type, + const std::string& name, + const IInterface* parent): +TupleToolBase ( type, name , parent ), + m_dva(0), + m_dist(0) +{ + + declareInterface(this); + + declareProperty( "ForceSamePV", + m_forcePV=true, + "Force only banned jets from same PV as initial B"); + + declareProperty("LocationJetsNoMu", + m_loc_jetsnomu="Phys/StdJetsNoJetIDNoMuFromB/Particles", + "Location of the jets where muons have been removed"); + + declareProperty("LocationJetsNoRemove", + m_loc_jetsinc="Phys/StdJetsNoJetID/Particles", + "Location of the jets where no particle has been removed"); + + declareProperty("LocationJetsForceB", + m_loc_jetsb="Phys/StdJetsNoJetIDForceB/Particles", + "Location of the jets where the B has been forced as a single particle"); + + declareProperty("UseVarsJetsNoMu", + m_use_jetsnomu=true, + "Store variables from the jets in which muons from B have been removed"); + + declareProperty("UseVarsJetsWithMu", + m_use_jetsinc=true, + "Store variables from the jets in which the B muons are present"); + + declareProperty("UseVarsJetsWithB", + m_use_jetsb=true, + "Store variables from the jets in which the B candidate is present"); + + + declareProperty("IndividualParticlePID",m_ind_part=13, + "This is initially for Bmunu or similar, the PID that should be searched for"); +} + +//==================================================================== +// Initialize DVAlg, etc +//==================================================================== +StatusCode TupleToolJetsForB::initialize() { + + // initialize the base class (the first action) + StatusCode sc = GaudiTool::initialize(); + if(sc.isFailure()) return sc; + + //initialize the dva algo + m_dva = Gaudi::Utils::getIDVAlgorithm ( contextSvc() , this) ; + if (0==m_dva) return Error("Couldn't get parent DVAlgorithm", + StatusCode::FAILURE); + + // Get distance calculator + m_dist = m_dva->distanceCalculator(); + if ( !m_dist ) { return Error("Unable to retrieve the IDistanceCalculator tool", + StatusCode::FAILURE); } + + m_TriggerTisTosTool = tool( "Hlt2TriggerTisTos","Hlt2TriggerTisTos",this ); + if(m_TriggerTisTosTool == 0) + return Error("Couldn't get requested jet tag tool", StatusCode::SUCCESS); + + + //initialize the nntag tool + //m_nnjettag = tool("LoKi::NNBTag",this); + + debug()<< "Initialization correct" << endmsg; + return StatusCode::SUCCESS; +} + +//============================================================================== +// Determine the maximum ratio of shard LHCbID by an HLT2 obj in a jet +//============================================================================= +double TupleToolJetsForB::jetNNTag(const LHCb::Particle* jet) +{ + + std::vector hltObjs + = m_TriggerTisTosTool->hltObjectSummaries("Hlt2Topo.*Decision",2,2); + + unsigned int num = hltObjs.size(); + + std::vector< LHCb::LHCbID > AllIDs; + AllIDs.clear(); + getJetLHCbIDs(jet, AllIDs); + double maxRatio = 0.; + for(unsigned int i = 0; i < num; i++){ + std::vector< LHCb::LHCbID > hltLHCbIDs; + hltLHCbIDs.clear(); + getHltObjLHCbIDs((hltObjs[i]),hltLHCbIDs); + double TotN = (double) hltLHCbIDs.size(); + double TotMatching = 0.0; + double ratio = 0.; + for(std::vector::iterator iID1 = hltLHCbIDs.begin(); iID1!= hltLHCbIDs.end(); iID1++){ + for(std::vector::iterator iAllIDs = AllIDs.begin(); iAllIDs != AllIDs.end(); iAllIDs++){ + if((*iID1).lhcbID() == (*iAllIDs).lhcbID()){ + TotMatching+=1.0; + ratio = TotMatching/TotN; + } + } + } + + if(ratio > maxRatio){ + maxRatio = ratio; + } + + } + + return maxRatio; +} + + + + +//========================================================================= +//Get the LHCbID of HLT obj +//========================================================================= +StatusCode TupleToolJetsForB::getHltObjLHCbIDs(const LHCb::HltObjectSummary * sum, std::vector< LHCb::LHCbID > & AllIDs) const{ + if (0==sum) return StatusCode::SUCCESS ; + if(sum->substructure().size()>0){ + for ( SmartRefVector< LHCb::HltObjectSummary >::const_iterator s = sum->substructure().begin() ; + s != sum->substructure().end() ; ++s) + getHltObjLHCbIDs(*s,AllIDs); + + + const std::vector< LHCb::LHCbID > lIDs = sum->lhcbIDsFlattened(); + AllIDs.insert(AllIDs.end(), lIDs.begin(), lIDs.end()); + + + }else{ + + const std::vector< LHCb::LHCbID > lIDs = sum->lhcbIDsFlattened(); + AllIDs.insert(AllIDs.end(), lIDs.begin(), lIDs.end()); + } + + return StatusCode::SUCCESS ; + +} + + + + +//========================================================================= +//Get daughters track the LHCbID of a jet. +//========================================================================= +StatusCode TupleToolJetsForB::getJetLHCbIDs(const LHCb::Particle* p, + std::vector< LHCb::LHCbID > & AllIDs) const{ + + if(p->particleID().abspid() == 98 ){ + LHCb::Particle::ConstVector daus = p->daughtersVector(); + for(LHCb::Particle::ConstVector::iterator idaus = daus.begin(); idaus != daus.end(); idaus++) + { + getJetLHCbIDs( (*idaus), AllIDs ); + } + }else{ + const LHCb::ProtoParticle * proto = p->proto() ; + if ( proto ) + { + if ( proto->track() ) { + const std::vector< LHCb::LHCbID > lIDs = proto->track()->lhcbIDs(); + AllIDs.insert(AllIDs.end(), lIDs.begin(), lIDs.end()); + } + else + { + for ( SmartRefVector::const_iterator iP = p->daughters().begin(); + iP != p->daughters().end(); ++iP ) + { + getJetLHCbIDs( *iP, AllIDs ); + } + } + } + } + return StatusCode::SUCCESS ; +} + +//============================================================================= +// Function to sort according to pT and same PV as B +//============================================================================= +void TupleToolJetsForB::pt_sorted_samePV(const LHCb::Particles & jets_list, + const int pvkey, std::vector & out_list) +{ + std::vector myPtParticleVector; + debug()<< jets_list.size() <<" jets to be sorted" << endmsg; + for( LHCb::Particles::const_iterator ijet = jets_list.begin() ; + ijet != jets_list.end() ; ++ijet){ + + // if pvkey<0, we skip this check + if (m_forcePV && pvkey>=0){ + const LHCb::VertexBase* BPV = m_dva->bestVertex(*ijet); + // only add if the pv is the same as the one of the B + if (BPV->key()!=pvkey) continue; + } + PtParticlePair mypair((*ijet)->pt(),(*ijet)); + myPtParticleVector.push_back(mypair); + } + //sort by pT (smaller to larger) + std::sort(myPtParticleVector.begin(), myPtParticleVector.end()); + //and now reverse it to have from larger to smaller + std::reverse(myPtParticleVector.begin(), myPtParticleVector.end()); + debug()<< myPtParticleVector.size() <<" jets sorted" << endmsg; + + // now store only the jets again + for( std::vector::const_iterator ipair = myPtParticleVector.begin() ; + ipair != myPtParticleVector.end() ; ++ipair){ + out_list.push_back(ipair->second->clone()); + } + debug()<< "Jet list ready" << endmsg; +} + +//============================================================================= +// Find jet with particle +//============================================================================= +StatusCode TupleToolJetsForB::find_jet_mu(const LHCb::Particles* list_of_jets, + const LHCb::Particle mu, LHCb::Particle& myjet) +{ + + debug() << "Looking for jets with muon "<< mu.key() << " inside" <begin() ; + ijet != list_of_jets->end() ; ++ijet){ + + // for each jet, loop in all the daughters + for( SmartRefVector< LHCb::Particle >::const_iterator idau = (*ijet)->daughters().begin() ; + idau != (*ijet)->daughters().end() ; ++idau){ + const LHCb::Particle dau = (*(*idau)); + // check if the daughter has the same key as the particle + if (!(dau.proto())) continue; + if (!(dau.proto()->track())) continue; + if (dau.proto()->track()->key()==mu.proto()->track()->key()) + { + jets_list.insert(*ijet,(*ijet)->key()); + debug()<< "Jet " << (*ijet)->key() << " has the muon inside!" < jets_list_sorted; + pt_sorted_samePV(jets_list,-1, jets_list_sorted); // the -1 is to avoid any PV check + // this is not needed because the PV of the muon should be the same as the PV of the jet (since the muon is inside) + debug()<< " These jets have been sorted " <begin() ; + ijet != list_of_jets->end() ; ++ijet){ + // for each jet, loop in all the daughters and store the jet if a B is part of the daughters + for( SmartRefVector< LHCb::Particle >::const_iterator idau = (*ijet)->daughters().begin() ; + idau != (*ijet)->daughters().end() ; ++idau){ + if ((*idau)->particleID().hasBottom()) { + jets_list.insert(*ijet,(*ijet)->key()); + debug()<< "Jet " << (*ijet)->key() << " has the B inside!" < jets_list_sorted; + pt_sorted_samePV(jets_list,-1,jets_list_sorted); // the -1 is to avoid any PV check, + // this is not needed because the PV of the B should be the same as the PV of the jet (since the B is inside) + if (!jets_list_sorted.size()) return StatusCode::FAILURE; + debug()<< " These jets have been sorted " < TupleToolJetsForB::emptyProperties(void) +{ + std::map out; + out["Px"]= -10.; + out["Py"]= -10.; + out["Pz"]= -10.; + out["PT"]= -10.; + out["JetWidth"]= -10.; + out["NNTag"]= -10.; + out["MNF"]= -10.; + debug() << "empty dict created" << endmsg; + return out; +} + + +//============================================================================= +// Empty properties list +//============================================================================= +std::map TupleToolJetsForB::fillProperties(LHCb::Particle* jet) +{ + std::map out; + out["Px"]= jet->momentum().x(); + out["Py"]= jet->momentum().y(); + out["Pz"]= jet->momentum().z(); + out["PT"]= jet->pt(); + out["JetWidth"]= LoKi::Cuts::INFO(9007,-10.)(jet); + out["MNF"]= LoKi::Cuts::INFO(9012,-10.)(jet); + out["NNTag"]= jetNNTag(jet); + debug() << "Dictionary created for jet " << jet->key() << endmsg; + debug() << "with value " << out << endmsg; + return out; +} + + +//============================================================================= +// Fill Output m_map +//============================================================================= +void TupleToolJetsForB::fillInfo(const std::string& prefix, + Tuples::Tuple& tuple){ + bool test = true; + + if (m_use_jetsnomu){ + test &= tuple->column(prefix+"_JETNOMU1PX",m_JetNoMu1["Px"]); + test &= tuple->column(prefix+"_JETNOMU1PY",m_JetNoMu1["Py"]); + test &= tuple->column(prefix+"_JETNOMU1PZ",m_JetNoMu1["Pz"]); + test &= tuple->column(prefix+"_JETNOMU1PT",m_JetNoMu1["PT"]); + test &= tuple->column(prefix+"_JETNOMU1JETWIDTH",m_JetNoMu1["JetWidth"]); + test &= tuple->column(prefix+"_JETNOMU1NNTAG",m_JetNoMu1["NNTag"]); + test &= tuple->column(prefix+"_JETNOMU1MNF",m_JetNoMu1["MNF"]); + test &= tuple->column(prefix+"_JETNOMU2PX",m_JetNoMu2["Px"]); + test &= tuple->column(prefix+"_JETNOMU2PY",m_JetNoMu2["Py"]); + test &= tuple->column(prefix+"_JETNOMU2PZ",m_JetNoMu2["Pz"]); + test &= tuple->column(prefix+"_JETNOMU2PT",m_JetNoMu2["PT"]); + test &= tuple->column(prefix+"_JETNOMU2JETWIDTH",m_JetNoMu2["JetWidth"]); + test &= tuple->column(prefix+"_JETNOMU2NNTAG",m_JetNoMu2["NNTag"]); + test &= tuple->column(prefix+"_JETNOMU2MNF",m_JetNoMu2["MNF"]); + test &= tuple->column(prefix+"_JETNOMU3PX",m_JetNoMu3["Px"]); + test &= tuple->column(prefix+"_JETNOMU3PY",m_JetNoMu3["Py"]); + test &= tuple->column(prefix+"_JETNOMU3PZ",m_JetNoMu3["Pz"]); + test &= tuple->column(prefix+"_JETNOMU3PT",m_JetNoMu3["PT"]); + test &= tuple->column(prefix+"_JETNOMU3JETWIDTH",m_JetNoMu3["JetWidth"]); + test &= tuple->column(prefix+"_JETNOMU3NNTAG",m_JetNoMu3["NNTag"]); + test &= tuple->column(prefix+"_JETNOMU3MNF",m_JetNoMu3["MNF"]); + } + + if (m_use_jetsinc){ + test &= tuple->column(prefix+"_JETMU1PX",m_JetMu1["Px"]); + test &= tuple->column(prefix+"_JETMU1PY",m_JetMu1["Py"]); + test &= tuple->column(prefix+"_JETMU1PZ",m_JetMu1["Pz"]); + test &= tuple->column(prefix+"_JETMU1PT",m_JetMu1["PT"]); + test &= tuple->column(prefix+"_JETMU1JETWIDTH",m_JetMu1["JetWidth"]); + test &= tuple->column(prefix+"_JETMU1NNTAG",m_JetMu1["NNTag"]); + test &= tuple->column(prefix+"_JETMU1MNF",m_JetMu1["MNF"]); + if (!(m_onemu)){ + test &= tuple->column(prefix+"_JETMU2PX",m_JetMu2["Px"]); + test &= tuple->column(prefix+"_JETMU2PY",m_JetMu2["Py"]); + test &= tuple->column(prefix+"_JETMU2PZ",m_JetMu2["Pz"]); + test &= tuple->column(prefix+"_JETMU2PT",m_JetMu2["PT"]); + test &= tuple->column(prefix+"_JETMU2JETWIDTH",m_JetMu2["JetWidth"]); + test &= tuple->column(prefix+"_JETMU2NNTAG",m_JetMu2["NNTag"]); + test &= tuple->column(prefix+"_JETMU2MNF",m_JetMu2["MNF"]); + } + } + if (m_use_jetsb){ + test &= tuple->column(prefix+"_JETBPX",m_JetB["Px"]); + test &= tuple->column(prefix+"_JETBPY",m_JetB["Py"]); + test &= tuple->column(prefix+"_JETBPZ",m_JetB["Pz"]); + test &= tuple->column(prefix+"_JETBPT",m_JetB["PT"]); + test &= tuple->column(prefix+"_JETBJETWIDTH",m_JetB["JetWidth"]); + test &= tuple->column(prefix+"_JETBNNTAG",m_JetB["NNTag"]); + test &= tuple->column(prefix+"_JETBMNF",m_JetB["MNF"]); + } + if (!test) Warning("Error in filling values "+prefix, StatusCode::SUCCESS, 1).ignore(); + +} + + +//============================================================================= +// Fill Jets RelatedInfo structure +//============================================================================= +StatusCode TupleToolJetsForB::fill( const LHCb::Particle* top + , const LHCb::Particle* part + , const std::string& head + , Tuples::Tuple& tuple) +{ + + const std::string prefix = fullName(head); + + debug() << "The top particle is " << top->key() << endmsg; + debug() << "And the particle is " << part->key() << endmsg; + + m_onemu = true; // in principle start with only one muon + m_JetNoMu1 = emptyProperties(); + m_JetNoMu2 = emptyProperties(); + m_JetNoMu3 = emptyProperties(); + m_JetMu1 = emptyProperties(); + m_JetMu2 = emptyProperties(); + m_JetB = emptyProperties(); + fillInfo(prefix,tuple); + + debug()<< "Filled empty dicts" << endmsg; + + // only fill infos for top particle! + if (part!=top) return StatusCode::SUCCESS; + + LHCb::Particle mu1; + LHCb::Particle mu2; + + // get bestPV of the top particle + const LHCb::VertexBase* BPV = m_dva->bestVertex(top); + + + // now find the RecVertex that is closest to the refitted one + double dist,distc2_tmp,distc2; + distc2 = 1e6; + LHCb::VertexBase* closePV=NULL; + LHCb::RecVertex::Container* verts = getIfExists(LHCb::RecVertexLocation::Primary); + // create a list of pairs ipchi2/vertex + for ( LHCb::RecVertex::Container::const_iterator iv = verts->begin(); iv != verts->end(); iv++) { + StatusCode sc = m_dist->distance(BPV,(*iv),dist,distc2_tmp); + if (sc.isFailure()) { + debug()<<"Failure obtaining IPchi2"<key(); + else bpvkey = 0; + debug() << "The top particle is associated to PV " << bpvkey << endmsg; + + // this is for Bmunu (m_ind_particle = 13) + if (top->particleID().pid()==m_ind_part ||top->particleID().pid()==((-1)*m_ind_part)) + { + mu1 = (*top); + m_onemu = true; + m_use_jetsb = false; + } + // and this for Bsmumu + else + { + mu1 = *(top->daughters().at(0)); + mu2 = *(top->daughters().at(1)); + m_onemu = false; + } + + debug()<< "m_onemu="<(m_loc_jetsnomu) ) + { + const LHCb::Particles* stdjets_nomu_0 = get(m_loc_jetsnomu); + // sort according to pT and same PV as B + std::vector stdjets_nomu; + pt_sorted_samePV(*stdjets_nomu_0,bpvkey,stdjets_nomu); + debug() << "Looking at " << stdjets_nomu.size()<< "jets" << endmsg; + if (stdjets_nomu.size()>0 ) m_JetNoMu1 = fillProperties(stdjets_nomu.at(0)); + if (stdjets_nomu.size()>1 ) m_JetNoMu2 = fillProperties(stdjets_nomu.at(1)); + if (stdjets_nomu.size()>2 ) m_JetNoMu3 = fillProperties(stdjets_nomu.at(2)); + debug() << "Jets info filled " << endmsg; + } + else debug() << "No jets found" << endmsg; + } + + + if (m_use_jetsinc) + { + debug() << "Jets with mu" <(m_loc_jetsinc) ) + { + const LHCb::Particles* stdjets_inc = get(m_loc_jetsinc); + LHCb::Particle myjet1; + StatusCode sc1 = find_jet_mu(stdjets_inc, mu1, myjet1); + if (sc1.isSuccess()){ + m_JetMu1 = fillProperties(&myjet1); + debug()<< "Jets with mu1, top pT" << myjet1.pt()<< endmsg; + } + + if (!m_onemu) + { + LHCb::Particle myjet2; + StatusCode sc2 = find_jet_mu(stdjets_inc, mu2, myjet2); + if (sc2.isSuccess()) { + debug()<< "Jets with mu2, top pT" << myjet2.pt()<< endmsg; + m_JetMu2 = fillProperties(&myjet2); + } + } + } + else debug() << "No jets found" << endmsg; + } + + if (m_use_jetsb) + { + debug() << "Jets with B" <(m_loc_jetsb) ) + { + const LHCb::Particles* stdjets_forceb = get(m_loc_jetsb); + LHCb::Particle myjet3; + StatusCode sc3 = find_jet_b(stdjets_forceb, myjet3); + if (sc3.isSuccess()) + { + debug()<< "Jets with B, top pT" << myjet3.pt()<< endmsg; + m_JetB = fillProperties(&myjet3); + } + } + else debug() << "No jets found" << endmsg; + } + + fillInfo(prefix,tuple); + return StatusCode::SUCCESS; +} + diff --git a/first-analysis-steps/DecayTrees/TupleToolJetsForB.h b/first-analysis-steps/DecayTrees/TupleToolJetsForB.h new file mode 100644 index 00000000..cad7ea0d --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolJetsForB.h @@ -0,0 +1,85 @@ +#ifndef TUPLETOOLJETSFORB_H +#define TUPLETOOLJETSFORB_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface + +#include "Kernel/IDistanceCalculator.h" +#include "Event/HltObjectSummary.h" + +#include "Kernel/ITriggerTisTos.h" + +struct IDVAlgorithm; + +typedef std::pair PtParticlePair; + +/** @class TupleToolJetsForB TupleToolJetsForB.h + * + * + * @author Xabier Cid Vidal + * @date 2014-06-30 + */ +class TupleToolJetsForB : public TupleToolBase, + virtual public IParticleTupleTool{ + +public: + /// Standard constructor + TupleToolJetsForB( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +protected: + +private: + + std::string m_loc_jetsnomu; //location of jets with no muons + std::string m_loc_jetsinc; //location of jets with no veto + std::string m_loc_jetsb; //locations of jets with B + bool m_use_jetsnomu; //look at jets with no muons + bool m_use_jetsinc; // look at jets with no veto + bool m_use_jetsb; // look at jets with B + bool m_onemu; // one muon only (for Bmunu) + int m_ind_part; // pid of the individual particle (13 for Bmunu) + + IDVAlgorithm *m_dva; // parent DVA Algorithm + const IDistanceCalculator* m_dist; // for obtaining the best PV + //IJetTagTool* m_nnjettag; //Jet Tag NN + ITriggerTisTos* m_TriggerTisTosTool; + // maps for all the extra info for all the jets + std::map m_JetNoMu1; + std::map m_JetNoMu2; + std::map m_JetNoMu3; + std::map m_JetMu1; + std::map m_JetMu2; + std::map m_JetB; + + bool m_forcePV;// force same PV as top candidate or not! + + double jetNNTag(const LHCb::Particle* jet); + StatusCode getJetLHCbIDs(const LHCb::Particle* p, std::vector< LHCb::LHCbID > & AllIDs) const; + StatusCode getHltObjLHCbIDs(const LHCb::HltObjectSummary * sum, std::vector< LHCb::LHCbID > & AllIDs) const; + + void pt_sorted_samePV(const LHCb::Particles & jets_list , const int pvkey, std::vector & out_list); + + StatusCode find_jet_b(const LHCb::Particles* list_of_jets, + LHCb::Particle& myjet); + StatusCode find_jet_mu(const LHCb::Particles* list_of_jets, + const LHCb::Particle mu, LHCb::Particle& myjet); + + void fillInfo(const std::string& prefix, Tuples::Tuple& tuple); + std::map fillProperties(LHCb::Particle* jet); + std::map emptyProperties(void); + +}; + +#endif // TUPLETOOLJETSFORB_H diff --git a/first-analysis-steps/DecayTrees/TupleToolKinematic.cpp b/first-analysis-steps/DecayTrees/TupleToolKinematic.cpp new file mode 100755 index 00000000..3c0d8452 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolKinematic.cpp @@ -0,0 +1,108 @@ +// $Id: TupleToolKinematic.cpp,v 1.6 2010-04-12 12:34:58 rlambert Exp $ +// Include files + +// local +#include "TupleToolKinematic.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" + +#include "Kernel/IParticleTransporter.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : EventInfoTupleTool +// +// 2007-11-07 : Jeremie Borel +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolKinematic ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolKinematic::TupleToolKinematic( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_transporter() + , m_transporterName ("ParticleTransporter:PUBLIC") +{ + declareInterface(this); + + declareProperty( "Transporter", m_transporterName ); +} + +//============================================================================= + +StatusCode TupleToolKinematic::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_transporter = tool(m_transporterName, this); + + return sc; +} + +//============================================================================= + +StatusCode TupleToolKinematic::fill( const LHCb::Particle* mother + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(head); + + bool test = true; + if( P ) + { + test &= tuple->column( prefix+"_P", P->p() ); + test &= tuple->column( prefix+"_PT", P->pt() ); + + // momentum components + test &= tuple->column( prefix+"_P", P->momentum() ); + + // reference point: + if(isVerbose()) test &= tuple->column( prefix+"_REFP", P->referencePoint() ); + // mass before fit (what CombinationCut cuts on) + //if(isVerbose() && !(P->isBasicParticle()) ) test &= tuple->column( prefix+"_PreFitMass", preFitMass(P) ); + + if( !P->isBasicParticle() || P->particleID().pid() == 111 ) test &= tuple->column( prefix+"_MM", P->measuredMass() ); + if( !P->isBasicParticle() || P->particleID().pid() == 111 ) test &= tuple->column( prefix+"_MMERR", P->measuredMassErr() ); + test &= tuple->column( prefix+"_M", P->momentum().M() ); + + if(isVerbose()&& mother &&P->isBasicParticle() && P->charge() != 0 ) { + const LHCb::Vertex* originvtx = mother->endVertex(); + if(originvtx){ + double zvtx = originvtx->position().Z(); + + LHCb::Particle transParticle; + if(!m_transporter) Error("null pointer m_transporter !!!!"); + test &= m_transporter->transport(P, zvtx, transParticle); + + test &= tuple->column( prefix+"_AtVtx_P", transParticle.momentum() ); + } + } + } + else + { + return StatusCode::FAILURE; + } + return StatusCode(test); +} + +//============================================================================= + +double TupleToolKinematic::preFitMass(const LHCb::Particle* p) const +{ + Gaudi::LorentzVector Mom ; + for ( SmartRefVector< LHCb::Particle >::const_iterator d = p->daughters().begin(); + d != p->daughters().end() ; ++d){ + Mom += (*d)->momentum(); + } + return Mom.M() ; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolKinematic.h b/first-analysis-steps/DecayTrees/TupleToolKinematic.h new file mode 100755 index 00000000..1b5615cd --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolKinematic.h @@ -0,0 +1,59 @@ +#ifndef JBOREL_TUPLETOOLKINEMATIC_H +#define JBOREL_TUPLETOOLKINEMATIC_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface + +/** @class TupleToolKinematic TupleToolKinematic.h jborel/TupleToolKinematic.h + * + * \brief Fill kinematic information for DecayTreeTuple + * + * - head_P : momentum's amplitude + * - head_PT : transverse momentum + * - head_P[E|X|Y|Z] : four vector momentum + * - head_MM : measured mass (or assigned mass in case of 'basic' particle + * - head_M : mass calculated from momentum four-vector + * - head_MMERR : error on the measured mass (only for non-basic parts) + * + * if Verbose: + * + * - head_REFP[X|Y|Z]: one point the particle momentum extrapolation + goes through + * - head_PreFitMass: Mass of 4-vectors of daughters, not yet extrapolated + * to the head decay vertex (only for composites). This is the quantity + * used in ADAMASS or AM in CombineParticles.CombinationCut + * - prefix_AtVtx_P[X|Y|Z]: momentum information of basic particles at + * origin vertex position + * + * \sa DecayTreeTuple + * + * @author Jeremie Borel + * @date 2007-11-07 + */ +struct IParticleTransporter; +class TupleToolKinematic : public TupleToolBase, virtual public IParticleTupleTool { +public: + /// Standard constructor + TupleToolKinematic( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + + double preFitMass(const LHCb::Particle*) const ; + + StatusCode initialize() override; + +private: + + IParticleTransporter* m_transporter; + std::string m_transporterName; + +}; + +#endif // JBOREL_TUPLETOOLKINEMATIC_H diff --git a/first-analysis-steps/DecayTrees/TupleToolL0Calo.cpp b/first-analysis-steps/DecayTrees/TupleToolL0Calo.cpp new file mode 100755 index 00000000..ec75479f --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolL0Calo.cpp @@ -0,0 +1,316 @@ +// Include files + +// local +#include "TupleToolL0Calo.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "Kernel/IParticleTupleTool.h" +#include "Event/Particle.h" +#include "CaloInterfaces/IPart2Calo.h" +#include "Event/L0CaloCandidate.h" +#include "Event/L0DUBase.h" +#include "Event/L0CaloAdc.h" +#include "CaloDAQ/ICaloTriggerAdcsFromRaw.h" + +#include "TMath.h" +#include "boost/foreach.hpp" + +//----------------------------------------------------------------------------- +// Implementation file for class : L0CaloTupleTool +// +// 2012-10-11 : Alexandra Martin Sanchez +//----------------------------------------------------------------------------- + +using namespace Gaudi; +using namespace LHCb; + +// parameters +namespace +{ + // HCAL constants + const double HCAL_CellSize_Inner = 131.3; + //const double HCAL_CellSize_Outer = 262.6; + const double HCAL_xMax_Inner = 2101; + const double HCAL_yMax_Inner = 1838; + const double HCAL_xMax_Outer = 4202; + const double HCAL_yMax_Outer = 3414; + + // ECAL constants + const double ECAL_CellSize_Inner = 40.4; + //const double ECAL_CellSize_Middle = 60.6; + //const double ECAL_CellSize_Outer = 121.2; + const double ECAL_xMax_Inner = 970; + const double ECAL_yMax_Inner = 725; + const double ECAL_xMax_Middle = 1940; + const double ECAL_yMax_Middle = 1210; + const double ECAL_xMax_Outer = 3880; + const double ECAL_yMax_Outer = 3150; +} + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolL0Calo ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolL0Calo::TupleToolL0Calo( const std::string& type, + const std::string& name, + const IInterface* parent ) +: TupleToolBase ( type, name , parent ) , m_fillTriggerEt( false ) , + m_caloDe( 0 ) , m_adcsHcal(NULL) + +{ + declareInterface(this); + declareProperty("WhichCalo", m_calo = "HCAL"); + declareProperty("TriggerClusterLocation" , m_location = "" ) ; +} + +//============================================================================= + +StatusCode TupleToolL0Calo::initialize( ) +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + m_part2calo = tool("Part2Calo","Part2Calo",this); + + // Check selected calo is valid + if (m_calo != "HCAL" && m_calo != "ECAL") { + err() << "TupleToolL0Calo -- Invalid calo: " << m_calo << "." << endmsg ; + return StatusCode::FAILURE; + } + + if ( m_calo == "HCAL" ) { + m_caloDe = getDet< DeCalorimeter >( DeCalorimeterLocation::Hcal ) ; + m_adcsHcal = tool( "CaloTriggerAdcsFromRaw", + "HcalTriggerAdcTool" ); + } else + m_caloDe = getDet< DeCalorimeter >( DeCalorimeterLocation::Ecal ) ; + + // Fill trigger info ? + if ( "" != m_location ) m_fillTriggerEt = true ; + + return sc; +} + +//============================================================================= +StatusCode TupleToolL0Calo::fill( const LHCb::Particle* /* mother */, + const LHCb::Particle* P, + const std::string& head, + Tuples::Tuple& tuple ) +{ + + bool test = true; + if( !(P->isBasicParticle()) ) return StatusCode(test); + + const std::string prefix = fullName(head); + + double trackET, xProjection, yProjection; + + // Project the track on the selected calo + if (m_calo == "HCAL"){ + m_part2calo->match( P, "/dd/Structure/LHCb/DownstreamRegion/Hcal" ); } + else if (m_calo == "ECAL") { + m_part2calo->match( P, "/dd/Structure/LHCb/DownstreamRegion/Ecal" ); } + + // Calculate a few observables + trackET = TMath::Sqrt(TMath::Power(m_part2calo->caloState().x(),2)+ + TMath::Power(m_part2calo->caloState().y(),2)) + /TMath::Sqrt(TMath::Power(m_part2calo->caloState().x(),2)+ + TMath::Power(m_part2calo->caloState().y(),2)+ + TMath::Power(m_part2calo->caloState().z(),2))* + TMath::Sqrt(TMath::Power(m_part2calo->caloState().p(),2)+ + TMath::Power(P->measuredMass(),2)); + + xProjection = m_part2calo->caloState().x(); + yProjection = m_part2calo->caloState().y(); + + double triggerET( -1. ) , triggerHCALET( -1. ) , xtrigger( 0. ) , ytrigger( 0. ) ; + + if ( m_fillTriggerEt ) { + triggerET = getAssociatedCluster( triggerHCALET , xtrigger , ytrigger ) ; + } + + // Fill the tuple + if (m_calo == "HCAL") { + test &= tuple->column( prefix+"_L0Calo_HCAL_realET", trackET ); + test &= tuple->column( prefix+"_L0Calo_HCAL_xProjection", xProjection ); + test &= tuple->column( prefix+"_L0Calo_HCAL_yProjection", yProjection ); + test &= tuple->column( prefix+"_L0Calo_HCAL_region", + isinside_HCAL( xProjection , yProjection ) ); + test &= tuple->column( prefix+"_L0Calo_HCAL_TriggerET", triggerET ) ; + test &= tuple->column( prefix+"_L0Calo_HCAL_TriggerHCALET", triggerHCALET ) ; + test &= tuple->column( prefix+"_L0Calo_HCAL_xTrigger", xtrigger ) ; + test &= tuple->column( prefix+"_L0Calo_HCAL_yTrigger", ytrigger ) ; + } + else if (m_calo == "ECAL") { + test &= tuple->column( prefix+"_L0Calo_ECAL_realET", trackET ); + test &= tuple->column( prefix+"_L0Calo_ECAL_xProjection", xProjection ); + test &= tuple->column( prefix+"_L0Calo_ECAL_yProjection", yProjection ); + test &= tuple->column( prefix+"_L0Calo_ECAL_region", + isinside_ECAL( xProjection , yProjection ) ); + test &= tuple->column( prefix+"_L0Calo_ECAL_TriggerET", triggerET ) ; + test &= tuple->column( prefix+"_L0Calo_ECAL_xTrigger", xtrigger ) ; + test &= tuple->column( prefix+"_L0Calo_ECAL_yTrigger", ytrigger ) ; + } + + + if( msgLevel( MSG::VERBOSE ) ) verbose() << "Returns " << test << endmsg; + return StatusCode(test); + +} + + +int TupleToolL0Calo::isinside_HCAL(double x, + double y) +{ + bool inside, inner, outer; + inside = true; + inner = false; + outer = false; + + // projection inside calo + if (TMath::Abs(x) < HCAL_xMax_Outer && TMath::Abs(y) < HCAL_yMax_Outer) { + // projection inside inner calo (else is outer calo) + if (TMath::Abs(x) < HCAL_xMax_Inner && TMath::Abs(y) < HCAL_yMax_Inner) { + // projections outside the beampipe (in x) + if (TMath::Abs(x) > 2*HCAL_CellSize_Inner) + inner = true; + // projections outside the beampipe (not in x, so in y) + else if (TMath::Abs(y) > 2*HCAL_CellSize_Inner) + inner = true; + else + inside = false; + } + else + outer = true; + } + else + inside = false; + + if (!inside) + return -1; + else if (inner) + return 1; + else if (outer) + return 0; + else + return -999; + +} + +int TupleToolL0Calo::isinside_ECAL(double x, + double y) +{ + bool inside, inner, middle, outer; + inside = true; + inner = false; + middle = false; + outer = false; + + // projection inside calo + if (TMath::Abs(x) < ECAL_xMax_Outer && TMath::Abs(y) < ECAL_yMax_Outer) { + // projection inside middle calo (else is outer calo) + if (TMath::Abs(x) < ECAL_xMax_Middle && TMath::Abs(y) < ECAL_yMax_Middle) { + // projection inside inner calo + if (TMath::Abs(x) < ECAL_xMax_Inner && TMath::Abs(y) < ECAL_yMax_Inner) { + // projections outside the beampipe (in x) + if (TMath::Abs(x) > 2*ECAL_CellSize_Inner) + inner = true; + // projections outside the beampipe (not in x, so in y) + else if (TMath::Abs(y) > 2*ECAL_CellSize_Inner) + inner = true; + else + inside = false; + } + else + middle = true; + } + else + outer = true; + } + else + inside = false; + + if (!inside) + return -1; + else if (inner) + return 2; + else if (middle) + return 1; + else if (outer) + return 0; + else + return -999; +} + +//============================================================================= +// Get associated L0 or LLT cluster +//============================================================================= +double TupleToolL0Calo::getAssociatedCluster( double & hcal_energy , double & xTrigger , + double & yTrigger ) { + // First get the CALO cells in the 3x3 cluster around the track projection + std::vector< LHCb::CaloCellID > cells3x3; + + if( m_part2calo -> isValid() ) { + const LHCb::CaloCellID centerCell = m_part2calo -> caloCellID(); + cells3x3.push_back( centerCell ) ; + BOOST_FOREACH( LHCb::CaloCellID cell, m_caloDe -> neighborCells( centerCell ) ) + { + cells3x3.push_back( cell ); + } ; + } + std::sort( cells3x3.begin() , cells3x3.end() ); + + // loop over the L0 candidates + LHCb::L0CaloCandidates * candidates = + getIfExists ( m_location ); + + int typeToCheck = L0DUBase::CaloType::Electron ; + if ( m_calo == "HCAL" ) typeToCheck = L0DUBase::CaloType::Hadron ; + + LHCb::L0CaloCandidates::iterator cand ; + double result = -1. ; + + for ( cand = candidates -> begin() ; candidates -> end() != cand ; + ++cand ) { + LHCb::L0CaloCandidate * theCand = (*cand) ; + if ( theCand -> type() == typeToCheck ) { + LHCb::CaloCellID cell1 , cell2 , cell3 , cell4 ; + cell1 = theCand -> id() ; + cell2 = LHCb::CaloCellID( cell1.calo() , cell1.area() , + cell1.row()+1 , cell1.col() ) ; + cell3 = LHCb::CaloCellID( cell1.calo() , cell1.area() , + cell1.row() , cell1.col()+1 ) ; + cell4 = LHCb::CaloCellID( cell1.calo() , cell1.area() , + cell1.row()+1 , cell1.col()+1 ) ; + if ( std::binary_search( cells3x3.begin() , cells3x3.end() , cell1 ) || + std::binary_search( cells3x3.begin() , cells3x3.end() , cell2 ) || + std::binary_search( cells3x3.begin() , cells3x3.end() , cell3 ) || + std::binary_search( cells3x3.begin() , cells3x3.end() , cell4 ) ) + { + if ( theCand -> et() > result ) { + xTrigger = m_caloDe -> cellX( cell1 ) ; + yTrigger = m_caloDe -> cellY( cell1 ) ; + result = theCand -> et() ; + // Compute the HCAL energy of this cluster + if ( m_calo == "HCAL" ) { + hcal_energy = 0. ; + const std::vector< LHCb::L0CaloAdc >& adcs = m_adcsHcal -> adcs() ; + for ( std::vector< LHCb::L0CaloAdc >::const_iterator itAdc = adcs.begin() ; + adcs.end() != itAdc ; ++itAdc ) + { + LHCb::CaloCellID id = (*itAdc).cellID() ; + if ( ( id == cell1 ) || (id == cell2 ) || ( id == cell3 ) || ( id == cell4 ) ) + hcal_energy += (*itAdc).adc() ; + } + if ( hcal_energy > 255 ) hcal_energy = 255 ; + hcal_energy = hcal_energy * ( m_caloDe -> L0EtGain() ) ; + } + } + } + } + } + + return result ; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolL0Calo.h b/first-analysis-steps/DecayTrees/TupleToolL0Calo.h new file mode 100755 index 00000000..ddb47d9b --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolL0Calo.h @@ -0,0 +1,72 @@ +#ifndef TUPLETOOLL0CALO_H +#define TUPLETOOLL0CALO_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface + +struct IPart2Calo; +class DeCalorimeter ; +struct ICaloTriggerAdcsFromRaw ; + +/** @class TupleToolL0Calo TupleToolL0Calo.h + * + * \brief Calorimeter information to compute L0 efficiencies + * + * The particle is projected on the selected calorimeter surface, and the projection information is retrieved. + * Tuple columns: + * - realET: ET of the particle when arrived on the calorimeter + * - xProjection: X dimension of the particle projection on the calorimeter + * - yProjection: Y dimension of the particle projection on the calorimeter + * - region: calorimeter region corresponding to the particle projection + * -1 = outside of calorimeter, + * HCAL: 0 = outer, 1 = inner + * ECAL: 0 = outer, 1 = middle, 2 = inner + * The calorimeter on which to project can be chosen by setting the + * "WhichCalo" property to "ECAL" or "HCAL". + * "HCAL" is selected by default. + * + * @author Alexandra Martin Sanchez + * @date 2012-10-11 + */ + +class TupleToolL0Calo : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolL0Calo( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolL0Calo( ){}; ///< Destructor + + StatusCode initialize() override; + StatusCode fill( const LHCb::Particle* /* mother */, + const LHCb::Particle* P, + const std::string& head, + Tuples::Tuple& tuple) override; + +private : + + int isinside_HCAL(double x, + double y); + int isinside_ECAL(double x, + double y); + /// Get the associated L0/LLT cluster + double getAssociatedCluster( double & hcal_energy , double & xTrigger , + double & yTrigger ); + + IPart2Calo* m_part2calo; + std::string m_calo; + std::string m_location ; + bool m_fillTriggerEt ; + DeCalorimeter * m_caloDe ; + ICaloTriggerAdcsFromRaw * m_adcsHcal ; ///< Tool to decode trigger adcs. + +}; + +#endif // TUPLETOOLL0CALO_H diff --git a/first-analysis-steps/DecayTrees/TupleToolL0Data.cpp b/first-analysis-steps/DecayTrees/TupleToolL0Data.cpp new file mode 100644 index 00000000..4eb0183e --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolL0Data.cpp @@ -0,0 +1,146 @@ +#include "TupleToolL0Data.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +//#include "Event/L0ProcessorData.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolL0Data +// +// - produce tuple branches for L0DU input data extracted from the L0DU bank as defined in EDMS-845277 +// (see $L0EVENTROOT/EVENT/L0DUBase.h for data naming) +// - produce the emulated L0 decision for the TCK list given in option +// +// - Properties : +// * 'TCKList' : list of registered TCK's for which the emulated decision is requested (vector) +// * 'DataList' : list of L0data to be tupled (vector) +// -> wildcard are allowed +// -> e.g. ["*Et*","*Pt*"] to tuple the L0 data with name containing 'Et' or 'Pt' +// -> e.g. ["ALL","!*Status*"] to tuple ALL L0 data except those with name containing 'Status' +// +// -> Default : ALL L0 data used for the standard decision making +// -> i.e. 'technical' data related to candidate address, status or intermediate value are rejected +// +// +// * 'ScaledData' : scale the candidate pT/eT data in MeV (boolean - default = false, i.e. no scaling) +// -> warning : the scaling factor relies on condDB for L0Calo and is partially hardcoded in L0DU s/w for L0Muon. +// -> the scaling has changed in July 2015. +// +// +// 2011-06-08 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolL0Data ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolL0Data::TupleToolL0Data( const std::string& type, + const std::string& name, + const IInterface* parent ): + TupleToolBase ( type, name , parent ) +{ + declareInterface(this); + + declareProperty( "ScaledData",m_scale=false); + declareProperty( "TCKList" , m_tcks ); + // Accepted/rejected data + m_list.push_back("ALL"); // add all data but ... + m_list.push_back("!*Status*"); + m_list.push_back("!*More*"); + m_list.push_back("!*CU*"); + m_list.push_back("!*M0*"); + m_list.push_back("!*M1*"); + m_list.push_back("!*M2*"); + m_list.push_back("!*M3*"); + m_list.push_back("!*M4*"); + m_list.push_back("!*M5*"); + m_list.push_back("!*M6*"); + m_list.push_back("!*M7*"); + m_list.push_back("!*Add*"); + declareProperty( "DataList", m_list ); +} + +StatusCode TupleToolL0Data::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + m_l0 = tool("L0DUFromRawTool","L0DUFromRaw" ,this ); + m_l0emu = tool("L0DUEmulatorTool","L0DUEmulator",this); + m_l0conf= tool( "L0DUMultiConfigProvider","L0DUConfig"); + return sc; +} + +//============================================================================= +// Destructor +//============================================================================= +TupleToolL0Data::~TupleToolL0Data() {} +//============================================================================= + +StatusCode TupleToolL0Data::fill( Tuples::Tuple& tuple) +{ + const std::string prefix=fullName(); + if(!m_l0->decodeBank())Warning("Unable to decode L0DU rawBank", StatusCode::SUCCESS).ignore(); + const std::map >& datamap = m_l0->datas(); + for(std::map >::const_iterator it = datamap.begin(); + datamap.end() != it ; ++it) + { + const std::string& name = it->first; + const int& val = (it->second).first; + const double& scale = (it->second).second; + if ( LHCb::CaloAlgUtils::StringMatcher(m_list,name) ) + { + if(m_scale)tuple->column( prefix+"L0Data_"+rename(name), double(val)*scale ); + else tuple->column( prefix+"L0Data_"+rename(name), val ); + if ( msgLevel(MSG::DEBUG) ) + debug() << "++ ACCEPT L0Data : '" << prefix<<"L0Data_"<L0ProcessorDatas(); + for( std::vector::iterator it=m_tcks.begin();m_tcks.end()!=it;++it ) + { + const std::string& stck = *it; + std::istringstream istck( stck.c_str() ); + int itck(0); + istck >> std::hex >> itck; + int dec = 0; + LHCb::L0DUConfig* config = m_l0conf->config( itck ); + if ( config ) + { + const StatusCode sc = m_l0emu->process(config, proDatas ); + if( sc.isSuccess() && config->emulatedDecision() )dec=1; + } + tuple->column( prefix+"L0Emu_TCK"+stck, dec); + if ( msgLevel(MSG::DEBUG) ) + debug() << " >> emulated (pre)decision for TCK : " << stck + << " ("<) + * * 'DataList' : list of L0data to be tupled (vector) + * -> wildcard are allowed + * -> e.g. ["*Et*","*Pt*"] to tuple the L0 data with name containing 'Et' or 'Pt' + * -> e.g. ["ALL","!*Status*"] to tuple ALL L0 data except those with name containing 'Status' + * + * -> Default : ALL L0 data used for the standard decision making + * -> i.e. 'technical' data related to candidate address, status or intermediate value are rejected + * + * + * * 'ScaledData' : scale the candidate pT/eT data in MeV (boolean - default = false, i.e. no scaling) + * -> warning : the scaling factor relies on condDB for L0Calo and is partially hardcoded in L0DU s/w for L0Muon. + * -> the scaling has changed in July 2015. + * + * @author Olivier Deschamps + * @date 2011-06-08 + */ +class TupleToolL0Data : public TupleToolBase, + virtual public IEventTupleTool +{ + +public: + + /// Standard constructor + TupleToolL0Data( const std::string& type, + const std::string& name, + const IInterface* parent ); + + virtual ~TupleToolL0Data( ); ///< Destructor + StatusCode fill(Tuples::Tuple& ) override; + StatusCode initialize() override; + +private: + + std::string rename(const std::string& name); + +private: + + std::vector m_list; + IL0DUFromRawTool* m_l0; + IL0DUConfigProvider* m_l0conf; + IL0DUEmulatorTool* m_l0emu; + bool m_scale; + std::vector m_tcks; + +}; + +#endif // TUPLETOOLL0DATA_H diff --git a/first-analysis-steps/DecayTrees/TupleToolMCAssociatedClusters.cpp b/first-analysis-steps/DecayTrees/TupleToolMCAssociatedClusters.cpp new file mode 100644 index 00000000..23e1fcf1 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolMCAssociatedClusters.cpp @@ -0,0 +1,269 @@ +// local +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "TupleToolMCAssociatedClusters.h" + +#include "Event/Particle.h" +#include "Event/MCParticle.h" + +// from Event/LinkerEvent +#include "Linker/LinkedTo.h" +#include "Linker/LinkedFrom.h" +#include "Linker/LinkedFromKey.h" + +// from Event/TrackEvent +#include "Event/Track.h" +#include "Kernel/OTChannelID.h" +#include "Event/OTTime.h" +#include "Event/STCluster.h" +#include "Event/VeloCluster.h" + +// from Event/MCEvent +#include "Event/MCParticle.h" + +// kernel +#include "Kernel/IParticle2MCAssociator.h" + +TupleToolMCAssociatedClusters::TupleToolMCAssociatedClusters(const std::string& type, const std::string& name, const IInterface* parent) : + TupleToolBase ( type, name, parent ) +{ + // interface + declareInterface ( this ); + + // MC associators to try, in order + m_p2mcAssocTypes.push_back ( "DaVinciSmartAssociator" ); + m_p2mcAssocTypes.push_back ( "MCMatchObjP2MCRelator" ); + declareProperty ( "IP2MCPAssociatorTypes", m_p2mcAssocTypes ); + + declareProperty ( "CheckUniqueness", m_checkUniqueness=true ); +} + + +//============================================================================= +// Initialization. Check parameters +//============================================================================= +StatusCode TupleToolMCAssociatedClusters::initialize() +{ + const StatusCode sc = TupleToolBase::initialize (); + if (sc.isFailure ()) + return sc; + + // the MC associators + m_p2mcAssocs.clear (); + for (std::vector::const_iterator iMCAss = m_p2mcAssocTypes.begin (); iMCAss != m_p2mcAssocTypes.end (); ++iMCAss) + { + m_p2mcAssocs.push_back ( tool ( *iMCAss, this ) ); + } + if (m_p2mcAssocs.empty ()) + { + return Error ( "No MC associators configured" ); + } + + + return StatusCode::SUCCESS; +} + +StatusCode TupleToolMCAssociatedClusters::fill(const LHCb::Particle*, + const LHCb::Particle* P, const std::string& head, Tuples::Tuple& tuple) +{ + // retrieve the currently linked MCP, this will be our working base + const LHCb::MCParticle* mcp ( NULL ); + const std::string prefix = fullName ( head ); + + unsigned int nFoundOT = 0; + unsigned int nFoundTT = 0; + unsigned int nFoundIT = 0; + unsigned int nFoundVelo = 0; + + unsigned int nFoundUniqueOT = 0; + unsigned int nFoundUniqueTT = 0; + unsigned int nFoundUniqueIT = 0; + unsigned int nFoundUniqueVelo = 0; + + size_t nMCHitsOT = 0; + size_t nMCHitsTT = 0; + size_t nMCHitsIT = 0; + size_t nMCHitsVelo = 0; + + if (!P) + return StatusCode::FAILURE; + + //first just return if the particle isn't supposed to have a track + if (!P->isBasicParticle ()) + return StatusCode::SUCCESS; + + const auto& protop = P->proto (); + if (!protop) + return StatusCode::SUCCESS; + + const auto& track = protop->track (); + if (!track) + return StatusCode::SUCCESS; + + const auto& lhcbIDs = track->lhcbIDs(); + + if (msgLevel ( MSG::VERBOSE )) + verbose() << "Number of lhcbIDs: " << lhcbIDs.size() << endmsg; + + if (msgLevel ( MSG::VERBOSE )) + verbose () << "Getting related MCP to " << P << endmsg; + + for (std::vector::const_iterator iMCAss = m_p2mcAssocs.begin (); iMCAss != m_p2mcAssocs.end (); ++iMCAss) + { + mcp = (*iMCAss)->relatedMCP ( P ); + if (mcp) + break; + } + + if (msgLevel ( MSG::VERBOSE )) + verbose () << "Got mcp " << mcp << endmsg; + + if (mcp != NULL) + { + // get VeloClusters and count correct and total number of clusters + // Get the linker table MCParticle => VeloCluster + if (msgLevel ( MSG::VERBOSE )) + verbose() << "Trying to retrieve linker tables." << endmsg; + + LinkedFromKey otLink ( evtSvc (), msgSvc (), LHCb::OTTimeLocation::Default ); + + LinkedTo ttLink ( evtSvc (), msgSvc (), LHCb::STClusterLocation::TTClusters ); + LinkedFrom ttLinkRev ( evtSvc (), msgSvc (), LHCb::STClusterLocation::TTClusters ); + + LinkedTo itLink ( evtSvc (), msgSvc (), LHCb::STClusterLocation::ITClusters ); + LinkedFrom itLinkRev ( evtSvc (), msgSvc (), LHCb::STClusterLocation::ITClusters ); + + LinkedFrom velo2MCPLink ( evtSvc (), msgSvc (), LHCb::VeloClusterLocation::Default ); + LinkedTo MCP2VeloLink ( evtSvc (), msgSvc (), LHCb::VeloClusterLocation::Default ); + + if (otLink.notFound ()) + return Error ( "Unable to retrieve MCParticle-Cluster linker table for OT" ); + + if (itLink.notFound ()) + return Error ( "Unable to retrieve MCParticle-Cluster linker table for IT" ); + + if (ttLink.notFound ()) + return Error ( "Unable to retrieve MCParticle-Cluster linker table for TT" ); + + if (velo2MCPLink.notFound ()) + return Error ( "Unable to retrieve MCParticle-VeloCluster linker table" ); + + if (msgLevel ( MSG::VERBOSE )) + verbose() << "Building cluster lists for this MCP." << endmsg; + + const auto& otChannelIdList = otLink.keyRange( mcp ); + const auto& itClusterList = itLinkRev.range( mcp ); + const auto& ttClusterList = ttLinkRev.range( mcp ); + const auto& veloClusterList = velo2MCPLink.range( mcp ); + + if (msgLevel ( MSG::VERBOSE )) + verbose() << "Counting cluster lists." << endmsg; + nMCHitsOT = otChannelIdList.size(); + nMCHitsIT = itClusterList.size(); + nMCHitsTT = ttClusterList.size(); + nMCHitsVelo = veloClusterList.size(); + + /** + * Comparing here the number of LHCb IDs v.s. the number of MCParticle clusters. + */ + std::vector usedVeloIDs; + std::vector usedOTIDs; + std::vector usedITIDs; + std::vector usedTTIDs; + + for (const auto& lhcbID : lhcbIDs) + { + if (lhcbID.isOT()) + { + const LHCb::OTChannelID& measuredOTChannelID = lhcbID.otID(); + const auto& it = std::find_if(otChannelIdList.begin(), otChannelIdList.end(), [&measuredOTChannelID] (const LHCb::OTChannelID& otchannelid) { return otchannelid == measuredOTChannelID; } ); + + if (it != otChannelIdList.end()) + { + if (m_checkUniqueness && std::find(usedOTIDs.begin(), usedOTIDs.end(), measuredOTChannelID) == usedOTIDs.end()) + { + usedOTIDs.push_back( measuredOTChannelID ); + nFoundUniqueOT++; + } + + nFoundOT++; + } + } + + if (lhcbID.isIT()) + { + const auto& measuredITChannelID = lhcbID.stID(); + const auto& it = std::find_if(itClusterList.begin(), itClusterList.end(), [&measuredITChannelID] (const LHCb::STCluster* const& cluster) { return cluster->channelID() == measuredITChannelID; } ); + + if (it != itClusterList.end()) + { + if (m_checkUniqueness && std::find(usedITIDs.begin(), usedITIDs.end(), measuredITChannelID) == usedITIDs.end()) + { + usedITIDs.push_back( measuredITChannelID ); + nFoundUniqueIT++; + } + + nFoundIT++; + } + } + + + if (lhcbID.isTT()) + { + const auto& measuredTTChannelID = lhcbID.stID(); + const auto& it = std::find_if(ttClusterList.begin(), ttClusterList.end(), [&measuredTTChannelID] (const LHCb::STCluster* const& cluster) { return cluster->channelID() == measuredTTChannelID; } ); + + if (it != itClusterList.end()) + { + if (m_checkUniqueness && std::find(usedTTIDs.begin(), usedTTIDs.end(), measuredTTChannelID) == usedTTIDs.end()) + { + usedTTIDs.push_back( measuredTTChannelID ); + nFoundUniqueTT++; + } + + nFoundTT++; + } + } + + if (lhcbID.isVelo()) + { + const auto& measuredVeloChannelID = lhcbID.veloID(); + const auto& it = std::find_if(veloClusterList.begin(), veloClusterList.end(), [&measuredVeloChannelID] (const LHCb::VeloCluster* const& cluster) { return cluster->channelID() == measuredVeloChannelID; } ); + + if (it != veloClusterList.end()) + { + if (m_checkUniqueness && std::find(usedVeloIDs.begin(), usedVeloIDs.end(), measuredVeloChannelID) == usedVeloIDs.end()) + { + usedVeloIDs.push_back( measuredVeloChannelID ); + nFoundUniqueVelo++; + } + + nFoundVelo++; + } + } + } + } + + tuple->column( prefix+"_MC_nUsedOTClusters", nFoundOT ); + tuple->column( prefix+"_MC_nUsedITClusters", nFoundIT ); + tuple->column( prefix+"_MC_nUsedTTClusters", nFoundTT ); + tuple->column( prefix+"_MC_nUsedVeloClusters", nFoundVelo ); + + if (m_checkUniqueness) + { + tuple->column( prefix+"_MC_nUsedUniqueOTClusters", nFoundUniqueOT ); + tuple->column( prefix+"_MC_nUsedUniqueITClusters", nFoundUniqueIT ); + tuple->column( prefix+"_MC_nUsedUniqueTTClusters", nFoundUniqueTT ); + tuple->column( prefix+"_MC_nUsedUniqueVeloClusters", nFoundUniqueVelo ); + } + + tuple->column( prefix+"_MC_nOTClusters", nMCHitsOT ); + tuple->column( prefix+"_MC_nITClusters", nMCHitsIT ); + tuple->column( prefix+"_MC_nTTClusters", nMCHitsTT ); + tuple->column( prefix+"_MC_nVeloClusters", nMCHitsVelo ); + + return StatusCode::SUCCESS; +} + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolMCAssociatedClusters ) diff --git a/first-analysis-steps/DecayTrees/TupleToolMCAssociatedClusters.h b/first-analysis-steps/DecayTrees/TupleToolMCAssociatedClusters.h new file mode 100644 index 00000000..bfa151a4 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolMCAssociatedClusters.h @@ -0,0 +1,53 @@ +#ifndef TUPLETOOL_MC_ASSOCIATED_CLUSTERS_ +#define TUPLETOOL_MC_ASSOCIATED_CLUSTERS_ 1 + +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface + +class IParticle2MCAssociator; + +namespace LHCb +{ + class Particle; +} + +/** + * The TupleToolMCAssociatedClusters stores information on the number of TT/IT/OT/Velo + * clusters which are associated with the MCParticle (which again is associated with the + * Particle currently looked at). + * + * The information that is stored: + * - How many clusters are there associated to this MCParticle + * - Out of the clusters used by the track reconstructed, how many are linked to this MCP + * + * Combining this with the LoKi track functors to count the total number of clusters + * used by the track, one then also can deduce the number of clusters used in the track + * which were not associated with the MCParticle. + * + * In order to use this, the linker tables must be there. For modern MC, + * this requires the DaVinci input file to be at least "LDST". + * + * A somewhat related Brunel-tool is the TrackCheckerNT, which runs over all tracks + * in the event. The goal of this tool is to get the information for a signal decay + * only. + * + * @author Laurent Dufour + */ +class TupleToolMCAssociatedClusters: public TupleToolBase, virtual public IParticleTupleTool +{ + public: + TupleToolMCAssociatedClusters(const std::string& type, const std::string& name, const IInterface* parent); + + StatusCode initialize() override; + + StatusCode fill(const LHCb::Particle*, const LHCb::Particle*, const std::string&, Tuples::Tuple&) override; + private: + std::vector m_p2mcAssocTypes; + std::vector m_p2mcAssocs; + + bool m_checkUniqueness; + +}; + +#endif + diff --git a/first-analysis-steps/DecayTrees/TupleToolMCBackgroundInfo.cpp b/first-analysis-steps/DecayTrees/TupleToolMCBackgroundInfo.cpp new file mode 100755 index 00000000..e5fecc07 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolMCBackgroundInfo.cpp @@ -0,0 +1,94 @@ +// Include files + +// local +#include "TupleToolMCBackgroundInfo.h" + +#include "Kernel/IBackgroundCategory.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : MCBackgroundInfoTupleTool +// +// 2007-11-07 : Jeremie Borel +//----------------------------------------------------------------------------- + +using namespace LHCb; + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolMCBackgroundInfo::TupleToolMCBackgroundInfo( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name, parent ) +{ + declareInterface(this); + m_backCatTypes.push_back( "BackgroundCategoryViaRelations" ); + m_backCatTypes.push_back( "BackgroundCategory" ); + declareProperty( "IBackgroundCategoryTypes", m_backCatTypes ); +} + +//============================================================================= + +StatusCode TupleToolMCBackgroundInfo::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + if (msgLevel(MSG::DEBUG)) + debug() << "Background Category tools " << m_backCatTypes << endmsg; + + for ( std::vector::const_iterator iT = m_backCatTypes.begin(); + iT != m_backCatTypes.end(); ++iT ) + { + m_bkgs.push_back( tool( *iT, *iT, this ) ); + } + + return sc; +} + +//============================================================================= + +StatusCode TupleToolMCBackgroundInfo::fill( const Particle* headP, + const Particle* P, + const std::string& head, + Tuples::Tuple& tuple ) +{ + StatusCode sc = StatusCode::SUCCESS; + + const std::string prefix = fullName(head); + + Assert( P && !m_bkgs.empty() , "This should not happen :(" ); + + if ( !P->isBasicParticle() ) + { + IBackgroundCategory::categories cat = IBackgroundCategory::Undefined; + + for ( std::vector::const_iterator iT = m_bkgs.begin(); + iT != m_bkgs.end(); ++iT ) + { + cat = (*iT)->category( P, headP ); + if ( cat != IBackgroundCategory::Undefined ) break; + } + + if (msgLevel(MSG::DEBUG)) + debug() << "BackgroundCategory decision for " + << prefix << " : " << cat << endmsg; + + sc = tuple->column( prefix+"_BKGCAT", (int)cat ); + } + + return sc; +} + +//============================================================================= + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolMCBackgroundInfo ) + +//============================================================================= diff --git a/first-analysis-steps/DecayTrees/TupleToolMCBackgroundInfo.h b/first-analysis-steps/DecayTrees/TupleToolMCBackgroundInfo.h new file mode 100755 index 00000000..fdd568e3 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolMCBackgroundInfo.h @@ -0,0 +1,59 @@ +// $Id: TupleToolMCBackgroundInfo.h,v 1.2 2010-01-26 15:39:26 rlambert Exp $ +#ifndef JBOREL_TUPLETOOLMCBACKGROUNDINFO_H +#define JBOREL_TUPLETOOLMCBACKGROUNDINFO_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface + +class IBackgroundCategory; + +namespace LHCb +{ + class Particle; +} + +/** @class TupleToolMCBackgroundInfo TupleToolMCBackgroundInfo.h + * + * \brief Fill the info from IBackgroundCategory + * + * An answer is only filled for composite particles. + * + * IBackgroundCategory controlled by property IBackgroundCatagoryType, default "BackgroundCategory". + * + * head_BKGCAT : category. + * + * \sa DecayTreeTuple + * + * @author Jeremie Borel + * @date 2007-11-07 + */ +class TupleToolMCBackgroundInfo : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolMCBackgroundInfo( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolMCBackgroundInfo( ){}; ///< Destructor + + StatusCode initialize() override; + + StatusCode fill( const LHCb::Particle*, + const LHCb::Particle*, + const std::string&, + Tuples::Tuple& ) override; + +private: + + std::vector m_backCatTypes; + std::vector m_bkgs; + +}; + +#endif // JBOREL_TUPLETOOLMCBACKGROUNDINFO_H diff --git a/first-analysis-steps/DecayTrees/TupleToolMCTruth.cpp b/first-analysis-steps/DecayTrees/TupleToolMCTruth.cpp new file mode 100755 index 00000000..7018ac9b --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolMCTruth.cpp @@ -0,0 +1,136 @@ +// Include files +#include "gsl/gsl_sys.h" +// from Gaudi +#include "GaudiKernel/PhysicalConstants.h" +// local +#include "TupleToolMCTruth.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" +#include "Event/MCParticle.h" + +// kernel +#include "Kernel/IParticle2MCAssociator.h" +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolMCTruth +// +// 2007-11-07 : Jeremie Borel +//----------------------------------------------------------------------------- + +using namespace LHCb; + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolMCTruth::TupleToolMCTruth( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_toolList(1,"MCTupleToolKinematic") +{ + // interface + declareInterface(this); + // The names of MCTupleTools to use on the associated mcp + declareProperty( "ToolList", m_toolList ); + // MC associators to try, in order + m_p2mcAssocTypes.push_back( "DaVinciSmartAssociator" ); + m_p2mcAssocTypes.push_back( "MCMatchObjP2MCRelator" ); + declareProperty( "IP2MCPAssociatorTypes", m_p2mcAssocTypes ); +} + +//============================================================================= + +StatusCode TupleToolMCTruth::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + // the MC associators + m_p2mcAssocs.clear(); + for ( std::vector::const_iterator iMCAss = m_p2mcAssocTypes.begin(); + iMCAss != m_p2mcAssocTypes.end(); ++iMCAss ) + { + m_p2mcAssocs.push_back( tool(*iMCAss,this) ); + } + if ( m_p2mcAssocs.empty() ) { return Error("No MC associators configured"); } + + // remove duplicate tools from the list + std::sort( m_toolList.begin(), m_toolList.end() ); + m_toolList.erase( std::unique(m_toolList.begin(),m_toolList.end()), m_toolList.end() ); + + // initialise the tuple tools + for ( std::vector::const_iterator it = m_toolList.begin(); + m_toolList.end()!=it ; ++it ) + { + if (msgLevel(MSG::VERBOSE)) verbose() << "Adding the tool " << *it << endmsg ; + IMCParticleTupleTool* aTool = tool(*it,this); + if ( aTool ) + { + m_mcTools.push_back(aTool); + } + else + { + Warning("There was a problem retrieving " + *it +" , this tool will be ignored").ignore(); + } + } + + if ( msgLevel(MSG::VERBOSE) ) + { + verbose() << "Completed TupleTool intialisation, " + << m_mcTools.size() + << " tools added " << endmsg ; + } + + return sc; +} + +//============================================================================= + +StatusCode TupleToolMCTruth::fill( const LHCb::Particle*, + const LHCb::Particle* P, + const std::string& head, + Tuples::Tuple& tuple ) +{ + const std::string prefix = fullName(head); + + bool test = true; + + const LHCb::MCParticle* mcp(NULL); + if ( P ) + { + //assignedPid = P->particleID().pid(); + if (msgLevel(MSG::VERBOSE)) verbose() << "Getting related MCP to " << P << endmsg ; + for ( std::vector::const_iterator iMCAss = m_p2mcAssocs.begin(); + iMCAss != m_p2mcAssocs.end(); ++iMCAss ) + { + mcp = (*iMCAss)->relatedMCP(P); + if ( mcp ) break; + } + if (msgLevel(MSG::VERBOSE)) + verbose() << "Got mcp " << mcp << endmsg ; + } + + // pointer is ready, prepare the values + const int mcPid = ( mcp ? mcp->particleID().pid() : 0 ); + + // fill the tuple: + test &= tuple->column( prefix+"_TRUEID", mcPid ); + + // fill all requested MCTools + for ( std::vector< IMCParticleTupleTool* >::const_iterator it = m_mcTools.begin(); + it != m_mcTools.end(); ++it ) + { + test &= (*it)->fill(NULL,mcp,prefix,tuple); + } + + return StatusCode(test); +} + +//============================================================================= + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolMCTruth ) + +//============================================================================= diff --git a/first-analysis-steps/DecayTrees/TupleToolMCTruth.h b/first-analysis-steps/DecayTrees/TupleToolMCTruth.h new file mode 100755 index 00000000..5a1c12a1 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolMCTruth.h @@ -0,0 +1,74 @@ +// $Id: TupleToolMCTruth.h,v 1.9 2010-01-26 15:39:26 rlambert Exp $ +#ifndef TUPLETOOLMCTRUTH_H +#define TUPLETOOLMCTRUTH_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IMCParticleTupleTool.h" // Interface +#include "Kernel/IParticleTupleTool.h" // Interface + +//struct Particle2MCLinker; +#include + +class IParticle2MCAssociator; + +/** @class TupleToolMCTruth TupleToolMCTruth.h + * + * \brief Fill MC truth info if a link is present + * + * Uses an IParticle2MCAssociator to perform the association. + * Properties: + * + * IP2MCPAssociatorType: Implementation of IP2MCAssociator to be used. Default: DaVinciSmartAssociator. + * + * ToolList: List of MCTupleTools to run. Default: [MCTupleToolKinematic] + * + * - head_TRUEID : true pid + * + + * To add more entries, add the appropriate MCTupleTool + + * Configure the option ToolList to add MCTupleTools + + * The MCAssociation is run only once, then these tuple tools are called + + + * \sa DecayTreeTuple + * + * @author Jeremie Borel + * @date 2007-11-07 + * 2008-09-23 Adlene Hicheur - Added true angles information for P2VV + * 2009-06-03 Rob Lambert - Major Changes + */ + +class TupleToolMCTruth : public TupleToolBase, virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolMCTruth( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolMCTruth(){}; ///< Destructor + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + + StatusCode initialize() override; + +private: + + std::vector m_p2mcAssocs; + std::vector m_p2mcAssocTypes; + std::vector m_toolList; ///< names of all MCTupleTools, set by the option ToolList + + std::vector m_mcTools; ///(this); + declareProperty( "PIDReplacements", m_replace, "List of PID replacements as dictionary of strings"); + declareProperty( "CC", m_revert = true, "Do cc by default"); +} + +//============================================================================= + +StatusCode TupleToolMassHypo::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + LHCb::IParticlePropertySvc* ppsvc = + svc("LHCb::ParticlePropertySvc",true) ; + + if (m_revert) info() << "Will apply cc on all replacement pairs" << endmsg ; + + for (std::map::const_iterator iterS = m_replace.begin(); + iterS != m_replace.end(); ++iterS ){ + const LHCb::ParticleProperty* prop1 = ppsvc->find( iterS->first ); + const LHCb::ParticleProperty* prop2 = ppsvc->find( iterS->second ); + if (!prop1 || !prop2 ) { + err() << "one of " << iterS->first << " " << iterS->second << " does nor exist" << endmsg ; + return StatusCode::FAILURE ; + } + int pid = prop1->pdgID().pid() ; + if ( m_revert) pid = abs(pid); + m_massMap.insert(std::pair(pid,prop1->mass())); + m_massMap.insert(std::pair(prop2->pdgID().pid(),prop2->mass())); + m_nameMap.insert(std::pair(pid,Decays::escape(prop1->name()))); + if (msgLevel(MSG::VERBOSE)) verbose() << "Inserted name ``" << Decays::escape(prop1->name()) << "''" << endmsg ; + m_nameMap.insert(std::pair(prop2->pdgID().pid(),Decays::escape(prop2->name()))); + if (msgLevel(MSG::VERBOSE)) verbose() << "Inserted name ``" << Decays::escape(prop2->name()) << "''" << endmsg ; + m_replacePDG.insert( std::pair( pid,prop2->pdgID().pid() )); + if (msgLevel(MSG::VERBOSE)) verbose() << "Inserted PID pair ``" << pid << "," + << prop2->pdgID().pid() << "''" << endmsg ; + } // iterS + m_transporter = tool("ParticleTransporter:PUBLIC", this); + + return sc ; +} + +//============================================================================= +StatusCode TupleToolMassHypo::fill( const LHCb::Particle* + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + if( !P ) return StatusCode::FAILURE; + if( P->isBasicParticle() ) return StatusCode::SUCCESS; + if (msgLevel(MSG::VERBOSE)) verbose() << "Entering with a " << P->particleID().pid() << endmsg ; + const std::string prefix=fullName(head); + bool test = true; + + //first just return if the particle is a final state + LHCb::Particle::ConstVector dv = P->daughtersVector(); + + possDecayVec possibilities = getPossibilities(dv); + if (possibilities.size()==1) { + Warning("The decay of this particle does not contain the declared PIDs.", + StatusCode::SUCCESS,1); + return StatusCode::SUCCESS ; // ignore cases where nothing is to be done + } + + for (possDecayVec::const_iterator p = possibilities.begin() ; p!=possibilities.end() ; ++p){ + std::string combname ; + if (msgLevel(MSG::VERBOSE)) verbose() << "Old mass " << P->measuredMass() << endmsg ; + double mass = recalculateMass(*p,P->referencePoint(),combname); + test &= tuple->column( prefix+"_M_with"+combname, mass ); + if (msgLevel(MSG::VERBOSE)) verbose() << "Filled column ``" << prefix+"_M_with"+combname + << "'' with mass " << mass << endmsg ; + }// + + return StatusCode(test); +} +//============================================================================= +double TupleToolMassHypo::recalculateMass(const possDecay& pd, const Gaudi::XYZPoint& pt, + std::string& combname){ + Gaudi::LorentzVector newM ; + for ( possDecay::const_iterator p = pd.begin() ; p != pd.end() ; ++p ){ + if (msgLevel(MSG::VERBOSE)) verbose() << "Loop ``" << combname << "'' pid : ``" << p->second << "''"<< endmsg ; + const LHCb::Particle* P = p->first; + if ( m_nameMap.find(p->second)!=m_nameMap.end()) combname += "_"+m_nameMap[p->second] ; + LHCb::Particle transParticle; + m_transporter->transport(P, pt.z(), transParticle); + Gaudi::LorentzVector mom = transParticle.momentum(); + if (P->particleID().pid()!=p->second || (m_revert && P->particleID().pid()!=-p->second)){ + double mm = m_massMap[p->second]; + if (msgLevel(MSG::VERBOSE)) verbose() << "Momentum is " << mom << " new mass = " << mm << endmsg ; + mom.SetE(sqrt(mom.P2()+(mm*mm))); + if (msgLevel(MSG::VERBOSE)) verbose() << "New Momentum is " << mom << endmsg ; + } + newM += mom ; + if (msgLevel(MSG::VERBOSE)) verbose() << "Total Momentum is now " << newM << endmsg ; + } + if (msgLevel(MSG::VERBOSE)) verbose() << "New mass with " << combname << " is " << newM.M() << endmsg ; + return newM.M(); +} +//============================================================================= +possDecayVec TupleToolMassHypo::getPossibilities(const LHCb::Particle::ConstVector& dv){ + possDecayVec possibilities; + // loop over daghters + for ( LHCb::Particle::ConstVector::const_iterator d1 = dv.begin() ; d1!=dv.end() ; ++d1){ + if (msgLevel(MSG::VERBOSE)) verbose() << "getPossibilities Looping over " << (*d1)->particleID().pid() << endmsg ; + possibilities = increaseVector(*d1,possibilities); + if (msgLevel(MSG::VERBOSE)) verbose() << "getPossibilities Size of possibilities " << possibilities.size() << endmsg ; + } + if ((possibilities.size()>1) && (msgLevel(MSG::DEBUG) || m_first)) printVec(possibilities); + if (m_first) m_first = false ; + return possibilities; +} +//============================================================================= +void TupleToolMassHypo::addPossPair(const LHCb::Particle* d, int pid, possDecay& pm){ + pm.push_back(possPair(d,pid)); + if (msgLevel(MSG::VERBOSE)) verbose() << "addPossPair Added " << pid << " size: " << pm.size() << endmsg ; +} + +//============================================================================= +// multiplies the vector +possDecayVec TupleToolMassHypo::increaseVector(const LHCb::Particle* d, possDecayVec& poss){ + int pid = d->particleID().pid(); + if (m_revert) pid = abs(pid); + if (msgLevel(MSG::VERBOSE)) verbose() << "increaseVector seeing a " + << d->particleID().pid() << " treated as " << pid << endmsg ; + possDecayVec tmp ; + if (poss.empty()){ + possDecay pm; + addPossPair(d,pid,pm); + tmp.push_back(pm); + if (m_replacePDG.find(pid)!=m_replacePDG.end()) { + possDecay pm2; + addPossPair(d,m_replacePDG[pid],pm2); + tmp.push_back(pm2); + } + } else { + if (msgLevel(MSG::VERBOSE)) verbose() << "increaseVector with poss size " << poss.size() << endmsg ; + for (possDecayVec::const_iterator i = poss.begin() ; i!=poss.end() ; ++i){ + possDecay pm = *i; + addPossPair(d,pid,pm); + tmp.push_back(pm); + if (m_replacePDG.find(pid)!=m_replacePDG.end()){ + int pid2 = m_replacePDG[pid]; + possDecay pm2 = *i; + addPossPair(d,pid2,pm2); + tmp.push_back(pm2); + } + } + } + if (msgLevel(MSG::VERBOSE)) printVec(tmp); + return tmp ; +} + +//============================================================================= +void TupleToolMassHypo::printVec(const possDecayVec& possibilities){ + for ( possDecayVec::const_iterator i = possibilities.begin() ; i!=possibilities.end() ; ++i){ + info() << "Combination: " ; + for ( possDecay::const_iterator j = i->begin() ; j!=i->end() ; ++j){ + info() << j->first->particleID().pid() << ": " << j->second << ", " ; + } + info() << endmsg ; + } +} diff --git a/first-analysis-steps/DecayTrees/TupleToolMassHypo.h b/first-analysis-steps/DecayTrees/TupleToolMassHypo.h new file mode 100755 index 00000000..74a2f89a --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolMassHypo.h @@ -0,0 +1,73 @@ +#ifndef JBOREL_TUPLETOOLMASSHYPO_H +#define JBOREL_TUPLETOOLMASSHYPO_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "Event/Particle.h" + +typedef std::pair possPair ; +typedef std::vector< possPair > possDecay ; // not a std::map +typedef std::vector< possDecay > possDecayVec ; + +/** @class TupleToolMassHypo TupleToolMassHypo.h jborel/TupleToolMassHypo.h + * + * \brief Return mass of composite under another PID hypothesis + * + * An example for Ks0: + * \verbatim + from configurables import TupleToolMassHypo + Tuple.addTool(TupleToolMassHypo) + Tuple.TupleToolMassHypo.PIDReplacements = { "pi+" : "p+" } + Tuple.TupleToolMassHypo.CC = True + \endverbatim + * + * will create 4 new entries in the nTuple called KS0_M_with_piplus_piminus, + * KS0_M_with_piplus_p~minus, KS0_M_with_pplus_piminus, KS0_M_with_pplus_p~minus. + * + * Cases with 3 or more daughters are possible but not tested. + * + * Warnings: + * + * 1) PIDReplacement is a python dictionary. To test two mass hypthesis replacements + * for the same daughter you must used 2 tool instances. + * + * 2) When CC = True (default), PIDReplacements implies cc. + * + * \sa DecayTreeTuple + * + * @author Patrick Koppenburg + * @date 2011-02-10 + */ +struct IParticleTransporter; +class TupleToolMassHypo : public TupleToolBase, virtual public IParticleTupleTool { +public: + /// Standard constructor + TupleToolMassHypo( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; ///< initialisation + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private : + double recalculateMass(const possDecay&, const Gaudi::XYZPoint&, std::string& combname); + possDecayVec getPossibilities(const LHCb::Particle::ConstVector&); + possDecayVec increaseVector(const LHCb::Particle* , possDecayVec& ); + void addPossPair(const LHCb::Particle* , int pid, possDecay& ); + void printVec(const possDecayVec&); + std::map m_replace ; ///< the PIDs to replace + std::map m_replacePDG ; ///< the PIDs to replace (as PDG codes) + bool m_revert ; ///< revert to positive PDG codes (default) + bool m_first ; + IParticleTransporter* m_transporter; + std::map m_massMap ; + std::map m_nameMap ; +}; + +#endif // JBOREL_TUPLETOOLMASSHYPO_H diff --git a/first-analysis-steps/DecayTrees/TupleToolMuonIDCalib.cpp b/first-analysis-steps/DecayTrees/TupleToolMuonIDCalib.cpp new file mode 100644 index 00000000..c7cb328f --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolMuonIDCalib.cpp @@ -0,0 +1,890 @@ +// Include files +#include "Event/Particle.h" +// kernel +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "GaudiKernel/PhysicalConstants.h" +#include "Kernel/IParticle2MCAssociator.h" +//#include "Kernel/Particle2MCLinker.h" +#include +#include "Kernel/IPVReFitter.h" +#include "Kernel/IBIntegrator.h" + +// +#include "TrackInterfaces/ITrackExtrapolator.h" +// MC stuff +#include "Event/GenHeader.h" +#include "Event/MCHeader.h" + +// from GSL +#include "gsl/gsl_math.h" +// Boost +#include + +// From the MuonDetector: +//#include "MuonAlgs/MuonBasicGeometry.h" +#include "MuonDet/MuonBasicGeometry.h" +#include "MuonDet/DeMuonDetector.h" +#include "Event/MuonDigit.h" +#include "Event/MCMuonDigit.h" +#include "Event/MCMuonDigitInfo.h" +#include "Event/IntLink.h" + +#include "TupleToolMuonIDCalib.h" +//#include "TMath.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolMuonIDCalib +// +// 2011-09-23 : Fatima Soomro +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( TupleToolMuonIDCalib ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolMuonIDCalib::TupleToolMuonIDCalib( const std::string& type, + const std::string& name, + const IInterface* parent) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); + declareProperty ( "NFoi" ,m_NFoi = 2 ) ; + declareProperty( "XFOIParameter1", m_xfoiParam1 ); + declareProperty( "XFOIParameter2", m_xfoiParam2 ); + declareProperty( "XFOIParameter3", m_xfoiParam3 ); + declareProperty( "YFOIParameter1", m_yfoiParam1 ); + declareProperty( "YFOIParameter2", m_yfoiParam2 ); + declareProperty( "YFOIParameter3", m_yfoiParam3 ); + declareProperty( "isVerbose", m_doVerbose = false); + declareProperty( "MomentumEstimate", m_estimate = true); + + std::vector tmp1 = boost::assign::list_of(0.015)(0.29); + declareProperty( "resParams", m_resParams = tmp1); + + std::vector tmp2 = boost::assign::list_of(1.04)(0.14); + declareProperty( "ParabolicCorrection", m_ParabolicCorrection = tmp2); + + declareProperty( "ConstantCorrection", m_Constant = 0.*Gaudi::Units::MeV ); + declareProperty( "Extrapolator" ,m_extrapolatorName = "TrackMasterExtrapolator" ) ; + +} + +//============================================================================= +// Fill the tuple +//============================================================================= +StatusCode TupleToolMuonIDCalib::fill( const LHCb::Particle * /* top */, + const LHCb::Particle *part, + const std::string & head, + Tuples::Tuple & tuple ) +{ + // nothing for particles that are not Bs + if( !part->isBasicParticle() || NULL==part->proto() ) + return StatusCode::SUCCESS; + + LoadMuonGeometry(); + if ( msgLevel(MSG::DEBUG) ) + debug () <<"Fatima: Loaded Geometry in TupleToolMuIDCalib"<< endmsg; + + m_bIntegrator = tool( "BIntegrator" ); + if (!m_bIntegrator) return StatusCode::FAILURE; + + m_extrapolator = tool( m_extrapolatorName, "MuEffExtrap",this ); + if (!m_extrapolator) return StatusCode::FAILURE; + + StatusCode sc = fillCoordVectors(); + if(!sc) error()<<"couldnt fillCoorVectors!!!"<("/dd/Structure/LHCb/DownstreamRegion/Muon"); + // set the size of the local vectors + m_regionInnerX.resize(m_NStation); + m_regionOuterX.resize(m_NStation); + m_regionInnerY.resize(m_NStation); + m_regionOuterY.resize(m_NStation); + for(int station = 0 ; station < m_NStation ; station++ ){ + m_stationZ.push_back(m_mudet->getStationZ(station)); + m_regionInnerX[station] = m_mudet->getInnerX(station); + m_regionOuterX[station] = m_mudet->getOuterX(station); + m_regionInnerY[station] = m_mudet->getInnerY(station); + m_regionOuterY[station] = m_mudet->getOuterY(station); + } + +} + +//========================================================================== +// fill vectors of x,y,z positions for the MuonCoords +//========================================================================== + +StatusCode TupleToolMuonIDCalib::fillCoordVectors(){ + + // m_HitInTrk.clear(); + m_coordPos.clear(); + m_coordPos.resize(m_NStation * m_NRegion); + m_hitInFOIx.clear(); + m_hitInFOIdx.clear(); + m_hitInFOIy.clear(); + m_hitInFOIdy.clear(); + m_hitInFOIz.clear(); + m_hitInFOIdz.clear(); + m_hitInFOIuncrossed.clear(); + m_hitInFOIID.clear(); + m_hitInFOITDC1.clear(); + m_hitInFOITDC2.clear(); + m_allMuonHitsX.clear(); + m_allMuonHitsDX.clear(); + m_allMuonHitsY.clear(); + m_allMuonHitsDY.clear(); + m_allMuonHitsZ.clear(); + m_allMuonHitsDZ.clear(); + m_allMuonHitsUncrossed.clear(); + m_allMuonHitsID.clear(); + m_allMuonHitsTDC1.clear(); + m_allMuonHitsTDC2.clear(); + + // get the MuonCoords for each station in turn + LHCb::MuonCoords* coords = NULL; + if(exist(LHCb::MuonCoordLocation::MuonCoords)) + coords = get(LHCb::MuonCoordLocation::MuonCoords); + if ( !coords ) + { + err() << "Cannot retrieve MuonCoords " << endmsg; + return StatusCode::FAILURE; + } + + // loop over the coords + LHCb::MuonCoords::const_iterator iCoord; + for ( iCoord = coords->begin() ; iCoord != coords->end() ; iCoord++ ){ + int region = (*iCoord)->key().region(); + int station = (*iCoord)->key().station(); + bool uncrossed = (*iCoord)->uncrossed(); + double x,dx,y,dy,z,dz; + int digitTDC1 = (*iCoord)->digitTDC1(); + int digitTDC2 = (*iCoord)->digitTDC2(); + LHCb::MuonTileID tile=(*iCoord)->key(); + StatusCode sc = m_mudet->Tile2XYZ(tile,x,dx,y,dy,z,dz); + if (sc.isFailure()){ + warning() << "Failed to get x,y,z of tile " << tile << endmsg; + continue; + } + m_coordPos[station*m_NRegion+region]. + push_back(coordExtent_(x,dx,y,dy,z,dz,uncrossed,digitTDC1,digitTDC2,*iCoord)); + // m_HitInTrk.push_back(false); + } + + return StatusCode::SUCCESS; + +} + +// return the FOI in x in a station and region for momentum (in MeV/c) +// this is a simpler version of the parameterization: +// foi = par0 + par2*exp(-par3*p) +//============================================================================= +double TupleToolMuonIDCalib::foiX(const int &station, const int ®ion, const double &p, + const double &dx){ + //============================================================================= + const double temp_x = ( m_xfoiParam1[ station * m_NRegion + region ] + + m_xfoiParam2[ station * m_NRegion + region ]* + std::exp(-m_xfoiParam3[ station * m_NRegion + region ]*p/Gaudi::Units::GeV ) )*dx; + //in the future optimize this checking that 2*dx =m_padSizeX[station * m_NRegion + region] + //then eliminates dx from function + + if ( msgLevel(MSG::VERBOSE) ) + verbose()<< "from FOIX "<isBasicParticle() ) || NULL==part->proto() ){ + error () << "!! Tried to fill MuonIDCalib quantities for particle " <particleID().pid()<< "!!! This should not happen"<< endmsg; + return StatusCode::SUCCESS; + } + + const LHCb::Track* track= part->proto()->track(); + if((track->checkFlag(LHCb::Track::Flags::Clone)) || + !( track->checkType(LHCb::Track::Types::Long) || track->checkType(LHCb::Track::Types::Downstream) + || track->checkType(LHCb::Track::Types::Ttrack) )){ + return StatusCode::SUCCESS ; + } + + ///------------------------------------------------------------------------------------- + // 6 March 2012, Add the muon detector hit positions related to the track, to the ntuple + // one has to get the muon part of the track (from muonPIDs)and then get the lhcbIDs related to it + ///------------------------------------------------------------------------------------- + + if(m_doVerbose){ + + std::vector m_x; + std::vector m_y; + std::vector m_z; + + LHCb::MuonPIDs* pMuids =NULL; + if(exist(LHCb::MuonPIDLocation::Default)) pMuids=get(LHCb::MuonPIDLocation::Default); + + if (!pMuids){ + error() << " Failed to get pMuids" << LHCb::MuonPIDLocation::Default << endmsg; + return StatusCode::FAILURE; + } + if ( msgLevel(MSG::DEBUG) ) + debug() << " >> number of Mu tracks in the event " << pMuids->size() << endmsg; + const LHCb::Track *mutrack=NULL; + LHCb::MuonPIDs::const_iterator ip; + for( ip = pMuids->begin(); ip != pMuids->end() ; ip++){ + if ((*ip)->idTrack() == track){ + mutrack = (*ip)->muonTrack(); + if (!mutrack) continue; + debug()<<"found a mutrack "< lhcbIDs = mutrack->lhcbIDs(); + if ( msgLevel(MSG::DEBUG) ) + debug() <<" Starting to find the muon hit info, have " <::const_iterator myID = lhcbIDs.begin(); + for ( ; myID != lhcbIDs.end(); myID++ ) + { + if ( ((*myID).isVelo()) ) countVelo++; + if ( ((*myID).isIT()) ) countIT++; + if ( ((*myID).isOT()) ) countOT++; + if ( ((*myID).isTT()) ) countTT++; + if ( ((*myID).isCalo()) ) countCALO++; + if ( ((*myID).isRich()) ) countRICH++; + + if ( ((*myID).isMuon()) ) + { + countMuon++; + const LHCb::MuonTileID mutile = (*myID).muonID(); + double x,dx,y,dy,z,dz; + StatusCode sc = m_mudet->Tile2XYZ(mutile,x,dx,y,dy,z,dz); + if ( msgLevel(MSG::DEBUG) ) + debug()<<"Muon pad hit: "<checkHistory(LHCb::Track::History::MuonID) <farray(prefix+"_LHCbID_X", m_x.begin(), m_x.end(), prefix+"_n", 100); + tuple->farray(prefix+"_LHCbID_Y", m_y.begin(), m_y.end(), prefix+"_n", 100); + tuple->farray(prefix+"_LHCbID_Z", m_z.begin(), m_z.end(), prefix+"_n", 100); + + }// m_doVerbose + + ///------------------------------------------------------------------------------- + /// Project the state at M1 into the rest of the muon stations and store the x, y + ///------------------------------------------------------------------------------- + + m_stateP = &(track->closestState(m_stationZ[0])); + + for(int station = 0; station < m_NStation ; station++){ + + m_trackX[station] = m_stateP->x() + ( m_stateP->tx() * (m_stationZ[station] - m_stateP->z()) ); + m_trackY[station] = m_stateP->y() + ( m_stateP->ty() * (m_stationZ[station] - m_stateP->z()) ); + if ( msgLevel(MSG::DEBUG) ) + debug () <<"Station: "<tx() <<" * ("<< m_stationZ[station] + <<" - "<z()<<" ) )"<< endmsg; + } // station + + // extrapolation through the stations to get expected positions with + // errors due to multiple scattering + + bool ecode = estrapola(); + if ( !ecode ) debug() << "estrapola: track extrapolation failed " << endmsg; + + bool test = true; + for(int station = 0; station < m_NStation ; station++) + { + std::stringstream ss; + ss << station+1; + test &= tuple->column(prefix+"_Xs"+ss.str(), m_trackX[station] ); + test &= tuple->column(prefix+"_Ys"+ss.str(), m_trackY[station] ); + + test &= tuple->column(prefix+"_extraXs"+ss.str(), m_TextraX[station] ); + test &= tuple->column(prefix+"_extraYs"+ss.str(), m_TextraY[station] ); + test &= tuple->column(prefix+"_ms2Xs"+ss.str(), m_ms2X[station] ); + test &= tuple->column(prefix+"_ms2Ys"+ss.str(), m_ms2Y[station] ); + test &= tuple->column(prefix+"_TRegs"+ss.str(), m_TextraReg[station] ); + } + + // ====================================== + // Calculate and fill DistAve and Xs, Ys + // ====================================== + + double m_momentum = m_stateP -> p(); + int nHits=0; + int ic_hit = 0; + //int ic_closesthit = 0; + float dist_ave = 0; + std::vector small_dist(m_NStation); + + for ( int i = 0; i < m_NStation; ++i ) + { + small_dist[i] = 100000000.; + m_smalldist_X[i] = 100000000.; + m_smalldist_Y[i] = 100000000.; + m_smalldist_Z[i] = 100000000.; + m_smalldist_dX[i] = 0.; + m_smalldist_dY[i] = 0.; + m_smalldist_dZ[i] = 0.; + } + + // store hit info if its in the FOI of the track + + + for(int station = 0 ; station < m_NStation ; station++){ + + for(int region = 0 ; region < m_NRegion ; region++){ + + if( !m_coordPos[station*m_NRegion + region].empty() ){ + + std::vector::const_iterator itPos; + + for(itPos = m_coordPos[station*m_NRegion + region].begin(); itPos != m_coordPos[station*m_NRegion + region].end(); itPos++){ + + // all muon hits + if(m_doVerbose) { + m_allMuonHitsX.push_back(itPos->m_x); + m_allMuonHitsDX.push_back(itPos->m_dx); + m_allMuonHitsY.push_back(itPos->m_y); + m_allMuonHitsDY.push_back(itPos->m_dy); + m_allMuonHitsZ.push_back(itPos->m_z); + m_allMuonHitsDZ.push_back(itPos->m_dz); + m_allMuonHitsUncrossed.push_back(itPos->m_uncrossed); + m_allMuonHitsID.push_back(station*m_NRegion + region); + m_allMuonHitsTDC1.push_back(itPos->m_digitTDC1); + m_allMuonHitsTDC2.push_back(itPos->m_digitTDC2); + } + + // hits in foi + double x = itPos->m_x; + double dx = itPos->m_dx; + double y = itPos->m_y; + double dy = itPos->m_dy; + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "Computing DistAve: x, dx, y, dy are "<m_x; + m_smalldist_Y[station] = itPos->m_y; + m_smalldist_Z[station] = itPos->m_z; + m_smalldist_dX[station] = itPos->m_dx; + m_smalldist_dY[station] = itPos->m_dy; + m_smalldist_dZ[station] = itPos->m_dz; + //ic_closesthit = ic_hit; + } + + // define the FOI in which we have to evaluate the average + double foiXDim = m_NFoi*foiX( station, region, m_momentum, dx); + double foiYDim = m_NFoi*foiY( station, region, m_momentum, dy); + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "Checking for FOI: "<< m_NFoi<<" "<m_z); + m_hitInFOIdz.push_back(itPos->m_dz); + m_hitInFOIuncrossed.push_back(itPos->m_uncrossed); + m_hitInFOIID.push_back(station*m_NRegion + region); + m_hitInFOITDC1.push_back(itPos->m_digitTDC1); + m_hitInFOITDC2.push_back(itPos->m_digitTDC2); + m_hitInFOIID.push_back(station*m_NRegion + region); + } + + } + + ++ic_hit; + }// for itPos + + }// region not empty + + }// region + + } // station + + if(m_doVerbose){ + tuple->farray(prefix+"_hitInFOI_X", m_hitInFOIx.begin(), m_hitInFOIx.end(), prefix+"_n_InFOI", 500); + tuple->farray(prefix+"_hitInFOI_dX", m_hitInFOIdx.begin(), m_hitInFOIdx.end(), prefix+"_n_InFOI", 500); + tuple->farray(prefix+"_hitInFOI_Y", m_hitInFOIy.begin(), m_hitInFOIy.end(), prefix+"_n_InFOI", 500); + tuple->farray(prefix+"_hitInFOI_dY", m_hitInFOIdy.begin(), m_hitInFOIdy.end(), prefix+"_n_InFOI", 500); + tuple->farray(prefix+"_hitInFOI_Z", m_hitInFOIz.begin(), m_hitInFOIz.end(), prefix+"_n_InFOI", 500); + tuple->farray(prefix+"_hitInFOI_dZ", m_hitInFOIdz.begin(), m_hitInFOIdz.end(), prefix+"_n_InFOI", 500); + tuple->farray(prefix+"_hitInFOI_ID", m_hitInFOIID.begin(), m_hitInFOIID.end(), prefix+"_n_InFOI", 500); + tuple->farray(prefix+"_hitInFOI_uncrossed", m_hitInFOIuncrossed.begin(), m_hitInFOIuncrossed.end(), prefix+"_n_InFOI", 500); + tuple->farray(prefix+"_hitInFOI_TDC1", m_hitInFOITDC1.begin(), m_hitInFOITDC1.end(), prefix+"_n_InFOI", 500); + tuple->farray(prefix+"_hitInFOI_TDC2", m_hitInFOITDC2.begin(), m_hitInFOITDC2.end(), prefix+"_n_InFOI", 500); + if(prefix=="lab2"){ + tuple->farray(prefix+"_allMuonHits_X", m_allMuonHitsX.begin(), m_allMuonHitsX.end(), prefix+"_n_AllHits", 10000); + tuple->farray(prefix+"_allMuonHits_dX", m_allMuonHitsDX.begin(), m_allMuonHitsDX.end(), prefix+"_n_AllHits", 10000); + tuple->farray(prefix+"_allMuonHits_Y", m_allMuonHitsY.begin(), m_allMuonHitsY.end(), prefix+"_n_AllHits", 10000); + tuple->farray(prefix+"_allMuonHits_dY", m_allMuonHitsDY.begin(), m_allMuonHitsDY.end(), prefix+"_n_AllHits", 10000); + tuple->farray(prefix+"_allMuonHits_Z", m_allMuonHitsZ.begin(), m_allMuonHitsZ.end(), prefix+"_n_AllHits", 10000); + tuple->farray(prefix+"_allMuonHits_dZ", m_allMuonHitsDZ.begin(), m_allMuonHitsDZ.end(), prefix+"_n_AllHits", 10000); + tuple->farray(prefix+"_allMuonHits_ID", m_allMuonHitsID.begin(), m_allMuonHitsID.end(), prefix+"_n_AllHits", 10000); + tuple->farray(prefix+"_allMuonHits_uncrossed", m_allMuonHitsUncrossed.begin(), m_allMuonHitsUncrossed.end(), prefix+"_n_AllHits", 10000); + tuple->farray(prefix+"_allMuonHits_TDC1", m_allMuonHitsTDC1.begin(), m_allMuonHitsTDC1.end(), prefix+"_n_AllHits", 10000); + tuple->farray(prefix+"_allMuonHits_TDC2", m_allMuonHitsTDC2.begin(), m_allMuonHitsTDC2.end(), prefix+"_n_AllHits", 10000); + } + + for(int station = 0; station < m_NStation ; ++station ) + { + std::stringstream ss; ss<< station+1 ; const std::string& mychar2 = ss.str(); + test &= tuple->column(prefix+"Stn"+mychar2+"X", m_smalldist_X[station]); + test &= tuple->column(prefix+"Stn"+mychar2+"Y", m_smalldist_Y[station]); + test &= tuple->column(prefix+"Stn"+mychar2+"Z", m_smalldist_Z[station]); + } + + } + + + if(m_estimate){ + // estimate the momentum of the muon-track assuming it cames from the primary vertex + // first --> do a linear fit with the closest hits in FOI, starting from M1 to M5, + // if successful call the tool to estimate the momentum + // + m_5pZM1 = 0.; + m_5qOverP = 0.; + m_5sigmaQOverP2 = 0.; + m_5pXPvtx = 0.; + m_5pYPvtx = 0.; + m_5pZPvtx = 0.; + + int FromM1 = 1; + bool fcode = linFit(FromM1); + if ( !fcode ) { + debug() << "linFit: linear fit closest hits in FOI failed " << endmsg; + } else { + bool pcode = calculatePt(FromM1); + if ( !pcode ) debug() << "calculatePt: calculation momentum of muon track failed From M1" << endmsg; + } + test &= tuple->column(prefix+"_5pZM1", m_5pZM1); + test &= tuple->column(prefix+"_5qOverP", m_5qOverP); + test &= tuple->column(prefix+"_5sigmaQOverP2", m_5sigmaQOverP2); + test &= tuple->column(prefix+"_5pXvtx", m_5pXPvtx); + test &= tuple->column(prefix+"_5pYvtx", m_5pYPvtx); + test &= tuple->column(prefix+"_5pZvtx", m_5pZPvtx); + + // estimate the momentum of the muon-track assuming it cames from the primary vertex + // first --> do a linear fit with the closest hits in FOI, starting from M2 to M5, + // if successful call the tool to estimate the momentum + // + m_4pZM1 = 0.; + m_4qOverP = 0.; + m_4sigmaQOverP2 = 0.; + m_4pXPvtx = 0.; + m_4pYPvtx = 0.; + m_4pZPvtx = 0.; + + int FromM1_2 = 0; + bool fcode_2 = linFit(FromM1_2); + if ( !fcode_2 ) { + debug() << "linFit: linear fit closest hits in FOI failed " << endmsg; + } else { + bool pcode_2 = calculatePt(FromM1_2); + if ( !pcode_2 ) debug() << "calculatePt: calculation momentum of muon track failed From M2" << endmsg; + } + test &= tuple->column(prefix+"_4pZM1", m_4pZM1); + test &= tuple->column(prefix+"_4qOverP", m_4qOverP); + test &= tuple->column(prefix+"_4sigmaQOverP2", m_4sigmaQOverP2); + test &= tuple->column(prefix+"_4pXvtx", m_4pXPvtx); + test &= tuple->column(prefix+"_4pYvtx", m_4pYPvtx); + test &= tuple->column(prefix+"_4pZvtx", m_4pZPvtx); + } + + if (nHits>0) + { + dist_ave = dist_ave/nHits; + } + + if ( msgLevel(MSG::VERBOSE) ) + verbose() <<" So the dist_ave for track "<< track->key()<<" ("<< track->charge() + << ") will be: " << dist_ave<< endmsg; + + test &= tuple->column( prefix+"_DistAve", dist_ave ) ; + return test ? StatusCode::SUCCESS : StatusCode::FAILURE; + +} // fillVars + + +/// track fitting with linear Chi^2 from M1/M2 to M5 +bool TupleToolMuonIDCalib::linFit(int &FromM1) +{ + + m_sx = m_sy = 0.; + m_bx = m_by = 0.; + m_errbx = m_errsx = m_covbsx = 0.; + m_errby = m_errsy = m_covbsy = 0.; + m_chi2x = m_chi2y = 0.; + + + int StartI = 0; // fit from M1 to M5 + if (FromM1==0) StartI = 1; // fit from M2 to M5 + + int nPunti = 0; + for ( int i = StartI; i < m_NStation; ++i ) { + if (m_smalldist_X[i]==0.0) continue; + nPunti++; + } + + double dof = nPunti - 2.; + if (dof== 0.) return false; + + double xc11,xc12,xc22,xv1,xv2,xxx; + xc11 = xc12 = xc22 = xv1 = xv2 = xxx = 0.; + double yc11,yc12,yc22,yv1,yv2,yyy; + yc11 = yc12 = yc22 = yv1 = yv2 = yyy = 0.; + double xdet,ydet; + xdet = ydet = 0.; + double xerr,yerr; + xerr = yerr = 0.; + + for ( int i = StartI; i < m_NStation; ++i ) { + + if (m_smalldist_dX[i]== 0.0) continue; + double x,dx,y,dy,z; //dz; + + x = m_smalldist_X[i]; + y = m_smalldist_Y[i]; + z = m_smalldist_Z[i]; + dx = m_smalldist_dX[i]; + dy = m_smalldist_dY[i]; + //dz = m_smalldist_dZ[i]; + + xerr = 2.* dx; + yerr = 2.* dy; + + // then fit them with a min chi^2 in the 2 projections xz and yz + //1) XZ projection: + xc11 += z*z/xerr/xerr; + xc12 += z/xerr/xerr; + xc22 += 1.0/xerr/xerr; + xv1 += z*x/xerr/xerr; + xv2 += x/xerr/xerr; + xxx += x*x/xerr/xerr; + + //2) YZ projection: + yc11 += z*z/yerr/yerr; + yc12 += z/yerr/yerr; + yc22 += 1.0/yerr/yerr; + yv1 += z*y/yerr/yerr; + yv2 += y/yerr/yerr; + yyy += y*y/yerr/yerr; + + } + + if( (xdet = xc11*xc22 - xc12*xc12) == 0 ) return false; + if( (ydet = yc11*yc22 - yc12*yc12) == 0 ) return false; + m_sx = (xv1*xc22-xv2*xc12)/xdet; + m_sy = (yv1*yc22-yv2*yc12)/ydet; + m_bx = (xv2*xc11-xv1*xc12)/xdet; + m_by = (yv2*yc11-yv1*yc12)/ydet; + + m_errbx = sqrt(xc11/xdet); + m_errsx = sqrt(xc22/xdet); + m_covbsx = -xc12/xdet; + + m_errby = sqrt(yc11/ydet); + m_errsy = sqrt(yc22/ydet); + m_covbsy = -yc12/ydet; + + m_chi2x = (xxx + m_sx*m_sx*xc11 + m_bx*m_bx*xc22 - 2.*m_sx*xv1 -2.*m_bx*xv2 + 2*m_sx*m_bx*xc12)/dof; + m_chi2y = (yyy + m_sy*m_sy*yc11 + m_by*m_by*yc22 - 2.*m_sy*yv1 -2.*m_by*yv2 + 2*m_sy*m_by*yc12)/dof; + + return true; +} + +//============================================================================= +// Determination of the field polarity +//============================================================================= +StatusCode TupleToolMuonIDCalib::FindFieldPolarity() +{ + // compute fiels polarity + // we will use this value for all tracks + + double Zfirst = m_stationZ[0]; // M1 + + Gaudi::XYZPoint begin( 0., 0., 0. ); + Gaudi::XYZPoint end( 0., 0., Zfirst ); + Gaudi::XYZVector bdl; + double z; + + StatusCode sc = m_bIntegrator -> calculateBdlAndCenter( begin, end, 0., 0., z, bdl ); + if (sc.isFailure()){ + return Error("Failed to find field centre !", StatusCode::FAILURE); + } + + if ( bdl.x() > 0.0 ) { + m_FieldPolarity = 1; + } + else { + m_FieldPolarity = -1; + } + + debug() << "Integrated B field is "<< bdl.x() << " Tm" << + " centered at Z="<< z/Gaudi::Units::m << " m"< calculateBdlAndCenter(begin, end, state.tx(), + state.ty(), zCenter, bdl ); + if (!sc){ + error() <<" Failed to integrate field !!"< TrackParameters::hiTolerance ) { + //can estimate momentum and charge + + //Rotate to the 0-0-z axis and do the ptkick + tX = state.tx(); + xCenter = state.x() + tX * ( zCenter - state.z() ); + + zeta_trk = -tX / sqrt( 1.0 + tX*tX ); + tx_vtx = xCenter / zCenter; + zeta_vtx = -tx_vtx/ sqrt( 1.0 + tx_vtx*tx_vtx ); + + // curvature + curv = ( zeta_trk - zeta_vtx ); + + // charge + int sign = 1; + if( curv < TrackParameters::hiTolerance ) { + sign *= -1; + } + if ( bdl.x() < TrackParameters::hiTolerance ) { + sign *= -1; + } + q = -1. * m_FieldPolarity*sign; + + // momentum + p = Gaudi::Units::eplus * Gaudi::Units::c_light *fabs(bdl.x()) + * sqrt((1.0 +tX*tX+gsl_pow_2(state.ty())) + /(1.0 +gsl_pow_2(tX)))/fabs(curv); + + // Addition Correction factor for the angle of the track! + if ( m_ParabolicCorrection.size() == 2u ) { + //p*= (a + b*tx*tx ) + p+= m_Constant; + p*= ( m_ParabolicCorrection[0] + (m_ParabolicCorrection[1] * tX * tX )); + } + + } + else { + // can't estimate momentum or charge + error() << "B integral is 0!" << endmsg; + return false; + } + + pZM1 = p; + qOverP = q / p; + const double err2 = gsl_pow_2(m_resParams[0]) + gsl_pow_2(m_resParams[1]/p) ; + sigmaQOverP2 = err2*gsl_pow_2(1.0/p); + + // set MuonTrack momentum variables (momentum at primary vertex) + if ( (tx_vtx*tx_vtx + state.ty()*state.ty()) > 1.) { + // can't estimate momentum vector components + error() << "can't estimate px, py, pz " << endmsg; + return false; + } + double pz_vtx = p * sqrt(1- tx_vtx*tx_vtx - state.ty()*state.ty() ); + Gaudi::XYZVector momentum_vtx( tx_vtx * pz_vtx, + state.ty()* pz_vtx, + pz_vtx); + pXPvtx = momentum_vtx.X(); + pYPvtx = momentum_vtx.Y(); + pZPvtx = momentum_vtx.Z(); + + if (FromM1==1) + { + m_5pZM1 = pZM1; + m_5qOverP = qOverP; + m_5sigmaQOverP2 = sigmaQOverP2; + m_5pXPvtx = pXPvtx; + m_5pYPvtx = pYPvtx; + m_5pZPvtx = pZPvtx; + } + else if (FromM1==0) + { + m_4pZM1 = pZM1; + m_4qOverP = qOverP; + m_4sigmaQOverP2 = sigmaQOverP2; + m_4pXPvtx = pXPvtx; + m_4pYPvtx = pYPvtx; + m_4pZPvtx = pZPvtx; + } + + return true; +} + +// extrapolation through the stations to get expected positions with +// errors due to multiple scattering +//======================================================= +bool TupleToolMuonIDCalib::estrapola(){ +//======================================================= + + LHCb::State ExtraState =*(m_stateP); + + for (int station=0; stationpropagate( ExtraState, m_stationZ[station], LHCb::Tr::PID::Muon() ); + if( sc.isFailure() ) { + debug() << " ==> Extrapolating to z = " << m_stationZ[station] << " failed "< m_xfoiParam1; + std::vector< double > m_xfoiParam2; + std::vector< double > m_xfoiParam3; + std::vector< double > m_yfoiParam1; + std::vector< double > m_yfoiParam2; + std::vector< double > m_yfoiParam3; + + //-------------------------- + // Muon Detector variables: + //-------------------------- + + int m_NStation; /// Number of stations + int m_NRegion; ///Number of regions + //Names of the station + std::vector m_stationNames; + // fill local arrays of pad sizes and region sizes + DeMuonDetector* m_mudet; + + // track state @ M1 + const LHCb::State *m_stateP; + + // These are indexed [station] + std::vector m_stationZ; // station position + double m_trackX[5]; // position of track in x(mm) in each station + double m_trackY[5]; // position of track in y(mm) in each station + + std::string m_extrapolatorName; + ITrackExtrapolator* m_extrapolator; ///< extrapolator + double m_TextraX[5]; // x(mm) position of extrapolated track in each station + double m_TextraY[5]; // y(mm) position of extrapolated track in each station + double m_ms2X[5]; // ms error on x(mm) position in each station + double m_ms2Y[5]; // ms error on y(mm) position in each station + double m_TextraReg[5]; // region crossed by the extrapolated track + + // closest hit in FOI[station] ==> input for linFit, the linear fit + double m_smalldist_X[5]; + double m_smalldist_Y[5]; + double m_smalldist_Z[5]; + double m_smalldist_dX[5]; + double m_smalldist_dY[5]; + double m_smalldist_dZ[5]; + + // linear fit results + double m_sx, m_sy; + double m_bx, m_by; + double m_errbx, m_errsx, m_covbsx; + double m_errby, m_errsy, m_covbsy; + double m_chi2x, m_chi2y; + + // pt calculation + std::vector m_ParabolicCorrection; + std::vector m_resParams; + double m_Constant; + IBIntegrator* m_bIntegrator; // magnetic field tool + double m_FieldPolarity; + + double m_4qOverP; + double m_4sigmaQOverP2; + double m_4pZM1; + double m_4pXPvtx; + double m_4pYPvtx; + double m_4pZPvtx; + + double m_5qOverP; + double m_5sigmaQOverP2; + double m_5pZM1; + double m_5pXPvtx; + double m_5pYPvtx; + double m_5pZPvtx; + + std::vector m_hitInFOIx; + std::vector m_hitInFOIdx; + std::vector m_hitInFOIy; + std::vector m_hitInFOIdy; + std::vector m_hitInFOIz; + std::vector m_hitInFOIdz; + std::vector m_hitInFOIuncrossed; + std::vector m_hitInFOIID; + std::vector m_hitInFOITDC1; + std::vector m_hitInFOITDC2; + std::vector m_allMuonHitsX; + std::vector m_allMuonHitsDX; + std::vector m_allMuonHitsY; + std::vector m_allMuonHitsDY; + std::vector m_allMuonHitsZ; + std::vector m_allMuonHitsDZ; + std::vector m_allMuonHitsUncrossed; + std::vector m_allMuonHitsTDC1; + std::vector m_allMuonHitsTDC2; + std::vector m_allMuonHitsID; + bool m_doVerbose; + bool m_estimate; + + // local array of region sizes + std::vector m_regionInnerX; // inner edge in abs(x) + std::vector m_regionOuterX; // outer edge in abs(x) + std::vector m_regionInnerY; // inner edge in abs(y) + std::vector m_regionOuterY; // outer edge in abs(y) + + // Store x,dx,y,dy of each coord + class coordExtent_{ + public: + coordExtent_(double x, double dx, double y, double dy, double z, double dz, bool uncrossed, int digitTDC1, int digitTDC2, + LHCb::MuonCoord *pCoord) : + m_x(x), m_dx(dx), m_y(y), m_dy(dy), m_z(z), m_dz(dz), m_uncrossed(uncrossed), m_digitTDC1(digitTDC1), m_digitTDC2(digitTDC2), m_pCoord(pCoord) {}; + double m_x; + double m_dx; + double m_y; + double m_dy; + double m_z; + double m_dz; + bool m_uncrossed; + int m_digitTDC1; + int m_digitTDC2; + LHCb::MuonCoord *m_pCoord; + }; + // vector of positions of coords (innner vector coords, + // outer is [station* m_NRegion + region ] + std::vector > m_coordPos; + + +}; + +#endif // TUPLETOOLMUONIDCALIB_H diff --git a/first-analysis-steps/DecayTrees/TupleToolMuonPid.cpp b/first-analysis-steps/DecayTrees/TupleToolMuonPid.cpp new file mode 100755 index 00000000..06459282 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolMuonPid.cpp @@ -0,0 +1,230 @@ +// Include files + +// from Gaudi +#include "DetDesc/IGeometryInfo.h" +#include "Event/MuonCoord.h" +#include "Kernel/LHCbID.h" +#include "Kernel/MuonTileID.h" +#include "Kernel/Particle2MCLinker.h" + + +// local +#include "TupleToolMuonPid.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" +//----------------------------------------------------------------------------- +// Implementation file for class : EventInfoTupleTool +// +// 2007-11-07 : Jeremie Borel +//----------------------------------------------------------------------------- + +using namespace LHCb; + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolMuonPid::TupleToolMuonPid( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); +} + +//============================================================================= + +//============================================================================= +StatusCode TupleToolMuonPid::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + // Get Basic Muon geometry info + m_NStation = 0; + m_NRegion = 0; + MuonBasicGeometry basegeometry( detSvc(),msgSvc()); + m_NStation= basegeometry.getStations(); + m_NRegion = basegeometry.getRegions(); + unsigned int i=0; + while(i("/dd/Structure/LHCb/DownstreamRegion/Muon"); + //m_mudet=getDet(DeMuonLocation::Default); + for(unsigned int station = 0 ; station < m_NStation ; station++ ){ + m_stationZ.push_back(m_mudet->getStationZ(station)); + } + if(!m_mudet) return StatusCode::FAILURE; + return sc; + +} +//============================================================================= + +StatusCode TupleToolMuonPid::fill( const Particle* + , const Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(head); + if (msgLevel(MSG::DEBUG)) debug() << "TupleToolMuonPid::fill: ++++++++ Filling info for particle with key " << P->key() << " head: " << head << " ++++++++ " << endmsg; + if( P ){ + bool test = true; + test &= tuple->column( prefix+"_ID", P->particleID().pid() ); + if( !P->isBasicParticle() ) return StatusCode(test); // no rich info for composite! + if( isPureNeutralCalo(P)) return StatusCode(test); // no rich information for calo neutrals + const ProtoParticle* proto = P->proto(); + if( proto ){ + // Combined DLLs + test &= tuple->column( prefix+"_CombDLLMu" + ,proto->info(LHCb::ProtoParticle::additionalInfo::CombDLLmu,-1000)); + test &= tuple->column( prefix+"_ProbNNmu" + ,proto->info(LHCb::ProtoParticle::additionalInfo::ProbNNmu,-1000)); + test &= tuple->column( prefix+"_ProbNNghost" + ,proto->info(LHCb::ProtoParticle::additionalInfo::ProbNNghost,-1000)); + test &= tuple->column( prefix+"_InMuonAcc" + ,proto->info(LHCb::ProtoParticle::additionalInfo::InAccMuon, -1000)); + bool hasMuon = false; + bool isMuon = false; + bool isMuonLoose = false; + //bool isMuonTight = false; + double muonLLmu = -99999; + double muonLLbg = -99999; + const MuonPID * muonPID = proto->muonPID(); + int NShared = -1; + double muonDist2 = -99999; + if(muonPID) { + hasMuon = true; + isMuon = muonPID->IsMuon(); + isMuonLoose = muonPID->IsMuonLoose(); + //isMuonTight = muonPID->IsMuonTight(); + NShared = muonPID->nShared(); + muonLLmu= muonPID->MuonLLMu(); + muonLLbg= muonPID->MuonLLBg(); + //std::cout << "before get Tracks" << std::endl; + const LHCb::Track* track = muonPID->muonTrack(); + if (track) { + //std::cout << "before get muonDist2" << std::endl; + muonDist2 = track->info(LHCb::Track::AdditionalInfo::MuonDist2, -1000); + } + } + + // Find region in M2 or M3 from track extrapolation, used to calculate muLL + const LHCb::Track *pTrack = proto->track(); + std::vector trackRegion(m_NStation,-1); + + //find track region + trackRegion=findTrackRegions(pTrack); + int region=trackRegion[1]; // M2 + if (region<0) { + if (msgLevel(MSG::DEBUG)) debug() << " Track extrapolation in station 2 gives non-existent region "<< endmsg; + region=trackRegion[2]; // M3 + } + if (region<0 && msgLevel(MSG::DEBUG)) debug() << " Track extrapolation in station 3 gives non-existent region " << endmsg; + + if (msgLevel(MSG::DEBUG)) debug() << "TupleToolMuonPid::fill:Track info: p = " << pTrack->p() << " Region in M2/M3: " << region + << " IsMuonLoose = " << isMuonLoose << " IsMuon = " << isMuon << " Dist2 = " << muonDist2 + << " muonLLmu = " << muonLLmu << " muonLLbg = " << muonLLbg << endmsg; + + //std::cout << "before add MuonDist2 to ntuple" << std::endl; + test &= tuple->column( prefix+"_MuonDist2", muonDist2); + test &= tuple->column( prefix+"_regionInM2", region); + int isMuonFromProto = -2000; + test &= tuple->column( prefix+"_hasMuon", hasMuon); + test &= tuple->column( prefix+"_isMuon", isMuon); + test &= tuple->column( prefix+"_isMuonLoose", isMuonLoose); + //test &= tuple->column( prefix+"_isMuonTight", isMuonTight); + test &= tuple->column( prefix+"_NShared", NShared); + test &= tuple->column( prefix+"_MuonLLmu", muonLLmu); + test &= tuple->column( prefix+"_MuonLLbg", muonLLbg); + + isMuonFromProto = ((int) (proto->info(LHCb::ProtoParticle::additionalInfo::MuonPIDStatus, -999)))%2; + test &= tuple->column( prefix+"_isMuonFromProto", isMuonFromProto ); + + //const LHCb::Track* track = proto->track(); + //if (track) { + // test &= tuple->column( prefix+"_MuonDist2", track->info(LHCb::Track::AdditionalInfo::MuonDist2, -1000)); + //} + + return StatusCode(test); + } + } + return StatusCode::FAILURE; +} + +//===================================================================== +// Extrapolate track to Muon system and find region in each chamber. Region in M2 is used in the dll calculation +// Code copied/adapted from MuonIDAlg. J. Helder. 04/2013 +//===================================================================== + +StatusCode TupleToolMuonPid::trackExtrapolate(const LHCb::Track *pTrack, std::vector &trackX, std::vector &trackY ){ + + // get first state for the preSel cut + const LHCb::State * state1 = &(pTrack->firstState()); + // get state closest to M1 for extrapolation + const LHCb::State * state = &(pTrack->closestState(9450.)); + + if(!state1) return Error(" Failed to get 1st state from track "); + if(!state) return Error(" Failed to get state from track "); + + // get the momentum (MeV/c) + //double momentum = state->p(); + //double momentumPre = state1->p(); + //if (msgLevel(MSG::DEBUG)) debug() << "trackExtrapolate: momentum = " << momentum << " momentumPre = " << momentumPre << endmsg; + + // Project the state into the muon stations + for(unsigned int station = 0; station < m_NStation ; station++){ + // x(z') = x(z) + (dx/dz * (z' - z)) + trackX.push_back(state->x() + ( state->tx() * + (m_stationZ[station] - state->z()) )); + trackY.push_back(state->y() + ( state->ty() * + (m_stationZ[station] - state->z()) )); + } + if (msgLevel(MSG::DEBUG)) { + debug() << "trackExtrapolate: trackX = " << trackX << endmsg; + debug() << "trackExtrapolate: trackY = " << trackY << endmsg; + } + return StatusCode::SUCCESS; +} + +//===================================================================== +std::vector TupleToolMuonPid::findTrackRegions(const LHCb::Track *pTrack){ + //===================================================================== + // comment: Returns the muon detector region of the extrapolated track; + // authors: G. Lanfranchi & S. Furcas & X. Cid Vidal, + // date: 10/3/11 + //===================================================================== + + std::vector trackX; + std::vector trackY; + trackExtrapolate(pTrack,trackX,trackY); + + //info() << "findTrackRegions: trackX = " << trackX << endmsg; + //info() << "findTrackRegions: trackY = " << trackY << endmsg; + + + std::vector trackRegion(m_NStation,-1); + // Region of the track extrapolated: + + for (unsigned int sta=0;staPos2StChamberNumber(trackX[sta],trackY[sta],sta,chnum,regnum).ignore(); + //if (msgLevel(MSG::DEBUG)) debug() << "TupleToolMuonPid: Station = " << sta << " chnum = " << chnum << " regnum = " << regnum << endmsg; + trackRegion[sta] = regnum; + if (trackRegion[sta]<0 && msgLevel(MSG::DEBUG) ) + debug() << format(" Track extrapolation in station %d gives not-existent region ",sta) << endmsg; + } + + if (msgLevel(MSG::DEBUG)) debug() << "TrackRegions: " << trackRegion << endmsg; + return trackRegion; +} + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolMuonPid ) diff --git a/first-analysis-steps/DecayTrees/TupleToolMuonPid.h b/first-analysis-steps/DecayTrees/TupleToolMuonPid.h new file mode 100755 index 00000000..a24379bf --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolMuonPid.h @@ -0,0 +1,56 @@ +// $Id: TupleToolMuonPid.h,v 1.4 2010-03-04 14:02:03 xieyu Exp $ +#ifndef TUPLETOOLMUONID_H +#define TUPLETOOLMUONID_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "MuonDet/MuonBasicGeometry.h" +#include "MuonDet/DeMuonDetector.h" +//#include "MuonDet/MuonNamespace.h" + +// From event packages +#include "Event/MuonPID.h" +#include "Event/Track.h" +#include "Event/MuonCoord.h" +#include "Event/MuonDigit.h" + + +/** @class TupleToolMuonPid TupleToolMuonPid.h + * + * @author Kazu Akiba + * @date 2011-09-01 + * + */ +class TupleToolMuonPid : public TupleToolBase, virtual public IParticleTupleTool { +public: + /// Standard constructor + TupleToolMuonPid( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; ///< Algorithm initialization + + virtual ~TupleToolMuonPid(){}; ///< Destructor + + StatusCode fill( const LHCb::Particle*, const LHCb::Particle* + , const std::string&, Tuples::Tuple& ) override; + + StatusCode trackExtrapolate(const LHCb::Track *pTrack, std::vector &trackX, std::vector &trackY ); + std::vector findTrackRegions(const LHCb::Track *pTrack); + +private: + DeMuonDetector* m_mudet; + unsigned int m_NStation; // Number of stations + unsigned int m_NRegion; //Number of regions + std::vector m_stationZ; // station position + std::vector m_trackX; // position of track in x(mm) in each station + std::vector m_trackY; // position of track in y(mm) in each station + + //Names of the station + std::vector m_stationNames; + + +}; +#endif // TUPLETOOLMUONID_H diff --git a/first-analysis-steps/DecayTrees/TupleToolNeutrinoReco.cpp b/first-analysis-steps/DecayTrees/TupleToolNeutrinoReco.cpp new file mode 100755 index 00000000..a9129a9b --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolNeutrinoReco.cpp @@ -0,0 +1,192 @@ +// Include files + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include +#include + +// local +#include "TupleToolNeutrinoReco.h" + +#include "Event/Particle.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolNeutrinoReco +// +// 2010-11-24 : Rob Lambert +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolNeutrinoReco ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolNeutrinoReco::TupleToolNeutrinoReco( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); + + declareProperty("MotherMass",m_motherMass=0.); +} + +//============================================================================= + +StatusCode TupleToolNeutrinoReco::initialize() +{ + if( ! TupleToolBase::initialize() ) return StatusCode::FAILURE; + + m_dva = Gaudi::Utils::getIDVAlgorithm ( contextSvc(), this ) ; + + if (!m_dva) return Error("Couldn't get parent DVAlgorithm", + StatusCode::FAILURE); + + return StatusCode::SUCCESS; +} + +//============================================================================= + +StatusCode TupleToolNeutrinoReco::fill( const LHCb::Particle* + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(head); + + bool test = true; + if( P ) + { + const LHCb::VertexBase* aPV = m_dva->bestVertex( P ); + // Parallel and Perpendicular Momentum of the particle + // releative to the flight direction + double Nu_Parl = MomentumParallel(aPV,P,&P->momentum()); + double Nu_Perp = MomentumPerpendicular(aPV,P,&P->momentum()); + + + if(isVerbose() || m_motherMass==0.) + { + + test &= tuple->column( prefix+"_Nu_Parl", Nu_Parl ); + test &= tuple->column( prefix+"_Nu_Perp", Nu_Perp ); + } + + if(isVerbose()) + { + //intermediate steps, + //all that do not require the mother mass + + double a=4.*(Nu_Perp*Nu_Perp+P->measuredMass()*P->measuredMass()); + double X=4.*Nu_Parl*(2*Nu_Perp*Nu_Perp+P->measuredMass()*P->measuredMass()); + double Y=4.*Nu_Perp*Nu_Perp*Nu_Parl*Nu_Parl; + test &= tuple->column( prefix+"_Nu_a", a ); + test &= tuple->column( prefix+"_Nu_X", X ); + test &= tuple->column( prefix+"_Nu_Y", Y ); + } + + if(m_motherMass!=0.) + { + double pb=MomentumQuadratic(Nu_Parl,Nu_Perp,P->measuredMass()); + double pd=MomentumSqrt(Nu_Parl,Nu_Perp,P->measuredMass()); + + if(isVerbose()) + { + test &= tuple->column( prefix+"_Nu_pb", pb ); + test &= tuple->column( prefix+"_Nu_pd", pd ); + } + + double P_Hi=Nu_Parl+pb+pd; + double P_Lo=Nu_Parl+pb-pd; + + test &= tuple->column( prefix+"_Nu_Hi", P_Hi ); + test &= tuple->column( prefix+"_Nu_Lo", P_Lo ); + + } + + + } + else + { + return StatusCode::FAILURE; + } + return StatusCode(test); +} +double TupleToolNeutrinoReco::MomentumParallel(const LHCb::VertexBase* pv, + const LHCb::Particle* b, + const ROOT::Math::LorentzVector >* mv) +{ + + // fd means flight distance + if (b->endVertex()==NULL || pv==NULL) return 0.; + + double fd_x = b->endVertex()->position().X()-pv->position().X(); + double fd_y = b->endVertex()->position().Y()-pv->position().Y(); + double fd_z = b->endVertex()->position().Z()-pv->position().Z(); + + double fd = sqrt(fd_x*fd_x + fd_y*fd_y + fd_z*fd_z); + + fd_x=fd_x/fd; + fd_y=fd_y/fd; + fd_z=fd_z/fd; + + // return the dot product of the flight distance unit vector + // with the momentum + return mv->Px()*fd_x + mv->Py()*fd_y + mv->Pz()*fd_z; +} + +double TupleToolNeutrinoReco::MomentumPerpendicular(const LHCb::VertexBase* pv, + const LHCb::Particle* b, + const ROOT::Math::LorentzVector >* mv) +{ + if (b->endVertex()==NULL || pv==NULL) return 0.; + double fd_x = b->endVertex()->position().X()-pv->position().X(); + double fd_y = b->endVertex()->position().Y()-pv->position().Y(); + double fd_z = b->endVertex()->position().Z()-pv->position().Z(); + + double fd = sqrt(fd_x*fd_x + fd_y*fd_y + fd_z*fd_z); + + fd_x=fd_x/fd; + fd_y=fd_y/fd; + fd_z=fd_z/fd; + + double P_Pa = mv->Px()*fd_x + mv->Py()*fd_y + mv->Pz()*fd_z; + + double P_Pa_x = fd_x*P_Pa; + double P_Pa_y = fd_y*P_Pa; + double P_Pa_z = fd_z*P_Pa; + + double P_Pe_x = mv->Px()-P_Pa_x; + double P_Pe_y = mv->Py()-P_Pa_y; + double P_Pe_z = mv->Pz()-P_Pa_z; + + return sqrt(P_Pe_x*P_Pe_x + P_Pe_y*P_Pe_y + P_Pe_z*P_Pe_z); +} + + +double TupleToolNeutrinoReco::MomentumQuadratic(const double Parl, + const double Perp, + const double Mass) +{ + return -0.5*Parl*(1.-(m_motherMass*m_motherMass-Perp*Perp)/(Perp*Perp+Mass*Mass)); +} + +double TupleToolNeutrinoReco::MomentumSqrt(const double Parl, + const double Perp, + const double Mass) +{ + double a=4.*(Perp*Perp+Mass*Mass); + double b=4.*Parl*(2.*Perp*Perp-m_motherMass*m_motherMass+Mass*Mass); + double c= + 4.*Perp*Perp*(Parl*Parl+m_motherMass*m_motherMass) + - + (m_motherMass*m_motherMass-Mass*Mass)*(m_motherMass*m_motherMass-Mass*Mass); + + double d=b*b-4.*a*c; + if (d>0.) return std::sqrt(d)/(2.*a); + else return 0; + +} + diff --git a/first-analysis-steps/DecayTrees/TupleToolNeutrinoReco.h b/first-analysis-steps/DecayTrees/TupleToolNeutrinoReco.h new file mode 100755 index 00000000..b850a0e0 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolNeutrinoReco.h @@ -0,0 +1,123 @@ +#ifndef TUPLETOOLNEUTRINORECO_H +#define TUPLETOOLNEUTRINORECO_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface + +/** @class TupleToolNeutrinoReco TupleToolNeutrinoReco.h + * + * \brief Fill neutrino reconstruction variables + * + * Assuming a particle of zero-mass has gone undetected, we can calculate + * the corrected momentum for the true moteh particle, if we know its mass. + * + * Firstly PT and P|| are the momenta perp and parl to the direction of flight. + * + * 0 = aP(neutrino)^2+bP(neutrino)+c + * a = 4(PT^2+M^2) + * b = 4P||(2PT^2 - mB^2 + M^2) = X - 4P||*mB^2 + * c = 4PT^2(P||^2 + mB^2) -(mB^2 - M^2)^2 = Y + 4PT ^2*mB*2 - (mB^2 - M^2)^2 + * + * P*(neutrino)= [-b +/- sqrt(b^2 - 4ac)]/(2a) + * + * With two ambiguous solutions + * + * PB=P||+P(neutrino) + * + * Option: + * - MotherMass: double: PDG Mass of the mother particle + * + * If no mother particle mass is set the following are filled: + * + * - head_Nu_Parl : momentum of the input particle paralell to the direction of flight + * - head_Nu_Perp : momentum of the input particle perpendicular to the direction of flight + * + * If a non-zero mother mass is set, the two solutions will be calculated + * - head_Nu_Hi : the B-momentum with the positive sqrt solution + * - head_Nu_Lo : the B-momentum with the negative sqrt solution + * + * If the verbose flag is set, the intemediate working will also be stored + * - head_Nu_a : a in the above equation + * - head_Nu_X : X in the above equation, 4P||(2PT^2 + M^2) + * - head_Nu_Y : Y in the above equation, 4PT^2*P||^2 + * + * It can be useful to store these variables, since they are the part of the + * equation which does not depend on the mass of the mother particle, in case an + * overall mass rescaling is required the remaining calculation can be done as follows: + * + * Note that the solution is given by the quadratic formula, + * Note also that -b/2a simplifies to: + * + * -b/2a = - P|| [ 1 - (mB^2 - PT^2)/(PT^2+M^2) ] / 2 + * + * So, with 'head' replaced by something like 'B0', and mB being the PDG mass: + * + * b = B0_Nu_X - 4*B0_Nu_Parl*mB*mB + * c = B0_Nu_Y + 4*B0_Nu_Perp*B0_Nu_Perp*mB*mB - (mB*mB - B0_MM*B0_MM)*(mB*mB - B0_MM*B0_MM) + * + * pb = -B0_Nu_Parl*( 1 - (mB*mB-B0_Nu_Perp*B0_Nu_Perp)/(B0_Nu_Perp*B0_Nu_Perp + B0_MM*B0_MM) )/2 + * pd = sqrt(b*b - 4*B0_Nu_a*c)/(2*B0_Nu_a) + * + * B0_Nu_Lo = B0_Nu_Parl+pb-pd + * B0_Nu_Hi = B0_Nu_Parl+pb+pd + * + * Are the two B-momentum solutions + * + * \sa DecayTreeTuple + * + * @author Rob Lambert + * @date 2010-11-30 + */ +namespace LHCb +{ + class VertexBase; + class Particle; +} +struct IDVAlgorithm; + +class TupleToolNeutrinoReco : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolNeutrinoReco( const std::string& type, + const std::string& name, + const IInterface* parent); + +public: + + StatusCode initialize() override; + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + + double MomentumParallel(const LHCb::VertexBase* , + const LHCb::Particle* , + const ROOT::Math::LorentzVector >* ); + + double MomentumPerpendicular(const LHCb::VertexBase* , + const LHCb::Particle* , + const ROOT::Math::LorentzVector >* ) ; + + double MomentumQuadratic(const double, + const double, + const double); + + double MomentumSqrt(const double, + const double, + const double); + +private: + + IDVAlgorithm* m_dva = nullptr; + double m_motherMass; + +}; + +#endif // TUPLETOOLNEUTRINORECO_H diff --git a/first-analysis-steps/DecayTrees/TupleToolP2VV.cpp b/first-analysis-steps/DecayTrees/TupleToolP2VV.cpp new file mode 100755 index 00000000..2f03e662 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolP2VV.cpp @@ -0,0 +1,110 @@ +// Include files + +#include "Event/Particle.h" +// kernel +#include "Kernel/IP2VVPartAngleCalculator.h" // Interface + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +// local +#include "TupleToolP2VV.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolP2VV +// +// 2007-12-18 : Patrick Koppenburg +// 2008-06-02 : Greig Cowan +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolP2VV ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolP2VV::TupleToolP2VV( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_angleTool() +{ + declareInterface(this); + declareProperty( "Calculator", m_calculator = "Bd2KstarMuMuAngleCalculator" ); + declareProperty( "FillTransversity", m_trans = true ); + declareProperty( "FillHelicity", m_helicity = true ); +} + +//========================================================================= +// initialize +//========================================================================= +StatusCode TupleToolP2VV::initialize( ) +{ + StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + debug() << "Calculator " << m_calculator << endmsg; + + m_angleTool = tool(m_calculator,this); + if( !m_angleTool ){ + Error("Unable to retrieve the IP2VVPartAngleCalculator tool"); + return StatusCode::FAILURE; + } + return sc; +} + +//========================================================================= +// Fill +//========================================================================= +StatusCode TupleToolP2VV::fill( const LHCb::Particle* + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + std::string prefix = fullName(head); + + bool test = true; + if( P ){ + + if ( m_helicity ){ + double thetaL = -1000.; + double thetaK = -1000.; + double phi = -1000.; + + StatusCode sc_hel = m_angleTool->calculateAngles( P, thetaL, thetaK, phi); + + if (msgLevel(MSG::DEBUG)) debug() << "Three helicity angles are theta_L : " + << thetaL + << " K: "<< thetaK + << " phi: " << phi << endmsg ; + + test &= tuple->column( prefix+"_ThetaL", thetaL ); + test &= tuple->column( prefix+"_ThetaK", thetaK ); + test &= tuple->column( prefix+"_Phi", phi ); + } + + if ( m_trans ) + { + double Theta_tr = -1000.; + double Phi_tr = -1000.; + double Theta_V = -1000.; + + StatusCode sc_tr = m_angleTool->calculateTransversityAngles( P, + Theta_tr, + Phi_tr, + Theta_V ); + + if (msgLevel(MSG::DEBUG)) debug() << "Three transversity angles are Theta_tr : " + << Theta_tr + << " Phi_tr: " << Phi_tr + << " Theta_phi_tr: " << Theta_V + << endmsg ; + + test &= tuple->column( prefix+"_ThetaTr", Theta_tr ); + test &= tuple->column( prefix+"_PhiTr", Phi_tr ); + test &= tuple->column( prefix+"_ThetaVtr", Theta_V ); + } + } else { + return StatusCode::FAILURE; + } + return StatusCode(test); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolP2VV.h b/first-analysis-steps/DecayTrees/TupleToolP2VV.h new file mode 100755 index 00000000..161ca7ae --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolP2VV.h @@ -0,0 +1,48 @@ +#ifndef TUPLETOOLP2VV_H +#define TUPLETOOLP2VV_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +/** @class TupleToolP2VV TupleToolP2VV.h + * + * \brief Fills three angles as defined in IP2VVPartAngleCalculator. + * + * - head_ThetaL : angle of the L+ wrt B in dilepton frame + * - head_ThetaK : angle of the K+ wrt B in dilepton frame + * - head_Phi : angle of the K* and LL decay planes in dilepton frame + * + * - head_Theta_tr : angle of the L+ wrt z-axis in dilepton frame + * - head_Phi_tr : azimutal angle of the L+ in dilepton frame + * - head_Theta_phi_tr : polar angle between the x'-axis and the decaying K+ in the dikaon frame + * + * @author Patrick Koppenburg, Greig Cowan + * @date 2007-12-18 + */ +struct IP2VVPartAngleCalculator; + +class TupleToolP2VV : public TupleToolBase, virtual public IParticleTupleTool { +public: + /// Standard constructor + TupleToolP2VV( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + std::string m_calculator; ///< Name of tool that you want to use to calculate the angles + bool m_helicity; ///< Write Helicity angles to tuple + bool m_trans; ///< Write Transversity angles to tuple + + IP2VVPartAngleCalculator* m_angleTool; + +}; +#endif // TUPLETOOLP2VV_H diff --git a/first-analysis-steps/DecayTrees/TupleToolParticleReFit.cpp b/first-analysis-steps/DecayTrees/TupleToolParticleReFit.cpp new file mode 100755 index 00000000..e61dc615 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolParticleReFit.cpp @@ -0,0 +1,153 @@ +// Include files + +// from Gaudi +#include "GaudiKernel/SmartIF.h" + +#include +#include +#include +#include "Kernel/IVertexFit.h" + +// local +#include "TupleToolParticleReFit.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" +#include "Event/Vertex.h" + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolParticleReFit +// +// 2010-11-02 : Yuehong Xie +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolParticleReFit ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolParticleReFit::TupleToolParticleReFit( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); +} + +//============================================================================= + +StatusCode TupleToolParticleReFit::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_dva = Gaudi::Utils::getIDVAlgorithm ( contextSvc(), this ) ; + if (0==m_dva) return Error("Couldn't get parent DVAlgorithm", + StatusCode::FAILURE); + + m_timefitter = m_dva->lifetimeFitter(); + if( !m_timefitter ) + { + return Error("Unable to retrieve the ILifetimeFitter tool"); + } + + m_vtxfitter = m_dva->vertexFitter(); + if( !m_vtxfitter ) + { + return Error("Unable to retrieve the IVertexFit tool"); + } + + return sc; +} + +//============================================================================= + +StatusCode TupleToolParticleReFit::fill( const Particle* mother + , const Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + + std::string prefix=fullName(head); + if (m_extraName=="") prefix = prefix + "_OVrefit"; + + Assert( m_timefitter && m_vtxfitter && P, + "Should not happen, you are inside TupleToolParticleReFit.cpp" ); + + + // no proper-time for basic parts. + if( P->isBasicParticle() ) return StatusCode::SUCCESS; + + //only head of a decay chain + if( P != mother ) return StatusCode::SUCCESS; + + + const VertexBase* originVtx = m_dva->bestVertex( mother ); + + if( originVtx ){} // I'm happy + else { + return Error("Can't get the origin vertex", StatusCode::FAILURE); + } + + int refit_status = 0; + int refit_ndof = -100; + double refit_chi2 = -100; + + double refit_mass =-100; + double refit_massErr =-100; + + double refit_p =-100; + double refit_pt =-100; + + double time = -100; + double timeErr = -100; + double timeChi2 = -100; + + LHCb::Particle O(*P); + StatusCode sc = m_vtxfitter->reFit(O); + + if(sc.isSuccess()) { + refit_status =1; + refit_ndof = O.endVertex()->nDoF(); + refit_chi2 = O.endVertex()->chi2(); + refit_p = O.p(); + refit_pt = O.pt(); + refit_mass = O.measuredMass(); + refit_massErr = O.measuredMassErr(); + + + sc = m_timefitter->fit ( *originVtx, O , time, timeErr, timeChi2 ); + if( !sc ){ + Warning("The propertime fit failed in TupleToolParticleReFit").ignore(); + time = -100; + timeErr = -100; + timeChi2 = -100; + } + + } + + bool test = true; + test &= tuple->column( prefix+"_status" , refit_status ); + test &= tuple->column( prefix+"_ENDVERTEX_NDOF", refit_ndof ); + test &= tuple->column( prefix+"_ENDVERTEX_CHI2", refit_chi2 ); + test &= tuple->column( prefix+"_MM", refit_mass ); + test &= tuple->column( prefix+"_MMERR", refit_massErr ); + test &= tuple->column( prefix+"_P", refit_p ); + test &= tuple->column( prefix+"_PT", refit_pt ); + + test &= tuple->column( prefix+"_P", O.momentum() ); + + test &= tuple->column( prefix+"_TAU" , time ); // nanoseconds + test &= tuple->column( prefix+"_TAUERR" , timeErr ); + test &= tuple->column( prefix+"_TAUCHI2" , timeChi2 ); + + return StatusCode(test); + +} + diff --git a/first-analysis-steps/DecayTrees/TupleToolParticleReFit.h b/first-analysis-steps/DecayTrees/TupleToolParticleReFit.h new file mode 100755 index 00000000..8ea60a26 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolParticleReFit.h @@ -0,0 +1,81 @@ +#ifndef TUPLETOOLPARTICLEREFIT_H +#define TUPLETOOLPARTICLEREFIT_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface + +struct IDVAlgorithm; +struct ILifetimeFitter; +struct IVertexFit; + +namespace LHCb +{ + class Particle; + class Vertex; +} + +/** @class TupleToolParticleReFit TupleToolParticleReFit.h jborel/TupleToolParticleReFit.h + * \brief Use a standard vertex fitter to refit head of a decay chain and fill DecayTreeTuple + * + * Columns filled: + * - head_OVrefit_status + * - head_OVrefit_ENDVERTEX_NDOF + * - head_OVrefit_ENDVERTEX_CHI2 + * - head_OVrefit_MM + * - head_OVrefit_MMERR + * - head_OVrefit_P + * - head_OVrefit_PT + * - head_OVrefit_P[E|X|Y|Z] + * - head_OVrefit_TAU + * - head_OVrefit_TAUERR + * - head_OVrefit_TAUCHI2 + * + * The middle name "OV" standard for "OfflineVertexFitter" and can be changed + * by setting the "ExtraName" property. + * + * The main purpose of the tool is to get the MM and TAU varibales after + * refitting the B particle with or without a certain daughter mass cosntraint. + * + * Example 1: refit in order to apply daughter mass cosntraint + * tuple.addTool(TupleToolParticleReFit()) + * tuple.TupleToolParticleReFit.addTool(OfflineVertexFitter()) + * tuple.TupleToolParticleReFit.OfflineVertexFitter.useResonanceVertex = True + * tuple.TupleToolParticleReFit.OfflineVertexFitter.applyDauMassConstraint = True + * + * Example 2: refit in order to get rid of already applied daughter mass cosntraint + * tuple.TupleToolParticleReFit.OfflineVertexFitter.useResonanceVertex = False + * + * \sa DecayTreeTuple + * + * @author Yuehong Xie + * @date 2010-11-2 + */ +class TupleToolParticleReFit : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolParticleReFit( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + + StatusCode fill( const LHCb::Particle*, + const LHCb::Particle*, + const std::string&, + Tuples::Tuple& ) override; + +private: + + IDVAlgorithm* m_dva = nullptr; + const ILifetimeFitter* m_timefitter = nullptr; + const IVertexFit* m_vtxfitter = nullptr; + +}; + +#endif // TUPLETOOLPARTICLEREFIT_H diff --git a/first-analysis-steps/DecayTrees/TupleToolParticleStats.cpp b/first-analysis-steps/DecayTrees/TupleToolParticleStats.cpp new file mode 100644 index 00000000..72c67176 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolParticleStats.cpp @@ -0,0 +1,59 @@ +// Include files + +// from Gaudi +#include "TupleToolParticleStats.h" +#include "Event/Track.h" +#include "Event/VeloCluster.h" +#include "Event/ODIN.h" + +// local +#include "TupleToolParticleStats.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolParticleStats +// +// 2009-02-11 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolParticleStats::TupleToolParticleStats( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name, parent ), + m_locations() +{ + declareInterface(this); + declareProperty("InputLocations",m_locations,"Locations to look at"); + m_locations.push_back("StdLooseAllPhotons"); +} + +//============================================================================= +// Destructor +//============================================================================= +TupleToolParticleStats::~TupleToolParticleStats() {} +//============================================================================= + +//============================================================================= +StatusCode TupleToolParticleStats::fill( Tuples::Tuple& tup ) +{ + const std::string prefix=fullName(); + bool test = true; + for ( std::vector::const_iterator l = m_locations.begin() ; + l != m_locations.end() ; ++l) { + if(!(exist("/Event/Phys/"+*l+"/Particles") ) ){ + error() << " your configuration is problematic, tthe location you requested: " << endmsg; + error() << " >>> " << ("/Event/Phys/"+*l+"/Particles") << " <<< doesnt seem to have been filled." << endmsg; + continue; + } + test &= tup->column(prefix+"NumberOf"+*l,number("/Event/Phys/"+*l+"/Particles")); + } + return StatusCode(test) ; +} + + + + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolParticleStats ) diff --git a/first-analysis-steps/DecayTrees/TupleToolParticleStats.h b/first-analysis-steps/DecayTrees/TupleToolParticleStats.h new file mode 100644 index 00000000..c6b63a50 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolParticleStats.h @@ -0,0 +1,39 @@ +#ifndef TUPLETOOLRECOSTATS_H +#define TUPLETOOLRECOSTATS_H 1 + +// Include files +// from Gaudi +#include "Kernel/IEventTupleTool.h" // Interface +#include "DecayTreeTupleBase/TupleToolBase.h" + +#include "Event/Track.h" +#include "Event/RecSummary.h" + +/** @class TupleToolParticleStats TupleToolParticleStats.h + * + * Fills Reco stats, from RecSummary + * + * @author Patrick Koppenburg, Fatima Soomro, Jibo He + * @date 2009-02-11 + */ +class TupleToolParticleStats : public TupleToolBase, + virtual public IEventTupleTool +{ + +public: + + /// Standard constructor + TupleToolParticleStats( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolParticleStats( ); ///< Destructor + StatusCode fill( Tuples::Tuple& ) override;///< Fill tuple +// int unusedVelo(); +private: + std::vector m_locations ; ///< Hlt locations to look at + +}; + +#endif // TUPLETOOLRECOSTATS_H + diff --git a/first-analysis-steps/DecayTrees/TupleToolPhotonInfo.cpp b/first-analysis-steps/DecayTrees/TupleToolPhotonInfo.cpp new file mode 100755 index 00000000..1b299a44 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolPhotonInfo.cpp @@ -0,0 +1,72 @@ +// $Id: TupleToolPhotonInfo.cpp,v 1.1 2010-05-21 17:03:11 odescham Exp $ +// Include files + +// local +#include "TupleToolPhotonInfo.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "Event/Particle.h" +#include "GaudiKernel/IRegistry.h" // + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolPhotonInfo +// +// 2008-10-31 :(Happy Halloween) +// Yasmine Amhis +//----------------------------------------------------------------------------- + +using namespace Gaudi; +using namespace LHCb; + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolPhotonInfo ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolPhotonInfo::TupleToolPhotonInfo( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ), + m_PhotonID(22) +{ + declareInterface(this); +} + +//============================================================================= + +StatusCode TupleToolPhotonInfo::fill(const Particle* , const Particle* P + ,const std::string& head + ,Tuples::Tuple& tuple ){ + const std::string prefix=fullName(head); + + bool filltuple = true; + if( P ){ + if (P->particleID().pid() == m_PhotonID && isPureNeutralCalo(P)) { + + const LHCb::ProtoParticle* proto = P->proto(); + if(NULL == proto)return StatusCode::SUCCESS; + + double match = proto->info(LHCb::ProtoParticle::CaloTrMatch, 9999.); + double pid = proto->info(LHCb::ProtoParticle::PhotonID, 0.); + double cnv = ( proto->info(LHCb::ProtoParticle::CaloDepositID, 0.)<0) ? 1 : 0; + double prs = proto->info(LHCb::ProtoParticle::CaloNeutralPrs, 0.); + double shape = proto->info(LHCb::ProtoParticle::ShowerShape, 0.); + + filltuple &= tuple->column( prefix+"_Converted", cnv ); + filltuple &= tuple->column( prefix+"_Prs", prs ); + filltuple &= tuple->column( prefix+"_Matching", match ); + filltuple &= tuple->column( prefix+"_PID", pid ); + filltuple &= tuple->column( prefix+"_CL" , P->confLevel() ); + filltuple &= tuple->column( prefix+"_ShowerShape", shape ); + + + }//this is a photon + }//get the particle + + return StatusCode(filltuple); + +} + + + diff --git a/first-analysis-steps/DecayTrees/TupleToolPhotonInfo.h b/first-analysis-steps/DecayTrees/TupleToolPhotonInfo.h new file mode 100755 index 00000000..d9493831 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolPhotonInfo.h @@ -0,0 +1,29 @@ +// $Id: TupleToolPhotonInfo.h,v 1.1 2010-05-21 17:03:11 odescham Exp $ +#ifndef _TUPLETOOLEPHOTONINFO_H +#define _TUPLETOOLEPHOTONINFO_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +// Interface +#include "Kernel/IParticleTupleTool.h" + +#include "CaloUtils/CaloParticle.h" + +//============================================================================ +class TupleToolPhotonInfo : public TupleToolBase, virtual public IParticleTupleTool { + //========================================================================== +public: + // Standard constructor + TupleToolPhotonInfo( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolPhotonInfo( ){}; ///< Destructor + + StatusCode fill(const LHCb::Particle*, const LHCb::Particle* + , const std::string& ,Tuples::Tuple& ) override; +private: + int m_PhotonID; +}; +#endif // _TUPLETOOLEPHOTONINFO_H diff --git a/first-analysis-steps/DecayTrees/TupleToolPi0Info.cpp b/first-analysis-steps/DecayTrees/TupleToolPi0Info.cpp new file mode 100755 index 00000000..25893cfc --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolPi0Info.cpp @@ -0,0 +1,276 @@ +// $Id: TupleToolPi0Info.cpp,v 1.4 2010-01-26 15:39:26 rlambert Exp $ +// Include files + +// local +#include "TupleToolPi0Info.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "Event/Particle.h" +#include "CaloUtils/CaloMomentum.h" +#include "GaudiKernel/IRegistry.h" // + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolPi0Info +// +// 2008-10-31 :(Happy Halloween) +// Yasmine Amhis +//----------------------------------------------------------------------------- + +using namespace Gaudi; +using namespace LHCb; + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolPi0Info ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolPi0Info::TupleToolPi0Info( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); + declareProperty("RequireMCTruth",m_RequireMCTruth = false); +} + +//============================================================================= +StatusCode TupleToolPi0Info::fill(const Particle* , const Particle* P + ,const std::string& head + ,Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(head); + + bool filltuple = true; + if ( P ) + { + if (P->particleID().pid() == m_Pi0ID && isPureNeutralCalo(P)) + { + if ( msgLevel(MSG::DEBUG) ) + { + debug() << " Make the special case for the pi0 " << P->particleID().pid() << endmsg; + debug() << " The pi0s has : " << P->daughters().size() << " daughters "<< endmsg; + } + const int Type = ( !P->daughters().empty() ? 2 : 1 ); + // 2 = resolved, 1 = merged. + + filltuple &= tuple->column( prefix+"_Type", Type ); + filltuple &= tuple->column( prefix+"_CL" , P->confLevel() ); + + // daughter info in case of merged pi0 + if ( Type == 1 ) + { + const auto hypo = P->proto()->calo().front(); + if ( LHCb::CaloHypo::Pi0Merged != hypo->hypothesis() ) + { + // == extract SplitPhotons hypos + const auto& hypos = hypo->hypos(); + if ( hypos.size() > 1 ) + { + const auto g1 = *(hypos.begin() ); + const auto g2 = *(hypos.begin()+1 ); + filltuple &= tuple->column( prefix+"_gamma0_PT" , LHCb::CaloMomentum(g1).pt() ); + filltuple &= tuple->column( prefix+"_gamma1_PT" , LHCb::CaloMomentum(g2).pt() ); + } + } + } + + if ( m_RequireMCTruth ) + { + Warning("MC association with TupleToolPi0Info is deprecated - please use the standard TupleToolMCTruth" + , StatusCode::SUCCESS).ignore(); + if ( msgLevel(MSG::DEBUG) ) + debug() << "Get the association done for a pi0 " << endmsg; + const MCParticle* MCPi0 = nullptr; + const MCParticle* MCPi0Mother = nullptr; + const MCParticle* MCPi0GrandMother = nullptr; + const MCParticle* MCPi0GrandGrandMother = nullptr; + + int MCPi0_id =0; + int MCPi0Mother_id =0; + int MCPi0GrandMother_id =0; + int MCPi0GrandGrandMother_id =0; + int MCPi0_key =0; + int MCPi0Mother_key =0; + int MCPi0GrandMother_key =0; + int MCPi0GrandGrandMother_key =0; + double weight = 1; + + MCPi0 = getMCPi0(P,weight); + if ( MCPi0 ) + { + MCPi0_id = MCPi0->particleID().pid(); + MCPi0_key = MCPi0->key(); + MCPi0Mother = MCPi0->mother() ; + }//particleMC info + if ( MCPi0Mother ) + { + MCPi0Mother_id = MCPi0Mother->particleID().pid(); + MCPi0Mother_key = MCPi0Mother->key(); + MCPi0GrandMother = MCPi0Mother->mother() ; + }//particle mother MC info + + if ( MCPi0GrandMother ) + { + MCPi0GrandMother_id = MCPi0GrandMother->particleID().pid(); + MCPi0GrandMother_key = MCPi0GrandMother->key(); + MCPi0GrandGrandMother = MCPi0GrandMother->mother() ; + } + if ( MCPi0GrandGrandMother ) + { + MCPi0GrandGrandMother_key = MCPi0GrandGrandMother->key(); + MCPi0GrandGrandMother_id = MCPi0GrandGrandMother->particleID().pid(); + } + + filltuple &= tuple->column( prefix+"_MCPi0_id", MCPi0_id ); + filltuple &= tuple->column( prefix+"_MCPi0_key", MCPi0_key ); + + filltuple &= tuple->column( prefix+"_MCPi0Mother_id", MCPi0Mother_id ); + filltuple &= tuple->column( prefix+"_MCPi0Mother_key", MCPi0Mother_key ); + + filltuple &= tuple->column( prefix+"_MCPi0GrandMother_id", MCPi0GrandMother_id ); + filltuple &= tuple->column( prefix+"_MCPi0GrandMother_key", MCPi0GrandMother_key ); + + filltuple &= tuple->column( prefix+"_MCPi0GrandGrandMother_id", MCPi0GrandGrandMother_id ); + filltuple &= tuple->column( prefix+"_MCPi0GrandGrandMother_key", MCPi0GrandGrandMother_key ); + if ( msgLevel(MSG::DEBUG) ) + debug() << "This is the MC part associated to your pi0 --> " + << MCPi0_id << " and its mother -->" + << MCPi0Mother_id << endmsg; + }//require MC truth + }//this is a pi0 + }//get the particle + + return StatusCode(filltuple); +} + +//================================================================================ +//Here you get the protoparticle corresponding to your pi0 candidate +//================================================================================ +TupleToolPi0Info::mcRange TupleToolPi0Info::getRange(const LHCb::Particle* part) +{ + const auto* proto = ( part ? part->proto() : nullptr ); + return ( proto ? getRange(proto) : mcRange() ); +} + +//================================================================================ +//Here you get the relation table between the protoparticles and the MC particles +//================================================================================ +TupleToolPi0Info::mcRange TupleToolPi0Info::getRange(const LHCb::ProtoParticle* proto) +{ + if ( !proto ) return mcRange(); + std::string locationhard; + if( 0 == proto->charge() ) + { + if( context() == "HLT") + { + debug () <<" You are running in the Hlt context " << context() << endmsg; + locationhard = "Relations/Hlt/ProtoP/Neutrals"; + } + else + { + debug () <<"You are running in the Offline context " << context() << endmsg; + locationhard = "Relations/Rec/ProtoP/Neutrals"; + } + } //check neutral + const mcTable* table = get ( locationhard ) ; + // create protoP<->MC output relation table + if ( msgLevel(MSG::DEBUG) ) + debug() <<"ProtoP<->MC output relation table " << table << endmsg; + return ( table ? table->relations( proto ) : mcRange() ); +} +//======================================================================================= + +const LHCb::MCParticle* TupleToolPi0Info::getMCPi0(const LHCb::Particle* part, double& weight ) +{ + // Return the highest-weighted matching MCPart WITH THE SAME particleID than part->ID + // if not the highest-weighted among ALL matching MCPart then weight = -weight + // If not found return the highest-weighted matching MCPART (irrespective of part->ID) + + weight = 0; + if ( !part ) return nullptr; + + double weightMax =- 99999; + double weightPart = -99999; + LHCb::MCParticle* mcBest = nullptr; + LHCb::MCParticle* mcPart = nullptr; + + if ( !part->daughters().empty() ) + { + //============================== + // special case of ResolvedPi0s + //============================== + const auto & daughters = part->daughters(); + auto ig1 = daughters.begin(); + auto ig2 = ig1+1; + auto range1 = getRange( *ig1 ); + auto range2 = getRange( *ig2 ); + if ( range1.empty() || range2.empty() ) return nullptr; + for ( const auto r1 : range1 ) + { + for ( const auto r2 : range2 ) + { + auto w = r1.weight(); + if ( r2.weight() > r1.weight() ) w = r2.weight(); + if ( r1.to() == r2.to() ) w = r1.weight() + r2.weight(); + if ( w > weightMax ) + { + weightMax = w; + mcBest = r1.to(); + if ( r2.weight() > r1.weight() ) mcBest = r2.to(); + } + if ( m_Pi0ID == abs(r1.to()->particleID().pid()) && r1.to() == r2.to() ) + { + if ( w > weightPart ) + { + mcPart = r1.to(); + weightPart = w; + } + } + } + } + } + else + { + //============== + // Pi0 merged + //============== + auto range = getRange(part); + if ( range.empty() ) return nullptr; + for ( const auto r : range ) + { + auto w = r.weight(); + if ( w > weightMax ) + { + weightMax = w; + mcBest = r.to(); + } + if ( m_Pi0ID == abs(r.to()->particleID().pid()) ) + { + if ( w > weightPart ) + { + mcPart = r.to(); + weightPart = w; + } + } + } + } + // + if ( mcPart ) + { + weight = weightPart; + if ( weightPart < weightMax ) weight = -weightPart; + return mcPart; + } + else if ( mcBest ) + { + weight = weightMax; + return mcBest; + } + else + { + weight = 0; + return nullptr; + } +} +//================================================================================================== diff --git a/first-analysis-steps/DecayTrees/TupleToolPi0Info.h b/first-analysis-steps/DecayTrees/TupleToolPi0Info.h new file mode 100755 index 00000000..58cf09bb --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolPi0Info.h @@ -0,0 +1,68 @@ +// $Id: TupleToolPi0Info.h,v 1.3 2010-01-26 15:39:26 rlambert Exp $ +#ifndef _TUPLETOOLEPI0INFO_H +#define _TUPLETOOLEPI0INFO_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" + // Interface +#include "Kernel/IParticleTupleTool.h" + +#include "Kernel/Particle2MCLinker.h" +#include "Kernel/IDaVinciAssociatorsWrapper.h" + + +#include "Kernel/PP2MCLocation.h" + +#include "Relations/RelationWeighted1D.h" + +#include "CaloUtils/Calo2MC.h" +#include "CaloUtils/CaloParticle.h" + +/** @class TupleToolPi0Info TupleToolPi0Info.h yamhis/TupleToolPi0Info.h + * + *"pi0s are special creatures they should to be treated in a special way....." + * + * + *----- This Tool returns the MC particle associated to a Pi0( id and key) + * and its whole family + *----- The association is done via the relation table between the ProtoParticle and the MC + *----- The pi0 type (resolved or merged) is taken into account + *----- This tool runs in the HltContext do not forget to switch it on + * using HltContext = True from your DaVinci Python Script + *This is Obviously heavily inspired from Olivier Deschamps codes for B2PiPiPi0 + * + * + * \sa DecayTreeTuple + * @author Amhis Yasmine + * @date 2008-10-31 + */ + + +//============================================================================ +class TupleToolPi0Info : public TupleToolBase, virtual public IParticleTupleTool { +//========================================================================== +public: + // Standard constructor + TupleToolPi0Info( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolPi0Info( ) = default; ///< Destructor + + StatusCode fill(const LHCb::Particle*, const LHCb::Particle* + , const std::string& ,Tuples::Tuple& ) override; +private: + const LHCb::MCParticle* getMCPi0(const LHCb::Particle* part, double& weight); + const LHCb::MCParticle* getMCGamma(const LHCb::Particle* part, double& weight); +private: + typedef IRelationWeighted mcTable; + typedef mcTable::Range mcRange; + mcRange getRange(const LHCb::Particle* part); + mcRange getRange(const LHCb::ProtoParticle* proto); +private: + bool m_RequireMCTruth; + int m_Pi0ID{111}; + std::vector m_assocInputs; +}; +#endif // _TUPLETOOLEPI0INFO_H diff --git a/first-analysis-steps/DecayTrees/TupleToolPid.cpp b/first-analysis-steps/DecayTrees/TupleToolPid.cpp new file mode 100755 index 00000000..95b54eed --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolPid.cpp @@ -0,0 +1,189 @@ +// $Id: TupleToolPid.cpp,v 1.6 2010-03-04 14:02:03 xieyu Exp $ +// Include files + +// local +#include "TupleToolPid.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" +//----------------------------------------------------------------------------- +// Implementation file for class : EventInfoTupleTool +// +// 2007-11-07 : Jeremie Borel +//----------------------------------------------------------------------------- + +using namespace LHCb; + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolPid::TupleToolPid( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); +} + +//============================================================================= + +StatusCode TupleToolPid::fill( const Particle* + , const Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + if ( P ) + { + const std::string prefix = fullName(head); + + bool test = true; + test &= tuple->column( prefix+"_ID", P->particleID().pid() ); + + if ( !P->isBasicParticle() ) return StatusCode(test); // no PID info for composite! + if ( isPureNeutralCalo(P) ) return StatusCode(test); // no PID information for calo neutrals + + const ProtoParticle* proto = P->proto(); + if ( proto ) + { + + // Combined DLLs + test &= tuple->column( prefix+"_PIDe" + ,proto->info(LHCb::ProtoParticle::CombDLLe,-1000)); + test &= tuple->column( prefix+"_PIDmu" + ,proto->info(LHCb::ProtoParticle::CombDLLmu,-1000)); + test &= tuple->column( prefix+"_PIDK" + ,proto->info(LHCb::ProtoParticle::CombDLLk,-1000)); + test &= tuple->column( prefix+"_PIDp" + ,proto->info(LHCb::ProtoParticle::CombDLLp,-1000)); + + // The MVA probabilities + // There is one for each hypothesis + test &= tuple->column( prefix+"_ProbNNe" + ,proto->info(LHCb::ProtoParticle::ProbNNe,-1000)); + test &= tuple->column( prefix+"_ProbNNk" + ,proto->info(LHCb::ProtoParticle::ProbNNk,-1000)); + test &= tuple->column( prefix+"_ProbNNp" + ,proto->info(LHCb::ProtoParticle::ProbNNp,-1000)); + test &= tuple->column( prefix+"_ProbNNpi" + ,proto->info(LHCb::ProtoParticle::ProbNNpi,-1000)); + test &= tuple->column( prefix+"_ProbNNmu" + ,proto->info(LHCb::ProtoParticle::ProbNNmu,-1000)); + test &= tuple->column( prefix+"_ProbNNghost" + ,proto->info(LHCb::ProtoParticle::ProbNNghost,-1000)); + + // Muon + const MuonPID * muonPID = proto->muonPID(); + test &= tuple->column( prefix+"_hasMuon", muonPID != NULL ); + test &= tuple->column( prefix+"_isMuon", muonPID ? muonPID->IsMuon() : false ); + + // RICH + const RichPID * richPID = proto->richPID(); + test &= tuple->column( prefix+"_hasRich", richPID != NULL ); + // Moved some RICH information variables to default since they are useful to determine + // how the PID information has been obtained. + test &= tuple->column( prefix+"_UsedRichAerogel", + richPID ? richPID->usedAerogel() : false ); + test &= tuple->column( prefix+"_UsedRich1Gas", + richPID ? richPID->usedRich1Gas() : false ); + test &= tuple->column( prefix+"_UsedRich2Gas", + richPID ? richPID->usedRich2Gas() : false ); + test &= tuple->column( prefix+"_RichAboveElThres", + richPID ? richPID->electronHypoAboveThres() : false ); + test &= tuple->column( prefix+"_RichAboveMuThres", + richPID ? richPID->muonHypoAboveThres() : false ); + test &= tuple->column( prefix+"_RichAbovePiThres", + richPID ? richPID->pionHypoAboveThres() : false ); + test &= tuple->column( prefix+"_RichAboveKaThres", + richPID ? richPID->kaonHypoAboveThres() : false ); + test &= tuple->column( prefix+"_RichAbovePrThres", + richPID ? richPID->protonHypoAboveThres() : false ); + + // CALO + test &= tuple->column( prefix+"_hasCalo", !proto->calo().empty() ); + + // The kitchen sink ... + if ( UNLIKELY(isVerbose()) ) + { + + // RICH variables + test &= tuple->column( prefix+"_RichDLLe", + proto->info(LHCb::ProtoParticle::RichDLLe,-1000) ); + test &= tuple->column( prefix+"_RichDLLmu", + proto->info(LHCb::ProtoParticle::RichDLLmu,-1000) ); + test &= tuple->column( prefix+"_RichDLLpi", + proto->info(LHCb::ProtoParticle::RichDLLpi,-1000) ); + test &= tuple->column( prefix+"_RichDLLk", + proto->info(LHCb::ProtoParticle::RichDLLk,-1000) ); + test &= tuple->column( prefix+"_RichDLLp", + proto->info(LHCb::ProtoParticle::RichDLLp,-1000) ); + test &= tuple->column( prefix+"_RichDLLbt", + proto->info(LHCb::ProtoParticle::RichDLLbt,-1000) ); + + // Muon variables + test &= tuple->column( prefix+"_InAccMuon", + proto->info(LHCb::ProtoParticle::InAccMuon,false)>0.5 ); + test &= tuple->column( prefix+"_isMuonLoose", muonPID ? muonPID->IsMuonLoose() : false ); + test &= tuple->column( prefix+"_isMuonTight", muonPID ? muonPID->IsMuonTight() : false ); + test &= tuple->column( prefix+"_MuonMuLL", muonPID ? muonPID->MuonLLMu() : -1000 ); + test &= tuple->column( prefix+"_MuonBkgLL", muonPID ? muonPID->MuonLLBg() : -1000 ); + test &= tuple->column( prefix+"_MuonNShared", muonPID ? muonPID->nShared() : -1 ); + test &= tuple->column( prefix+"_MuonChi2Corr", muonPID ? muonPID->chi2Corr() : -1. ); + + // ECAL variables + test &= tuple->column( prefix+"_InAccEcal", + proto->info(LHCb::ProtoParticle::InAccEcal,false)>0.5 ); + test &= tuple->column( prefix+"_CaloEcalE", + proto->info(LHCb::ProtoParticle::CaloEcalE,-10000.)); + test &= tuple->column( prefix+"_EcalPIDe", + proto->info(LHCb::ProtoParticle::EcalPIDe,-10000.)); + test &= tuple->column( prefix+"_EcalPIDmu", + proto->info(LHCb::ProtoParticle::EcalPIDmu,-10000.)); + + // HCAL + test &= tuple->column( prefix+"_InAccHcal", + proto->info(LHCb::ProtoParticle::InAccHcal,false)>0.5 ); + test &= tuple->column( prefix+"_CaloHcalE", + proto->info(LHCb::ProtoParticle::CaloHcalE,-10000.)); + test &= tuple->column( prefix+"_HcalPIDe", + proto->info(LHCb::ProtoParticle::HcalPIDe,-10000.)); + test &= tuple->column( prefix+"_HcalPIDmu", + proto->info(LHCb::ProtoParticle::HcalPIDmu,-10000.)); + + // PRS + test &= tuple->column( prefix+"_InAccPrs", + proto->info(LHCb::ProtoParticle::InAccPrs,false)>0.5 ); + test &= tuple->column( prefix+"_PrsPIDe", + proto->info(LHCb::ProtoParticle::PrsPIDe,-10000.)); + test &= tuple->column( prefix+"_CaloPrsE", + proto->info(LHCb::ProtoParticle::CaloPrsE,-999) ); + + + // SPD + test &= tuple->column( prefix+"_InAccSpd", + proto->info(LHCb::ProtoParticle::InAccSpd,false)>0.5 ); + test &= tuple->column( prefix+"_CaloSpdE", + proto->info(LHCb::ProtoParticle::CaloSpdE,-999) ); + + // BREM + test &= tuple->column( prefix+"_InAccBrem", + proto->info(LHCb::ProtoParticle::InAccBrem,false)>0.5 ); + test &= tuple->column( prefix+"_BremPIDe", + proto->info(LHCb::ProtoParticle::BremPIDe,-10000.)); + + // VELO + test &= tuple->column( prefix+"_VeloCharge", + proto->info(LHCb::ProtoParticle::VeloCharge,-10000.)); + + } + + return StatusCode(test); + } + } + + return StatusCode::FAILURE; +} + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolPid ) diff --git a/first-analysis-steps/DecayTrees/TupleToolPid.h b/first-analysis-steps/DecayTrees/TupleToolPid.h new file mode 100755 index 00000000..574236d0 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolPid.h @@ -0,0 +1,56 @@ +// $Id: TupleToolPid.h,v 1.4 2010-03-04 14:02:03 xieyu Exp $ +#ifndef JBOREL_TUPLETOOLPID_H +#define JBOREL_TUPLETOOLPID_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface + +/** @class TupleToolPid TupleToolPid.h + * + * @brief DLL and PID information to be stored in a Tuple + * + * \sa DecayTreeTuple + * + * For all particles: + * - head_ID : particleID().pid(); + * + * For the long lived particles (isBasicParticle()). + * - head_PIDe : LHCb::ProtoParticle::CombDLLe + * - head_PIDmu : LHCb::ProtoParticle::CombDLLmu + * - head_PIDK : LHCb::ProtoParticle::CombDLLk + * - head_PIDp : LHCb::ProtoParticle::CombDLLp + * + * @author Jeremie Borel + * @date 2007-11-07 + * + * Add more info: + * -hasRich: proto->richPID()!=0 + * -hasCalo: proto->calo().size()>0 + * -hasMuon: proto->muonPID()!=0 + * -isMuon: proto->muonPID->IsMuon() + * + * @date 2010-03-04 + */ +class TupleToolPid : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolPid( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolPid(){}; ///< Destructor + + StatusCode fill( const LHCb::Particle*, + const LHCb::Particle*, + const std::string&, + Tuples::Tuple& ) override; + +}; + +#endif // JBOREL_TUPLETOOLPID_H diff --git a/first-analysis-steps/DecayTrees/TupleToolPrimaries.cpp b/first-analysis-steps/DecayTrees/TupleToolPrimaries.cpp new file mode 100755 index 00000000..09500881 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolPrimaries.cpp @@ -0,0 +1,130 @@ +#include "TupleToolPrimaries.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "Event/VertexBase.h" +#include "Event/Track.h" + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolPrimaries +// +// 2007-11-07 : Jeremie Borel +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolPrimaries ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolPrimaries::TupleToolPrimaries( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name, parent ) +{ + declareInterface(this); + declareProperty("InputLocation", + m_pvLocation = LHCb::RecVertexLocation::Primary, + "PV location to be used."); +} + +//============================================================================= +//============================================================================= + +StatusCode TupleToolPrimaries::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + debug() << "Will be looking for PVs at " << m_pvLocation << endmsg ; + + return sc; +} + +//============================================================================= +//============================================================================= + +StatusCode TupleToolPrimaries::fill( Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(); + + if (msgLevel(MSG::VERBOSE)) + verbose() << "Storing PVs with prefix ``" << prefix << "''" << endmsg ; + + std::vector pvx, pvy, pvz; + std::vector epvx, epvy, epvz; + std::vector pvchi2, pvndof, pvntracks, pvsumpt; + + const RecVertex::Container* PV = getIfExists(m_pvLocation); + if ( PV ) + { + + if( PV->size() > m_maxPV ) + { + Warning("Too many primaries, no PVs will be stored.").ignore(); + } + else + { + for(RecVertex::Container::const_iterator i = PV->begin() ; PV->end()!=i ; ++i ) + { + if (msgLevel(MSG::VERBOSE)) verbose() << "PV: " << (*i)->position() << endmsg ; + pvx.push_back( (*i)->position().X() ); + pvy.push_back( (*i)->position().Y() ); + pvz.push_back( (*i)->position().Z() ); + if (msgLevel(MSG::VERBOSE)) verbose() << "PV matrix: " << (*i)->covMatrix()(0,0) << " " + << (*i)->covMatrix()(1,1) << " " + << (*i)->covMatrix()(2,2) << endmsg ; + epvx.push_back( std::sqrt((*i)->covMatrix()(0,0)) ); + epvy.push_back( std::sqrt((*i)->covMatrix()(1,1)) ); + epvz.push_back( std::sqrt((*i)->covMatrix()(2,2)) ); + pvchi2.push_back((*i)->chi2()); + pvndof.push_back((double)(*i)->nDoF()); + pvntracks.push_back((double)(*i)->tracks().size()); + if (isVerbose()) pvsumpt.push_back(sumPT(*i)) ; + if (msgLevel(MSG::VERBOSE)) verbose() << "Tracks: " << (*i)->tracks().size() << endmsg ; + } + } + if (msgLevel(MSG::DEBUG)) + debug() << "There are " << PV->size() << " PVs at " << pvz << endmsg ; + } + else if (msgLevel(MSG::DEBUG)) + { + debug() << "PV container is empty" << endmsg ; + } + + bool test=true; + test &= tuple->farray( prefix+"PVX", pvx, prefix+"nPV", m_maxPV ); + test &= tuple->farray( prefix+"PVY", pvy, prefix+"nPV", m_maxPV ); + test &= tuple->farray( prefix+"PVZ", pvz, prefix+"nPV", m_maxPV ); + test &= tuple->farray( prefix+"PVXERR", epvx, prefix+"nPV", m_maxPV ); + test &= tuple->farray( prefix+"PVYERR", epvy, prefix+"nPV", m_maxPV ); + test &= tuple->farray( prefix+"PVZERR", epvz, prefix+"nPV", m_maxPV ); + + test &= tuple->farray( prefix+"PVCHI2", pvchi2, prefix+"nPV", m_maxPV ); + test &= tuple->farray( prefix+"PVNDOF", pvndof, prefix+"nPV", m_maxPV ); + test &= tuple->farray( prefix+"PVNTRACKS", pvntracks, prefix+"nPV", m_maxPV ); + if (isVerbose()) test &= tuple->farray( prefix+"PVsumPT", pvsumpt, prefix+"nPV", m_maxPV ); + + return StatusCode(test); + // return StatusCode::SUCCESS; +} +//============================================================================= +// Sum PT +//============================================================================= +double TupleToolPrimaries::sumPT(const LHCb::RecVertex* pv) const { + if (!pv) Exception("Not a RecVertex?"); + double spt = 0 ; + for (SmartRefVector< LHCb::Track >::const_iterator t = pv->tracks().begin() ; + t!= pv->tracks().end() ; ++t) { + if (0==*t) { + Warning("Cannot resolve pointer to Track. Probably a microDST. Set Verbose to false.", + StatusCode::FAILURE,10); + return -1; + } + spt += (*t)->pt(); + } + return spt ; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolPrimaries.h b/first-analysis-steps/DecayTrees/TupleToolPrimaries.h new file mode 100755 index 00000000..d5a408a7 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolPrimaries.h @@ -0,0 +1,46 @@ +// $Id: TupleToolPrimaries.h,v 1.7 2010-03-01 11:47:34 rlambert Exp $ +#ifndef JBOREL_TUPLETOOLPRIMARIES_H +#define JBOREL_TUPLETOOLPRIMARIES_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface +#include "Event/RecVertex.h" + +class DVAlgorithm ; + +/** @class TupleToolPrimaries TupleToolPrimaries.h jborel/TupleToolPrimaries.h + * + * \brief Primary vertices properties for DecayTreeTuple + * + * Tuple columns: + * - coordinates PVX, PVY, PVZ + * - errors PVXERR, PVYERR, PVZERR + * - vertex chi2 PVCHI + * - vertex ndf PVNDOF + * - Nb of tracks used to do the vertex PVNTRACKS + * + * \sa DecayTreeTuple + * @author Jeremie Borel + * @date 2007-11-07 + */ +class TupleToolPrimaries : public TupleToolBase, virtual public IEventTupleTool { +public: + /// Standard constructor + TupleToolPrimaries( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolPrimaries( ){}; ///< Destructor + StatusCode initialize() override; + + StatusCode fill( Tuples::Tuple& ) override; + +private: + double sumPT(const LHCb::RecVertex* pv) const ; ///< sum of Pt of all tracks + std::string m_pvLocation ; ///< PV location to be used. If empty, take context-dependent default + //DVAlgorithm* m_dva; + +}; +#endif // JBOREL_TUPLETOOLPRIMARIES_H diff --git a/first-analysis-steps/DecayTrees/TupleToolPropertime.cpp b/first-analysis-steps/DecayTrees/TupleToolPropertime.cpp new file mode 100755 index 00000000..89e3555b --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolPropertime.cpp @@ -0,0 +1,148 @@ +// $Id: TupleToolPropertime.cpp,v 1.7 2010-04-23 09:34:39 pkoppenb Exp $ +// Include files + +// from Gaudi +#include "GaudiKernel/SmartIF.h" + +#include +#include +#include + +// local +#include "TupleToolPropertime.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" +#include "Event/Vertex.h" + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : EventInfoTupleTool +// +// 2007-11-07 : Jeremie Borel +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolPropertime ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolPropertime::TupleToolPropertime( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_dva(0) + , m_fit(0) +{ + declareInterface(this); + // true determines proper time of all particles w.r.t. their best PV + // false (default) determines proper time w.r.t. mother particle + declareProperty("FitToPV", m_fitToPV = false ); +}//============================================================================= + +StatusCode TupleToolPropertime::initialize() +{ + if( ! TupleToolBase::initialize() ) return StatusCode::FAILURE; + + m_dva = Gaudi::Utils::getIDVAlgorithm ( contextSvc(), this ) ; + if (0==m_dva) return Error("Couldn't get parent DVAlgorithm", + StatusCode::FAILURE); + + m_fit = m_dva->lifetimeFitter(); + if( !m_fit ) + { + return Error("Unable to retrieve the ILifetimeFitter tool"); + } + + return StatusCode::SUCCESS; +} + +//============================================================================= + +StatusCode TupleToolPropertime::fill( const Particle* mother + , const Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + + const std::string prefix=fullName(head); + + Assert( m_fit && P, + "Should not happen, you are inside TupleToolPropertime.cpp" ); + + // no proper-time for basic parts. + if( P->isBasicParticle() ) return StatusCode::SUCCESS; + + const VertexBase* originVtx = NULL; + if( m_fitToPV ){ + originVtx = m_dva->bestVertex( P ); + } + else { + if( mother != P ){ + originVtx = originVertex( mother, P ); // the origin vertex is + // somewhere in the decay + } else { // the origin vertex is the primary. + originVtx = m_dva->bestVertex( mother ); + } + } + + if( originVtx ){} // I'm happy + else { + Error("Can't get the origin vertex"); + return StatusCode::FAILURE; + } + + double pt = -100; + double ept = -100; + double chi2 = -100; + StatusCode sc = m_fit->fit ( *originVtx, *P , pt, ept, chi2 ); + + if( !sc ){ + Warning("The propertime fit failed").ignore(); + pt = -100; + ept = -100; + chi2 = -100; + } + + bool test = true; + test &= tuple->column( prefix+"_TAU" , pt ); // nanoseconds + test &= tuple->column( prefix+"_TAUERR" , ept ); + test &= tuple->column( prefix+"_TAUCHI2" , chi2 ); + + return StatusCode(test); + +} + +const Vertex* TupleToolPropertime::originVertex( const Particle* top + , const Particle* P ) const +{ + if( top == P || P->isBasicParticle() ) return NULL; + + const SmartRefVector< LHCb::Particle >& dau = top->daughters (); + if( dau.empty() ) return NULL; + + for( SmartRefVector::const_iterator it = dau.begin(); + dau.end() != it; ++it ) + { + if( P == *it ){ + return top->endVertex(); + } + } + + // vertex not yet found, get deeper in the decay: + for( SmartRefVector::const_iterator it = dau.begin(); + dau.end() != it; ++it ) + { + if( P != *it && !(*it)->isBasicParticle() ) + { + const Vertex* vv = originVertex( *it, P ); + if( vv ) return vv; + } + } + return NULL; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolPropertime.h b/first-analysis-steps/DecayTrees/TupleToolPropertime.h new file mode 100755 index 00000000..a60bccbe --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolPropertime.h @@ -0,0 +1,60 @@ +#ifndef JBOREL_TUPLETOOLPROPERTIME_H +#define JBOREL_TUPLETOOLPROPERTIME_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface + +struct IDVAlgorithm; +struct ILifetimeFitter; + +namespace LHCb +{ + class Particle; + class Vertex; +} + +/** @class TupleToolPropertime TupleToolPropertime.h jborel/TupleToolPropertime.h + * \brief Fills the propertime for DecayTreeTuple + * + * Columns filled: + * - head_TAU + * - head_TAUERR + * - head_TAUCHI2 + * + * \sa DecayTreeTuple + * + * @author Jeremie Borel + * @date 2007-11-07 + */ +class TupleToolPropertime : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolPropertime( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + + StatusCode fill( const LHCb::Particle*, const LHCb::Particle* + , const std::string&, Tuples::Tuple& ) override; + +private: + + const LHCb::Vertex* originVertex( const LHCb::Particle* + , const LHCb::Particle* ) const; + +private: + + IDVAlgorithm* m_dva; + const ILifetimeFitter* m_fit; + bool m_fitToPV; + +}; + +#endif // JBOREL_TUPLETOOLPROPERTIME_H diff --git a/first-analysis-steps/DecayTrees/TupleToolProtoPData.cpp b/first-analysis-steps/DecayTrees/TupleToolProtoPData.cpp new file mode 100644 index 00000000..ac4fce38 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolProtoPData.cpp @@ -0,0 +1,58 @@ +#include "TupleToolProtoPData.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "CaloUtils/CaloAlgUtils.h" +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolProtoPData +// +// 2011-06-08 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolProtoPData ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolProtoPData::TupleToolProtoPData( const std::string& type, + const std::string& name, + const IInterface* parent ): + TupleToolBase ( type, name , parent ){ + declareInterface(this); + declareProperty( "DataList", m_list ); + declareProperty( "LastData", m_last=1000); + // default : all Comb and Prob data + m_list.push_back("*Comb*"); + m_list.push_back("*Prob*"); + } + +//============================================================================= + + + +StatusCode TupleToolProtoPData::fill( const LHCb::Particle* + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ){ + const std::string prefix=fullName(head); + + if( !P->isBasicParticle() )return StatusCode::SUCCESS; + const LHCb::ProtoParticle* pp = P->proto(); + if( NULL == pp )return StatusCode::SUCCESS; + + bool fill=true; + + double def = -999999.; + int last = (m_last < 0) ? LHCb::ProtoParticle::LastGlobal : m_last; + for(int i=0; i < last ; ++i){ + std::ostringstream var(""); + var << (LHCb::ProtoParticle::additionalInfo) i; + if( std::string::npos != var.str().find("ERROR") )continue; + if( LHCb::CaloAlgUtils::StringMatcher( m_list , var.str() ) ){ + double val = pp->info( (LHCb::ProtoParticle::additionalInfo) i , def); + fill &= tuple->column( prefix+"_PP_"+var.str(), val ); + } + } + + return StatusCode::SUCCESS; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolProtoPData.h b/first-analysis-steps/DecayTrees/TupleToolProtoPData.h new file mode 100644 index 00000000..ee92a6df --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolProtoPData.h @@ -0,0 +1,31 @@ +// $Id: TupleToolProtopinfo.h,v 1.1 2010-05-21 17:03:11 odescham Exp $ +#ifndef _TUPLETOOLEPROTOPDATA_H +#define _TUPLETOOLEPROTOPDATA_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +// Interface +#include "Kernel/IParticleTupleTool.h" +#include "Event/ProtoParticle.h" + +//============================================================================ +class TupleToolProtoPData : public TupleToolBase, virtual public IParticleTupleTool { + //========================================================================== +public: + // Standard constructor + TupleToolProtoPData( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolProtoPData(){}; + StatusCode fill(const LHCb::Particle*, + const LHCb::Particle*, + const std::string& , + Tuples::Tuple& ) override; + +private: + std::vector m_list; + int m_last; +}; +#endif // _TUPLETOOLEPROTOPDATA_H diff --git a/first-analysis-steps/DecayTrees/TupleToolRICHPid.cpp b/first-analysis-steps/DecayTrees/TupleToolRICHPid.cpp new file mode 100755 index 00000000..dfe604c8 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolRICHPid.cpp @@ -0,0 +1,136 @@ +#include "TupleToolRICHPid.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" +#include "Event/RichPID.h" + +#include "RichUtils/RichTrackSegment.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : EventInfoTupleTool +// +// 02 Nov 20010 : Andrew Powell +//----------------------------------------------------------------------------- + +using namespace LHCb; + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolRICHPid::TupleToolRICHPid( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); +} + +//============================================================================= + +StatusCode TupleToolRICHPid::fill( const Particle* + , const Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + + const std::string prefix = fullName(head); + if( P ) + { + bool test = true; + + int Assign_PDGID = P->particleID().pid(); + Rich::ParticleIDType Assign_RICHID = Rich::Unknown; + if(abs(Assign_PDGID)==211) + { + Assign_RICHID = Rich::Pion; + } + else if(abs(Assign_PDGID)==321) + { + Assign_RICHID = Rich::Kaon; + } + else if(abs(Assign_PDGID)==11) + { + Assign_RICHID = Rich::Electron; + } + else if(abs(Assign_PDGID)==13) + { + Assign_RICHID = Rich::Muon; + } + else if(abs(Assign_PDGID)==2212) + { + Assign_RICHID = Rich::Proton; + } + + if( !P->isBasicParticle() ) return StatusCode(test); // no rich info for composite! + + if( isPureNeutralCalo(P) )return StatusCode(test); // no rich information for calo neutrals + + const ProtoParticle* proto = P->proto(); + + if( proto ) + { + test &= tuple->column( prefix+"_RICHDLLe" + ,proto->info(ProtoParticle::RichDLLe,-1000)); + + test &= tuple->column( prefix+"_RICHDLLmu" + ,proto->info(ProtoParticle::RichDLLmu,-1000)); + + test &= tuple->column( prefix+"_RICHDLLpi" + ,proto->info(ProtoParticle::RichDLLpi,-1000)); + + test &= tuple->column( prefix+"_RICHDLLK" + ,proto->info(ProtoParticle::RichDLLk,-1000)); + + test &= tuple->column( prefix+"_RICHDLLp" + ,proto->info(ProtoParticle::RichDLLp,-1000)); + + test &= tuple->column( prefix+"_RICHDLLbt" + ,proto->info(ProtoParticle::RichDLLbt,-1000)); + + if( !tuple->column( prefix+"_RICHBestID", proto->richPID() ? + (proto->richPID()->bestParticleID()) : -2)) return StatusCode::FAILURE; + + if( !tuple->column( prefix+"_RICHThreshold", proto->richPID() ? + (proto->richPID()->isAboveThreshold(Assign_RICHID)) : -1)) return StatusCode::FAILURE; + + if( !tuple->column( prefix+"_RICHThresholdEl", proto->richPID() ? + (proto->richPID()->isAboveThreshold(Rich::Electron)) : -1)) return StatusCode::FAILURE; + + if( !tuple->column( prefix+"_RICHThresholdMu", proto->richPID() ? + (proto->richPID()->isAboveThreshold(Rich::Muon)) : -1)) return StatusCode::FAILURE; + + if( !tuple->column( prefix+"_RICHThresholdPi", proto->richPID() ? + (proto->richPID()->isAboveThreshold(Rich::Pion)) : -1)) return StatusCode::FAILURE; + + if( !tuple->column( prefix+"_RICHThresholdKa", proto->richPID() ? + (proto->richPID()->isAboveThreshold(Rich::Kaon)) : -1)) return StatusCode::FAILURE; + + if( !tuple->column( prefix+"_RICHThresholdPr", proto->richPID() ? + (proto->richPID()->isAboveThreshold(Rich::Proton)) : -1)) return StatusCode::FAILURE; + + if( !tuple->column( prefix+"_RICHAerogelUsed", proto->richPID() ? + (proto->richPID()->traversedRadiator(Rich::Aerogel)) : -1)) return StatusCode::FAILURE; + + if( !tuple->column( prefix+"_RICH1GasUsed", proto->richPID() ? + (proto->richPID()->traversedRadiator(Rich::Rich1Gas)) : -1)) return StatusCode::FAILURE; + + if( !tuple->column( prefix+"_RICH2GasUsed", proto->richPID() ? + (proto->richPID()->traversedRadiator(Rich::Rich2Gas)) : -1)) return StatusCode::FAILURE; + + if( !tuple->column( prefix+"_TRACK_Eta", proto->track() ? + (proto->track()->pseudoRapidity()) : -4.0)) return StatusCode::FAILURE; + + if( !tuple->column( prefix+"_TRACK_Phi", proto->track() ? + (proto->track()->phi()) : -4.0)) return StatusCode::FAILURE; + + return StatusCode(test); + } + } + return StatusCode::FAILURE; +} + +// Declarations of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolRICHPid ) diff --git a/first-analysis-steps/DecayTrees/TupleToolRICHPid.h b/first-analysis-steps/DecayTrees/TupleToolRICHPid.h new file mode 100755 index 00000000..4b450413 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolRICHPid.h @@ -0,0 +1,46 @@ +// $Id: TupleToolPid.h,v 1.2 2008/11/11 07:47:58 pkoppenb Exp $ +#ifndef APOWELL_TupleToolRICHPid_H +#define APOWELL_TupleToolRICHPid_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "Kernel/RichRadiatorType.h" + +/** @class TupleToolRICHPid TupleToolRICHPid.h powell/TupleToolRICHPid.h + * + * \brief DLL and PID information to be stored in a Tuple + * + * \sa DecayTreeTuple + * + * For the long lived particles (isBasicParticle()). + * - head_RICHDLLe : LHCb::ProtoParticle::RICHDLLe + * - head_RICHDLLmu : LHCb::ProtoParticle::RICHDLLmu + * - head_RICHDLLK : LHCb::ProtoParticle::RICHDLLk + * - head_RICHDLLp : LHCb::ProtoParticle::RICHDLLp + * - head_RICHDLLpi : LHCb::ProtoParticle::RICHDLLpi + * + * @author Andrew Powell + * @date 02-Nov-2010 + */ +class TupleToolRICHPid : public TupleToolBase, virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolRICHPid( const std::string& type, + const std::string& name, + const IInterface* parent); + + ~TupleToolRICHPid() = default; ///< Destructor + + StatusCode fill( const LHCb::Particle*, + const LHCb::Particle*, + const std::string&, + Tuples::Tuple& ) override; + +}; + +#endif // APOWELL_TupleToolRICHPid_H diff --git a/first-analysis-steps/DecayTrees/TupleToolRecoStats.cpp b/first-analysis-steps/DecayTrees/TupleToolRecoStats.cpp new file mode 100644 index 00000000..fe84ceb6 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolRecoStats.cpp @@ -0,0 +1,103 @@ +#include "TupleToolRecoStats.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolRecoStats +// +// 2009-02-11 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolRecoStats::TupleToolRecoStats( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name, parent ) +,m_conv(NULL) +{ + declareInterface(this); +} + +//============================================================================= +// Destructor +//============================================================================= +TupleToolRecoStats::~TupleToolRecoStats() {} + +//============================================================================= +StatusCode TupleToolRecoStats::fill( Tuples::Tuple& tup ) +{ + // Initialise the converter tool + m_conv = tool("ReportConvertTool", this ); + if ( !m_conv ){ + return Error("Unable to retrieve the Report converter tool"); + } + m_conv->setReportVersionLatest(); + bool toDelete=false; + + const std::string prefix = fullName(); + + // Load the RecSummary object + LHCb::RecSummary * rS = getIfExists(evtSvc(),LHCb::RecSummaryLocation::Default); + if ( !rS ) + { + rS = getIfExists(evtSvc(),LHCb::RecSummaryLocation::Default,false); + } + if ( !rS ) + { + rS = getIfExists(evtSvc(),"/Event/Turbo/Rec/Summary",false); + } + // If not there then try to recreate from selection reports + if ( !rS ) + { + toDelete=true; + rS = new LHCb::RecSummary(); + const LHCb::HltSelReports* selReports = get( "Hlt2/SelReports" ); + if(selReports){ + const LHCb::HltObjectSummary* recsummaryObj = selReports->selReport("Hlt2RecSummary"); + if(recsummaryObj){ + const LHCb::HltObjectSummary* Rec_subobj = recsummaryObj->substructure()[0].target(); + if(Rec_subobj){ + const LHCb::HltObjectSummary::Info& Rec_info = Rec_subobj->numericalInfo(); + m_conv->RecSummaryObjectFromSummary(&Rec_info,rS); + } + } + } + } + + // Fill the tuple + bool test = true; + + test &= tup->column( prefix+"nPVs", rS ? rS->info(LHCb::RecSummary::nPVs,-1) : -2 ); + + test &= tup->column( prefix+"nTracks", rS ? rS->info(LHCb::RecSummary::nTracks,-1) : -2 ); + test &= tup->column( prefix+"nLongTracks", rS ? rS->info(LHCb::RecSummary::nLongTracks,-1) : -2 ); + test &= tup->column( prefix+"nDownstreamTracks", rS ? rS->info(LHCb::RecSummary::nDownstreamTracks,-1) : -2 ); + test &= tup->column( prefix+"nUpstreamTracks", rS ? rS->info(LHCb::RecSummary::nUpstreamTracks,-1) : -2 ); + test &= tup->column( prefix+"nVeloTracks", rS ? rS->info(LHCb::RecSummary::nVeloTracks,-1) : -2 ); + test &= tup->column( prefix+"nTTracks", rS ? rS->info(LHCb::RecSummary::nTTracks,-1) : -2 ); + test &= tup->column( prefix+"nBackTracks", rS ? rS->info(LHCb::RecSummary::nBackTracks,-1) : -2 ); + + test &= tup->column( prefix+"nRich1Hits", rS ? rS->info(LHCb::RecSummary::nRich1Hits,-1) : -2 ); + test &= tup->column( prefix+"nRich2Hits", rS ? rS->info(LHCb::RecSummary::nRich2Hits,-1) : -2 ); + + test &= tup->column( prefix+"nVeloClusters", rS ? rS->info(LHCb::RecSummary::nVeloClusters,-1) : -2 ); + + test &= tup->column( prefix+"nITClusters", rS ? rS->info(LHCb::RecSummary::nITClusters,-1) : -2 ); + test &= tup->column( prefix+"nTTClusters", rS ? rS->info(LHCb::RecSummary::nTTClusters,-1) : -2 ); + test &= tup->column( prefix+"nOTClusters", rS ? rS->info(LHCb::RecSummary::nOTClusters,-1) : -2 ); + + test &= tup->column( prefix+"nSPDHits", rS ? rS->info(LHCb::RecSummary::nSPDhits,-1) : -2 ); + + test &= tup->column( prefix+"nMuonCoordsS0", rS ? rS->info(LHCb::RecSummary::nMuonCoordsS0,-1) : -2 ); + test &= tup->column( prefix+"nMuonCoordsS1", rS ? rS->info(LHCb::RecSummary::nMuonCoordsS1,-1) : -2 ); + test &= tup->column( prefix+"nMuonCoordsS2", rS ? rS->info(LHCb::RecSummary::nMuonCoordsS2,-1) : -2 ); + test &= tup->column( prefix+"nMuonCoordsS3", rS ? rS->info(LHCb::RecSummary::nMuonCoordsS3,-1) : -2 ); + test &= tup->column( prefix+"nMuonCoordsS4", rS ? rS->info(LHCb::RecSummary::nMuonCoordsS4,-1) : -2 ); + test &= tup->column( prefix+"nMuonTracks", rS ? rS->info(LHCb::RecSummary::nMuonTracks,-1) : -2 ); + + if(toDelete) delete rS; + return StatusCode(test); +} + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolRecoStats ) diff --git a/first-analysis-steps/DecayTrees/TupleToolRecoStats.h b/first-analysis-steps/DecayTrees/TupleToolRecoStats.h new file mode 100644 index 00000000..4a8228f2 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolRecoStats.h @@ -0,0 +1,43 @@ +// $Id: TupleToolRecoStats.h,v 1.7 2010-09-09 12:22:42 pkoppenb Exp $ +#ifndef TUPLETOOLRECOSTATS_H +#define TUPLETOOLRECOSTATS_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface + +#include "Event/Track.h" +#include "Event/RecSummary.h" +#include "HltDAQ/IReportConvert.h" +#include "HltDAQ/ReportConvertTool.h" + +/** @class TupleToolRecoStats TupleToolRecoStats.h + * + * Fills Reco stats, from RecSummary + * + * @author Patrick Koppenburg, Fatima Soomro, Jibo He + * @date 2009-02-11 + */ +class TupleToolRecoStats : public TupleToolBase, + virtual public IEventTupleTool +{ + +public: + + /// Standard constructor + TupleToolRecoStats( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolRecoStats( ); ///< Destructor + StatusCode fill( Tuples::Tuple& ) override;///< Fill tuple + +private: + /// for converting objects in to summaries + IReportConvert* m_conv; + +}; + +#endif // TUPLETOOLRECOSTATS_H + diff --git a/first-analysis-steps/DecayTrees/TupleToolSelResults.cpp b/first-analysis-steps/DecayTrees/TupleToolSelResults.cpp new file mode 100644 index 00000000..c94a3ff1 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolSelResults.cpp @@ -0,0 +1,61 @@ +// Include files + +// local +#include "TupleToolSelResults.h" +#include "Kernel/ICheckSelResults.h" // Interface + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolSelResults +// +// 2009-02-11 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolSelResults ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolSelResults::TupleToolSelResults( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ), + m_selTool(0), + m_selections(0) +{ + declareInterface(this); + declareProperty("Selections", m_selections, "List of algorithm names"); + //deprecated, use ExtraName instead + //declareProperty("Head", m_head = "", "This will be appended before any tuple entry"); +} + +//============================================================================= +// init +//============================================================================= +StatusCode TupleToolSelResults::initialize() +{ + StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + m_selTool = tool("CheckSelResultsTool",this); + return sc ; +} + +//============================================================================= +// Fill +//============================================================================= +StatusCode TupleToolSelResults::fill( Tuples::Tuple& tup) +{ + const std::string prefix = fullName(); + bool test = true; + for ( std::vector::const_iterator s = m_selections.begin() ; + s != m_selections.end(); ++s ) + { + test &= tup->column(prefix+(*s),m_selTool->isSelected(*s)); + if (!test) + { + err() << "Cannot fill variable name " << prefix+(*s) << endmsg ; + break; + } + } + return StatusCode(test) ; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolSelResults.h b/first-analysis-steps/DecayTrees/TupleToolSelResults.h new file mode 100644 index 00000000..b440bdd7 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolSelResults.h @@ -0,0 +1,41 @@ +#ifndef TUPLETOOLSELRESULTS_H +#define TUPLETOOLSELRESULTS_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface + +/** @class TupleToolSelResults TupleToolSelResults.h + * + * Fill entries for a given list of algorithm names. + * + * @code + * EventTuple.TupleToolSelResults.Selections = [ "Hlt2", "Hlt2", "MySelection" ] + * @endcode + * + * Warning : It will create fields "Hlt2", "Hlt2", "MySelection" in the Tuple. There might be clashes. + * + * @author Patrick Koppenburg + * @date 2009-02-11 + */ +struct ICheckSelResults ; +class TupleToolSelResults : public TupleToolBase, virtual public IEventTupleTool { +public: + /// Standard constructor + TupleToolSelResults( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; ///< init + StatusCode fill( Tuples::Tuple& ) override; ///< Fill tuple + +protected: + +private: + ICheckSelResults* m_selTool ; ///< CheckselResults tool + std::vector m_selections ; ///< list of algorithm names + //std::string m_head ; ///< head, just in case there are clashes + +}; +#endif // TUPLETOOLSELRESULTS_H diff --git a/first-analysis-steps/DecayTrees/TupleToolStripping.cpp b/first-analysis-steps/DecayTrees/TupleToolStripping.cpp new file mode 100644 index 00000000..78c14c05 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolStripping.cpp @@ -0,0 +1,132 @@ +#include "TupleToolStripping.h" +#include "Event/HltDecReports.h" +#include "Event/HltDecReport.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +// gaudirun.py ~/cmtuser/Saved-options/DVTestStripping-ReadDST.py ~/cmtuser/Saved-options/DiMuon_100419.py | tee test + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolStripping +// +// 2010-04-23 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolStripping ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolStripping::TupleToolStripping( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolTriggerBase ( type, name , parent ) +{ + declareInterface(this); + /// @todochange with rootontes + declareProperty("StrippingReportsLocations", m_location = "/Event/Strip/Phys/DecReports" ); + declareProperty("StrippingList", m_strippingList );// act as TriggerList in base class + m_doL0=false; + m_doHlt1=false; + m_doHlt2=false; + m_doStripping=true; + m_verboseStripping=true; +} + +//============================================================================= +// Destructor +//============================================================================= +TupleToolStripping::~TupleToolStripping() {} + +//============================================================================= + +StatusCode TupleToolStripping::initialize ( ) +{ + + // before initializing the base class + if( m_triggerList.empty() && m_strippingList.empty()) + return Warning("You MUST explicitely configure the list of stripping lines", + StatusCode::FAILURE); + if( !m_triggerList.empty() && !m_strippingList.empty()) + return Warning("You must configure either StrippingList or TriggerList (equivalent) but not both", + StatusCode::FAILURE); + if( !m_strippingList.empty()) { m_triggerList = m_strippingList; } + m_strippingList.clear(); + + const StatusCode sc = TupleToolTriggerBase::initialize(); + if ( sc.isFailure() ) return sc; + + if ( m_doL0 || !m_l0.empty() ) + Warning("L0 line(s) requested : You should use TupleToolStripping for that", + StatusCode::SUCCESS); + if ( m_doHlt1 || !m_hlt1.empty() ) + Warning("HLT1 line(s) requested : You should use TupleToolStripping for that", + StatusCode::SUCCESS); + if ( m_doHlt2 || !m_hlt2.empty() ) + Warning("HLT1 line(s) requested : You should use TupleToolStripping for that", + StatusCode::SUCCESS); + + if ( !m_doStripping || m_stripping.empty() ) + return Error("You MUST explicitly configure the list of stripping lines", + StatusCode::FAILURE); + + // + info() << "Requested information for stripping lines : " << m_stripping << endmsg; + + return sc ; +} + +//============================================================================= + +StatusCode TupleToolStripping::fill( Tuples::Tuple& tuple ) +{ + + bool fillTup=true; + const LHCb::HltDecReports* dr = getIfExists(evtSvc(),m_location,false); + if ( !dr ) { dr = getIfExists(evtSvc(),m_location); } + + if ( dr ) + { + if ( msgLevel(MSG::DEBUG) ) + { + debug() << "There are " << dr->size() << " DecReports at " << m_location << endmsg ; + } + if ( msgLevel(MSG::VERBOSE) ) + { + const std::vector & names = dr->decisionNames() ; + verbose() << "NAMES: " << names << endmsg ; + } + } + else + { + Warning( "No DecReports at "+m_location, StatusCode::SUCCESS, 1).ignore(); + } + + unsigned int i = 0 ; + for ( std::vector::const_iterator s = m_stripping.begin() ; + s != m_stripping.end(); ++s, ++i ) + { + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "Trying " << i << " " << *s << " in " << m_stripping << endmsg ; + + if ( dr && dr->hasDecisionName(*s) ) + { + const LHCb::HltDecReport* report = dr->decReport(*s); + if ( !report ) Exception("Cannot find report "+*s); + if(msgLevel(MSG::VERBOSE)) verbose() << *s << " says " << report->decision() << endmsg ; + fillTup &= tuple->column( *s, report->decision() ) ; + } + else + { + if(msgLevel(MSG::VERBOSE)) + verbose() <<" no report for " << *s << " decision is 0" << endmsg ; + const unsigned int dec = 0; + fillTup &= tuple->column( *s, dec ) ; + } + } + + return StatusCode(fillTup); +} + +//============================================================================= diff --git a/first-analysis-steps/DecayTrees/TupleToolStripping.h b/first-analysis-steps/DecayTrees/TupleToolStripping.h new file mode 100644 index 00000000..e1d7c71b --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolStripping.h @@ -0,0 +1,44 @@ +// $Id: TupleToolStripping.h,v 1.1 2010-04-26 12:49:59 pkoppenb Exp $ +#ifndef TUPLETOOLSTRIPPING_H +#define TUPLETOOLSTRIPPING_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" + +#include "TupleToolTriggerBase.h" +#include "Kernel/IEventTupleTool.h" // Interface + +/** @class TupleToolStripping TupleToolStripping.h + * + * + * @author Patrick Koppenburg + * @date 2010-04-23 + */ +class TupleToolStripping : public TupleToolTriggerBase, + virtual public IEventTupleTool +{ + +public: + + /// Standard constructor + TupleToolStripping( const std::string& type, + const std::string& name, + const IInterface* parent); + + ~TupleToolStripping( ); ///< Destructor + + StatusCode initialize() override; + + using TupleToolTriggerBase::fill; + StatusCode fill( Tuples::Tuple& tuple ) override; + +private: + + std::string m_location ; ///< HDR location + + /// property: list of stripping lines to specifically look at + std::vector m_strippingList; +}; + +#endif // TUPLETOOLSTRIPPING_H diff --git a/first-analysis-steps/DecayTrees/TupleToolSubMass.cpp b/first-analysis-steps/DecayTrees/TupleToolSubMass.cpp new file mode 100644 index 00000000..afeaf10b --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolSubMass.cpp @@ -0,0 +1,368 @@ +// $Id: TupleToolSubMass.cpp,v 1.12 2010-04-23 12:01:26 jhe Exp $ +// Include files + +// local +#include "TupleToolSubMass.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include +#include +#include +#include "Kernel/IParticleCombiner.h" +#include +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolSubMass +// +// 2011-02-10 Patrick Koppenburg +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolSubMass ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolSubMass::TupleToolSubMass( const std::string& type, + const std::string& name, + const IInterface* parent ) +: TupleToolBase ( type, name , parent ) + ,m_dva(0) + ,m_vertex(true) + ,m_endTree(){ + declareInterface(this); + declareProperty( "SetMax" , m_max=0); + declareProperty( "Substitution" , m_subst); + declareProperty( "DoubleSubstitution", m_subst2); + declareProperty( "SubVertexFit" , m_vertex); + declareProperty( "EndTreePIDs" , m_endTree); + + // converted photons and V0s are considered as basic particles + m_endTree.push_back(22); + m_endTree.push_back(310); // + m_endTree.push_back(3122); // +} + +//============================================================================= + +StatusCode TupleToolSubMass::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + // get parent DV + m_dva = Gaudi::Utils::getIDVAlgorithm ( contextSvc(), this ) ; + if ( !m_dva ) { return Error( "Couldn't get parent DVAlgorithm", StatusCode::FAILURE ); } + // get property service + m_ppsvc = svc("LHCb::ParticlePropertySvc",true) ; + + // consistentcy checks + for( std::vector::const_iterator is = m_subst.begin(); m_subst.end() !=is ; ++is){ + const std::pair fromto=parseSubst(*is); + const std::string from = fromto.first; + const std::string to = fromto.second; + if( NULL == property(from) )return Warning("Cannot substitute from unknown particle " + from, StatusCode::FAILURE); + if( NULL == property(to) )return Warning("Cannot substitute to unknown particle " + to, StatusCode::FAILURE); + } + for( std::vector::const_iterator is = m_subst2.begin(); m_subst2.end() !=is ; ++is){ + const std::pair fromto=parseSubst(*is); + const std::string from = fromto.first; + const std::string to = fromto.second; + if( parseID(from).first == "NONE" ) + return Warning("Cannot substitute from unknown particles pair " + from, StatusCode::FAILURE); + if( parseID(to).first == "NONE" ) + return Warning("Cannot substitute to unknown particles pair " + from, StatusCode::FAILURE); + } + return sc ; +} + +//============================================================================= +StatusCode TupleToolSubMass::fill( const LHCb::Particle* + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ){ + const std::string prefix=fullName(head); + bool fill = true; + if( !P ) return StatusCode::FAILURE; + if( P->isBasicParticle() ) return StatusCode::SUCCESS; + + // get the final state tree + m_ancestor = P; // cache the ancestor for cc-independant tree-sorting + std::vector tree=getTree( P ); + + //== check sorting + std::string decay = property( P->particleID())->name() + " -> ["; + for( unsigned int pos =0; pos < tree.size() ; pos++){ + if( pos >= tree.size())return Warning("Unexpected error",StatusCode::FAILURE); + //if(msgLevel(MSG::DEBUG))debug() << " Ancestor : " << P->particleID().pid() << " daughter " << pos << " : " << tree[pos]->particleID().pid() << endmsg; + std::string sep = ( pos != 0) ? "," : ""; + decay += sep + property( tree[pos]->particleID() )->name(); + } + decay += "]"; + if(msgLevel(MSG::DEBUG))debug() << "===> sorted decay structure for " << P->particleID().pid() << " : " << decay << endmsg; + + counter(decay)+=1; + + + //=== Get all combinaisons + unsigned int nfs= tree.size();; + unsigned int max = ( m_max > 1) ? m_max : nfs; + if( max > nfs)max=nfs; + + for(unsigned int level=2;level<=max;++level){ + for( unsigned int d=0; d < max-level+1; ++d){ + std::vector v; + std::vector > vv; + v.push_back( d ); + vv.push_back(v); + // produce the combinations tables + std::vector > out=combine( vv , level, nfs); + // loop over combinations tables + for( std::vector >::const_iterator ivv = out.begin(); ivv != out.end(); ++ivv){ + const std::vector map = *ivv; + + //==== Mass for the current combination (no substition) + std::pair fMass = getMass( tree, map ); + if( fMass.first != "NONE")fill &= tuple->column( prefix + "_M"+fMass.first, fMass.second ); + if(m_vertex)fill &= fillVertexInfo(P,tree,map,tuple,prefix); + + + //==== Try single substitution when requested + for( std::vector::const_iterator is = m_subst.begin(); m_subst.end() !=is ; ++is){ + const std::pair fromto=parseSubst(*is); + const std::string from = fromto.first; + const std::string to = fromto.second; + unsigned int fromID = property(from)->pid().abspid() ; + double toMass = property(to)->mass(); + for( std::vector::const_iterator im = map.begin() ; map.end() != im ; ++im){ + int pos = *im; + const LHCb::Particle* part = tree[ pos ]; + if( part->particleID().abspid() == fromID){ + std::pair sMass = getMass( tree, map, pos , toMass ); + if( sMass.first != "NONE")fill &= tuple->column( prefix + "_M" + + sMass.first + "_" + getFlag(from,to,pos), sMass.second ); + } + } + } + //==== Try double substitutions when requested + for( std::vector::const_iterator iss = m_subst2.begin(); m_subst2.end() != iss ; ++iss){ + const std::pair fromto=parseSubst(*iss); + const std::string from = fromto.first; + const std::string to = fromto.second; + const std::string from1 = parseID(from).first; + const std::string from2 = parseID(from).second; + const std::string to1 = parseID(to).first; + const std::string to2 = parseID(to).second; + int fromID1 = property(from1)->pid().pid() ; + int fromID2 = property(from2)->pid().pid() ; + double toMass1 = property(to1)->mass(); + double toMass2 = property(to2)->mass(); + unsigned int size=map.size(); + for( unsigned int i1 = 0; i1 < size ; i1++){ + for( unsigned int i2 = i1+1; i2 < size ; i2++){ + int pos1 = map[i1]; + int pos2 = map[i2]; + const LHCb::Particle* part1 = tree[ pos1 ]; + const LHCb::Particle* part2 = tree[ pos2 ]; + int pid1 = part1->particleID().pid(); + int apid1 = (part1->charge() == 0 ) ? pid1 : -pid1 ; + int pid2 = part2->particleID().pid(); + int apid2 = (part2->charge() == 0 ) ? pid2 : -pid2 ; + if( ( pid1 == fromID1 && pid2 == fromID2 ) || ( apid1 == fromID1 && apid2 == fromID2 ) ){ + std::pair sMass = getMass( tree, map, pos1 , toMass1, pos2, toMass2 ); + if( sMass.first != "NONE"){ + fill &= tuple->column( prefix + "_M"+ sMass.first + "_" + getFlag(from1,to1,pos1,from2,to2,pos2),sMass.second); + } + }else if( ( pid1 == fromID2 && pid2 == fromID1 ) || ( apid2 == fromID1 && apid1 == fromID2 )){ + std::pair sMass = getMass( tree, map, pos1 , toMass2, pos2, toMass1 ); + if( sMass.first != "NONE"){ + fill &= tuple->column( prefix + "_M"+ sMass.first + "_" + getFlag(from1,to1,pos1,from2,to2,pos2),sMass.second); + } + } + } + } + } + } + } + } + return StatusCode(fill); +} + +// ------ parse substitution string +std::pair TupleToolSubMass::parseSubst(std::string subst){ + int i = subst.find_last_of("=>"); + std::string from = subst.substr(0,i-1); + std::string to = subst.substr(i+1,std::string::npos); + boost::erase_all(from," "); + boost::erase_all(to," "); + return std::make_pair(from,to); +} + + +//------- particleID parser for double substitution map +std::pair TupleToolSubMass::parseID(std::string PID){ + // syntax a/b + if( PID.find_last_of("/") != std::string::npos){ + int i = PID.find_last_of("/"); + std::string pid1 = PID.substr(0,i); + std::string pid2 = PID.substr(i+1,std::string::npos); + if( property(pid1) != NULL && property(pid2) != NULL)return std::make_pair(property(pid1)->name(),property(pid2)->name()); + }else{ + // try another syntax : ab + for( unsigned int i=1 ; iname(),property(pid2)->name()); + } + } + // parsing failed + return std::make_pair("NONE","NONE"); +} + +//------- produce the ntuple entry flag : +std::string TupleToolSubMass::getFlag(std::string from,std::string to,int pos,std::string from2,std::string to2,int pos2){ + boost::replace_all(from,"+",""); + boost::replace_all(from,"-",""); + boost::replace_all(to,"+",""); + boost::replace_all(to,"-",""); + boost::replace_all(from2,"+",""); + boost::replace_all(from2,"-",""); + boost::replace_all(to2,"+",""); + boost::replace_all(to2,"-",""); + if( pos2 < 0)return "Subst"+Gaudi::Utils::toString(pos)+"_"+from+"2"+to; + return "Subst"+Gaudi::Utils::toString(pos)+Gaudi::Utils::toString(pos2)+"_"+from+from2+"2"+to+to2; +} + +//------- compute momentum (possibly with PID substitution) +Gaudi::LorentzVector TupleToolSubMass::sMomentum(const LHCb::Particle* part , double sMass) { + Gaudi::LorentzVector momentum = part ->momentum(); + if( isPureNeutralCalo( part ) ){// photon (E is measured) - use-case : gamma <->pi0 substitution + if( sMass < momentum.E() ){ + double P = sqrt( momentum.E()*momentum.E() - sMass*sMass); + double px = momentum.px()/momentum.P()*P; + double py = momentum.py()/momentum.P()*P; + double pz = momentum.pz()/momentum.P()*P; + momentum.SetPx(px); + momentum.SetPy(py); + momentum.SetPz(pz); + } + }else{// tracks (p is measured) + double E = sqrt(momentum.P()*momentum.P() + sMass*sMass); + momentum.SetE( E ); + } + return momentum; +} + + +//-------- compute vertex information for the combination : +bool TupleToolSubMass::fillVertexInfo(const LHCb::Particle* P, + std::vector tree, + const std::vector map , + Tuples::Tuple& tuple,const std::string prefix){ + bool fill=true; + LHCb::Vertex vertex; + LHCb::Particle mother; + LHCb::Particle::ConstVector subTree ; + std::string flag; + for( std::vector::const_iterator iv = map.begin(); iv != map.end(); ++iv){ + int pos = *iv; + const LHCb::Particle* part = tree[ pos ]; + subTree.push_back( part ); + flag += Gaudi::Utils::toString( pos ); + } + + // Vertex chi2 + StatusCode sc = m_dva->particleCombiner()->combine( subTree, mother, vertex ); + double chi2= (sc.isSuccess()) ? vertex.chi2() : -1.; + double nDoF= (sc.isSuccess()) ? vertex.nDoF() : 0.; + fill &= tuple->column( prefix+"_VtxChi2_"+flag , chi2); + fill &= tuple->column( prefix+"_VtxnDoF"+flag , nDoF); + fill &= tuple->column( prefix+"_VtxM"+flag , mother.momentum().M()); + + // IP chi2 + double ip=0; + double ipchi2=0; + const LHCb::VertexBase* PV = m_dva->bestVertex ( P ); + bool ok = m_dva->distanceCalculator()->distance ( &mother, PV, ip, ipchi2 ).isSuccess(); + if (!ok){ + ip=0; + ipchi2=-1.; + } + fill &= tuple->column( prefix+"_IP"+flag , ip); + fill &= tuple->column( prefix+"_IPChi2_"+flag , ipchi2); + return fill; +} + + + + +//-------- compute the combination mass (possibly with PID substitution(s)) +std::pair TupleToolSubMass::getMass(std::vector tree, const std::vector map, + int sPos, double sMass,int sPos2, double sMass2){ + Gaudi::LorentzVector sum; + std::string flag; + bool doSub1 = false; + bool doSub2 = false; + for( std::vector::const_iterator iv = map.begin(); iv != map.end(); ++iv){ + int pos = *iv; + const LHCb::Particle* part = tree[ pos ]; + + if( pos == sPos ){ + doSub1 = true; + sum += sMomentum(part,sMass); + }else if( pos == sPos2 ){ + doSub2 = true; + sum += sMomentum(part,sMass2); + }else + sum += part->momentum(); + flag += Gaudi::Utils::toString( pos ); + } + if( (!doSub1 && sPos >=0) || (!doSub2 && sPos2 >=0))return std::make_pair("NONE",0.); + return std::make_pair(flag,sum.M()); +} + + +bool TupleToolSubMass::isEndTree(const LHCb::Particle* p){ + if( p->isBasicParticle() )return true; + for(std::vector::iterator it = m_endTree.begin(); m_endTree.end() != it ; ++it){ + if( (int) p->particleID().abspid() == *it)return true; + } + return false; +} + + + +//-------- get sorted tree (cc-independant) +std::vector TupleToolSubMass::getTree( const LHCb::Particle* P ){ + std::vector tree; + //if( P->isBasicParticle() ){ + if( isEndTree(P) ){ + tree.push_back( P ); + }else{ + SmartRefVector daughters = P->daughters(); // local copy to sort + std::stable_sort ( daughters.begin(),daughters.end(),SortDaughtersByPID(m_ancestor,m_ppsvc)); + for (SmartRefVector::const_iterator idau = daughters.begin(); idau!= daughters.end();++idau){ + std::vector temp=getTree( *idau ); + for( std::vector::iterator dd=temp.begin();temp.end() !=dd; ++dd){ + tree.push_back( *dd ); + } + } + } + return tree; +} + +//-------- get the combinations tables +std::vector > TupleToolSubMass::combine( std::vector > vec, unsigned int level, int nfs){ + if( (vec.back()).size() == level )return vec; + std::vector > cc ; // local vector + for( std::vector >::iterator iv = vec.begin(); iv != vec.end(); ++iv){ + if( iv->size() == level )continue; + int min=iv->back(); + for(int i=min+1 ; i c = *iv; + c.push_back(i); + cc.push_back( c ); + }; + } + return combine( cc, level, nfs); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolSubMass.h b/first-analysis-steps/DecayTrees/TupleToolSubMass.h new file mode 100644 index 00000000..b3601eac --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolSubMass.h @@ -0,0 +1,118 @@ +#ifndef TUPLETOOLSUBMASS_H +#define TUPLETOOLSUBMASS_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "Event/Particle.h" +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" +struct IDVAlgorithm; + + +/** @class TupleToolSubMass TupleToolSubMass.h jborel/TupleToolSubMass.h + * + * \brief Return all n-bodies mass combinations from the decay tree + * + * + * \verbatim +from configurables import TupleToolSubMass +Tuple.addTool(TupleToolSubMass) +Tuple.TupleToolSubMass.SetMax = 3 # look to 2- and 3-bodies (defaut all possible n-bodies) +\endverbatim + * + * - will create Sum_{p=2,max) C(N,p) new entries in the nTuple called [head]_M[ij...] + * + * - Particle daughters are sorted by PID at each branch of the tree (cc-independant) + * + * **** Substitution property + * + * - usage : + * TupleTool.Substitution += ["pi+ => K+"] + * TupleTool.Substitution += ["K+ => pi+"] + * + * - produce alternative mass with substituted PID pi<->K (cc is assumed) + * + * -change only one pion (K) at once in case of several pion (K) in the decay tree (producing separate output par pion (K) ) + * + * **** DoubleSubstitution property + * + * - usage : + * TupleTool.DoubleSubstitution += ["K+/pi- => pi+/K-"] + * TupleTool.DoubleSubstitution += ["K+/K-" => pi+/pi-"] + * + * - change all [K+pi-]cc ([K+K-]cc) pairs to (pi+K-)cc ([pi+pi-]cc) + * - change only one pair at once in case of several pairs in the decay tree (producing separate output per pair) + * - "/" separator is not mandatory : K+pi- syntax is allowed (just a bit slower to parse) + * + * @author Olivier Deschamps + * @date 2011-06-01 + */ + +class SortDaughtersByPID { +public: + SortDaughtersByPID(const LHCb::Particle* P,LHCb::IParticlePropertySvc* ppsvc){ + m_sign=1; + m_ppsvc=ppsvc; + if ( P )m_sign = ( P->particleID().pid() > 0) ? +1 : -1; + } + bool operator()(const LHCb::Particle* c1, const LHCb::Particle* c2) { + int p1 = ( property( c1->particleID())->selfcc() ) ? c1->particleID().pid() : m_sign*c1->particleID().pid(); + int p2 = ( property( c2->particleID())->selfcc() ) ? c2->particleID().pid() : m_sign*c2->particleID().pid(); + // special case c1 == c2 but with different decay structure (e.g. pi0->g(g->ee) : check daughters size + if( p1 == p2 && c1->daughters().size() != c2->daughters().size())return c1->daughters().size() > c2->daughters().size() ; + // add a complete test of the decay structure (above test won't work for e.g. Bs->phi(KsKs)phi(K+K-) decay + // .. + // else + return p1 > p2 ; + }; +private : + const LHCb::ParticleProperty* property(const LHCb::ParticleID pid){return (m_ppsvc) ? m_ppsvc->find( pid ) : NULL;}; + LHCb::IParticlePropertySvc* m_ppsvc; + int m_sign; +}; + + +class TupleToolSubMass : public TupleToolBase, virtual public IParticleTupleTool { +public: + /// Standard constructor + TupleToolSubMass( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; ///< initialisation + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private : + std::vector > combine(std::vector > vec, unsigned int level, int nfs); + std::vector getTree(const LHCb::Particle* P ); + bool isEndTree(const LHCb::Particle* p); + bool fillVertexInfo(const LHCb::Particle* P, std::vector tree, const std::vector map, + Tuples::Tuple& tuple,const std::string prefix); + std::pair getMass(std::vector tree , const std::vector map, + int sPos=-1, double sMass=0.,int sPos2=-1,double sMass2=0.); + std::string getFlag(std::string from,std::string to,int pos, + std::string from2="",std::string to2="",int pos2=-1); + Gaudi::LorentzVector sMomentum(const LHCb::Particle* part , double sMass); + std::pair parseID(std::string PID); + std::pair parseSubst(std::string subst); + + + unsigned int m_max; + std::vector m_subst; + std::vector m_subst2; + LHCb::IParticlePropertySvc* m_ppsvc; + const LHCb::ParticleProperty* property(std::string name){return (m_ppsvc) ? m_ppsvc->find( name ) : NULL;}; + const LHCb::ParticleProperty* property(const LHCb::ParticleID pid){return (m_ppsvc) ? m_ppsvc->find( pid ) : NULL;}; + const LHCb::Particle* m_ancestor; + IDVAlgorithm* m_dva; + bool m_vertex; + std::vector m_endTree; +}; + +#endif // TUPLETOOLSUBMASS_H diff --git a/first-analysis-steps/DecayTrees/TupleToolSwimmingInfo.cpp b/first-analysis-steps/DecayTrees/TupleToolSwimmingInfo.cpp new file mode 100755 index 00000000..c1748c17 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolSwimmingInfo.cpp @@ -0,0 +1,334 @@ +// $Id: TupleToolSwimmingInfo.cpp,v 1.6 2010-03-04 14:02:03 xieyu Exp $ +// Include files + +// boost +#include +#include + +// local +#include "TupleToolSwimmingInfo.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolSwimmingInfo +// +// 2011-10-15 : V Gligorov & R Aaij +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolSwimmingInfo ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolSwimmingInfo::TupleToolSwimmingInfo( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); + declareProperty("RelationsLocation", m_swimRelTableLoc); + declareProperty("ReportStage" , m_swimRepsStage = "Trigger"); +} + +bool TupleToolSwimmingInfo::hasDescendant(const LHCb::Particle *mother, const LHCb::Particle *desc) +{ + if(!mother || !desc) + { + error() << "TupleToolSwimmingInfo::hasDescendant(" << mother << ", " << desc << ")" << endmsg; + return false; + } + + LHCb::Particle::ConstVector daughters(mother->daughtersVector()); + for(LHCb::Particle::ConstVector::iterator diter = daughters.begin(); diter != daughters.end(); diter++) + { + const LHCb::Particle *daug(*diter); + if(daug == desc or hasDescendant(daug, desc)) + return true; + } + return false; +} + +bool TupleToolSwimmingInfo::getRelationsFromDescendant(P2TPRelation::Range &range, const P2TPRelation *relatePart, const LHCb::Particle* Phead, const LHCb::Particle *P) +{ + if(!relatePart || !Phead || !P) + { + error() << "TupleToolSwimmingInfo::getRelationsFromDescendant(range, " << relatePart << ", " << Phead << ", " << P << ")" << endmsg; + return false; + } + + LHCb::Particle::ConstVector daughters(Phead->daughtersVector()); + for(LHCb::Particle::ConstVector::iterator diter = daughters.begin(); diter != daughters.end(); diter++) + { + const LHCb::Particle *daug(*diter); + range = relatePart->relations(daug); + debug() << "Got range.size() = " << range.size() << endmsg; + if(range.size() == 1) + { + // This could be the swum B/D + if(hasDescendant(daug, P)) + { + // It is the correct swum B/D + debug() << "getRelationsFromDescendant() found the correct B/D from " << relatePart->relations(P).size() << " choices" << endmsg; + debug() << "swum descendant is " << *daug << " which has " << *P << " as a descendant" << endmsg; + return true; + } + else + { + debug() << "Found particle " << daug << " with exactly one related swimming report, but it didn't have our track as a descentant" << endmsg; + if(daug) + debug() << *daug << endmsg; + } + } + else + { + // Recurse down before we move onto the next 'Phead' daughter. + if(getRelationsFromDescendant(range, relatePart, daug, P)) + { + debug() << "Succeeded calling getRelationsFromDescendant(range, relatePart, " << daug << ", " << P << ")" << endmsg; + return true; + } + } + } + + return false; +} + +//============================================================================= +StatusCode TupleToolSwimmingInfo::fill( const Particle* Phead + , const Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix(fullName(head) + "_" + m_swimRepsStage); + const unsigned int maxTurns(1000); + + typedef std::vector doubleVec; + typedef std::set stringSet; + typedef std::map > MapType; + + doubleVec raw, dec, tau, ip; + P2TPRelation *relatePart(NULL); + if(exist(m_swimRelTableLoc)) + { + relatePart = get(m_swimRelTableLoc); + debug() << "Found Particle2TurningPointRelations at " << m_swimRelTableLoc << endmsg; + if(!relatePart) + return Error("Retrieved NULL Particle2TurningPointRelations"); + } + else + { + error() << "Couldn't get Particle2TurningPointRelations from " << m_swimRelTableLoc << endmsg; + return StatusCode::FAILURE; + } + + // We need to find some reports. Any reports. Just so we can get a list of names, so we always consistently + // set some value for all of the branches. + // It's not (/no longer) acceptable to just return some error code without tidying up when we find a candidate + // which wasn't swum + stringSet decisions, infonames, extranames; + P2TPRelation::Range allreports(relatePart->relations()); + for(P2TPRelation::Range::const_iterator report_iter = allreports.begin(); report_iter != allreports.end(); report_iter++) + { + const SwimmingReport *report(report_iter->to()); + const tPoints& turns = report->turningPoints(m_swimRepsStage); + BOOST_FOREACH(const LHCb::TurningPoint& tp, turns) + { + BOOST_FOREACH(const std::string& name, tp.decisions()) + { + decisions.insert(name); // things like Hlt2CharmHadD02HHXDst_hhXDecision, /Event/Phys/StripBlah/Particles + } + BOOST_FOREACH(const std::string& name, tp.infoNames()) + { + infonames.insert(name); // things like trRec_VELO_OFF, trRec_HLT1 + } + BOOST_FOREACH(const std::string &name, tp.extraNames()) + { + extranames.insert(name); // things like 'mipchi2', 'fdchi2' + } + } + } + + if(decisions.empty()) + return Error("Failed to populate decisions"); + + // Now we should have the information to know what all of our branches are called + debug() << "Found decisions:"; + for(stringSet::const_iterator dec_iter = decisions.begin(); dec_iter != decisions.end(); dec_iter++) + debug() << " " << *dec_iter; + debug() << endmsg; + debug() << "Found infonames:"; + for(stringSet::const_iterator inf_iter = infonames.begin(); inf_iter != infonames.end(); inf_iter++) + debug() << " " << *inf_iter; + debug() << endmsg; + debug() << "Found extranames:"; + for(stringSet::const_iterator xtra_iter = extranames.begin(); xtra_iter != extranames.end(); xtra_iter++) + debug() << " " << *xtra_iter; + debug() << endmsg; + + if(P) + { + P2TPRelation::Range range(relatePart->relations(P)); + debug() << "Got range.size() = " << range.size() << endmsg; + // range.size() will be zero if we failed to find any associated TPs -- in this case we don't fill anything and nTP = 0. + // range.size() will be one if everything is simple and there is only one swum candidate 'P' could possibly be associated with + // range.size() will be larger if there are multiple swum candidates and 'P' is part of more than one of them. + LHCb::SwimmingReport *report(range.size() == 1 ? range.begin()->to() : NULL); + if(range.size() == 1 and !report) + return Error("Got NULL LHCb::SwimmingReport"); + + if(range.size() > 1) + { + // There can be multiple B/D candidates swum in one event. This means there will be multiple SwimmingReports. + // A particular B/D descendant track/particle may be part of more than one B/D candidate, and therefore we may + // find more than one related SwimmingReport in the relations table. + // In this case we need to find which SwimmingReport corresponds to the B/D candidate which we are currently + // processing. + // Start searching from 'Phead' downwards, until we find a particle with exactly one SwimmingReport and which + // has 'P' as a descendant. + debug() << "Phead = " << Phead << endmsg; + if(Phead) + debug() << "*Phead = " << *Phead << endmsg; + if(getRelationsFromDescendant(range, relatePart, Phead, P) && range.size() == 1) + { + debug() << "Successfully found relations despite range.size() initially being > 1" << endmsg; + report = range.begin()->to(); + } + else + { + debug() << "About to fail, range.size() == " << range.size() << endmsg; + return Error("Failed to find the correct swimming report"); + } + } + + bool test(true); + const std::string + triggerPrefix("Trigger"), + strippingPrefix("Stripping"); + if( !P->isBasicParticle() ) + { + // Loop over turning points to fill decision names and insert vectors + MapType line_decisions, extra_info; + + // If there is only one decision then the next part would just be duplicating ..._TP_DEC above. + bool doDecisions(decisions.size() > 1); + + // This is just setting up some structures rather than actually filling turning point values + // Even if we didn't swim this event, we still need to fill in the right branches in the tree + // This is why 'decisions' was populated earlier... + for(stringSet::const_iterator dec_iter = decisions.begin(); doDecisions && dec_iter != decisions.end(); dec_iter++) + line_decisions.insert(make_pair(*dec_iter, doubleVec())); + for(stringSet::const_iterator xtra_iter = extranames.begin(); xtra_iter != extranames.end(); xtra_iter++) + extra_info.insert(make_pair(*xtra_iter, doubleVec())); + + if(report) + { + // After all that, we do have swimming reports to associate with this event + const tPoints& turns = report->turningPoints(m_swimRepsStage); + debug() << "Retrieved " << turns.size() << " turning points" << endmsg; + // Loop over turning points to fill vectors + BOOST_FOREACH(const LHCb::TurningPoint& tp, turns) + { + // Fill variables + raw.push_back(tp.raw()); + dec.push_back(tp.dec()); + tau.push_back(tp.tau()); + ip.push_back (tp.ip() ); + + if(doDecisions) + { + // Decisions must not change between turning points + BOOST_FOREACH(MapType::value_type& entry, line_decisions) + { + if (!tp.dec()) + { + entry.second.push_back(false); + } + else + { + entry.second.push_back(tp.decision(entry.first)); + } + } + } + + BOOST_FOREACH(MapType::value_type& entry, extra_info) + { + entry.second.push_back(tp.extra(entry.first)); + } + } + } + + if(raw.size() > maxTurns) + warning() << "Have " << raw.size() << " turning points, which is > maxTurns = " << maxTurns << endmsg; + + // Fill tuple from vectors + test &= tuple->farray( prefix+"_TP_RAW", raw ,prefix+"_nTP",maxTurns ); + test &= tuple->farray( prefix+"_TP_DEC", dec ,prefix+"_nTP",maxTurns ); + test &= tuple->farray( prefix+"_TP_TAU", tau ,prefix+"_nTP",maxTurns ); + test &= tuple->farray( prefix+"_TP_IP" , ip ,prefix+"_nTP",maxTurns ); + + if(doDecisions) + { + debug() << "Populating line_decisions stuff" << endmsg; + BOOST_FOREACH(const MapType::value_type& entry, line_decisions) + { + std::string branch(entry.first); + boost::algorithm::replace_all(branch, "/", "_"); + test &= tuple->farray(prefix + "_TP_DEC_" + branch, entry.second, prefix + "_nTP", maxTurns); + } + } + + debug() << "Populating extra_info..." << endmsg; + BOOST_FOREACH(const MapType::value_type& entry, extra_info) + { + test &= tuple->farray(prefix + "_TP_" + entry.first, entry.second, prefix + "_nTP", maxTurns); + } + } + else if (m_swimRepsStage.size() >= triggerPrefix.size() and m_swimRepsStage.substr(0, triggerPrefix.size()) == triggerPrefix) + { + //The each track part is only for the trigger + // Loop over turning points to fill info names and insert vectors + MapType track_infos; + + debug() << "Doing per-track trigger stuff" << endmsg; + + for(stringSet::const_iterator infoname_iter = infonames.begin(); infoname_iter != infonames.end(); infoname_iter++) + track_infos.insert(make_pair(*infoname_iter, doubleVec())); + + if(report) + { + const tPoints& turns = report->turningPoints(m_swimRepsStage); + debug() << "Got " << turns.size() << " per-track TPs..." << endmsg; + BOOST_FOREACH(const LHCb::TurningPoint& tp, turns) + { + // Fill infos + BOOST_FOREACH(MapType::value_type& entry, track_infos) + { + if (!tp.dec()) { + entry.second.push_back(false); + } else { + entry.second.push_back(tp.participated(entry.first, *P)); + } + } + } + } + + // Fill tuple with infos + BOOST_FOREACH(const MapType::value_type& entry, track_infos) + { + test &= tuple->farray(prefix + "_TP_DEC_" + entry.first, entry.second, + prefix + "_nTP", maxTurns); + } + + debug() << "Finished doing track stuff" << endmsg; + } + } + return StatusCode::SUCCESS; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolSwimmingInfo.h b/first-analysis-steps/DecayTrees/TupleToolSwimmingInfo.h new file mode 100755 index 00000000..be2482ee --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolSwimmingInfo.h @@ -0,0 +1,47 @@ +// $Id: TupleToolSwimmingInfo.h,v 1.4 2010-03-04 14:02:03 xieyu Exp $ +#ifndef VVGRA_TUPLETOOLSWIMMINGINFO_H +#define VVGRA_TUPLETOOLSWIMMINGINFO_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "Relations/Relations.h" +#include "Event/SwimmingReport.h" +#include "Event/TurningPoint.h" +#include + +/** @class TupleToolSwimmingInfo TupleToolSwimmingInfo.h + * + * authors : V.V. Gligorov & R. Aaij + * + * Tool to save swimming information + * + * @data 2011-10-15 + */ +class TupleToolSwimmingInfo : public TupleToolBase, virtual public IParticleTupleTool { +public: + /// Standard constructor + TupleToolSwimmingInfo( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolSwimmingInfo(){}; ///< Destructor + + StatusCode fill( const LHCb::Particle*, const LHCb::Particle* + , const std::string&, Tuples::Tuple& ) override; + +private: + //typedef std::vector stringVec; + //stringVec m_swimRelTableLocs; + std::string m_swimRelTableLoc; + std::string m_swimRepsStage; + //bool m_useExtraLoc; + //std::string m_extraLoc; + typedef LHCb::Relation2D P2TPRelation; + typedef std::vector tPoints; + + bool hasDescendant(const LHCb::Particle *mother, const LHCb::Particle *desc); + bool getRelationsFromDescendant(P2TPRelation::Range &range, const P2TPRelation *relateParts, const LHCb::Particle* Phead, const LHCb::Particle *P); +}; +#endif // VVGRA_TUPLETOOLSWIMMINGINFO_H diff --git a/first-analysis-steps/DecayTrees/TupleToolTISTOS.cpp b/first-analysis-steps/DecayTrees/TupleToolTISTOS.cpp new file mode 100755 index 00000000..cfcbbc4c --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTISTOS.cpp @@ -0,0 +1,301 @@ +// Include files +#include "boost/regex.hpp" + +#include "Event/HltDecReports.h" +#include "Event/HltSelReports.h" +#include "Event/Particle.h" +// kernel +#include "Kernel/IANNSvc.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +// local +#include "TupleToolTISTOS.h" + +//#include + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolTISTOS +// +// 2008-04-09 : V. Gligorov +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolTISTOS ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolTISTOS::TupleToolTISTOS(const std::string &type, + const std::string &name, + const IInterface *parent) + : TupleToolTriggerBase(type, name, parent), + m_Hlt1TriggerTisTosName("Hlt1TriggerTisTos"), + m_Hlt2TriggerTisTosName("Hlt2TriggerTisTos"), + m_L0TriggerTisTosName("L0TriggerTisTos"), m_Hlt1TriggerTisTosTool(NULL), + m_Hlt2TriggerTisTosTool(NULL), m_L0TriggerTisTosTool(NULL), + m_pidList(0) // 1, 22) +{ + declareInterface(this); + declareProperty("Hlt1TriggerTisTosName", m_Hlt1TriggerTisTosName); + declareProperty("Hlt2TriggerTisTosName", m_Hlt2TriggerTisTosName); + declareProperty("L0TriggerTisTosName", m_L0TriggerTisTosName); + declareProperty("PIDList", m_pidList); + declareProperty("TopParticleOnly", m_onlyTop = false); + declareProperty("Hlt1Phys", m_hlt1Phys = "Hlt1(?!ODIN)(?!L0)(?!Lumi)(?!Tell1)(?!MB)(?!NZS)(?!Velo)(?!BeamGas)(?!Incident).*Decision"); + declareProperty("Hlt2Phys", m_hlt2Phys = "Hlt2(?!Forward)(?!DebugEvent)(?!Express)(?!Lumi)(?!Transparent)(?!PassThrough).*Decision"); + declareProperty("TIS", m_TIS = true); + declareProperty("TOS", m_TOS = true); + declareProperty("TUS", m_TUS = false); + declareProperty("TPS", m_TPS = false); +} + +//============================================================================= +// Destructor +//============================================================================= +TupleToolTISTOS::~TupleToolTISTOS() {} + +//============================================================================= + +//========================================================================= +// initialize +//========================================================================= +StatusCode TupleToolTISTOS::initialize() +{ + const StatusCode sc = TupleToolTriggerBase::initialize(); + if (sc.isFailure()) + { + return sc; + } + + m_Hlt1TriggerTisTosTool = tool(m_Hlt1TriggerTisTosName, "Hlt1TriggerTisTos", this); + m_Hlt2TriggerTisTosTool = tool(m_Hlt2TriggerTisTosName, "Hlt2TriggerTisTos", this); + m_L0TriggerTisTosTool = tool(m_L0TriggerTisTosName, "L0TriggerTisTos", this); + + return sc; +} + +void TupleToolTISTOS::fillDecision(ITriggerTisTos *triggerTisTosTool, + const std::string &decision, + const std::string &prefix, + const std::string &decisionName, + Tuples::Tuple &tuple) +{ + triggerTisTosTool->setTriggerInput(decision); + const auto classifiedDec = triggerTisTosTool->tisTosTobTrigger(); + tuple->column(prefix + "_" + decisionName + "_Dec", classifiedDec.decision()); + if (m_TIS) + tuple->column(prefix + "_" + decisionName + "_TIS", classifiedDec.tis()); + if (m_TOS) + tuple->column(prefix + "_" + decisionName + "_TOS", classifiedDec.tos()); + if (m_TUS) + tuple->column(prefix + "_" + decisionName + "_TUS", classifiedDec.tus()); + if (m_TPS) + tuple->column(prefix + "_" + decisionName + "_TPS", classifiedDec.tps()); +} + +//========================================================================= +// Fill +//========================================================================= +StatusCode TupleToolTISTOS::fillBasic(const LHCb::Particle *top, + const LHCb::Particle *P, + const std::string &head, + Tuples::Tuple &tuple) +{ + if (m_onlyTop) + { + if (P != top) + { + return StatusCode::SUCCESS; + } + } + + m_checkPID = false; + + // check if the particle matched any of the PIDs given in list IF there is a list + if (!m_pidList.empty()) + { + for (std::vector::const_iterator it = m_pidList.begin(); + m_pidList.end() != it; ++it) + { + if (!m_checkPID && abs(P->particleID().pid()) == *it) + { + m_checkPID = true; + } + } + if (!m_checkPID) + { + return StatusCode::SUCCESS; + } + } + else + { + m_checkPID = true; + } + + if (msgLevel(MSG::VERBOSE)) + { + verbose() << "Filling TISTOS information for particle with pid " + << P->particleID().pid() << endmsg; + } + const std::string prefix = fullName(head); + + // Since the tools can be configured differently, it is safer to do it for each tool. + m_L0TriggerTisTosTool->setOfflineInput(*P); + m_Hlt1TriggerTisTosTool->setOfflineInput(*P); + m_Hlt2TriggerTisTosTool->setOfflineInput(*P); + + if (m_doL0) + { + fillDecision(m_L0TriggerTisTosTool, "L0.*Decision", prefix, "L0Global", tuple); + } + + if (m_doHlt1) + { + // Fill the decision, tis and tos parametres for the Hlt1 as a whole + fillDecision(m_Hlt1TriggerTisTosTool, "Hlt1.*Decision", prefix, "Hlt1Global", tuple); + // Hlt1Phys + fillDecision(m_Hlt1TriggerTisTosTool, m_hlt1Phys, prefix, "Hlt1Phys", tuple); + } + + if (m_doHlt2) + { + // In Turbo03 Hlt2SelReports are missing. + if (!exist("Hlt2/SelReports", false)) + { + if (!exist("Hlt2/SelReports")) + { + return StatusCode::SUCCESS; + } + } + // Do the Hlt2 + fillDecision(m_Hlt2TriggerTisTosTool, "Hlt2.*Decision", prefix, + "Hlt2Global", tuple); + // Hlt2Phys + fillDecision(m_Hlt2TriggerTisTosTool, m_hlt2Phys, prefix, "Hlt2Phys", + tuple); + } + + return StatusCode::SUCCESS; +} + +StatusCode TupleToolTISTOS::fillVerbose(const LHCb::Particle *top, + const LHCb::Particle *P, + const std::string &head, + Tuples::Tuple &tuple) +{ + if (m_onlyTop) + { + if (P != top) + { + return StatusCode::SUCCESS; + } + } + + if (!m_checkPID) + { + return StatusCode::SUCCESS; + } + const std::string prefix = fullName(head); + + ITriggerTisTos::TisTosTob classifiedDec; + + // I think this is not needed as it has to run through fillBasic + // m_L0TriggerTisTosTool->setOfflineInput(*P); + // m_Hlt1TriggerTisTosTool->setOfflineInput(*P); + // m_Hlt2TriggerTisTosTool->setOfflineInput(*P); + + if (m_verboseL0) + { + for (const auto &s : m_l0) + { + const std::string name = getName(s); + if (msgLevel(MSG::VERBOSE)) + { + verbose() << "Selection " << s << endmsg; + } + fillDecision(m_L0TriggerTisTosTool, s, prefix, name, tuple); + } + } + + if (m_verboseHlt1) + { + for (const auto &s : m_hlt1) + { + const std::string name = getName(s); + if (msgLevel(MSG::VERBOSE)) + { + verbose() << "Selection " << s << endmsg; + } + if (s.find("Hlt1L0") != 0) + { + fillDecision(m_Hlt1TriggerTisTosTool, s, prefix, name, tuple); + } + else + { + // assume that we want to look at L0 rather than Hlt1L0 decisions + const auto classifiedDec = m_Hlt1TriggerTisTosTool->tisTosTobSelection(s); + bool decision = m_Hlt1TriggerTisTosTool->hltSelectionObjectSummaries(s).size() != 0; + tuple->column(prefix + "_" + name + "_Dec", decision); + if (m_TIS) + tuple->column(prefix + "_" + name + "_TIS", classifiedDec.tis()); + if (m_TOS) + tuple->column(prefix + "_" + name + "_TOS", classifiedDec.tos()); + if (m_TUS) + tuple->column(prefix + "_" + name + "_TUS", classifiedDec.tus()); + if (m_TPS) + tuple->column(prefix + "_" + name + "_TPS", classifiedDec.tps()); + } + } + } + + if (m_verboseHlt2) + { + // In Turbo03 Hlt2SelReports are missing. + if (!exist("Hlt2/SelReports", false)) + { + if (!exist("Hlt2/SelReports")) + { + return StatusCode::SUCCESS; + } + } + for (const auto &s : m_hlt2) + { + const std::string name = getName(s); + if (msgLevel(MSG::VERBOSE)) + { + verbose() << "Selection " << s << endmsg; + } + fillDecision(m_Hlt2TriggerTisTosTool, s, prefix, name, tuple); + } + } + return StatusCode::SUCCESS; +} + +std::string TupleToolTISTOS::getName(const std::string &mystr) +{ + std::string name = mystr; + const int found = name.find(".*"); + if (found >= 0) + { + name.replace(found, 2, "__"); + if (msgLevel(MSG::VERBOSE)) + { + verbose() << "From the function... Replaced " << mystr << " with " + << name << endmsg; + } + } + return name; +} + +StatusCode TupleToolTISTOS::fillBasic(Tuples::Tuple &T) +{ + return TupleToolTriggerBase::fillBasic(T); +} + +StatusCode TupleToolTISTOS::fillVerbose(Tuples::Tuple &T) +{ + return TupleToolTriggerBase::fillVerbose(T); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolTISTOS.h b/first-analysis-steps/DecayTrees/TupleToolTISTOS.h new file mode 100755 index 00000000..53a98eb7 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTISTOS.h @@ -0,0 +1,117 @@ +#ifndef TUPLETOOLTISTOS_H +#define TUPLETOOLTISTOS_H 1 + +// Include files +// from Gaudi +#include "TupleToolTriggerBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "Kernel/ITriggerTisTos.h" + + +/** @class TupleToolTISTOS TupleToolTISTOS.h + * + * This is an adaptation of the TISTOS example by Tomasz + * Skwarnicki for the DecayTreeTuple framework + * + * It saves the trigger TIS/TOS decisions for each + * particle for the L0, and each HLT Alley and HltSelection + * + * Saved values for each trigger: + * + * Dec : the trigger decision, 1 is pass, 0 is fail + * TIS : was the event tis? 1 is yes, 0 is no. + * TOS : was the event tos? 1 is yes, 0 is no. + * + * If verbose is true the tool needs somehow to find a list of triggers to fill. + * In this case it uses the base class TupleToolTriggerBase to sort everything out. + * + * If \b VerboseL0 = true + * L0Decision_xxx : LHCb::L0DUReport->channelDecisionByName(xxx) + * + * If \b VerboseHlt1 = true + * Hlt1_xxx_Decision : filled + * + * If \b VerboseHlt2 = true + * Hlt2_xxx_Decision : filled + * + * Verbose flag is a shortcut to turn all verbosity on. + * + * @author V. Gligorov + * @date 2008-04-09 + */ + +class TupleToolTISTOS : public TupleToolTriggerBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolTISTOS( const std::string& type, + const std::string& name, + const IInterface* parent); + + ~TupleToolTISTOS( ); ///< Destructor + + StatusCode initialize() override; + +protected: + + /// to make it possible to replace standard TisTos tools. + std::string m_Hlt1TriggerTisTosName; + std::string m_Hlt2TriggerTisTosName; + std::string m_L0TriggerTisTosName; + +private: + + ITriggerTisTos* m_Hlt1TriggerTisTosTool; + ITriggerTisTos* m_Hlt2TriggerTisTosTool; + ITriggerTisTos* m_L0TriggerTisTosTool; + +private: + + StatusCode fillBasic( const LHCb::Particle* top + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) override; + + StatusCode fillVerbose( const LHCb::Particle* top + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) override; + + void fillDecision( ITriggerTisTos* triggerTisTosTool + , const std::string& decision + , const std::string& prefix + , const std::string& decisionName + , Tuples::Tuple &tuple); + + std::string getName(const std::string& mystr); + +private: + + StatusCode fillBasic( Tuples::Tuple& T ) override; + + StatusCode fillVerbose( Tuples::Tuple& T ) override; + +private: + + // copied from TisTosTobbing/TisTos/TisTos.h to avoid dependence + enum HitType {kVelo=0,kAllHits=kVelo,kOTIT,kTT,kMuon,kEcal,kHcal,nHitTypes,kNotUsed=nHitTypes}; + + std::vector m_pidList; + bool m_checkPID = false; + std::string m_hlt1Phys; + std::string m_hlt2Phys; + + // must be true to fill this info + bool m_TIS; + bool m_TOS; + bool m_TUS; + bool m_TPS; + + // set to true to fill only top particle in decay descriptor + bool m_onlyTop; +}; + +#endif // TUPLETOOLTISTOS_H diff --git a/first-analysis-steps/DecayTrees/TupleToolTagging.cpp b/first-analysis-steps/DecayTrees/TupleToolTagging.cpp new file mode 100755 index 00000000..a366f85c --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTagging.cpp @@ -0,0 +1,452 @@ +// $Id: TupleToolTagging.cpp,v 1.9 2010-01-27 11:43:50 rlambert Exp $ +// Include files + +// from Gaudi +#include "GaudiKernel/SmartIF.h" + +#include +#include +#include +#include + +// local +#include "TupleToolTagging.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" +#include "Event/Vertex.h" +#include "Event/RecVertex.h" +#include +#include + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : EventInfoTupleTool +// +// 2007-11-07 : Jeremie Borel +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolTagging ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolTagging::TupleToolTagging( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_dva(0) + , m_dist(0) + , m_fitter(0) + , m_tagging(0) + , m_tagger_map() + , m_tagger_rmap() + , m_activeTaggers(0) +{ + declareInterface(this); + + //there is a long list of taggers defined in the enum + m_tagger_map[(int)Tagger::none]="none"; + m_tagger_map[(int)Tagger::unknown]="unknown"; + m_tagger_map[(int)Tagger::OS_Muon]="OS_Muon"; + m_tagger_map[(int)Tagger::OS_Electron]="OS_Electron"; + m_tagger_map[(int)Tagger::OS_Kaon]="OS_Kaon"; + m_tagger_map[(int)Tagger::SS_Kaon]="SS_Kaon"; + m_tagger_map[(int)Tagger::SS_Pion]="SS_Pion"; + m_tagger_map[(int)Tagger::SS_PionBDT]="SS_PionBDT"; + m_tagger_map[(int)Tagger::VtxCharge]="VtxCharge"; + m_tagger_map[(int)Tagger::Topology]="Topology"; + m_tagger_map[(int)Tagger::jetCharge]="jetCharge"; + m_tagger_map[(int)Tagger::OS_nnetKaon]="OS_nnetKaon"; + m_tagger_map[(int)Tagger::SS_nnetKaon]="SS_nnetKaon"; + m_tagger_map[(int)Tagger::SS_Proton]="SS_Proton"; + m_tagger_map[(int)Tagger::OS_Charm]="OS_Charm"; + + for(std::map::const_iterator t=m_tagger_map.begin(); + t!=m_tagger_map.end(); t++) + { + m_tagger_rmap[t->second]=t->first; + } + + //but only these ones really need to be filled, and only these are really used + m_activeTaggers.push_back("OS_Muon"); + m_activeTaggers.push_back("OS_Electron"); + m_activeTaggers.push_back("OS_Kaon"); + m_activeTaggers.push_back("SS_Kaon"); + m_activeTaggers.push_back("SS_Pion"); + m_activeTaggers.push_back("SS_PionBDT"); + m_activeTaggers.push_back("VtxCharge"); + m_activeTaggers.push_back("OS_nnetKaon"); + m_activeTaggers.push_back("SS_nnetKaon"); + m_activeTaggers.push_back("SS_Proton"); + m_activeTaggers.push_back("OS_Charm"); + + declareProperty("TaggingToolName", m_toolName = "", + "The Tagging Tool, if empty string, the tool will be retrieved from the parent DVAlg"); + declareProperty("StoreTaggersInfo", m_extendedTagging = false); + + declareProperty("ActiveTaggers", m_activeTaggers ); + declareProperty("useFTonDST", m_useFTonDST = false ); + + declareProperty("TagBeautyOnly", m_tagBeautyOnly = true); + +}//============================================================================= + +StatusCode TupleToolTagging::initialize() { + if( ! TupleToolBase::initialize() ) return StatusCode::FAILURE; + if( msgLevel( MSG::DEBUG ) ){ + if( m_useFTonDST ) debug() << " Going to write Tagging informations written on DST " << endmsg; + else debug() << " Going to rerun FT !!!! (Ignore informations written on DST) " << endmsg; + } + + m_dva = Gaudi::Utils::getIDVAlgorithm ( contextSvc(), this ) ; + //if (m_dva==NULL) return Error("Couldn't get parent DVAlgorithm", + // StatusCode::FAILURE); + m_dist = m_dva->distanceCalculator(); + + //m_fitter = tool("OfflineVertexFitter"); + m_fitter = tool("LoKi::VertexFitter"); + + //if null string, get parent DVA, else use own private tool + if(m_toolName == "" && m_dva!=NULL) m_tagging = m_dva->flavourTagging(); + else if (m_toolName != "") m_tagging = tool( m_toolName, this ); + + if( !m_tagging && m_dva==NULL ) + { + return Error("Unable to retrieve the IBTaggingTool tool, unable to retrieve parent DVAlg",StatusCode::FAILURE); + } + if( !m_tagging ) + { + return Error("Unable to retrieve the IBTaggingTool tool",StatusCode::FAILURE); + } + + if( m_tagBeautyOnly ) debug() << "Running Flavour Tagging only on b-hadron particles" << endmsg; + else debug() << "Running Flavour Tagging on all particles (not only b-hadrons)" << endmsg; + + return StatusCode::SUCCESS; +} + +//============================================================================= +VerboseData TupleToolTagging::getVerboseData(const LHCb::Particle *particle, const LHCb::Particle *B) { + const ProtoParticle *proto = particle->proto(); + VerboseData data; + + data.id = particle->particleID().pid(); + data.p = particle->momentum().P(); + data.px = particle->momentum().Px(); + data.py = particle->momentum().Py(); + data.pz = particle->momentum().Pz(); + data.pt = particle->momentum().Pt(); + data.theta = particle->momentum().theta(); + data.phi = particle->momentum().phi(); + if(proto!=NULL) + { + + data.pid_e = proto->info(LHCb::ProtoParticle::CombDLLe, -1000); + data.pid_mu = proto->info(LHCb::ProtoParticle::CombDLLmu, -1000); + data.pid_k = proto->info(LHCb::ProtoParticle::CombDLLk, -1000); + data.pid_p = proto->info(LHCb::ProtoParticle::CombDLLp, -1000); + } + else + { + data.pid_e = -999; + data.pid_mu = -999; + data.pid_k = -999; + data.pid_p = -999; + } + // ip wrt the B primary vertex + const VertexBase *primVtxB = m_dva->bestVertex(B); + StatusCode test = StatusCode::FAILURE; + if ( primVtxB!=NULL) test = m_dist->distance(particle, primVtxB, data.ip, data.chi2); + if ( !test ) + { + data.ip = -1; + data.chi2 = -1; + } + + // ip wrt the B decay vertex + const VertexBase *decayVtxB = B->endVertex(); + test = StatusCode::FAILURE; + + if ( decayVtxB!=NULL) test = m_dist->distance (particle, decayVtxB, data.bip, data.bchi2); + if ( !test ) + { + data.bip = -1; + data.bchi2 = -1; + } + + + + + Vertex vtx; + test = m_fitter->fit(vtx,*B,*particle); + if( !test ) data.bp_chi2 = -1.; + else data.bp_chi2 = vtx.chi2()/(float)vtx.nDoF(); + + return data; +} + + +StatusCode TupleToolTagging::fill( const Particle* mother + , const Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix=fullName(head); + + Assert( P && mother && m_dva && m_tagging, + "Should not happen, you are inside TupleToolTagging.cpp" ); + + std::string loc = objectLocation( P->parent() ); + + // nothing to tag on something which is not a B (unless explicitly required) + if( m_tagBeautyOnly ) + { + if( !P->particleID().hasBottom()) return StatusCode::SUCCESS; + } + + if( msgLevel( MSG::DEBUG ) ){ + debug() << " Going to Save Tagging information for candidate " + << endmsg; + } + + FlavourTag theTag; + FlavourTags* tags = NULL; + bool check = false; + + StatusCode sc=StatusCode::SUCCESS; + + boost::replace_all( loc, "/Particles", "/FlavourTags" ); + if( m_useFTonDST ) { + if( exist < LHCb::FlavourTags > (loc,IgnoreRootInTES)) + tags = get< LHCb::FlavourTags > (loc,IgnoreRootInTES ); + } + + if (tags) { + for(FlavourTags::const_iterator it = tags->begin(); it != tags->end(); ++it) { + if( P != (**it).taggedB()) continue; + theTag = **it; + check = true; + } + if (!check) sc = StatusCode::FAILURE; + } else { + const VertexBase* v = m_dva->bestVertex( mother ); + const RecVertex* vtx = dynamic_cast(v); + if( !vtx ){ + sc = m_tagging->tag( theTag, P ); + } else { + sc = m_tagging->tag( theTag, P, vtx ); + } + } + // try to find unphysical defaults + int dec = 0; + double omega = 0.5; + int decOS = 0; + double omegaOS = 0.5; + + if( sc ){ + dec = theTag.decision(); + omega = theTag.omega(); // predicted wrong tag fraction. + decOS = theTag.decisionOS(); + omegaOS = theTag.omegaOS(); // predicted wrong tag fraction. + } else { + Warning("The tagging algorithm failed"); + } + + bool test = true; + test &= tuple->column( prefix+"_TAGDECISION" , dec ); + test &= tuple->column( prefix+"_TAGOMEGA" , omega ); + test &= tuple->column( prefix+"_TAGDECISION_OS" , decOS ); + test &= tuple->column( prefix+"_TAGOMEGA_OS" , omegaOS ); + + int taggers_code = 0; + // intialize tagger by tagger W : + + std::vector taggers = theTag.taggers(); + + for(size_t i=0; icolumn( prefix+"_TAGGER" , taggers_code); + + if(isVerbose()) + { + // Initialize all columns to default values + for(size_t i=0; icolumn( prefix+"_"+active+"_DEC", (short int)0 ); + test &= tuple->column( prefix+"_"+active+"_PROB", (float)0.5 ); + + if(m_extendedTagging){ + if( true ) { + std::vector id, p, px, py, pz, pt, theta, phi; + std::vector pid_e, pid_mu, pid_k, pid_p; + std::vector ip, chi2, bip, bchi2, bp_chi2; + + const std::string num_name = prefix+"_"+active+"_PARTICLES_NUM"; + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_ID", id.begin(), id.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_P", p.begin(), p.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PX", px.begin(), px.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PY", py.begin(), py.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PZ", pz.begin(), pz.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PT", pt.begin(), pt.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_THETA", theta.begin(), theta.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PHI", phi.begin(), phi.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PIDe", pid_e.begin(), pid_e.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PIDmu", pid_mu.begin(), pid_mu.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PIDk", pid_k.begin(), pid_k.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PIDp", pid_p.begin(), pid_p.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_IP_OWNPV", ip.begin(), ip.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_IPCHI2_OWNPV", chi2.begin(), chi2.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_IP_BVertex", bip.begin(), bip.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_IPCHI2_BVertex", bchi2.begin(), bchi2.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+active+"_PARTICLES_CHI2_BpVertex", bp_chi2.begin(), bp_chi2.end(), num_name, 20 ); + } + } + + } + + for(size_t i=0; icolumn( prefix+"_"+name+"_DEC", tagger.decision() ); + test &= tuple->column( prefix+"_"+name+"_PROB", tagger.omega() ); + + if(m_extendedTagging){ + // Save interesting tagging data + std::vector id, p, px, py, pz, pt, theta, phi; + std::vector pid_e, pid_mu, pid_k, pid_p; + std::vector ip, chi2, bip, bchi2, bp_chi2; + + SmartRefVector parts = tagger.taggerParts(); + for(SmartRefVector::const_iterator it=parts.begin(); + it != parts.end(); it++) { + + VerboseData data = getVerboseData(*it, P); + + id.push_back(data.id); + p.push_back(data.p); + px.push_back(data.px); + py.push_back(data.py); + pz.push_back(data.pz); + pt.push_back(data.pt); + theta.push_back(data.theta); + phi.push_back(data.phi); + pid_e.push_back(data.pid_e); + pid_mu.push_back(data.pid_mu); + pid_k.push_back(data.pid_k); + pid_p.push_back(data.pid_p); + ip.push_back(data.ip); + chi2.push_back(data.chi2); + bip.push_back(data.bip); + bchi2.push_back(data.bchi2); + bp_chi2.push_back(data.bp_chi2); + } + + const std::string num_name = prefix+"_"+name+"_PARTICLES_NUM"; + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_ID", id.begin(), id.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_P", p.begin(), p.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PX", px.begin(), px.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PY", py.begin(), py.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PZ", pz.begin(), pz.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PT", pt.begin(), pt.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_THETA", theta.begin(), theta.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PHI", phi.begin(), phi.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PIDe", pid_e.begin(), pid_e.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PIDmu", pid_mu.begin(), pid_mu.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PIDk", pid_k.begin(), pid_k.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PIDp", pid_p.begin(), pid_p.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_IP_OWNPV", ip.begin(), ip.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_IPCHI2_OWNPV", chi2.begin(), chi2.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_IP_BVertex", bip.begin(), bip.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_IPCHI2_BVertex", bchi2.begin(), bchi2.end(), num_name, 20 ); + test &= tuple->farray( prefix+"_"+name+"_PARTICLES_CHI2_BpVertex", bp_chi2.begin(), bp_chi2.end(), num_name, 20 ); + } + } + } + } + + + if( msgLevel( MSG::DEBUG ) ){ + debug() << "Tagging summary: decision: " << dec + << ", omega=" << omega << endmsg; + } + + return StatusCode(test); + +} + +// CRJ : Not used +// const DVAlgorithm* TupleToolTagging::getParent() const { + +// // look for desktop +// const IAlgTool* atool = this ; +// // get last tool in chain +// debug() << "Looking for parents of " << atool->name() << endmsg ; +// while ( NULL!=dynamic_cast(atool->parent())){ +// atool = dynamic_cast(atool->parent()); +// debug() << "... tool is owned by tool " << atool->name() << endmsg ; +// } +// // check it's not the ToolSvc +// const IToolSvc* tsvc = dynamic_cast( atool->parent() ); +// if ( NULL!=tsvc ){ +// warning() << "Parent of " << atool->name() << " is the ToolSvc." << endmsg ; +// return NULL; +// } + +// // check if it is an algorithm +// const DVAlgorithm* dvalgo = dynamic_cast( atool->parent() ); +// if ( NULL==dvalgo ){ +// warning() << "Parent of " << atool->name() << " is not a DVAlgorithm." << endmsg ; +// return NULL; +// } + +// debug() << atool->name() << " is owned by " << dvalgo->name() << endmsg ; +// return dvalgo; +// } + +// std::string TupleToolTagging::getCatName( const LHCb::Tagger& tag ) const{ +// std::string tts; +// switch ( tag.type() ) { +// case Tagger::none : tts="none"; break; +// case Tagger::unknown : tts="unknown"; break; +// case Tagger::OS_Muon : tts="OS_Muon"; break; +// case Tagger::OS_Electron : tts="OS_Electron"; break; +// case Tagger::OS_Kaon : tts="OS_Kaon"; break; +// case Tagger::SS_Kaon : tts="SS_Kaon"; break; +// case Tagger::SS_Pion : tts="SS_Pion"; break; +// case Tagger::jetCharge : tts="jetCharge"; break; +// case Tagger::OS_jetCharge: tts="OS_jetCharge";break; +// case Tagger::SS_jetCharge: tts="SS_jetCharge";break; +// case Tagger::VtxCharge : tts="VtxCharge"; break; +// case Tagger::Topology : tts="Topology"; break; +// default: tts="Unknown tag category"; +// } +// return tts; +// } + diff --git a/first-analysis-steps/DecayTrees/TupleToolTagging.h b/first-analysis-steps/DecayTrees/TupleToolTagging.h new file mode 100755 index 00000000..d9c093a9 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTagging.h @@ -0,0 +1,106 @@ +#ifndef JBOREL_TUPLETOOLTAGGING_H +#define JBOREL_TUPLETOOLTAGGING_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "Kernel/IVertexFit.h" + +struct IDVAlgorithm; +struct IDistanceCalculator; +struct IBTaggingTool; +struct IVertexFit; + +struct VerboseData { + double id, p, px, py, pz, pt, theta, phi; + double pid_e, pid_mu, pid_k, pid_p; + double ip, chi2, bip, bchi2, bp_chi2 ; + VerboseData(): id(0), p(0), px(0), pz(0), pt(0), theta(0), phi(0), + pid_e(0), pid_mu(0), pid_k(0), pid_p(0), + ip(0), chi2(0), bip(0), bchi2(0), bp_chi2(0) {} +}; + +/** @class TupleToolTagging TupleToolTagging.h jborel/TupleToolTagging.h + * + * \brief Fill the tagging information in the tuple. + * + * There are many taggers for whom there is an enum, and maybe even code, + * but are not active at the moment. + * The list of active taggers can be defined here with the property ActiveTaggers + * + * Typically however these are + * - ("OS_Muon"); + * - ("OS_Electron"); + * - ("OS_Kaon"); + * - ("SS_Kaon"); + * - ("SS_Pion"); + * - ("VtxCharge"); + * - ("OS_nnetKaon"); + * - ("SS_nnetKaon"); + * - ("SS_Proton"); + * - ("OS_Charm"); + * + * Since only one of SS_Kaon and SS_Pion will fire at any on time, these typical + * cases are packed into a single variable: head+_TAGGER + * + * @code + * if(tdec) switch ( taggers[i].type() ) { + * case Tagger::OS_Charm : taggers_code +=1000000000 *(tdec+2); break; + * case Tagger::SS_Proton : taggers_code += 100000000 *(tdec+2); break; + * case Tagger::OS_nnetKaon : taggers_code += 10000000 *(tdec+2); break; + * case Tagger::SS_nnetKaon : taggers_code += 1000000 *(tdec+2); break; + * case Tagger::OS_Muon : taggers_code += 100000 *(tdec+2); break; + * case Tagger::OS_Electron : taggers_code += 10000 *(tdec+2); break; + * case Tagger::OS_Kaon : taggers_code += 1000 *(tdec+2); break; + * case Tagger::SS_Kaon : taggers_code += 100 *(tdec+2); break; + * case Tagger::SS_Pion : taggers_code += 10 *(tdec+2); break; + * case Tagger::VtxCharge : taggers_code += 1 *(tdec+2); break; + * + * } + * @endcode + * + * If the list of active taggers is different, you will need to switch to Verbose mode + * + * if Verbose is set the probability and decision for each tagger will be filled. + * - head+tagger+DEC + * - head+tagger+PROB + * + * @see BTaggingTool + * @see Tagger + * + * @author Jeremie Borel + * @date 2007-11-07 + */ +class TupleToolTagging : public TupleToolBase, virtual public IParticleTupleTool { +public: + /// Standard constructor + TupleToolTagging( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolTagging(){}; ///< Destructor + + StatusCode initialize() override; + + StatusCode fill( const LHCb::Particle*, const LHCb::Particle* + , const std::string&, Tuples::Tuple& ) override; + + +private: + + std::string m_inputLocation, m_toolName; + IDVAlgorithm* m_dva; + const IDistanceCalculator* m_dist; + IVertexFit *m_fitter; + IBTaggingTool* m_tagging; + + std::map m_tagger_map; /// m_tagger_rmap;/// m_activeTaggers; ///(this); + declareProperty( "StoreFirstMeasurement", m_storeFirstMeasurement = false, "Store first measurement" ); +} + +//============================================================================= + +StatusCode TupleToolTrackInfo::fill( const LHCb::Particle* + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix = fullName(head); + + bool test = true; + if ( !P ) return StatusCode::FAILURE; + + //first just return if the particle isn't supposed to have a track + if ( !P->isBasicParticle() ) return StatusCode::SUCCESS; + + const LHCb::ProtoParticle* protop = P->proto(); + if (!protop) return StatusCode::SUCCESS; + + const LHCb::Track* track = protop->track(); + if (!track) return StatusCode::SUCCESS; + + if (msgLevel(MSG::DEBUG)) + debug() << prefix << " " << track->type() + << " "+prefix+"_TRACK_CHI2 " << track->chi2() << endmsg ; + if (msgLevel(MSG::VERBOSE)) verbose() << *track << endmsg ; + test &= tuple->column( prefix+"_TRACK_Type", track->type() ); + test &= tuple->column( prefix+"_TRACK_Key", track->key() ); + + if(isVerbose()) test &= tuple->column( prefix+"_TRACK_CHI2", track->chi2() ); + int nDoF = track->nDoF(); + if(isVerbose()) test &= tuple->column( prefix+"_TRACK_NDOF", nDoF ); + if (nDoF) + { + test &= tuple->column( prefix+"_TRACK_CHI2NDOF", track->chi2()/nDoF ); + test &= tuple->column( prefix+"_TRACK_PCHI2", track->probChi2() ); + if(isVerbose()) + { + if ( track->info(LHCb::Track::AdditionalInfo::FitVeloNDoF,0) > 0 ) + { + test &= tuple->column( prefix+"_TRACK_VeloCHI2NDOF", + track->info(LHCb::Track::AdditionalInfo::FitVeloChi2, -1.)/ + track->info(LHCb::Track::AdditionalInfo::FitVeloNDoF, 0) ); + } + else test &= tuple->column( prefix+"_TRACK_VeloCHI2NDOF",-1.); + if ( track->info(LHCb::Track::AdditionalInfo::FitTNDoF,0) > 0 ) + { + test &= tuple->column( prefix+"_TRACK_TCHI2NDOF", + track->info(LHCb::Track::AdditionalInfo::FitTChi2, -1.)/ + track->info(LHCb::Track::AdditionalInfo::FitTNDoF, 0) ); + } + else test &= tuple->column( prefix+"_TRACK_TCHI2NDOF",-1.); + } + + } + else + { + if (msgLevel(MSG::VERBOSE)) verbose() << "No NDOF" << endmsg ; + test &= tuple->column( prefix+"_TRACK_PCHI2",-1.); + test &= tuple->column( prefix+"_TRACK_CHI2NDOF", -1 ); + if(isVerbose()) test &= tuple->column( prefix+"_TRACK_VeloCHI2NDOF",-1.); + if(isVerbose()) test &= tuple->column( prefix+"_TRACK_TCHI2NDOF",-1.); + } + if ( isVerbose() ) + { + // -- Run I+II + int nVeloR = 0; + int nVeloPhi = 0; + int nVelo = 0; + int nVeloPileUp = 0; + int nTT = 0; + int nIT = 0; + int nOT = 0; + // -- Run III + int nVP = 0; + int nUT = 0; + int nFT = 0; + + //-- hopefully unique double constructed from multiplying all hit IDs + double veloUTID = 1.; + double ttUTID = 1.; + double itUTID = 1.; + double otUTID = 1.; + double vpUTID = 1.; + double utUTID = 1.; + double ftUTID = 1.; + + for ( LHCb::LHCbID id : track->lhcbIDs() ){ + if ( id.isVelo() ){ + veloUTID *= (double(id.veloID().channelID())/1000000.); + ++nVelo; + if( id.isVeloR() ) ++nVeloR; + if( id.isVeloPhi() ) ++nVeloPhi; + if( id.isVeloPileUp() ) ++nVeloPileUp; + }else if( id.isTT() ){ + ttUTID *= (double(id.stID().channelID())/10000000.); + ++nTT; + }else if( id.isIT() ){ + itUTID *= (double(id.stID().channelID())/20000000.); + ++nIT; + }else if( id.isOT() ){ + otUTID *= (double(id.otID().channelID())/50000000.); + ++nOT; + // -- numbers to divide by for upgrade are 'untuned' + }else if( id.isVP() ){ + vpUTID *= (double(id.vpID().channelID())/1000000.); + ++nVP; + }else if( id.isUT() ){ + utUTID *= (double(id.stID().channelID())/10000000.); + ++nUT; + }else if( id.isFT() ){ + ftUTID *= (double(id.ftID().channelID())/100000000.); + ++nFT; + } + } + // -- unique ids + test &= tuple->column( prefix+"_TRACK_VELO_UTID", veloUTID ); + test &= tuple->column( prefix+"_TRACK_TT_UTID", ttUTID ); + test &= tuple->column( prefix+"_TRACK_IT_UTID", itUTID ); + test &= tuple->column( prefix+"_TRACK_OT_UTID", otUTID ); + test &= tuple->column( prefix+"_TRACK_VP_UTID", vpUTID ); + test &= tuple->column( prefix+"_TRACK_UT_UTID", utUTID ); + test &= tuple->column( prefix+"_TRACK_FT_UTID", ftUTID ); + + // -- nHits + test &= tuple->column( prefix+"_TRACK_nVeloHits", nVelo ); + test &= tuple->column( prefix+"_TRACK_nVeloRHits", nVeloR ); + test &= tuple->column( prefix+"_TRACK_nVeloPhiHits", nVeloPhi ); + test &= tuple->column( prefix+"_TRACK_nVeloPileUpHits", nVeloPileUp ); + test &= tuple->column( prefix+"_TRACK_nTTHits", nTT ); + test &= tuple->column( prefix+"_TRACK_nITHits", nIT ); + test &= tuple->column( prefix+"_TRACK_nOTHits", nOT ); + test &= tuple->column( prefix+"_TRACK_nVPHits", nVP ); + test &= tuple->column( prefix+"_TRACK_nUTHits", nUT ); + test &= tuple->column( prefix+"_TRACK_nFTHits", nFT ); + + // -- history of the track (= which algorithm the track was made with) + test &= tuple->column( prefix+"_TRACK_History", track->history() ); + + } + + const LHCb::State* uState = track->stateAt( LHCb::State::FirstMeasurement ); + if ( m_storeFirstMeasurement || isVerbose()) { + test &= tuple->column( prefix+"_TRACK_FirstMeasurementX" , uState ? uState->x() : -999 ); + test &= tuple->column( prefix+"_TRACK_FirstMeasurementY" , uState ? uState->y() : -999 ); + test &= tuple->column( prefix+"_TRACK_FirstMeasurementZ" , uState ? uState->z() : -999 ); + test &= tuple->column( prefix+"_TRACK_FirstMeasurementQOverP", uState ? uState->qOverP() : -999 ); + test &= tuple->column( prefix+"_TRACK_FirstMeasurementTx" , uState ? uState->tx() : -999 ); + test &= tuple->column( prefix+"_TRACK_FirstMeasurementTy" , uState ? uState->ty() : -999 ); + } + + + test &= tuple->column( prefix+"_TRACK_MatchCHI2", + track->info(LHCb::Track::AdditionalInfo::FitMatchChi2,-1) ); + test &= tuple->column( prefix+"_TRACK_GhostProb", + track->ghostProbability() ); + test &= tuple->column( prefix+"_TRACK_CloneDist", + track->info(LHCb::Track::AdditionalInfo::CloneDist,-1) ); + test &= tuple->column( prefix+"_TRACK_Likelihood", + track->likelihood() ); + + return StatusCode(test); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolTrackInfo.h b/first-analysis-steps/DecayTrees/TupleToolTrackInfo.h new file mode 100755 index 00000000..1087f0d0 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTrackInfo.h @@ -0,0 +1,71 @@ +#ifndef JBOREL_TUPLETOOLTRACKINFO_H +#define JBOREL_TUPLETOOLTRACKINFO_H 1 + +// Include files +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface + +/** @class TupleToolTrackInfo TupleToolTrackInfo.h + * + * \brief Fill track information for DecayTreeTuple + * + * - X_TRACK_CHI2NDOF : track chi2/ndof + * - X_TRACK_TYPE : track type + * - X_TRACK_PCHI2 : track Chi2 probability + * - X_TRACK_GhostProb : Ghost probability (run NeuralNetTmva to fill it) + * - X_TRACK_CloneDist : Only available for 2009 data + * + * If Verbose: + * + * - X_TRACK_CHI2 : track chi2 + * - X_TRACK_NDOF : track ndof + * - X_TRACK_VeloCHI2NDOF : Track fit velo chi2/nDoF + * - X_TRACK_TCHI2NDOF : Track fit T chi2/nDoF + * - X_TRACK_VELO_UTID : hopefully unique double constructed from multiplying all Velo hit IDs + * - X_TRACK_TT_UTID : hopefully unique double constructed from multiplying all TT hit IDs + * - X_TRACK_IT_UTID : hopefully unique double constructed from multiplying all IT hit IDs + * - X_TRACK_OT_UTID : hopefully unique double constructed from multiplying all OT hit IDs + * - X_TRACK_VP_UTID : hopefully unique double constructed from multiplying all VP hit IDs + * - X_TRACK_UT_UTID : hopefully unique double constructed from multiplying all UT hit IDs + * - X_TRACK_FT_UTID : hopefully unique double constructed from multiplying all FT hit IDs + * - X_TRACK_nVeloHits : Number of Velo hits on the track + * - X_TRACK_nVeloRHits : Number of Velo R hits on the track + * - X_TRACK_nVeloPhiHits : Number of Velo phi hits on the track + * - X_TRACK_nVeloPileUpHits : Number of Velo pile-up hits on the track + * - X_TRACK_nTTHits : Number of TT hits on the track + * - X_TRACK_nITHits : Number of IT hits on the track + * - X_TRACK_nOTHits : Number of OT hits on the track + * - X_TRACK_nVPHits : Number of VP hits on the track + * - X_TRACK_nUTHits : Number of UT hits on the track + * - X_TRACK_nFTHits : Number of FT hits on the track + * - X_TRACK_FirstMeasurementX: x position of state at 'FirstMeasurement' + * - X_TRACK_FirstMeasurementY: y position of state at 'FirstMeasurement' + * - X_TRACK_FirstMeasurementZ: z position of state at 'FirstMeasurement' + * - X_TRACK_History: Algorithm which the track was made with + * - X_TRACK_qOverp : q/p of state at 'FirstMeasurement' + * - X_TRACK_Tx : x slope of state at 'FirstMeasurement' + * - X_TRACK_Ty : y slope of state at 'FirstMeasurement' + * + * \sa DecayTreeTuple + * + * @author Stephane Poss + * @date 2008-03-17 + */ +class TupleToolTrackInfo : public TupleToolBase, virtual public IParticleTupleTool { +public: + /// Standard constructor + TupleToolTrackInfo( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolTrackInfo(){}; ///< Destructor + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; +private: + bool m_storeFirstMeasurement ; ///< If true stores first measurement +}; + +#endif diff --git a/first-analysis-steps/DecayTrees/TupleToolTrackIsolation.cpp b/first-analysis-steps/DecayTrees/TupleToolTrackIsolation.cpp new file mode 100644 index 00000000..b567634b --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTrackIsolation.cpp @@ -0,0 +1,311 @@ +#include "Event/Particle.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "GaudiKernel/PhysicalConstants.h" + +// local +#include "TupleToolTrackIsolation.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolTrackIsolation +// +// 2009-05-06 : Michel De Cian +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( TupleToolTrackIsolation ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolTrackIsolation::TupleToolTrackIsolation( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) +{ + declareInterface(this); + declareProperty( "MinConeAngle", m_minConeAngle = 0.5, + "Set the minimal deltaR of the cone (default = 0.5), in radians"); + declareProperty( "MaxConeAngle", m_maxConeAngle = 1.0, + "Set the maximum deltaR of the cone (default = 1.0), in radians"); + declareProperty( "StepSize", m_stepSize = 0.1, + "Set the step of deltaR between two iterations (default = 0.1), in radians"); + declareProperty( "TrackType", m_trackType = 3, + "Set the type of tracks which are considered inside the cone (default = 3)"); + declareProperty( "FillAsymmetry", m_fillAsymmetry = false, + "Flag to fill the asymmetry variables (default = false)"); + declareProperty( "FillDeltaAngles", m_fillDeltaAngles = false, + "Flag to fill the delta angle variables (default = false)"); +} + +//============================================================================= +// Destructor +//============================================================================= +TupleToolTrackIsolation::~TupleToolTrackIsolation() {} + +//============================================================================= +// Initialization +//============================================================================= +StatusCode TupleToolTrackIsolation::initialize() +{ + StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + if ( m_minConeAngle > m_maxConeAngle ) + { + return Error( "Max conesize smaller than min conesize." ); + } + + if ( isVerbose() ) { m_fillAsymmetry = m_fillDeltaAngles = true; } + + return sc; +} + +//============================================================================= +// Fill the tuple +//============================================================================= +StatusCode TupleToolTrackIsolation::fill( const LHCb::Particle *top, + const LHCb::Particle *part, + const std::string &head, + Tuples::Tuple & tuple ) +{ + bool test = true; + + if ( part ) + { + + const std::string prefix = fullName(head); + if ( msgLevel(MSG::DEBUG) ) debug() << "==> Fill" << endmsg; + + // -- The vector m_decayParticles contains all the particles that belong to the given decay + // -- according to the decay descriptor. + + // -- Clear the vector with the particles in the specific decay + m_decayParticles.clear(); + + // -- Add the mother (prefix of the decay chain) to the vector + if ( msgLevel(MSG::DEBUG) ) debug() << "Filling particle with ID " << top->particleID().pid() << endmsg; + m_decayParticles.push_back( top ); + + // -- Save all particles that belong to the given decay in the vector m_decayParticles + saveDecayParticles( top ); + + // -- Get all tracks in the event + LHCb::Tracks* tracks = get(LHCb::TrackLocation::Default); + if ( tracks->empty() ) + { + return Warning( "Could not retrieve tracks. Skipping" ); + } + + if ( msgLevel(MSG::VERBOSE) ) verbose() << "Start looping through different conesizes" << endmsg; + + // -- Loop over the different conesizes + double coneSizeCounter = m_minConeAngle; + while ( coneSizeCounter <= m_maxConeAngle ) + { + + if ( msgLevel(MSG::VERBOSE) ) verbose() << "Filling variables with conesize " << coneSizeCounter << endmsg; + + // -- Retrieve momentum information of tracks in the cone + std::pair, int> myPair = ConeP(part, tracks, coneSizeCounter); + const std::vector & myVector = myPair.first; + + const double conePx = myVector[0]; + const double conePy = myVector[1]; + const double conePz = myVector[2]; + + const double conePx2 = conePx*conePx; + const double conePy2 = conePy*conePy; + + const double coneP = std::sqrt( conePx2 + conePy2 + conePz*conePz ); + const double conePt = std::sqrt( conePx2 + conePy2 ); + + // -- Create a vector with the summed momentum of all tracks in the cone + Gaudi::XYZVector momentumInCone; + momentumInCone.SetX(conePx); + momentumInCone.SetY(conePy); + momentumInCone.SetZ(conePz); + + // -- Calculate the difference in Eta and Phi between the summed momentum of all tracks in the cone and the + // -- track of the particle in question + const double deltaEta = part->momentum().Eta() - momentumInCone.Eta(); + double deltaPhi = fabs(part->momentum().Phi() - momentumInCone.Phi()); + if(deltaPhi > M_PI) deltaPhi = 2*M_PI-deltaPhi; + + // -- Convert the conesize to a string + char coneNumber[4]; + sprintf(coneNumber, "%.2f", coneSizeCounter); + std::string conesize(coneNumber); + + // -- Fill the tuple with the variables + test &= tuple->column( prefix+"_cpx_"+conesize, conePx); + test &= tuple->column( prefix+"_cpy_"+conesize, conePy); + test &= tuple->column( prefix+"_cpz_"+conesize, conePz); + test &= tuple->column( prefix+"_cpt_"+conesize, conePt ); + test &= tuple->column( prefix+"_cp_"+conesize, coneP ); + test &= tuple->column( prefix+"_cmult_"+conesize, myPair.second); + + // -- Fill the difference in Eta and Phi between the summed momentum of all tracks in the cone and the + // -- track of the particle in question if requested + if(m_fillDeltaAngles) + { + test &= tuple->column( prefix+"_deltaEta_"+conesize, deltaEta ); + test &= tuple->column( prefix+"_deltaPhi_"+conesize, deltaPhi ); + } + + // -- Fill the asymmetry information if requested + if(m_fillAsymmetry) + { + test &= tuple->column( prefix+"_pxasy_"+conesize, + (part->momentum().Px() - conePx)/(part->momentum().Px() + conePx) ); + test &= tuple->column( prefix+"_pyasy_"+conesize, + (part->momentum().Py() - conePy)/(part->momentum().Py() + conePy) ); + test &= tuple->column( prefix+"_pzasy_"+conesize, + (part->momentum().Pz() - conePz)/(part->momentum().Pz() + conePz) ); + test &= tuple->column( prefix+"_pasy_"+conesize, + (part->p() - coneP)/(part->p() + coneP) ); + test &= tuple->column( prefix+"_ptasy_"+conesize, + (part->pt() - conePt)/(part->pt() + conePt) ); + } + + // -- Increase the counter with the stepsize + coneSizeCounter += m_stepSize; + + } + + if ( msgLevel(MSG::VERBOSE) ) verbose() << "Stop looping through different conesizes" << endmsg; + + } + else + { + return Warning( "The particle in question is not valid" ); + } + + return StatusCode(test); +} + +//============================================================================= +// Save the particles in the decay chain (recursive function) +//============================================================================= +void TupleToolTrackIsolation::saveDecayParticles( const LHCb::Particle *top) +{ + + // -- Get the daughters of the top particle + const SmartRefVector< LHCb::Particle > & daughters = top->daughters(); + + // -- Fill all the daugthers in m_decayParticles + for( SmartRefVector< LHCb::Particle >::const_iterator idau = daughters.begin(); + idau != daughters.end(); ++idau ) + { + + // -- If the particle is stable, save it in the vector, or... + if( (*idau)->isBasicParticle() ) + { + if ( msgLevel(MSG::DEBUG) ) debug() << "Filling particle with ID " << (*idau)->particleID().pid() << endmsg; + m_decayParticles.push_back( (*idau) ); + } + else + { + // -- if it is not stable, call the function recursively + m_decayParticles.push_back( (*idau) ); + if ( msgLevel(MSG::DEBUG) ) debug() << "Filling particle with ID " << (*idau)->particleID().pid() << endmsg; + saveDecayParticles( (*idau) ); + } + + } + +} + +//============================================================================= +// Loop over all the tracks in the cone which do not belong to the desired decay +//============================================================================= +std::pair< std::vector, int> +TupleToolTrackIsolation::ConeP(const LHCb::Particle *part, + const LHCb::Tracks* tracks, + const double rcut) +{ + + // -- Get the (4-) momentum of the particle in question + const Gaudi::LorentzVector& partMomentum = part->momentum(); + double sumPx = 0.0; + double sumPy = 0.0; + double sumPz = 0.0; + int counter = 0; + + for( LHCb::Tracks::const_iterator it = tracks->begin(); it != tracks->end(); ++it ) + { + LHCb::Track* track = (*it); + + // -- Check if the track belongs to the decay itself + bool isInDecay = isTrackInDecay(track); + if(isInDecay) continue; + + // -- Get the (3-) momentum of the track + const Gaudi::XYZVector& trackMomentum = track->momentum(); + //double tracketa = track->pseudoRapidity(); + const double trackpx = trackMomentum.X(); + const double trackpy = trackMomentum.Y(); + const double trackpz = trackMomentum.Z(); + + // -- Calculate the difference in Eta and Phi between the particle in question and a track + double deltaPhi = fabs( partMomentum.Phi() - trackMomentum.Phi() ); + if(deltaPhi > M_PI) deltaPhi = 2*M_PI-deltaPhi; + + const double deltaEta = partMomentum.Eta() - trackMomentum.Eta(); + + const double deltaR = std::sqrt(deltaPhi * deltaPhi + deltaEta * deltaEta); + + // -- Add the tracks to the summation if deltaR is smaller than the cut value of deltaR + if ( deltaR < rcut && track->type() == m_trackType ) + { + sumPx += trackpx; + sumPy += trackpy; + sumPz += trackpz; + ++counter; + } + + + } + + // -- Fill a vector and return it + std::vector myVector; + myVector.push_back(sumPx); + myVector.push_back(sumPy); + myVector.push_back(sumPz); + + std::pair, int> myPair; + myPair.first = myVector; + myPair.second = counter; + + return myPair; + +} + +//============================================================================= +// Check if the track is already in the decay +//============================================================================= +bool TupleToolTrackIsolation::isTrackInDecay(const LHCb::Track* track){ + + bool isInDecay = false; + + for( std::vector::iterator it = m_decayParticles.begin() ; it != m_decayParticles.end() ; ++it ){ + + const LHCb::ProtoParticle* proto = (*it)->proto(); + if(proto){ + const LHCb::Track* myTrack = proto->track(); + + if(myTrack){ + + if(myTrack == track){ + if ( msgLevel(MSG::DEBUG) ) debug() << "Track is in decay, skipping it" << endmsg; + isInDecay = true; + } + } + + } + + } + + return isInDecay; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolTrackIsolation.h b/first-analysis-steps/DecayTrees/TupleToolTrackIsolation.h new file mode 100644 index 00000000..c9398b56 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTrackIsolation.h @@ -0,0 +1,100 @@ +// $Id: TupleToolTrackIsolation.h,v 1.2 2010-01-26 15:48:57 rlambert Exp $ +#ifndef TUPLETOOLTRACKISOLATION_H +#define TUPLETOOLTRACKISOLATION_H 1 + +// Include files +// from DaVinci, this is a specialized GaudiAlgorithm +#include "Kernel/IParticleTupleTool.h" +#include "DecayTreeTupleBase/TupleToolBase.h" + +/** @class TupleToolTrackIsolation TupleToolTrackIsolation.h + * + * \brief Fill track isolation for DecayTreeTuple. + * Open up a cone around head, exclude all tracks + * that are in the decay descriptor + * (i.e. that belong to the decay you are looking for), + * build the variables with the remaining tracks. + * + * - head_cmult : Number of tracks inside cone. + * - head_cp : Summed p inside cone + * - head_cpt : Summed pt inside cone + * - head_cpx : Summed px inside cone + * - head_cpy : Summed py inside cone + * - head_cpz : Summed pz inside cone + * + * If Verbose, or other flags are set: + * + * Asymmetry variables + * - head_pasy : (head_P - head_cp)/(head_P + head_cp) + * - head_ptasy : (head_PT - head_cpt)/(head_PT + head_cpt) + * - head_pxasy : (head_Px - head_cpx)/(head_Px + head_cpx) + * - head_pyasy : (head_Py - head_cpy)/(head_Py + head_cpy) + * - head_pzasy : (head_Pz - head_cpz)/(head_Pz + head_cpz) + * Delta angle variables + * - head_DeltaEta : Difference in eta between summed tracks and head + * - head_DeltaPhi : Difference in phi between summed tracks and head + * + * + * Options: + * + * - MinConeAngle: Set the minimal deltaR of the cone (default = 0.5), in radians + * - MaxConeAngle: Set the maximum deltaR of the cone (default = 1.0), in radians + * - StepSize: Set the step of deltaR between two iterations (default = 0.1), in radians + * - TrackType: Set the type of tracks which are considered inside the cone (default = 3) + * - FillAsymmetry: Flag to fill the asymmetry variables (default = false) + * - FillDeltaAngles: Flag to fill the delta angle variables (default = false) + * \sa DecayTreeTuple + * + * @author Michel De Cian + * @date 2009-08-04 + */ + + +class TupleToolTrackIsolation : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolTrackIsolation( const std::string& type, + const std::string& name, + const IInterface* parent ); + + /// Loop over differnt conesizes and fill the variables into the tuple + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + + virtual ~TupleToolTrackIsolation( ); ///< Destructor + + StatusCode initialize() override; ///< Algorithm initialization + +private: + + double m_minConeAngle; + double m_maxConeAngle; + double m_stepSize; + int m_trackType; + bool m_fillAsymmetry; + bool m_fillDeltaAngles; + + std::vector m_decayParticles; + +private: + + /// Save all particles in your decay descriptor in a vector + void saveDecayParticles( const LHCb::Particle *top); + + /// Calculate properties of your remaining tracks inside the cone + std::pair< std::vector, int> ConeP( const LHCb::Particle *part, + const LHCb::Tracks* tracks, + const double rcut ); + + /// Check if your track belongs to your decay or not + bool isTrackInDecay(const LHCb::Track* track); + +}; + +#endif // TUPLETOOLTRACKISOLATION_H diff --git a/first-analysis-steps/DecayTrees/TupleToolTrackKink.cpp b/first-analysis-steps/DecayTrees/TupleToolTrackKink.cpp new file mode 100644 index 00000000..01ea331e --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTrackKink.cpp @@ -0,0 +1,317 @@ +// Include files + +// from Gaudi +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +// local +#include "TupleToolTrackKink.h" +#include "Event/Track.h" +#include "Event/FitNode.h" +#include "Event/TrackFitResult.h" +#include "Event/ChiSquare.h" +#include "TrackKernel/TrackTraj.h" +#include "Event/KalmanFitResult.h" + +#include +#include +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolTrackKink +// +// 2013-02-23 : Francesco Dettori +// francesco.dettori@cern.ch +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolTrackKink ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolTrackKink::TupleToolTrackKink( const std::string& type, + const std::string& name, + const IInterface* parent ) +: TupleToolBase ( type, name , parent ), + m_trackfitter("TrackMasterFitter",this) +{ + declareInterface(this); + declareProperty( "TrackFitter", m_trackfitter ) ; +} + +//============================================================================= +// Destructor +//============================================================================= +TupleToolTrackKink::~TupleToolTrackKink() {} + +StatusCode TupleToolTrackKink::initialize() +{ + StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + sc = m_trackfitter.retrieve() ; + + return sc; +} + +//============================================================================= +StatusCode TupleToolTrackKink::fill( const LHCb::Particle*, + const LHCb::Particle* P, + const std::string& head, + Tuples::Tuple& tuple ) +{ + const std::string prefix = fullName(head); + bool test = true; + + if ( !P ) return StatusCode::FAILURE; + + //first just return if the particle isn't supposed to have a track + if ( !P->isBasicParticle() ) return StatusCode::SUCCESS; + + const LHCb::ProtoParticle* protop = P->proto(); + if (!protop) return StatusCode::SUCCESS; + + const LHCb::Track* track = protop->track(); + if (!track) return StatusCode::SUCCESS; + + if (msgLevel(MSG::DEBUG)) + debug() << prefix << " " << track->type() + << " "+prefix+"_TRACK_CHI2 " << track->chi2() << endmsg ; + if (msgLevel(MSG::VERBOSE)) verbose() << *track << endmsg ; + + if (msgLevel(MSG::DEBUG)) + debug() << "Going to refit track " << endmsg; + + double kinkchi2(-999.), zkink(-999.); + StatusCode sc = m_trackfitter->operator()( const_cast(*track) ) ; + if (sc.isSuccess()) + { + sc = kinkChi2(*track, kinkchi2, zkink); + }else{ + Warning( "Unable to refit track: kinkChi2 will have default value -999" ).ignore(); + } + + // First method + test &= tuple->column( prefix+"_TRACK_kinkChi2", kinkchi2 ); + test &= tuple->column( prefix+"_TRACK_kinkChi2z", zkink ); + + // second method + double kink_deltaR(-999), kink_deltaR_err(-999), kink_deltaR_z(-999), kink_chi2(-999); + sc = fitKink(*track,kink_deltaR, kink_deltaR_err, kink_chi2, kink_deltaR_z); + + test &= tuple->column( prefix+"_TRACK_kinkFitChi2", kink_chi2); + test &= tuple->column( prefix+"_TRACK_kinkFitDeltaR", kink_deltaR); + test &= tuple->column( prefix+"_TRACK_kinkFitDeltaRE", kink_deltaR_err); + test &= tuple->column( prefix+"_TRACK_kinkFitDeltaRZ", kink_deltaR_z); + + return StatusCode::SUCCESS; +} + +//============================================================================= +StatusCode TupleToolTrackKink::kinkChi2( const LHCb::Track& track, + double &chi2kink, + double &zkink) const +{ + chi2kink = 0; + zkink = 0; + + // Get Track fit result + const LHCb::TrackFitResult* fitresult = track.fitResult() ; + + if ( fitresult ) + { + + const LHCb::TrackFitResult::NodeContainer& nodes = fitresult->nodes() ; + + // Loop on nodes and get the ones with measurement + std::vector< const LHCb::FitNode* > measnodes ; + measnodes.reserve( nodes.size()) ; + BOOST_FOREACH( const LHCb::Node* node, nodes ) + { + if ( !node ) + { + return Warning( "Nodes not found, lets skip this entry" ); + + } + if( node->hasMeasurement() ) + measnodes.push_back( static_cast(node) ) ; + } + + int N = measnodes.size() ; + if ( N<1 ) + { + return Warning( "No measurement nodes found" ); + } + + // Get chi2 in the forward direction up to each node + std::vector chi2forward(N,0) ; + chi2forward[0] = (measnodes[0] ? measnodes[0]->deltaChi2Forward().chi2() :0.) ; + for( int i=1; ideltaChi2Forward().chi2() : 0.0 ); + } + + // Get chi2 in the backward direction up to each node + std::vector chi2backward(N,0) ; + chi2backward[N-1] = (measnodes[N-1] ? measnodes[N-1]->deltaChi2Backward().chi2() : 0.) ; + for( int i=N-2; i>=0; --i) + { + chi2backward[i] = (measnodes[i] ? chi2backward[i+1] + measnodes[i]->deltaChi2Backward().chi2() :0.) ; + } + + const double chi2tot = std::max( chi2forward[N-1], chi2backward[0] ) ; + + // find the kink as the pont with largest chi2 variation + const int minkinkstep=4 ; + const size_t ndof = 5 ; + int ikink(0) ; + for( int i=minkinkstep-1; i chi2kink ) + { + ikink = i ; + chi2kink = thischi2kink ; + } + } + // Get z position of the kink + zkink = 0.5 * ( measnodes[ikink]->z() + measnodes[ikink+1]->z() ) ; + + } + else + { + Warning( "No fit result found", StatusCode::SUCCESS ).ignore(); + } + + return StatusCode::SUCCESS; +} + +//============================================================================= +StatusCode TupleToolTrackKink::fitKink( const LHCb::Track &input_track, + double &kink_deltaR, double &kink_deltaR_err, + double &kink_chi2, double &kink_z ) +{ + + // Scan in z or in nodes + const LHCb::TrackFitResult* fitresult = input_track.fitResult(); + bool upstream = (input_track.fitResult()->nodes().front()->z() > + input_track.fitResult()->nodes().back()->z()) ; + + double max_chi2(-1); + if( fitresult ) + { + if (msgLevel(MSG::VERBOSE)) + verbose() << "fitKink: got fit result " << endmsg; + + const LHCb::TrackFitResult::NodeContainer& nodes = fitresult->nodes() ; + // const std::vector& measures = fitresult->measurements(); + + std::vector< const LHCb::FitNode* > measnodes ; + measnodes.reserve( nodes.size()) ; + // Get only measnodes + BOOST_FOREACH( const LHCb::Node* node, nodes ) + { + if ( !node ) + { + return Warning( "Nodes not found, lets skip this entry" ); + } + if( node->hasMeasurement() ) + { + measnodes.push_back( static_cast(node) ) ; + } + } + + // Loop on measnodes and get states + BOOST_FOREACH( const LHCb::FitNode* node, measnodes ) + { + const LHCb::State& stateUp = upstream ? node->filteredStateForward() : node->predictedStateForward() ; + const LHCb::State& stateDown = upstream ? node->predictedStateBackward() : node->filteredStateBackward() ; + + // Get vector of difference between the two states ant its covariance + Gaudi::TrackVector delta_zero = stateUp.stateVector() - stateDown.stateVector() ; + Gaudi::TrackSymMatrix cov = stateUp.covariance() + stateDown.covariance() ; + if ( delta_zero(0) == 0 ) continue; + + // Set up matrix of constraints + Matrix3x5 Dconstr; + Dconstr(0,0) = Dconstr(1,1) = Dconstr(2,4) = 1; + Matrix5x3 DconstrT; + DconstrT(0,0) = DconstrT(1,1) = DconstrT(4,2) = 1; // Faster than Transpose + + // Matrix3x5 tmp_m = Dconstr * cov; + Matrix3x3 DVD = Dconstr * cov * DconstrT; + // 3x3 = 3x5 * 5x5 * 5x3 + Matrix3x3 DVDinv = DVD; + + if (msgLevel(MSG::VERBOSE)) + { + verbose() << "covariance " << std::endl + << cov << endmsg; + verbose() << "DMATRIX" << std::endl + << Dconstr << std::endl + << DconstrT << endmsg; + verbose() << "DVD " << std::endl + << DVD << endmsg; + } + + if ( !DVDinv.Invert() ) + { + return Warning( "No inverse matrix, no kink fit chi2" ); + } + if (msgLevel(MSG::DEBUG)) + debug() << "DVD inverted " << std::endl + << DVDinv << endmsg; + + Matrix5x5 H = cov * DconstrT * DVDinv * Dconstr; + // 5x5 = 5x5 * 5x3 * 3x3 * 3*5 + + Gaudi::Vector3 lambda = DVDinv * Dconstr *delta_zero; + // 3 = 3x3 * 3x5 * 5 + + Gaudi::TrackVector delta = delta_zero - H * delta_zero; + // 5 = 5 - 5x5 * 5 + + Gaudi::Vector3 lambda_mod = DVD * lambda ; + // 3 = 3x3 *3 + + if (msgLevel(MSG::DEBUG)) + { + debug() << " delta was " << delta_zero << " now it is " << delta << endmsg; + debug() << " lambda is " << lambda << endmsg; + } + + // // Then we get the chi2 + double chi2 = ROOT::Math::Dot(lambda ,lambda_mod); + if (msgLevel(MSG::DEBUG)) + debug() << " Chi2 is " << chi2 << endmsg; + + Matrix5x5 cov_2 = cov - H * cov; + // 5x5 = 5x5 - 5x5 * 5x5 + + // DeltaR = sqrt [( dy/dz - (dy/dz)' )^2 + ( dx/dz - (dx/dz)' )^2 ] + double deltaR = std::sqrt(delta(2)*delta(2) + delta(3)*delta(3)); + double deltaR_err = std::sqrt(std::pow(delta(2),2)*cov_2(2,2) + std::pow(delta(3),2)*cov_2(3,3)+ + delta(2)*delta(3)*cov_2(2,3)) / deltaR; + + + // Get largest chi2 variation and its correspondent parameters + if(chi2 > max_chi2) + { + max_chi2 = chi2; + kink_deltaR = deltaR; + kink_deltaR_err = deltaR_err; + kink_z = (upstream ? stateUp.z() : stateDown.z()); + } + + if (msgLevel(MSG::DEBUG)) + debug() << "DeltaR is " << deltaR << " +- " << deltaR_err + << " chi2 is " << chi2 << " max_chi2 "<< max_chi2 << endmsg; + } + } + else + { + return Warning( "Fit result not found, skipping kinkFit calculation" ); + } + kink_chi2 = max_chi2; + + return StatusCode::SUCCESS; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolTrackKink.h b/first-analysis-steps/DecayTrees/TupleToolTrackKink.h new file mode 100755 index 00000000..9d2beaa7 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTrackKink.h @@ -0,0 +1,69 @@ +#ifndef DecayTreeTupleTracking_TupleToolTrackKink_H +#define DecayTreeTupleTracking_TupleToolTrackKink_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "GaudiKernel/ToolHandle.h" +#include "TrackInterfaces/ITrackFitter.h" +/** @class TupleToolTrackKink TupleToolTrackKink.h + * \brief TupleTool to reconstruct and save information about kinks on given tracks + * + * Two methods are provided: + * - KinkChi2 + * - KinkFitChi2 + * The following variables are stored: + * - _TRACK_kinkChi2, _TRACK_kinkChi2z + * - _TRACK_kinkFitChi2, _TRACK_kinkFitDeltaR, _TRACK_kinkFitDeltaRE, _TRACK_kinkFitDeltaRZ + * + * @author Francesco Dettori + * @date 2013-23-02 + */ + +class TupleToolTrackKink : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolTrackKink( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolTrackKink(); ///< Destructor + + StatusCode initialize() override; + +public: + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + StatusCode kinkChi2( const LHCb::Track& track, double &chi2kink, + double &zkink) const; + + StatusCode fitKink(const LHCb::Track &track, + double &kink_deltaR, double &kink_deltaR_err, + double &kink_chi2, + double &kink_z); + +private: + + typedef ROOT::Math::SMatrix Matrix3x3; + typedef ROOT::Math::SMatrix Matrix5x3; + typedef ROOT::Math::SMatrix Matrix3x5; + typedef ROOT::Math::SMatrix Matrix5x5; + +private: + + ToolHandle m_trackfitter; + +}; + +#endif // DecayTreeTupleTracking_TupleToolTrackKink_H diff --git a/first-analysis-steps/DecayTrees/TupleToolTrackPosition.cpp b/first-analysis-steps/DecayTrees/TupleToolTrackPosition.cpp new file mode 100644 index 00000000..f5165a01 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTrackPosition.cpp @@ -0,0 +1,99 @@ +// Include files + + +#include "Event/Particle.h" +//#include "Event/Track.h" +// kernel +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +//#include "GaudiKernel/PhysicalConstants.h" + +// local +#include "TrackInterfaces/ITrackExtrapolator.h" +#include "TrackInterfaces/ITrackStateProvider.h" +#include "TupleToolTrackPosition.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolTrackPosition +// +// 2009-05-06 : Michel De Cian +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( TupleToolTrackPosition ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolTrackPosition::TupleToolTrackPosition( const std::string& type, + const std::string& name, + const IInterface* parent) + : TupleToolBase ( type, name , parent ), + m_Z(2500.), + m_extrapolator(NULL), + m_extrapolatorName("") +{ + declareInterface(this); + declareProperty( "Z", m_Z = 2500., + "Which Z-position to propagate the track to, defaults to 2500, the position of the TT-stations"); + declareProperty( "Extrapolator", m_extrapolatorName = "TrackStateProvider", + "Which extrapolator to use"); + +} +//============================================================================= +// Destructor +//============================================================================= +TupleToolTrackPosition::~TupleToolTrackPosition() {} + +//============================================================================= +// Initialization +//============================================================================= +StatusCode TupleToolTrackPosition::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_extrapolator=tool(m_extrapolatorName,this); + + if ( msgLevel(MSG::DEBUG) ) debug() << "==> Initialize" << endmsg; + + return sc; +} + +//============================================================================= +// Fill the tuple +//============================================================================= +StatusCode TupleToolTrackPosition::fill( const LHCb::Particle *, const LHCb::Particle * part, + const std::string & head, Tuples::Tuple & tuple ) +{ + + const std::string prefix=fullName(head); + if ( msgLevel(MSG::DEBUG) ) debug() << "==> Fill" << endmsg; + + bool test=true; + + double X=-999999; + double Y=-999999; + + + if( part && part->proto() && part->proto()->track() ) + { + + if ( msgLevel(MSG::VERBOSE) ) verbose() << "extrapolating track to Z="<< m_Z << endmsg; + + LHCb::State aState=LHCb::State(); + //const LHCb::Track aTrack= *(part->proto()->track()); + StatusCode sc=m_extrapolator->stateFromTrajectory(aState,*(part->proto()->track()),m_Z); + if(sc.isSuccess()) + { + X=aState.x(); + Y=aState.y(); + } + + } + + test &= tuple->column( prefix+"_X", X ); + test &= tuple->column( prefix+"_Y", Y ); + + return StatusCode(test); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolTrackPosition.h b/first-analysis-steps/DecayTrees/TupleToolTrackPosition.h new file mode 100644 index 00000000..7706d3ab --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTrackPosition.h @@ -0,0 +1,68 @@ +#ifndef TUPLETOOLTRACKPOSITION_H +#define TUPLETOOLTRACKPOSITION_H 1 + +// Include files +// from DaVinci, this is a specialized GaudiAlgorithm +//#include "Kernel/DVAlgorithm.h" +#include "Kernel/IParticleTupleTool.h" +#include "DecayTreeTupleBase/TupleToolBase.h" +//#include "TrackInterfaces/ITrackExtrapolator.h" + +/** @class TupleToolTrackPosition TupleToolTrackPosition.h + * + * \brief Plot the X/Y position at a given Z + * + * Steer with: + * - Z : the Z-position at which to plot the X/Y, double, defaults to 2500 (TT-stations) + * - Extrapolator : which track extrapolator to use, defaults to the TrackStateProvider + * - ExtraName : the universal TupleTool option, in case you want to use multiples of this tool + * + * fills: + * - head_X + * - head_Y + * + * \sa DecayTreeTuple + * + * @author Rob Lambert + * @date 2011-01-20 + */ + +struct ITrackExtrapolator; +struct ITrackStateProvider; + + +class TupleToolTrackPosition : public TupleToolBase, virtual public IParticleTupleTool { +public: + /// Standard constructor + TupleToolTrackPosition( const std::string& type, + const std::string& name, + const IInterface* parent ); + /// Loop over differnt conesizes and fill the variables into the tuple + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + + + + virtual ~TupleToolTrackPosition( ); ///< Destructor + + StatusCode initialize() override; ///< Algorithm initialization + + +protected: + +private: + + double m_Z; /// +#include + +#include "Event/Track.h" +#include "Event/OTMeasurement.h" +#include "Event/FitNode.h" +#include "LHCbMath/ValueWithError.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolTrackTime +// +// 2016-02-26 : Francesco Dettori +// francesco.dettori@cern.ch +// +// Based on code from W. Hulsbergen +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolTrackTime ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolTrackTime::TupleToolTrackTime( const std::string& type, + const std::string& name, + const IInterface* parent ) +: TupleToolBase ( type, name , parent ), + m_trackfitter("TrackMasterFitter",this) +{ + declareInterface(this); + declareProperty( "TrackFitter", m_trackfitter ) ; +} + +//============================================================================= +// Destructor +//============================================================================= +TupleToolTrackTime::~TupleToolTrackTime() {} + +StatusCode TupleToolTrackTime::initialize() +{ + StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + sc = m_trackfitter.retrieve() ; + + return sc; +} + +//============================================================================= +StatusCode TupleToolTrackTime::fill( const LHCb::Particle*, + const LHCb::Particle* P, + const std::string& head, + Tuples::Tuple& tuple ) +{ + if (msgLevel(MSG::VERBOSE)) verbose() << " filling particle " << endmsg; + const std::string prefix = fullName(head); + bool test = true; + + if ( !P ) return StatusCode::FAILURE; + + //first just return if the particle isn't supposed to have a track + if ( !P->isBasicParticle() ) return StatusCode::SUCCESS; + + const LHCb::ProtoParticle* protop = P->proto(); + if (!protop){ + if (msgLevel(MSG::DEBUG))debug() << "Protoparticle not found for this particle" << endmsg; + return StatusCode::SUCCESS; + } + + const LHCb::Track* track = protop->track(); + if (!track){ + if (msgLevel(MSG::DEBUG))debug() << "Track not found for this particle" << endmsg; + return StatusCode::SUCCESS; + } + + if (msgLevel(MSG::DEBUG)) + debug() << prefix << " " << track->type() + << " "+prefix+"_TRACK_CHI2 " << track->chi2() << endmsg ; + if (msgLevel(MSG::VERBOSE)) verbose() << *track << endmsg ; + + + Gaudi::Math::ValueWithError track_t0(0,0); + try + { + const LHCb::Track *clone = track->cloneWithKey(); + + StatusCode sc = m_trackfitter->operator()( const_cast(*clone) ) ; + if (sc.isSuccess()) + { + track_t0 = computeTrackT0(*clone); + if (msgLevel(MSG::DEBUG)) debug() << " Obtained t0: " << track_t0 << endmsg; + }else{ + Warning( "Unable to refit track: track time will have default value 0" ).ignore(); + } + delete clone; + + }catch(const GaudiException & ) + { + Warning( "There was a problem accessing data for track refit" ).ignore(); + } + + + // First method + test &= tuple->column( prefix+"_TRACK_time", track_t0.value() ); + test &= tuple->column( prefix+"_TRACK_time_err", track_t0.error() ); + + + return StatusCode::SUCCESS; +} + + + +Gaudi::Math::ValueWithError TupleToolTrackTime::computeTrackT0( const LHCb::Track& track ) +{ + + if (msgLevel(MSG::VERBOSE)) verbose() << " Computing track t0 " << endmsg; + + + double sumwtimeres(0) ; + double sumw(0) ; + + + if (msgLevel(MSG::VERBOSE)) verbose() << " track nodes " << track.nodes().size() << endmsg; + + // Check if fit result is available (this should always be the case) + const LHCb::TrackFitResult* fitresult = track.fitResult() ; + Gaudi::Math::ValueWithError rc(0,0) ; + + if ( !fitresult ) return rc; + + // Get nodes from track + const LHCb::TrackFitResult::NodeContainer& nodes = fitresult->nodes() ; + + // iterate over all track nodes + for( const LHCb::Node* node: nodes ) { + if ( !node ) + { + Warning( "Nodes not found, lets skip this entry" ).ignore(); + continue; + } + if( ! node->hasMeasurement() ) continue; + + if (msgLevel(MSG::VERBOSE)) verbose() << " Node type " << node->type() + << " node measurement type " << node->measurement().type() << endmsg; + + if( node->type() == LHCb::Node::HitOnTrack && + node->measurement().type() == LHCb::Measurement::OT ) { + + // get fit node + const LHCb::FitNode* fitnode = dynamic_cast(node); + const LHCb::OTMeasurement* measurement = dynamic_cast(&node->measurement()); + bool drifttimeWasUsed = + measurement->driftTimeStrategy() == LHCb::OTMeasurement::FitTime || + measurement->driftTimeStrategy() == LHCb::OTMeasurement::FitDistance ; + if( drifttimeWasUsed ) { + + double timeresidual(0) ; + double timeresidualV(0) ; + + if( measurement->driftTimeStrategy() == LHCb::OTMeasurement::FitDistance ) { + // compute the residual in the drifttime + // Get the rt relation + const OTDet::RtRelation& rtr = measurement->module().rtRelation() ; + + // Get distance from wire + double radius = std::min( (double)rtr.rmax(), std::abs(fitnode->doca()) ) ; + + // Get expected drifttime + OTDet::DriftTimeWithError predictedtime = rtr.drifttimeWithError( radius ) ; + + // get dt/dr + double dtdr = rtr.dtdr( radius ) ; + + // Get measure drit time + double measureddrifttime = measurement->driftTimeFromY( fitnode->state().y() ) ; + + // Compute residual difference + timeresidual = measureddrifttime - predictedtime.val ; + + // this is the easiest. it would be better to first compute the error on the radius, then ... + timeresidualV = fitnode->errResidual2() * dtdr * dtdr ; + } else { + + timeresidual = fitnode->residual() ; + timeresidualV = fitnode->errResidual2() ; + } + // Compute sum of weights and sum of weighted times + if( timeresidualV > 0 ) { + double weight = 1/timeresidualV ; + sumwtimeres += weight * timeresidual ; + sumw += weight ; + } + } + } + } + + + // Return weighted average + if( sumw > 0 ) + rc = Gaudi::Math::ValueWithError( sumwtimeres/sumw, 1/sumw ) ; + if (msgLevel(MSG::DEBUG))debug() << "Returning time " << rc << endmsg; + + return rc ; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolTrackTime.h b/first-analysis-steps/DecayTrees/TupleToolTrackTime.h new file mode 100755 index 00000000..2a27762b --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTrackTime.h @@ -0,0 +1,52 @@ +#ifndef DecayTreeTupleTracking_TupleToolTrackTime_H +#define DecayTreeTupleTracking_TupleToolTrackTime_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "GaudiKernel/ToolHandle.h" +#include "TrackInterfaces/ITrackFitter.h" +#include "LHCbMath/ValueWithError.h" + +/** @class TupleToolTrackTime TupleToolTrackTime.h + * \brief TupleTool to calculate timing information on the track + * + * @author Francesco Dettori + * @date 2016-26-02 + */ + +class TupleToolTrackTime : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolTrackTime( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolTrackTime(); ///< Destructor + + StatusCode initialize() override; + +public: + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + Gaudi::Math::ValueWithError computeTrackT0( const LHCb::Track& track ); + + +private: + + ToolHandle m_trackfitter; + +}; + +#endif // DecayTreeTupleTracking_TupleToolTrackTime_H diff --git a/first-analysis-steps/DecayTrees/TupleToolTrigger.cpp b/first-analysis-steps/DecayTrees/TupleToolTrigger.cpp new file mode 100755 index 00000000..ad79e77e --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTrigger.cpp @@ -0,0 +1,306 @@ +#include "TupleToolTrigger.h" + +#include "Event/L0DUReport.h" +#include "Event/HltDecReports.h" +#include "Kernel/IANNSvc.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "Kernel/ReadRoutingBits.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TriggerTupleTool +// +// 2007-11-07 : Jeremie Borel +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolTrigger ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolTrigger::TupleToolTrigger( const std::string& type, + const std::string& name, + const IInterface* parent ) +: TupleToolTriggerBase ( type, name , parent ) + , m_routingBits(0) +{ + declareInterface(this); + //declareProperty( "FillL0", m_fillL0=true, "Fill L0" ); now in the base class + //declareProperty( "FillHlt", m_fillHlt=true, "Fill Hlt" ); now in the base class + //depracated, use VerboseHlt1, VerboseHlt2 or VerboseL0 + //declareProperty( "AllIntermediateSteps", m_allSteps=false, "Fill also intermediate steps" ); + for ( unsigned int i = 32 ; i < 96 ; ++i ) + { + m_routingBits.push_back(i); + } + declareProperty( "RoutingBits", m_routingBits, "Routing bits to fill" ); + m_rawEventLocs.push_back( LHCb::RawEventLocation::Trigger ); + m_rawEventLocs.push_back( LHCb::RawEventLocation::Default ); + declareProperty( "RawEventLocations", m_rawEventLocs ); +} + +//========================================================================= + +StatusCode TupleToolTrigger::initialize ( ) +{ + const StatusCode sc = TupleToolTriggerBase::initialize(); + if ( m_doStripping || !m_stripping.empty() ) + { + return Error("You should use TupleToolStripping for that", StatusCode::FAILURE); + } + return sc ; +} + +//============================================================================= + +StatusCode TupleToolTrigger::fillBasic( Tuples::Tuple& tuple ) +{ + if (msgLevel(MSG::DEBUG)) debug() << "Tuple Tool Trigger Basic" << endmsg ; + + const std::string prefix = fullName(); + //fill the L0 global + if ( m_doL0 ) + { + LHCb::L0DUReport* report = + getIfExists(evtSvc(),LHCb::L0DUReportLocation::Default); + if ( !report ) + { + report = + getIfExists(evtSvc(),LHCb::L0DUReportLocation::Default,false); + } + if ( ! tuple->column( prefix+"L0Global", report ? report->decision() : 0 ) ) + return StatusCode::FAILURE; + if ( report ) + { + if (msgLevel(MSG::DEBUG)) debug() << "L0 decision: " << report->decision() << endmsg; + } + } + + // fill the HLT global + if ( m_doHlt1 || m_doHlt2 ) + { + // Use of the split locations should be backwards compatible, i.e. we an use the Hlt1/Hlt2 + // specific locations even for Run 1 data. + const LHCb::HltDecReports* decReports2(0); + const LHCb::HltDecReports* decReports1 = + getIfExists(evtSvc(),LHCb::HltDecReportsLocation::Hlt1Default); + if ( !decReports1 ) + { + decReports1 = + getIfExists(evtSvc(),LHCb::HltDecReportsLocation::Hlt1Default,false); + } + + if(! decReports1 ) + debug() << "No reports at LHCb::HltDecReportsLocation::Hlt1Default (" << LHCb::HltDecReportsLocation::Hlt1Default << ")" << endmsg; + + // allow data with only Hlt2 report + decReports2 = + getIfExists(evtSvc(), LHCb::HltDecReportsLocation::Hlt2Default); + if ( !decReports2 ) + { + decReports2 = + getIfExists(evtSvc(),LHCb::HltDecReportsLocation::Hlt2Default,false); + } + + if(! decReports2 ) + debug() << "No reports at LHCb::HltDecReportsLocation::Hlt2Default (" << LHCb::HltDecReportsLocation::Hlt2Default << ")" << endmsg; + + //fill the HLT1 global + if ( !tuple->column( prefix+"Hlt1Global", + decReports1 && decReports1->decReport("Hlt1Global") ? + decReports1->decReport("Hlt1Global")->decision() : 0 ) ) + return StatusCode::FAILURE; + + //fill the HLT2 global + if ( !tuple->column( prefix+"Hlt2Global", + decReports2 && decReports2->decReport("Hlt2Global") ? + decReports2->decReport("Hlt2Global")->decision() : 0 ) ) + return StatusCode::FAILURE; + + } + + if (msgLevel(MSG::DEBUG)) debug() << "Done" << endmsg ; + + return StatusCode::SUCCESS; +} + +//============================================================================= + +StatusCode TupleToolTrigger::fillVerbose( Tuples::Tuple& tuple ) +{ + bool test=true; + if (msgLevel(MSG::DEBUG)) debug() << "Tuple Tool Trigger Verbose" << endmsg ; + + //fill the L0 verbose + if (m_doL0 && m_verboseL0) + { + test&=fillL0(tuple); + } + if (msgLevel(MSG::DEBUG)) debug() << "Tuple Tool Trigger L0 " << test << endmsg ; + + //fill the HLT1 verbose + if (m_doHlt1 && m_verboseHlt1) + { + test&=fillHlt(tuple, "Hlt1"); + } + if (msgLevel(MSG::DEBUG)) debug() << "Tuple Tool Trigger Hlt1 " << test << endmsg ; + + //fill the HLT2 verbose + if (m_doHlt2 && m_verboseHlt2) + { + test&=fillHlt(tuple, "Hlt2"); + } + if (msgLevel(MSG::DEBUG)) debug() << "Tuple Tool Trigger Hlt2 " << test << endmsg ; + + test &= fillRoutingBits(tuple); + if (msgLevel(MSG::DEBUG)) debug() << "Tuple Tool Trigger RoutingBits " << test << endmsg ; + + if (!test) Warning("Failure from Trigger::fillVerbose"); + return StatusCode(test); +} + +//============================================================================= + +StatusCode TupleToolTrigger::fillL0( Tuples::Tuple& tuple ) +{ + return fillHlt(tuple,"L0"); +} + +//============================================================================ + +StatusCode TupleToolTrigger::fillHlt( Tuples::Tuple& tuple, const std::string & level) +{ + const std::string prefix = fullName(); + + const LHCb::HltDecReports* decReports(0); + if( level == "L0" ){ + const std::string loca = "HltLikeL0/DecReports"; + decReports = getIfExists(evtSvc(),loca); + if ( !decReports ) + { + decReports = getIfExists(evtSvc(),loca,false); + } + } else { + // Split reports should be all we need. + std::string loca = level + "/DecReports"; + decReports = getIfExists(evtSvc(),loca); + if ( !decReports ) + { + decReports = getIfExists(evtSvc(),loca,false); + } + } + + if ( decReports ) + { + unsigned int nsel = 0 ; + + std::vector names = std::vector(0); + + if(level=="L0") names=m_l0; + else if(level=="Hlt1") names=m_hlt1; + else if(level=="Hlt2") names=m_hlt2; + else return StatusCode::FAILURE; + + for ( std::vector::const_iterator n = names.begin() ; n!= names.end() ; ++n) + { + int found = -1 ; + if ( msgLevel(MSG::DEBUG) ) debug() << " In verbose HLT, Trying to fill " << (*n) << endmsg; + // individual Hlt trigger lines + for ( LHCb::HltDecReports::Container::const_iterator it=decReports->begin(); + it != decReports->end(); ++it ) + { + if (msgLevel(MSG::VERBOSE)) verbose() << " Hlt trigger name= " << it->first << endmsg; + if ( ( it->first == *n ) ) + { + if (msgLevel(MSG::DEBUG)) debug() << " Hlt trigger name= " << it->first + << " decision= " << it->second.decision() << endmsg; + found = it->second.decision() ; + //only print all the names if output level is verbose otherwise this is a waste of time + if(!msgLevel(MSG::VERBOSE)) break; + } + } + if (msgLevel(MSG::VERBOSE)) verbose() << "Added " << *n << " " << found + << " to " << nsel << endmsg ; + const bool isDecision = ( n->find("Decision") == n->length()-8 ) ; // 8 is length of Decision + if (isDecision && found>0) nsel++ ; + //if (isDecision || m_allSteps) + //{ + if ( ! tuple->column(prefix+*n, found ) ) return StatusCode::FAILURE; + //} + } + if ( ! tuple->column(prefix+level+"nSelections" , nsel ) ) return StatusCode::FAILURE; + } + else return Warning("No HltDecReports found ",StatusCode::FAILURE,2); + if (msgLevel(MSG::DEBUG)) debug() << "Done " << prefix+level << endmsg ; + return StatusCode::SUCCESS ; +} + +//============================================================================ + +StatusCode TupleToolTrigger::fillRoutingBits( Tuples::Tuple& tuple ) +{ + const std::string prefix = fullName(); + + LHCb::RawEvent * rawEvent = NULL; + for ( std::vector::const_iterator iLoc = m_rawEventLocs.begin(); + iLoc != m_rawEventLocs.end(); ++iLoc ) + { + rawEvent = getIfExists(evtSvc(),*iLoc,true); + if ( !rawEvent ) { rawEvent = getIfExists(evtSvc(),*iLoc,false); } + if ( rawEvent ) { break; } + } + + if ( rawEvent ) + { + try + { + std::vector yes = Hlt::firedRoutingBits(rawEvent,m_routingBits); + if (msgLevel(MSG::DEBUG)) debug() << yes << endmsg ; + if (!tuple->farray(prefix+"RoutingBits", yes, prefix+"MaxRoutingBits" , m_routingBits.size() )) + { + return Warning("Failure to fill routing bits"); + } + if (msgLevel(MSG::DEBUG)) debug() << "RoutingBits OK " << endmsg ; + } + catch ( const GaudiException & ) + { + Warning( "Cannot access the HLT Routing Bits. No information from these is available", + StatusCode::SUCCESS, 1 ).ignore(); + } + + } + + return StatusCode::SUCCESS; +} + +StatusCode TupleToolTrigger::fillBasic( const LHCb::Particle* P1 + , const LHCb::Particle* P2 + , const std::string& S + , Tuples::Tuple& T ) +{ + return TupleToolTriggerBase::fillBasic(P1,P2,S,T); +} + +StatusCode TupleToolTrigger::fillVerbose( const LHCb::Particle* P1 + , const LHCb::Particle* P2 + , const std::string& S + , Tuples::Tuple& T ) +{ + return TupleToolTriggerBase::fillBasic(P1,P2,S,T); +} + +StatusCode TupleToolTrigger::fill( Tuples::Tuple& tuple ) +{ + return TupleToolTriggerBase::fill(tuple); +} + +StatusCode TupleToolTrigger::fill( const LHCb::Particle* top + , const LHCb::Particle* part + , const std::string& head + , Tuples::Tuple& tuple ) +{ + return TupleToolTriggerBase::fill(top,part,head,tuple); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolTrigger.h b/first-analysis-steps/DecayTrees/TupleToolTrigger.h new file mode 100755 index 00000000..9e1dbe4d --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTrigger.h @@ -0,0 +1,97 @@ +// $Id: TupleToolTrigger.h,v 1.12 2010-03-16 01:11:28 rlambert Exp $ +#ifndef JBOREL_TUPLETOOLTRIGGER_H +#define JBOREL_TUPLETOOLTRIGGER_H 1 + +#include + +#include "TupleToolTriggerBase.h" +#include "Kernel/IEventTupleTool.h" // Interface + +/** @class TupleToolTrigger TupleToolTrigger.h jborel/TupleToolTrigger.h + * + * \brief Fill the trigger informations for the DecayTreeTuple. + * + * - L0Decision : LHCb::L0DUReport->decision() + * - Hlt1Global : Global HLT1 decision + * - Hlt2Global : Global HLT2 decision + * - StrippingGlobal : Global Stripping decision + * + * If verbose is true the tool needs somehow to find a list of triggers to fill. + * In this case it uses the base class TupleToolTriggerBase to sort everything out. + * + * If \b VerboseL0 = true + * L0Decision_xxx : LHCb::L0DUReport->channelDecisionByName(xxx) + * + * If \b VerboseHlt1 = true + * Hlt1_xxx_Decision : filled ... [ -1, 0, 1 ] = [not run, decision false, decision true] + * + * If \b VerboseHlt2 = true + * Hlt2_xxx_Decision : filled ... [ -1, 0, 1 ] = [not run, decision false, decision true] + * + * If \b VerboseStripping = true + * Stripping_xxx_Decision : filled ... [ -1, 0, 1 ] = [not run, decision false, decision true] + * + * Verbose flag is a shortcut to turn all verbosity on. + * + * + * @author Jeremie Borel + * @date 2007-11-07 + */ +class TupleToolTrigger : public TupleToolTriggerBase, + virtual public IEventTupleTool +{ + +public: + + /// Standard constructor + TupleToolTrigger( const std::string& type, + const std::string& name, + const IInterface* parent ); + + ~TupleToolTrigger( ) {} ///< Destructor + + StatusCode initialize() override; + +public: + + StatusCode fill( Tuples::Tuple& tuple ) override; + + StatusCode fill( const LHCb::Particle* top + , const LHCb::Particle* part + , const std::string& head + , Tuples::Tuple& tuple ) override; + +private: + + ///fill verbose information for the L0 + StatusCode fillL0( Tuples::Tuple& ); + ///fill verbose information for the HLT + StatusCode fillHlt( Tuples::Tuple&, const std::string &); + StatusCode fillRoutingBits( Tuples::Tuple& ); + + StatusCode fillBasic(Tuples::Tuple& tuple ) override; + + StatusCode fillVerbose(Tuples::Tuple& tuple ) override; + +private: + + StatusCode fillBasic( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + + StatusCode fillVerbose( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + std::vector m_routingBits ; ///< Routing bits to fill + + // RawEvent Locations to search + std::vector m_rawEventLocs; + +}; + +#endif // JBOREL_TUPLETOOLTRIGGER_H diff --git a/first-analysis-steps/DecayTrees/TupleToolTriggerBase.cpp b/first-analysis-steps/DecayTrees/TupleToolTriggerBase.cpp new file mode 100755 index 00000000..7d3e9292 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTriggerBase.cpp @@ -0,0 +1,213 @@ +// Include files +#include "boost/regex.hpp" + +#include "Event/Particle.h" +// kernel +#include "Kernel/IANNSvc.h" +#include "Event/L0DUReport.h" +#include "Event/HltDecReports.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +// local +#include "TupleToolTriggerBase.h" + +//#include + +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolTriggerBase +// +// 2008-04-09 : V. Gligorov +//----------------------------------------------------------------------------- + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolTriggerBase::TupleToolTriggerBase( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ), + m_l0(0), + m_hlt1(0), + m_hlt2(0), + m_stripping(0), + m_triggerList(0) +{ + //declareInterface(this); + + //to turn all verbosity on, set Verbose=true + declareProperty( "VerboseL0", m_verboseL0=false ); + declareProperty( "VerboseHlt1", m_verboseHlt1=false ); + declareProperty( "VerboseHlt2", m_verboseHlt2=false ); + declareProperty( "VerboseStripping", m_verboseStripping=false ); + declareProperty( "FillL0", m_doL0=true ); + declareProperty( "FillHlt1", m_doHlt1=true ); + declareProperty( "FillHlt2", m_doHlt2=true ); + declareProperty( "FillStripping", m_doStripping=false ); + + //List of triggers to look at + declareProperty( "TriggerList", m_triggerList=std::vector(0) ); +} + +//============================================================================= +// Destructor +//============================================================================= +TupleToolTriggerBase::~TupleToolTriggerBase() {} + +//============================================================================= + +//========================================================================= +// initialize +//========================================================================= +StatusCode TupleToolTriggerBase::initialize( ) +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + if (isVerbose()) m_verboseL0=m_verboseHlt1=m_verboseHlt2=m_verboseStripping=true; + const bool iv = (m_verboseL0||m_verboseHlt1||m_verboseHlt2||m_verboseStripping); + + if ( !m_triggerList.empty() && !iv ) + { + warning() << "You have set a list of triggers to look for, but not asked for verbose mode ... OK, but this is weird! " + << endmsg; + } + + if(m_triggerList.size() == 0 && iv ) + { + warning() << "You have not set a list of triggers to look for, but have asked for verbose output. " + << endmsg; + m_verboseL0 = m_verboseHlt1 = m_verboseHlt2 = m_verboseStripping =false; + } + + //bug, missing this line + if ( !m_triggerList.empty() ) compileMyList(m_triggerList); + + return sc; +} + +//========================================================================= +// Fill +//========================================================================= + +StatusCode TupleToolTriggerBase::fill( const LHCb::Particle* M + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + if(msgLevel(MSG::DEBUG)) debug() << "fill particle " << P + << endmsg; + + bool test=true; + test &= fillBasic(M, P, head, tuple); + + //Fill details about the requested triggers + if(m_verboseL0 || m_verboseHlt1 || m_verboseHlt2 || m_verboseStripping || isVerbose()) + test &=fillVerbose(M, P, head, tuple); + + return StatusCode(test); +} + +StatusCode TupleToolTriggerBase::fill(Tuples::Tuple& tuple ) +{ + if(msgLevel(MSG::DEBUG)) debug() << "fill tuple " + << endmsg; + bool test=true; + test &= fillBasic(tuple); + + //Fill details about the requested triggers + if(m_verboseL0 || m_verboseHlt1 || m_verboseHlt2 || m_verboseStripping || isVerbose()) test &=fillVerbose(tuple); + + return StatusCode(test); +} + + +bool TupleToolTriggerBase::compileMyList(const std::vector& list) +{ + + if(msgLevel(MSG::DEBUG)) debug() << "compiling List " + << endmsg; + + //boost::regex l0("Hlt1L0.*Decision"); + //boost::regex hlt1("Hlt1[^L0].*Decision"); + boost::regex l0("L0.*Decision"); + boost::regex hlt1("Hlt1.*Decision"); + boost::regex hlt2("Hlt2.*Decision"); + boost::regex strip("Stripping.*Decision"); + + for ( std::vector< std::string >::const_iterator s = list.begin(); + s != list.end(); ++s ) + { + if( boost::regex_match( *s, l0 ) ) + { + m_l0.push_back(*s); + } + else if( boost::regex_match( *s, hlt1 ) ) + { + m_hlt1.push_back(*s); + } + else if( boost::regex_match( *s, hlt2 ) ) + { + m_hlt2.push_back(*s); + } + else if( boost::regex_match( *s, strip ) ) + { + m_stripping.push_back(*s); + } + else + { + error() << "List member ``" << *s + << "'' does not match any known pattern. Have you forgotten the trailing 'Decision' or the starting 'Stripping' ?" + << endmsg ; + } + } + + + if(msgLevel(MSG::DEBUG)) + { + debug() << " ==== L0 ==== " << endmsg; + for (std::vector::const_iterator s=m_l0.begin();s != m_l0.end();++s) debug() << " " << (*s); + debug() <::const_iterator s=m_hlt1.begin();s != m_hlt1.end();++s) debug() << " " << (*s); + debug() <::const_iterator s=m_hlt2.begin();s != m_hlt2.end();++s) debug() << " " << (*s); + debug() <::const_iterator s=m_stripping.begin();s != m_stripping.end();++s) debug() << " " << (*s); + debug() < m_l0; + std::vector m_hlt1; + std::vector m_hlt2; + std::vector m_stripping; + + + std::vector m_triggerList;//property: list of triggers to specifically look at + + bool compileMyList(const std::vector& list); + bool appendToList(); + + std::vector< std::string > l0TriggersFromL0DU() const; + +protected: + + virtual StatusCode fillBasic( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ); + + virtual StatusCode fillBasic( Tuples::Tuple& ); + + virtual StatusCode fillVerbose( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ); + + virtual StatusCode fillVerbose( Tuples::Tuple& ); + +}; + +#endif // TUPLETOOLTRIGGERBASE_H diff --git a/first-analysis-steps/DecayTrees/TupleToolTriggerRecoStats.cpp b/first-analysis-steps/DecayTrees/TupleToolTriggerRecoStats.cpp new file mode 100644 index 00000000..67ca3a42 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTriggerRecoStats.cpp @@ -0,0 +1,51 @@ +#include "TupleToolTriggerRecoStats.h" +#include "Event/Particle.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolTriggerRecoStats +// +// 2009-07-30 : Patrick Koppenburg +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolTriggerRecoStats ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolTriggerRecoStats::TupleToolTriggerRecoStats( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ), + m_locations() +{ + declareInterface(this); + m_locations.push_back("Hlt2NoCutsPions"); + m_locations.push_back("Hlt2GoodPions"); + m_locations.push_back("Hlt2Muons"); + m_locations.push_back("Hlt2Electrons"); + m_locations.push_back("Hlt2Photons"); + m_locations.push_back("Hlt2BiKalmanFittedRichKaons"); + declareProperty("InputLocations",m_locations,"Locations to look at"); +} + +//============================================================================= +// Destructor +//============================================================================= +TupleToolTriggerRecoStats::~TupleToolTriggerRecoStats() { } + +//============================================================================= +//============================================================================= +// Fill +//============================================================================= +StatusCode TupleToolTriggerRecoStats::fill( Tuples::Tuple& tup) +{ + const std::string prefix=fullName(); + bool test = true; + for ( std::vector::const_iterator l = m_locations.begin() ; + l != m_locations.end() ; ++l) + { + test &= tup->column(prefix+"NumberOf"+*l,number("/Event/Hlt2/"+*l+"/Particles")); + } + return StatusCode(test) ; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolTriggerRecoStats.h b/first-analysis-steps/DecayTrees/TupleToolTriggerRecoStats.h new file mode 100644 index 00000000..6275bc32 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTriggerRecoStats.h @@ -0,0 +1,35 @@ +// $Id: TupleToolTriggerRecoStats.h,v 1.2 2010-01-26 15:39:27 rlambert Exp $ +#ifndef TUPLETOOLTRIGGERRECOSTATS_H +#define TUPLETOOLTRIGGERRECOSTATS_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IEventTupleTool.h" // Interface + + +/** @class TupleToolTriggerRecoStats TupleToolTriggerRecoStats.h + * + * Counts the number of particles per type + * + * @author Patrick Koppenburg + * @date 2009-07-30 + */ +class TupleToolTriggerRecoStats : public TupleToolBase, virtual public IEventTupleTool { +public: + /// Standard constructor + TupleToolTriggerRecoStats( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolTriggerRecoStats( ); ///< Destructor + StatusCode fill( Tuples::Tuple& ) override;///< Fill tuple + +protected: + +private: + + std::vector m_locations ; ///< Hlt locations to look at + +}; +#endif // TUPLETOOLTRIGGERRECOSTATS_H diff --git a/first-analysis-steps/DecayTrees/TupleToolTwoParticleMatching.cpp b/first-analysis-steps/DecayTrees/TupleToolTwoParticleMatching.cpp new file mode 100644 index 00000000..ab88a826 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTwoParticleMatching.cpp @@ -0,0 +1,138 @@ +// $Id: TupleToolTwoParticleMatching.cpp,v 1.0 2015-02-27 08:59:11 ikomarov $ + +#include "TupleToolTwoParticleMatching.h" +#include "Kernel/HashIDs.h" +#include "Kernel/ParticleProperty.h" +#include "Kernel/IParticlePropertySvc.h" +#include +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolTwoParticleMatching +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolTwoParticleMatching ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolTwoParticleMatching::TupleToolTwoParticleMatching( const std::string& type, + const std::string& name, + const IInterface* parent ) +: TupleToolBase ( type, name, parent ) + //,m_tuple ( NULL ) +{ + std::vector toolNames_default; + + toolNames_default.push_back ( "TupleToolKinematic" ); + toolNames_default.push_back ( "TupleToolPid" ); + //toolNames_default.push_back ( "TupleToolGeometry" ); + toolNames_default.push_back ( "TupleToolMCTruth" ); + toolNames_default.push_back ( "TupleToolMCBackgroundInfo" ); + + declareProperty ( "MatchLocations" , m_matching_locations ); + declareProperty( "ToolList", m_toolNames = toolNames_default ); + declareProperty( "Prefix", m_headPrefix = "Matched_" ); + declareProperty( "Suffix", m_headSuffix = ""); + declareProperty( "MatcherTool", m_teslaMatcherName = "TeslaMatcher:PUBLIC" ); + declareInterface(this); + +// PROPERTY INCLUDED TO PRESERVE BACKWARD COMPATIBILITY + declareProperty( "MatchWith", m_matching_location = "OBSOLETE" ); + declareProperty( "TupleTools", m_toolNames); + +} + +//============================================================================= + +StatusCode TupleToolTwoParticleMatching::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + for(std::vector::iterator iName = m_toolNames.begin(); iName != m_toolNames.end(); ++iName) + { + if ((*iName)=="TupleToolGeometry") + { + warning()<<"Geometry tuple tool can not be used in matching (yet). Please find a way how to include it by yourself."<( *iName, *iName+":PUBLIC", this )); + } + } + + if (m_matching_location != "OBSOLETE") + { + error() << "Option MatchWith is deprecated. Use MatchLocations instead." << endmsg; + m_matching_locations ["J/psi(1S)"] = m_matching_location; + } + + // Gets the ParticleProperty service + LHCb::IParticlePropertySvc* ppSvc = + this -> template svc + ( "LHCb::ParticlePropertySvc" , true) ; + + std::map::const_iterator matchLocation; + + for (matchLocation = m_matching_locations.begin(); + matchLocation != m_matching_locations.end(); + matchLocation++) + { + const LHCb::ParticleProperty* property = ppSvc->find(matchLocation->first); + if (property) + m_parsed_locations [ abs(property->pdgID().pid()) ] = matchLocation->second; + } + + m_matcher = tool(m_teslaMatcherName, this); + + return sc; +} + +//============================================================================= + +StatusCode TupleToolTwoParticleMatching::fill( const LHCb::Particle* + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + StatusCode sc = StatusCode::SUCCESS; + + const std::string prefix = m_headPrefix + fullName(head) + m_headSuffix; + + if (!P) + return StatusCode ( true ); + + const int pid = abs(P->particleID().pid()); + const int apid = abs(pid); + + if (m_parsed_locations.count(apid)) + { + const LHCb::Particle* best_particle = P; + const std::string matching_location ( m_parsed_locations [ apid ] ); + + double o1(-9999), o2(-9999), counter(-9999); + + if ( sc ) sc = m_matcher->findBestMatch (P, best_particle, matching_location); + if (sc && best_particle) + { + std::pair o = LHCb::HashIDs::overlap(best_particle, P); + + o1 = o.first; o2 = o.second; + counter = 1; + } + else + { + best_particle = P; //reset to P + Error("Matching failed.", StatusCode::SUCCESS); + } + + if ( sc ) sc = tuple->column("NMatchingCand_"+fullName(head)+m_headSuffix, counter); + if ( sc ) sc = tuple->column("Overlap_loaded_"+fullName(head)+m_headSuffix, o1); + if ( sc ) sc = tuple->column("Overlap_original_"+fullName(head)+m_headSuffix, o2); + + + for(std::vector::const_iterator iTool = m_tuple.begin(); iTool != m_tuple.end(); ++iTool) + if ( sc ) sc = (*iTool)->fill( best_particle, best_particle, prefix, tuple ); + } + return sc; +} diff --git a/first-analysis-steps/DecayTrees/TupleToolTwoParticleMatching.h b/first-analysis-steps/DecayTrees/TupleToolTwoParticleMatching.h new file mode 100644 index 00000000..e1191fe4 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolTwoParticleMatching.h @@ -0,0 +1,101 @@ +// $Id: TupleToolTwoParticleMatching.h,v 1.0 2015-02-27 08:59:11 ikomarov $ +#ifndef _TupleToolTwoParticleMatching_H +#define _TupleToolTwoParticleMatching_H 1 + +// Base class +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "TupleToolKinematic.h" + +// Interfaces +#include "Kernel/IParticleTupleTool.h" +#include "RecInterfaces/IChargedProtoANNPIDTupleTool.h" + +// TeslaTools +#include "TeslaTools/ITeslaMatcher.h" + + +/** @class TupleToolTwoParticleMatching TupleToolTwoParticleMatching.h + * + * \brief Find the best matching particle from given location and wfill information about it to nTuple + * + * This tool should be applied as usual tuple tool for certain particle. + * + * As an input it takes locstion in dst, which contain paticles to compare with. + * For example, one might run this tool for Tesla candidates and give location of + * stripping candidates to compare with. + * + * Having original particle (TupleTool was called for this particle in gaudi script) + * and a list of particles in the same event from given location, tool finds best matching candidate. + * Best matching candidate (a.k.a. matched particle) has maximal overlap in LHCbIDs with original particle. + * + * Another input is the list of tuple tools which should be aplied to matched particle. + * Pay attention that it takes just name of the tools, so at this moment it's impossible + * to use pre-configured tool (unfortunately, LoKi TupleTool will not work) + * Another restriction - since location of PVs should be the same for both particles, + * tools like TupleToolGeometry will not work correctly and they are obsoleted in current version. + * + * Leaves filled by the tool: + * - NMatchingCand_(head): Number of candidates in the same event in given location + * - Overlap_original_(head): output of HashIDs::overlap(original_particle, loaded_particle) for original particle + * - Overlap_loaded_(head): output of HashIDs::overlap(original_particle, loaded_particle) for matched particle + * - Matched_(head)_(Property_of_Matching_Particle): output of tuple tool aplied for best matching particle + * + * Example of usage in gaudi script: + * @code + * matching_tools = [ "TupleToolKinematic", "TupleToolMCTruth", "TupleToolMCBackgroundInfo"] + * tm = tesla_tuple.addTupleTool(TupleToolTwoParticleMatching, name = "TupleToolTwoParticleMatching") + * tm.MatchLocations = { + * "J/psi(1S)" : "Phys/SelMyJPsi/Particles", #Location of particles to match J/psi with + * } + * tm.ToolList = matching_tools + * + * from Configurables import LoKi__Hybrid__TupleTool as LoKiTool + * lokitool = LoKiTool ( "MatchedLoki" ) + * lokitool.Variables = { "P" : "P" } + * tm.addTool ( lokitool ) + * tm.ToolList += ["LoKi::Hybrid::TupleTool/MatchedLoki"] + * + * @endcode + * + * \sa DecayTreeTuple + * + * @author Ilya Komarov + * @date 2015-02-27 + */ +class TupleToolTwoParticleMatching : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + // Standard constructor + TupleToolTwoParticleMatching( const std::string& type, + const std::string& name, + const IInterface* parent); + + ~TupleToolTwoParticleMatching() {} + + StatusCode initialize() override; + +public: + + StatusCode fill(const LHCb::Particle*, + const LHCb::Particle*, + const std::string& , + Tuples::Tuple& ) override; + +private: + std::vector m_toolNames; + std::vector m_tuple; + std::string m_headPrefix, m_headSuffix; + std::string m_matching_location; + + std::map m_matching_locations; + std::map m_parsed_locations; + + std::string m_teslaMatcherName; + ITeslaMatcher* m_matcher; + +}; + +#endif diff --git a/first-analysis-steps/DecayTrees/TupleToolVELOClusters.cpp b/first-analysis-steps/DecayTrees/TupleToolVELOClusters.cpp new file mode 100644 index 00000000..2ee4bff8 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolVELOClusters.cpp @@ -0,0 +1,90 @@ +// Include files + +// from Gaudi +#include "TupleToolVELOClusters.h" +#include "Event/Track.h" +#include "Event/ODIN.h" + +// local +#include "TupleToolVELOClusters.h" + +//----------------------------------------------------------------------------- + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolVELOClusters::TupleToolVELOClusters( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name, parent ) +{ + declareInterface(this); +} + +StatusCode TupleToolVELOClusters::fill( Tuples::Tuple& tup ) +{ + const std::string prefix = fullName(); + + // Fill the tuple + bool test = true; + std::vector stations; + std::vector stationADC; + + std::vector vids; vids.reserve(1000); + LHCb::Tracks* tracksCont = get( LHCb::TrackLocation::Default ); + if ( !tracksCont || tracksCont->empty() ) + { + return StatusCode::FAILURE; + } + for (LHCb::Tracks::iterator iter = tracksCont->begin(); + iter != tracksCont->end(); ++iter){ + const std::vector& ids = (*iter)->lhcbIDs(); + for ( std::vector::const_iterator it = ids.begin(); it != ids.end(); ++it ) + { + if ( it->isVelo() ) vids.push_back(it->veloID()); + } // lhcbids + } // tracks + + std::sort(vids.begin(), vids.end()); + std::vector::iterator u = std::unique(vids.begin(), vids.end()); + vids.resize(u - vids.begin()); + + LHCb::VeloClusters* clusters = getIfExists( evtSvc() , m_locationClusters ); + if ( !clusters || clusters->empty() ) + { + Warning( "No VeloClusters found at location " + m_locationClusters + " for this event " ).ignore(); + return StatusCode::SUCCESS; + } + // MDN loop over the clusters + for ( LHCb::VeloClusters::iterator iterV = clusters->begin(); iterV != clusters->end(); ++iterV ) + { + // check if used on track + if (std::find(vids.begin(), vids.end(),(*iterV)->channelID()) == vids.end()) + { + + if ( msgLevel(MSG::DEBUG) ) + debug() << "hit is not on track " + << (*iterV)->isRType() << " "<< (*iterV)->isPhiType() << " " + << (*iterV)->isPileUp() << endmsg; + + const double mysensor = (double)(*iterV)->channelID().sensor(); + stations.push_back(mysensor); + const double adc = (*iterV)->totalCharge(); + stationADC.push_back(adc); + + } + } + + const int unusedvelo = clusters->size() - vids.size() ; + + //info() << " n unused = " << unusedvelo << endmsg; + test &= tup->column( prefix+"nUnusedVeloClusters", unusedvelo); + test &= tup->farray( prefix+"UNUSED_VELO_STATION_ADC", stationADC.begin(), stationADC.end(), "nClusters" , 100); + test &= tup->farray( prefix+"UNUSED_VELO_STATION_VECTOR", stations.begin(), stations.end(), "nClusters", 100); + + return StatusCode(test); +} + + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolVELOClusters ) diff --git a/first-analysis-steps/DecayTrees/TupleToolVELOClusters.h b/first-analysis-steps/DecayTrees/TupleToolVELOClusters.h new file mode 100644 index 00000000..816bcd9f --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolVELOClusters.h @@ -0,0 +1,36 @@ +#ifndef TUPLETOOLRECOSTATS_H +#define TUPLETOOLRECOSTATS_H 1 + +// Include files +// from Gaudi +#include "Kernel/IEventTupleTool.h" // Interface +#include "DecayTreeTupleBase/TupleToolBase.h" + +#include "Event/VeloCluster.h" +#include "Event/Track.h" + +/** @class TupleToolVELOClusters TupleToolVELOClusters.h + * + * Fills VELO information + */ +class TupleToolVELOClusters : public TupleToolBase, + virtual public IEventTupleTool +{ + +public: + + /// Standard constructor + TupleToolVELOClusters( const std::string& type, + const std::string& name, + const IInterface* parent); + + /// Declare properties + Gaudi::Property< std::string > m_locationClusters{this, "VeloClusterLocation", LHCb::VeloClusterLocation::Default, "Location of VELO clusters"}; + + StatusCode fill( Tuples::Tuple& ) override;///< Fill tuple + // int unusedVelo(); + +}; + +#endif // TUPLETOOLRECOSTATS_H + diff --git a/first-analysis-steps/DecayTrees/TupleToolVeloTrackClusterInfo.cpp b/first-analysis-steps/DecayTrees/TupleToolVeloTrackClusterInfo.cpp new file mode 100755 index 00000000..4b620fae --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolVeloTrackClusterInfo.cpp @@ -0,0 +1,98 @@ +// Include files + +// local +#include "TupleToolVeloTrackClusterInfo.h" + +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" + +#include "Event/Particle.h" +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolVeloTrackClusterInfo +// +// 2012-12-12 : Kazu Akiba +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolVeloTrackClusterInfo ) + + //============================================================================= + // Standard constructor, initializes variables + //============================================================================= +TupleToolVeloTrackClusterInfo::TupleToolVeloTrackClusterInfo( const std::string& type, + const std::string& name, + const IInterface* parent ) +: TupleToolBase ( type, name , parent ) +{ + declareInterface(this); + +} + +//============================================================================= + +StatusCode TupleToolVeloTrackClusterInfo::fill( const LHCb::Particle* + , const LHCb::Particle* P + , const std::string& head + , Tuples::Tuple& tuple ) +{ + const std::string prefix = fullName(head); + + const size_t maxStationsInVeloTrack = 100; + bool test = true; + if ( !P ) return StatusCode::FAILURE; + + //first just return if the particle isn't supposed to have a track + if ( !P->isBasicParticle() ) return StatusCode::SUCCESS; + + const LHCb::ProtoParticle* protop = P->proto(); + if (!protop) return StatusCode::SUCCESS; + + const LHCb::Track* track = protop->track(); + if (!track) return StatusCode::SUCCESS; + + else test &= tuple->column( prefix+"_TRACK_TCHI2NDOF",-1.); + std::vector stations; + std::vector stationADC; + double averageCharge =0; + double totalChargeOnTrack=0; + double nClustersOnTrack =0; + const std::vector& ids = (track)->lhcbIDs(); + for ( std::vector::const_iterator it = ids.begin(); it != ids.end(); ++it ){ + if (it->isVelo() == true) { + const LHCb::VeloChannelID vcID = (it)->veloID(); + //Veloclusters: + LHCb::VeloClusters *m_clusters = get( m_locationClusters ); + debug() << " -> number of clusters found in TES: " << m_clusters->size() <object( vcID ); + if(!cluster) return StatusCode::SUCCESS; + if ( 0 == cluster ) { + error() << "Missing cluster with ID " << vcID << endmsg; + continue; + } + int sensor = it->veloID().sensor(); + double mysensor = sensor; + stations.push_back(mysensor); + double adc = cluster->totalCharge(); + stationADC.push_back(adc); + averageCharge+=adc; + nClustersOnTrack++; + } + } // lhcbids + + totalChargeOnTrack=averageCharge; + if (nClustersOnTrack>0) averageCharge/=nClustersOnTrack; + else averageCharge = -1000; + + int nVeloClustersOnTrack = (int) nClustersOnTrack; + test &= tuple->column( prefix+"_TRACK_VELO_TOTALCHARGE", totalChargeOnTrack); + test &= tuple->column( prefix+"_TRACK_VELO_AVERAGECHARGE", averageCharge); + test &= tuple->column( prefix+"_TRACK_VELO_CLUSTERSONTRACK", nVeloClustersOnTrack); + //for (int ii = 0; ii farray( prefix+"_TRACK_VELO_STATION_ADC", stationADC.begin(), stationADC.end(), "nClusters" , maxStationsInVeloTrack); + //for (int ii = 0; ii farray( prefix+"_TRACK_VELO_STATION_VECTOR", stations.begin(), stations.end(), "nClusters", maxStationsInVeloTrack); + + return StatusCode(test); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolVeloTrackClusterInfo.h b/first-analysis-steps/DecayTrees/TupleToolVeloTrackClusterInfo.h new file mode 100755 index 00000000..93a5359e --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolVeloTrackClusterInfo.h @@ -0,0 +1,43 @@ +#ifndef JBOREL_TUPLETOOLTRACKINFO_H +#define JBOREL_TUPLETOOLTRACKINFO_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "Event/VeloCluster.h" +#include "Event/Track.h" +#include "Event/Particle.h" +#include "TrackInterfaces/IVeloClusterPosition.h" +#include "TrackInterfaces/IVeloExpectation.h" +#include "TrackInterfaces/IMeasurementProvider.h" + +/** @class TupleToolVeloTrackClusterInfo TupleToolVeloTrackClusterInfo.h jborel/TupleToolVeloTrackClusterInfo.h + * + * _TRACK_VELO_TOTALCHARGE sum of the adc counts of the velo clusters + * _TRACK_VELO_AVERAGECHARGE average adc counts + * _TRACK_VELO_CLUSTERSONTRACK how many velo clusters on this track + * _TRACK_VELO_STATION_ADC adc counts indexed in a vector + * _TRACK_VELO_STATION_VECTOR vector with the sensor numbers of the clusters same index as the adc. + * + * @author Kazu Akiba + * @date 2012-12-12 + */ +class TupleToolVeloTrackClusterInfo : public TupleToolBase, virtual public IParticleTupleTool { +public: + /// Standard constructor + TupleToolVeloTrackClusterInfo( const std::string& type, + const std::string& name, + const IInterface* parent); + + /// Declare properties + Gaudi::Property< std::string > m_locationClusters{this, "VeloClusterLocation", LHCb::VeloClusterLocation::Default, "Location of VELO clusters"}; + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +}; + +#endif // JBOREL_TUPLETOOLTRACKINFO_H diff --git a/first-analysis-steps/DecayTrees/TupleToolVeloTrackMatch.cpp b/first-analysis-steps/DecayTrees/TupleToolVeloTrackMatch.cpp new file mode 100644 index 00000000..32e14622 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolVeloTrackMatch.cpp @@ -0,0 +1,240 @@ +#include +#include +// local +#include "TupleToolVeloTrackMatch.h" + +using namespace LHCb ; + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolVeloTrackMatch +// +// 2013-11-21 : Andrea Contu +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolVeloTrackMatch ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolVeloTrackMatch::TupleToolVeloTrackMatch( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name, parent ) + , m_dva(0) + , m_slopediff(0) + , m_momentumcone(false) +{ + declareInterface(this); + declareProperty("ConeAngle", m_slopediff = 0.05); + declareProperty("ConeAroundMomentum", m_momentumcone = false); + declareProperty("VerboseInfo", m_verbose = false); + declareProperty("MaxIPwrtBestPV", m_maxVbestPVdist=0.5); +} + +//============================================================================= +// Initialize +//============================================================================= +StatusCode TupleToolVeloTrackMatch::initialize(){ + StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_dva = Gaudi::Utils::getIDVAlgorithm ( contextSvc(), this ) ; + if (!m_dva) return Error("Couldn't get parent DVAlgorithm", + StatusCode::FAILURE); + + return sc; +} + + + +//============================================================================= +// Fill +//============================================================================= +StatusCode TupleToolVeloTrackMatch::fill( const LHCb::Particle * /* top */, + const LHCb::Particle *part, + const std::string & head, + Tuples::Tuple & tuple ){ + + const std::string prefix=fullName(head); + StatusCode sc=StatusCode::SUCCESS; + + const unsigned int maxVeloTracks = 2000 ; + + std::vector vfirstpoints; + std::vector vslopes; + std::vector vslopesx,vslopesy; + std::vector vslopesxxerr,vslopesyyerr,vslopesxyerr; + std::vector vslopesxratio,vslopesyratio,vR; + std::vector vfpx,vfpy,vfpz; + std::vector vfpxxerr,vfpyyerr,vfpxyerr; + std::vector vconedist; + std::vector vbestip; + + double ipcut=m_maxVbestPVdist; + + double bestdt=9999.; + double bestip=9999.; + double nvelotracks=-1.; + double bestsloperatiox=9999.; + double bestsloperatioy=9999.; + double bestconedist=9999.; + unsigned int besttrackindex=-1; + Gaudi::XYZPoint bestfposition; + Gaudi::SymMatrix3x3 bestfpositionerr; + Gaudi::XYZPoint bestslopes; + Gaudi::SymMatrix3x3 bestslopeserr; + + if(!part->isBasicParticle() && part->endVertex()){ + + Gaudi::LorentzVector lorvectmother=part->momentum(); + + bool conemom=m_momentumcone; + const VertexBase* aPV = NULL; + + if(!m_momentumcone) { + aPV = m_dva->bestVertex (part); + if(!aPV){ + conemom=true; + ipcut=9999.; + Warning("Could not find best PV, falling back to momentum cone!"); + } + } + else{ + conemom=true; + } + + double mpx=9999.; + double mpy=9999.; + double mpz=9999.; + + if(!conemom){ + mpx=aPV->position().x()-part->endVertex()->position().x(); + mpy=aPV->position().y()-part->endVertex()->position().y(); + mpz=aPV->position().z()-part->endVertex()->position().z(); + } + + else{ + mpx=lorvectmother.Px(); + mpy=lorvectmother.Py(); + mpz=lorvectmother.Pz(); + } + double msx=mpx/mpz; + double msy=mpy/mpz; + + LHCb::Track::Range vtrax=get(LHCb::TrackLocation::Velo); + + if(vtrax.size()==0){ + return Warning("Could not find any VELO track, you may need to re-run the VELO tracking",sc); + } + + for(LHCb::Track::Range::const_iterator tri=vtrax.begin(); tri!= vtrax.end(); ++tri){ + const Track *tmptrack=(*tri); + if(tmptrack->type()==LHCb::Track::Types::Velo){ + Gaudi::XYZPoint tmpfp; + Gaudi::SymMatrix3x3 fperror; + tmptrack->position(tmpfp,fperror); + + Gaudi::XYZVector tmpslope; + Gaudi::SymMatrix3x3 slopeerror; + tmptrack->slopes(tmpslope,slopeerror); + double dtx = msx - tmpslope.X() ; + double dty = msy - tmpslope.Y() ; + double dt = std::sqrt(dtx*dtx+dty*dty) ; + double tmpR3d=sqrt(pow((1-tmpslope.X()/msx),2)+pow((1-tmpslope.Y()/msy),2)); + + double ipbestpv=-1.; + double tmpvect2=0.; + double tmpscalar2=0.; + + if(!conemom){ + tmpvect2= pow((tmpfp.X()-aPV->position().x()),2) + pow((tmpfp.Y()-aPV->position().y()),2) + pow((tmpfp.Z()-aPV->position().z()),2); + tmpscalar2=pow( ((tmpfp.X()-aPV->position().x())*tmpslope.X() + (tmpfp.Y()-aPV->position().y())*tmpslope.Y() + (tmpfp.Z()-aPV->position().z())),2)/(tmpslope.X()*tmpslope.X()+tmpslope.Y()*tmpslope.Y()+tmpslope.Z()*tmpslope.Z()); + ipbestpv=sqrt(tmpvect2-tmpscalar2); + } + + if(dtcolumn(prefix+"_VM_cand_slope_X",msx); + tuple->column(prefix+"_VM_cand_slope_Y",msy); + tuple->column(prefix+"_VM_nvelotracks",nvelotracks); + tuple->column(prefix+"_VM_R",bestdt); + tuple->column(prefix+"_VM_IP",bestip); + tuple->column(prefix+"_VM_CD",bestconedist); + tuple->column(prefix+"_VM_index",besttrackindex); + tuple->column(prefix+"_VM_fpos_X",bestfposition.X()); + tuple->column(prefix+"_VM_fpos_Y",bestfposition.Y()); + tuple->column(prefix+"_VM_fpos_Z",bestfposition.Z()); + tuple->column(prefix+"_VM_fpos_err_XX",bestfpositionerr(0,0)); + tuple->column(prefix+"_VM_fpos_err_YY",bestfpositionerr(1,1)); + tuple->column(prefix+"_VM_fpos_err_XY",bestfpositionerr(0,1)); + tuple->column(prefix+"_VM_sloperatio_X",bestsloperatiox); + tuple->column(prefix+"_VM_sloperatio_Y",bestsloperatioy); + tuple->column(prefix+"_VM_slope_X",bestslopes.X()); + tuple->column(prefix+"_VM_slope_Y",bestslopes.Y()); + tuple->column(prefix+"_VM_slope_err_XX",bestslopeserr(0,0)); + tuple->column(prefix+"_VM_slope_err_YY",bestslopeserr(1,1)); + tuple->column(prefix+"_VM_slope_err_XY",bestslopeserr(0,1)); + + if(m_verbose){ + tuple->farray( prefix+"_VM_array_fpos_X", vfpx ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_fpos_Y", vfpy ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_fpos_Z", vfpz ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_fpos_err_XX", vfpxxerr ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_fpos_err_YY", vfpyyerr ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_fpos_err_XY", vfpxyerr ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_slope_X", vslopesx ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_slope_Y", vslopesy ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_slope_err_XX", vslopesxxerr ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_slope_err_YY", vslopesyyerr ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_slope_err_XY", vslopesxyerr ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_sloperatio_X", vslopesxratio ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_sloperatio_Y", vslopesyratio ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_R", vR ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_IP", vbestip ,prefix+"_VM_nTP",maxVeloTracks ); + tuple->farray( prefix+"_VM_array_CD", vconedist ,prefix+"_VM_nTP",maxVeloTracks ); + } + } + else{ + return Warning("Particle "+prefix+" is not composite or does not have an endvertex!",sc); + } + return sc; +} +//============================================================================= +// Destructor +//============================================================================= +TupleToolVeloTrackMatch::~TupleToolVeloTrackMatch() {} + +//============================================================================= diff --git a/first-analysis-steps/DecayTrees/TupleToolVeloTrackMatch.h b/first-analysis-steps/DecayTrees/TupleToolVeloTrackMatch.h new file mode 100644 index 00000000..c30ec855 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolVeloTrackMatch.h @@ -0,0 +1,105 @@ +// $Id: TupleToolVeloTrackMatch.h +#ifndef TupleToolVeloTrackMatch_H +#define TupleToolVeloTrackMatch_H 1 + +#include "Kernel/IParticleTupleTool.h" +#include "DecayTreeTupleBase/TupleToolBase.h" + +/** @class TupleToolVeloTrackMatch TupleToolVeloTrackMatch.h +* \brief Fill information about velo tracks matching the flight direction of a downstream composite candidate +* The tool searches for velo tracks at LHCb::TrackLocation::Velo around a given direction, re-running the Velo tracking beforehand may be necessary +* +* -The cone angle can be set using the property "ConeRadius", the default value is 0.05 +* This is an approximation of the true angle, it is sqrt( (slopedifference_X)^2 + (slopedifference_Y)^2 ), +* Where slopedifference is the difference in slope between the velo track and the reference direction +* +* -The minimum distance of the VELO tracks from the best PV can be set using the property "MaxIPwrtBestPV", the default value is 0,5 mm +* +* -If ConeAroundMomentum=True: +* The reference direction is set to be the 3-momentum of the downstream candidate +* if False (default value) is the flight direction determined by the decay vertex and the associate PV +* +* -If sxratio(syratio) is the ratio between the slope dx/dz(dy/dz) of the velo track wrt the reference direction +* we define R +* R=sqrt( (1-sxratio)^2 + (1-syratio)^2 ) +* the "best velo" track is the one with the smaller R +* +* head_VM_cand_slope_X: dx/dz of reference direction +* head_VM_cand_slope_Y: dy/dz of reference direction +* head_VM_nvelotracks: number of velo tracks inside the cone +* head_VM_R: R of best velo track +* head_VM_IP: IP of best velo track wrt best PV +* head_VM_CD: cone angle best velo track +* head_VM_chi2: chi2 of velo track fit +* head_VM_index: index of best velo track +* head_VM_nMeas: number of measurements for the best velo track +* head_VM_fpos_X: X position at first state for best velo track +* head_VM_fpos_Y: Y position at first state for best velo track +* head_VM_fpos_Z: Z position at first state for best velo track +* head_VM_fpos_err_XX: XX error matrix of first state for best velo track +* head_VM_fpos_err_YY: YY error matrix of first state for best velo track +* head_VM_fpos_err_XY: ZZ error matrix of first state for best velo track +* head_VM_sloperatio_X: slope ratio X of best velo track wrt reference direction +* head_VM_sloperatio_Y: slope ratio Y of best velo track wrt reference direction +* head_VM_slope_X: dx/dz slope of best velo track +* head_VM_slope_Y: dy/dz slope of best velo track +* head_VM_slope_err_XX: XX error matrix of the slope for best velo track +* head_VM_slope_err_YY: YY error matrix of the slope for best velo track +* head_VM_slope_err_XY: YY error matrix of the slope for best velo track +* +* -If Verbose=True +* Same meaning as amove but for all velo tracks in the cone +* head_VM_array_fpos_X +* head_VM_array_fpos_Y +* head_VM_array_fpos_Z +* head_VM_array_fpos_err_XX +* head_VM_array_fpos_err_YY +* head_VM_array_fpos_err_XY +* head_VM_array_slope_X +* head_VM_array_slope_Y +* head_VM_array_slope_err_XX +* head_VM_array_slope_err_YY +* head_VM_array_slope_err_XY +* head_VM_array_sloperatio_X +* head_VM_array_sloperatio_Y +* head_VM_array_R +* head_VM_array_IP +* head_VM_array_CD +* head_VM_array_chi2 +* head_VM_array_nMeas +* +* @author Andrea Contu +* @date 2013-11-21 +*/ +class TupleToolVeloTrackMatch : public TupleToolBase, public virtual IParticleTupleTool{ + + public: + + /// Standard constructor + TupleToolVeloTrackMatch(const std::string& type, + const std::string& name, + const IInterface* parent ); + + /// Standard initialization + StatusCode initialize() override; + + virtual ~TupleToolVeloTrackMatch( ); ///< Destructor + + public: + + StatusCode fill( const LHCb::Particle*, const LHCb::Particle*, + const std::string & head, Tuples::Tuple& tuple ) override; + + private: + + + + private: + IDVAlgorithm* m_dva; + double m_slopediff; + bool m_momentumcone; + bool m_verbose; + double m_maxVbestPVdist; +}; +#endif // TupleToolVeloTrackMatch_H + diff --git a/first-analysis-steps/DecayTrees/TupleToolVeto.cpp b/first-analysis-steps/DecayTrees/TupleToolVeto.cpp new file mode 100644 index 00000000..87aa95af --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolVeto.cpp @@ -0,0 +1,114 @@ +// $Id: TupleToolVeto.cpp +// Include files + +// local +#include "TupleToolVeto.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "Event/Particle.h" +#include "GaudiKernel/IRegistry.h" // +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolVeto +// +// Flag particle P when it overlaps with any particle from given container(s) +// +// usage : +// +// mytuple.Particle="name" # the specific particle to be checked (default : all maked DecayTreeTuple::DecayDescriptor particles) +// mytuple.TupleToolVeto[VetoName].["Container1","Container2",...] # list of containers to be checked +// +// +// e.g.: +// - pi0-Veto for single photon : flag all photons which are already used to build a pi0 as defined in StdLooseResolvedPi0 +// mytuple.TupleToolVeto.Particle="gamma" +// mytuple.TupleToolVeto.Veto[Pi0R]=["/Event/Phys/StdLooseResolvedPi0/Particles"] +// +// - pi0-veto for pi0 : flag all pi0 which are not exclusive with respect to **other** pi0's +// mytuple.TupleToolVeto.Particle="pi0" +// mytuple.TupleToolVeto.VetoOther[Pi0R]=["/Event/Phys/StdLooseResolvedPi0/Particles"] +// +// -> the overlap of the pi0 with itself is not considered (property VetoOther) - only partial overlap are checked +// +// - works for any (composite or basic) particle. Relies on tool DaVinciTools/ParticleVeto (see doxygen for details) +// +// +//----------------------------------------------------------------------------- + +using namespace Gaudi; +using namespace LHCb; + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolVeto ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolVeto::TupleToolVeto( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ), + m_pid(0) +{ + declareInterface(this); + declareProperty("Particle",m_part=""); + declareProperty("Veto", m_veto); + declareProperty("VetoOther", m_vetoOther); +} + +StatusCode TupleToolVeto::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + m_check = tool("ParticleVeto","ParticleVeto" ,this ); + if ( !m_part.empty() ) + { + LHCb::IParticlePropertySvc* ppsvc = + svc("LHCb::ParticlePropertySvc",true) ; + const LHCb::ParticleProperty* pp = ppsvc->find( m_part ); + m_pid = (pp) ? pp->pdgID().abspid() : 0; + } + return sc; +} + +//============================================================================= + +StatusCode TupleToolVeto::fill( const Particle* , const Particle* P, + const std::string& head, + Tuples::Tuple& tuple ) +{ + const std::string prefix = fullName(head); + + bool filltuple = true; + if ( P ) + { + + if ( !m_part.empty() && m_pid != P->particleID().abspid() ) + { + return StatusCode::SUCCESS; + } + + for ( std::map >::const_iterator i = m_veto.begin(); + m_veto.end() != i; ++i ) + { + const std::string& flag = i->first; + const std::vector& cont = i->second; + const bool veto = m_check->foundOverlap( P, cont ); + filltuple &= tuple->column( prefix+"_Veto"+flag, veto ); + } + + for( std::map >::const_iterator i = m_vetoOther.begin(); + m_vetoOther.end() != i; ++i ) + { + const std::string& flag = i->first; + const std::vector& cont = i->second; + const bool veto = m_check->foundOverlap( P, cont , 0x3); // mode == 3 + filltuple &= tuple->column( prefix+"_VetoOther"+flag, veto ); + } + + } + + return StatusCode(filltuple); +} diff --git a/first-analysis-steps/DecayTrees/TupleToolVeto.h b/first-analysis-steps/DecayTrees/TupleToolVeto.h new file mode 100644 index 00000000..e1a9bdab --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolVeto.h @@ -0,0 +1,47 @@ +// $Id: TupleToolVeto.h +#ifndef _TUPLETOOLVETO_H +#define _TUPLETOOLVETO_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +// Interfaces +#include "Kernel/IParticleTupleTool.h" +#include "Kernel/IParticleVeto.h" +#include + +//============================================================================ + +class TupleToolVeto : public TupleToolBase, virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolVeto( const std::string& type, + const std::string& name, + const IInterface* parent ); + + /// Initialise + StatusCode initialize() override; + + /// Destructor + virtual ~TupleToolVeto( ){} + +public: + + StatusCode fill( const LHCb::Particle*, + const LHCb::Particle*, + const std::string&, + Tuples::Tuple& ) override; +private: + + IParticleVeto* m_check; + std::string m_part; + unsigned int m_pid; + std::map > m_veto; + std::map > m_vetoOther; + +}; + +#endif // _TUPLETOOLVETO_H diff --git a/first-analysis-steps/DecayTrees/TupleToolVtxIsoln.cpp b/first-analysis-steps/DecayTrees/TupleToolVtxIsoln.cpp new file mode 100755 index 00000000..5abfc7f3 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolVtxIsoln.cpp @@ -0,0 +1,105 @@ +// Include files + +// local +#include "TupleToolVtxIsoln.h" + +#include +#include +#include +#include +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "CaloUtils/CaloAlgUtils.h" + +#include "Event/Particle.h" +using namespace LHCb; + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolVtxIsoln +// +// @author Mitesh Patel, Patrick Koppenburg +// @date 2008-04-15 +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +// actually acts as a using namespace TupleTool +DECLARE_COMPONENT( TupleToolVtxIsoln ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= + TupleToolVtxIsoln::TupleToolVtxIsoln( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolBase ( type, name , parent ) + , m_isolationTool(0) +{ + declareInterface(this); +} + +//============================================================================= + +StatusCode TupleToolVtxIsoln::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + + m_isolationTool = tool("VertexIsolation", "VertexIsolation", this) ; + if ( !m_isolationTool ) + { + Error("Unable to retrieve the isolation tool"); + return StatusCode::FAILURE; + } + // Get var names + m_indices.first = m_isolationTool->getFirstIndex() ; + m_indices.last = m_isolationTool->getNumberOfParameters() + m_indices.first ; + double dummy ; + std::string varName ; + for (int index = m_indices.first; index != m_indices.last; index++) + { + m_isolationTool->getInfo(index, dummy, varName) ; + m_varNames[index] = varName ; + } + + return sc; +} + +//============================================================================= + +StatusCode TupleToolVtxIsoln::fill( const Particle* mother + , const Particle* P + , const std::string& head + , Tuples::Tuple& tuple ){ + + const std::string prefix = fullName(head); + Assert( P && mother, "This should not happen, you are inside TupleToolVtxIsoln.cpp :(" ); + // Check the ExtraInfo + bool test = true ; + if ( P->isBasicParticle() ) return StatusCode::SUCCESS ; + // Fill tuple + if ( P->hasInfo(m_indices.first) ) + { + double def = -999999. ; + double val ; + for (int index = m_indices.first; index != m_indices.last; ++index) + { + val = P->info(index, def) ; + test &= tuple->column(prefix+"_"+m_varNames[index], val); + } + } + else + { + m_isolationTool->calculateExtraInfo(P, P) ; + double val ; + int result ; + for (int index = m_indices.first; index != m_indices.last; ++index) + { + std::string name ; + result = m_isolationTool->getInfo(index, val, name) ; + if ( !result ) continue ; + test &= tuple->column(prefix+"_"+name, val); + } + } + return StatusCode(test) ; +} + diff --git a/first-analysis-steps/DecayTrees/TupleToolVtxIsoln.h b/first-analysis-steps/DecayTrees/TupleToolVtxIsoln.h new file mode 100755 index 00000000..e4d981a7 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolVtxIsoln.h @@ -0,0 +1,71 @@ +#ifndef TUPLETOOLVTXISOLN_H +#define TUPLETOOLVTXISOLN_H 1 + +// Include files +// from Gaudi +#include "DecayTreeTupleBase/TupleToolBase.h" +#include "Kernel/IParticleTupleTool.h" // Interface +#include "Kernel/IExtraInfoTool.h" // Interface + +struct IDVAlgorithm; +struct IDistanceCalculator; +struct IVertexFit; + +namespace LHCb { + class Particle; + class Vertex; +} + +/** @class TupleToolVtxIsoln TupleToolVtxIsoln.h + * + * \brief Fill vertex isolation information for DecayTreeTuple + * Take vertexed particle and add other tracks of the + * event, one by one, building a new vertex. By default, this tool + * will look for ExtraInfo filled by the VertexIsolation tool. If it + * is not found, the tool is run to fill the ExtraInfo. + * + * Leaves filled by the tool: + * - (head)_NumVtxWithinChi2WindowOneTrack: number of particles that generate a vertex within a chi2 window + * - (head)_SmallestDeltaChi2OneTrack: smallest delta chi2 when adding one track + * - (head)_SmallestDeltaChi2MassOneTrack: mass of the candidate with the smallest delta chi2 + * - (head)_SmallestDeltaChi2TwoTracks: smallest delta chi2 when adding one track to the + * combination that has the smallest delta chi2 when adding one track + * - (head)_SmallestDeltaChi2MassTwoTracks: mass of the candidate with the smallest delta chi2 + * when adding one track to the combination that has the smallest delta chi2 when adding one track + * + * + * @author Albert Puig, based on previous work from Mitesh Patel, Patrick Koppenburg + * @date 2013-08-05 + * + */ +class TupleToolVtxIsoln : public TupleToolBase, + virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolVtxIsoln( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + +private: + + // Isolation tool + IExtraInfoTool *m_isolationTool ; + struct IsolationIndices { int first; int last; } ; + IsolationIndices m_indices ; + // Variable names to store in the tuple + std::map< int, std::string > m_varNames ; +}; + +#endif // TUPLETOOLVTXISOLN_H + +// EOF diff --git a/first-analysis-steps/DecayTrees/TupleToolWZJets.cpp b/first-analysis-steps/DecayTrees/TupleToolWZJets.cpp new file mode 100644 index 00000000..2bbe8e48 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolWZJets.cpp @@ -0,0 +1,337 @@ +#include "TupleToolWZJets.h" +#include "GaudiAlg/Tuple.h" +#include "GaudiAlg/TupleObj.h" +#include "Event/Particle.h" +#include "Kernel/IJetMaker.h" +#include "LoKi/AParticleCuts.h" +#include "boost/lexical_cast.hpp" +#include "boost/assign.hpp" +#include +#include +#include +#include + + +#include "LoKi/ParticleCuts.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : TupleToolWZJets +// Autor: Albert Bursche +//----------------------------------------------------------------------------- + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +TupleToolWZJets::TupleToolWZJets( const std::string& type, + const std::string& name, + const IInterface* parent ) + : TupleToolJetsBase ( type, name , parent ), + m_ppSvc(NULL), + m_magic(528), + m_DPHI(LoKi::Cuts::ONE ), + m_DETA(LoKi::Cuts::ONE ), + m_DR2(LoKi::Cuts::ONE ) +{ + declareInterface(this); + declareProperty( "BaseName", m_BaseName = "jet", + "Configure this if you want to run this tool more than once in a job." ); + declareProperty( "ParticleContainer",m_PartContainer = std::vector(), + "Where to find the particles to make the jets of" ); + declareProperty( "MaxJets",m_MaxJets = 4, + "Maximal number of jets to be stored in the tuple" ); + declareProperty( "IsoJetAbsID",m_IsoJetAbsID = false, + "Use AbsID for naming the isojet variables (change this if you get spurious segfaults)" ); +} + +//============================================================================= +StatusCode TupleToolWZJets::initialize() +{ + const StatusCode sc = TupleToolBase::initialize(); + if ( sc.isFailure() ) return sc; + // PP Svc + m_ppSvc = svc("LHCb::ParticlePropertySvc", true ); + //get LoKi objects + m_AdditionalJetMaker = tool( "LoKi::FastJetMaker","AdditionalJetMaker", this ); + m_IsoJetMaker = tool( "LoKi::FastJetMaker","IsoJetMaker", this ); + m_LokiAddJetFilter = tool("LoKi::Hybrid::FilterCriterion","AdditionalJetsFilter",this); + m_LokiIsoJetFilter = tool("LoKi::Hybrid::FilterCriterion","IsolationJetsFilter",this); + return sc; +} +StatusCode TupleToolWZJets::fill( const LHCb::Particle *top, + const LHCb::Particle* P, + const std::string& /* head */, + Tuples::Tuple& tuple ) +{ + m_tuple = &tuple; + m_prefix=m_BaseName;//+fullName(head); + + //intitalise LoKi comparators to reference particle + m_DPHI = LoKi::Cuts::DPHI(P->momentum().Phi()); + m_DETA = LoKi::Cuts::DETA(P->momentum().Eta()); + m_DR2 = LoKi::Cuts::DR2(P->momentum()); + bool test = true; + LHCb::Particles& myParts = GetParticles(); + + // Get particles in decay + m_decayParticles.clear(); + if ( msgLevel(MSG::DEBUG) ) debug() << "Filling particle with ID " << top->particleID().pid() << endmsg; + m_decayParticles.push_back( P->clone() ); + SaveDecayChainParticles( P ); + IJetMaker::Jets AddJets; //jets in the event additional to the particle in question + IJetMaker::Jets IsoJets; //jets containg the particle in question. Used to make an isolation criterion + StatusCode scAdd = m_AdditionalJetMaker->makeJets(myParts.begin(), myParts.end(),AddJets ); + if ( msgLevel(MSG::DEBUG) ) debug() << "Recieved" << AddJets.size() << "additional jets from the jet algorithm."<< endmsg; + AddDecProducts(myParts); + StatusCode scIso = m_IsoJetMaker->makeJets(myParts.begin(), myParts.end(), IsoJets); + if ( msgLevel(MSG::DEBUG) ) debug() << "Recieved " << AddJets.size() + << " isolation jet canditates from the jet algorithm."<< endmsg; + + // match IsoJets to particles + test &= StoreAdditionalJets(AddJets); + test &= MatchAndStoreIsoJets(IsoJets); + + if (!exist("/Event/Phys/"+m_BaseName+"IsoCollection/Particles")) + put(&myParts, "/Event/Phys/"+m_BaseName+"IsoCollection/Particles"); + else + if(msgLevel(MSG::WARNING)) + warning() << "Cannot write to TES at /Event/Phys/"+m_BaseName+"IsoCollection/Particles" << endmsg; + if (!exist< LHCb::Particles>("/Event/Phys/"+m_BaseName+"AddJets/Particles")) + { + LHCb::Particles * jets =new LHCb::Particles(); + for ( IJetMaker::Jets::iterator iJet = AddJets.begin() ; AddJets.end() != iJet ; ++iJet ) + jets->insert(*iJet); + put(jets, "/Event/Phys/"+m_BaseName+"AddJets/Particles"); + } + else + if(msgLevel(MSG::WARNING)) + warning() << "Cannot write to TES at /Event/Phys/"+m_BaseName+"AddJets/Particles" << endmsg; + if (!exist< LHCb::Particles>("/Event/Phys/"+m_BaseName+"IsoJets/Particles")) + { + LHCb::Particles * jets =new LHCb::Particles(); + for ( IJetMaker::Jets::iterator iJet = IsoJets.begin() ; IsoJets.end() != iJet ; ++iJet ) + jets->insert(*iJet); + put(jets, "/Event/Phys/"+m_BaseName+"IsoJets/Particles"); + } + else + if(msgLevel(MSG::WARNING)) + warning() << "Cannot write to TES at /Event/Phys/"+m_BaseName+"IsoJets/Particles" << endmsg; + //In case the objects cannot be saved in TES some memory gets lost! + //But I can not call delete on these objects yet because I don't know what happens later. + + return StatusCode(test); +} + +//============================================================================= +// Save the particles in the decay chain (recursive function) +//============================================================================= +void TupleToolWZJets::SaveDecayChainParticles( const LHCb::Particle *top){ + + // -- Get the daughters of the top particle + const SmartRefVector& daughters = top->daughters(); + + // -- Fill all the daugthers in m_decayParticles + for( SmartRefVector< LHCb::Particle >::const_iterator idau = daughters.begin() ; idau != daughters.end() ; ++idau){ + + // -- If the particle is stable, save it in the vector, or... + if( (*idau)->isBasicParticle() ){ + if ( msgLevel(MSG::DEBUG) ) debug() << "Filling particle with ID " << (*idau)->particleID().pid() << endmsg; + m_decayParticles.push_back( (*idau)->clone() ); + }else{ + // -- if it is not stable, call the function recursively + m_decayParticles.push_back( (*idau)->clone() ); + if ( msgLevel(MSG::DEBUG) ) debug() << "Filling particle with ID " << (*idau)->particleID().pid() << endmsg; + SaveDecayChainParticles( (*idau) ); + } + } +} + +//============================================================================= +// Check if the particle is already in the decay +//============================================================================= +bool TupleToolWZJets::isParticleInDecay(const LHCb::Particle* part){ + bool isInDecay = false; + const LHCb::ProtoParticle* proto1 = part->proto(); + if (!proto1) + { + warning() << "Could not retrieve protoparticle! Cannot check overlap!" << endmsg; + return false; + } + const LHCb::Track* track = proto1->track(); + for( std::vector::iterator it = m_decayParticles.begin() ; it != m_decayParticles.end() ; ++it ){ + const LHCb::ProtoParticle* proto = (*it)->proto(); + if(proto){ + const LHCb::Track* myTrack = proto->track(); + if(myTrack == track){ + if ( msgLevel(MSG::DEBUG) ) debug() << "Track is in decay, skipping it" << endmsg; + isInDecay = true; + } + } + } + return isInDecay; +} +LHCb::Particles& TupleToolWZJets::GetParticles() +{ + // -- Get all particles in the event to cluster jets + LHCb::Particle::ConstVector inputParts; + for(std::vector::const_iterator InputContainer= m_PartContainer.begin(); + InputContainer!=m_PartContainer.end();++InputContainer) + { + if ( msgLevel(MSG::DEBUG) ) debug() << "Getting particles from: " << *InputContainer << endmsg; + if (exist(*InputContainer)) + { + LHCb::Particle::Range addInp = get(*InputContainer); + inputParts.insert(inputParts.begin(),addInp.begin(),addInp.end()); + } + } + //filter the decay products from the collection + //this filter only looks for overlag with the decay products + //(other filters can be applied with a filter desktop before running the tuple) + LHCb::Particles& myParts = *new LHCb::Particles(); + std::map particleCharges = boost::assign::map_list_of(-1,0)(0,0)(1,0); //counter + addBasicParticles(particleCharges, myParts,inputParts); + + if (m_verbose) + { + (*m_tuple)->column( m_prefix+"_ChargedTracksUsed",particleCharges[-1]+particleCharges[+1]); + (*m_tuple)->column( m_prefix+"_NeutralObjectsUsed",particleCharges[0]); + (*m_tuple)->column( m_prefix+"_PositiveTracksUsed",particleCharges[+1]); + (*m_tuple)->column( m_prefix+"_NegativeTracksUsed",particleCharges[-1]); + } + + return myParts; +} + +void TupleToolWZJets::addBasicParticles(std::map& particleCharges, + LHCb::Particles& myParts, + LHCb::Particle::ConstVector inputParts) +{ + for(LHCb::Particle::ConstVector::const_iterator parts = inputParts.begin(); parts != inputParts.end(); ++parts) + if ((*parts)->isBasicParticle ()) + { + if (!isParticleInDecay(*parts)) + { + myParts.insert(new LHCb::Particle(**parts)); + particleCharges[(*parts)->charge()]++; + } + } + else + addBasicParticles(particleCharges, myParts,(*parts)->daughtersVector()); +} + +void TupleToolWZJets::AddDecProducts(LHCb::Particles& myParts) +{ + int PartID = 0; // counter for decay product (needed later when matching IsoJets) + for( std::vector< LHCb::Particle* >::iterator idau = m_decayParticles.begin() ; + idau != m_decayParticles.end() ; ++idau) + if((*idau)->isBasicParticle()) + { + (*idau)->addInfo(LHCb::Particle::LastGlobal + m_magic,PartID++); + //myParts.push_back(&**idau); + myParts.insert(new LHCb::Particle(**idau)); + } + if ( msgLevel(MSG::DEBUG) ) debug() << "Added " << PartID << " particles to the collection."<< endmsg; +} +bool TupleToolWZJets::StoreAdditionalJets(const IJetMaker::Jets& AddJets) +{ + bool test = true; + unsigned int numJets = 0; + for ( IJetMaker::Jets::const_iterator iJet = AddJets.begin() ; AddJets.end() != iJet ; ++iJet ) + if((*m_LokiAddJetFilter)(*iJet)) + { + numJets = numJets+1; + if (numJets <= m_MaxJets) + test &= WriteJetComparisonToTuple(*iJet,m_prefix+"_Jet"+ boost::lexical_cast(numJets)); + } + else + if ( msgLevel(MSG::DEBUG) ) debug() << "Jet number " + << std::distance( (IJetMaker::Jets::const_iterator) AddJets.begin(),iJet) + << " failed selection."<< endmsg; + for(unsigned int i = numJets+1;i<=m_MaxJets;i++)// fill remaining jets slots in tuple with dummys + test &= WriteJetComparisonToTuple(NULL,m_prefix+"_Jet"+ boost::lexical_cast(i)); + test &= (*m_tuple)->column( m_prefix+"_NumJets", numJets); + return test; +} +bool TupleToolWZJets::MatchAndStoreIsoJets(const IJetMaker::Jets& IsoJets) +{ + bool test = true; + std::vector isoJetFound(m_decayParticles.size()) ; + for (std::vector::iterator it = isoJetFound.begin();it!=isoJetFound.end();++it) + *it=false; + for ( IJetMaker::Jets::const_iterator iJet = IsoJets.begin() ; IsoJets.end() != iJet ; ++iJet ) + { + std::vector::iterator ThisIsoJetFound = isoJetFound.begin(); + for (std::vector::const_iterator DecProduct=m_decayParticles.begin(); + DecProduct!=m_decayParticles.end(); + ++DecProduct) + { + for(SmartRefVector< LHCb::Particle >::const_iterator daughter = (*iJet)->daughters().begin(); + daughter!=(*iJet)->daughters().end();++daughter ) + if((*DecProduct)->info(LHCb::Particle::LastGlobal + m_magic, 1000)== + (*daughter) ->info(LHCb::Particle::LastGlobal + m_magic,-1000)&& + (*m_LokiIsoJetFilter)(*iJet)) + { + const LHCb::ParticleProperty* ppp = m_ppSvc->find((LHCb::ParticleID)((*DecProduct)->particleID().abspid())); + if (!ppp) + { + std::ostringstream mess; + mess << "Unknown ParticleID " << (*DecProduct)->particleID().abspid(); + Exception( mess.str() ); + } + if (m_IsoJetAbsID) + test &= WriteJetComparisonToTuple(*iJet,ppp->name()); + else + test &= WriteJetComparisonToTuple(*iJet,ppp->name()); + if ((*ThisIsoJetFound)&&msgLevel(MSG::WARNING)) + warning() << "Found more than one IsoJet!" << endmsg; + *ThisIsoJetFound = true; + } + ++ThisIsoJetFound; + } + } + { + std::vector::iterator ThisIsoJetFound = isoJetFound.begin(); + for (std::vector::const_iterator DecProduct=m_decayParticles.begin(); + DecProduct!=m_decayParticles.end(); + ++DecProduct) + if (!*ThisIsoJetFound++)//write default value to tuple + { + const LHCb::ParticleProperty* ppp = m_ppSvc->find((LHCb::ParticleID)((*DecProduct)->particleID().abspid())); + if (0==ppp) { + err() << "Unknown PID " << (*DecProduct)->particleID().abspid() << endmsg ; + Exception("Unknown PID"); + } + if (m_IsoJetAbsID) + test &= WriteJetComparisonToTuple(NULL,m_BaseName+"IsoJet"+ppp->name()); + else + test &= WriteJetComparisonToTuple(NULL,m_BaseName+"IsoJet"+ppp->name()); + if(msgLevel(MSG::DEBUG)) + debug() << "IsoJet missing!" << endmsg; + } + } + return test; +} +bool TupleToolWZJets::WriteJetComparisonToTuple(const LHCb::Particle*jet,std::string prefix) +{ + //filter plus and minus signs out to the prefix (dublicated in TuplToolJetsBase) + std::map replacements ; + replacements["+"]="plus"; + replacements["-"]="minus"; + for (std::map::iterator it = replacements.begin();it != replacements.end();++it) + { + size_t point = 0; + while((point = prefix.find(it->first))!=std::string::npos) + prefix = prefix.replace(point,it->second.size(),it->second); + } + + bool result = true; + if (m_verbose) + { + result &= (*m_tuple)->column( prefix+"_DETA", jet?m_DETA(jet):-10.0); + result &= (*m_tuple)->column( prefix+"_DPHI", jet?m_DPHI(jet):-10.0); + result &= (*m_tuple)->column( prefix+"_DR", jet?sqrt(m_DR2(jet)):-1.0); + } + return result&=WriteJetToTuple(jet,prefix); +} + +// Declaration of the Tool Factory +DECLARE_COMPONENT( TupleToolWZJets ) diff --git a/first-analysis-steps/DecayTrees/TupleToolWZJets.h b/first-analysis-steps/DecayTrees/TupleToolWZJets.h new file mode 100644 index 00000000..251c1595 --- /dev/null +++ b/first-analysis-steps/DecayTrees/TupleToolWZJets.h @@ -0,0 +1,69 @@ +#ifndef TUPLETOOLWZJETS_H +#define TUPLETOOLWZJETS_H 1 +#include "TupleToolJetsBase.h" +#include "Kernel/IParticleFilter.h" +#include "Kernel/IParticleTupleTool.h" +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" +#include "Kernel/FilterParticlesBase.h" +#include +#include "Kernel/IJetMaker.h" +#include "LoKi/PhysTypes.h" + +//autor: Albert Bursche +class TupleToolWZJets : public TupleToolJetsBase, virtual public IParticleTupleTool +{ + +public: + + /// Standard constructor + TupleToolWZJets( const std::string& type, + const std::string& name, + const IInterface* parent); + + virtual ~TupleToolWZJets(){}; ///< Destructor + + StatusCode fill( const LHCb::Particle* + , const LHCb::Particle* + , const std::string& + , Tuples::Tuple& ) override; + + StatusCode initialize() override; + +private: + + std::vector m_decayParticles; + + /// Check if your track belongs to your decay or not + bool isParticleInDecay(const LHCb::Particle* part); + + /// Save all particles in your decay descriptor in a vector + void SaveDecayChainParticles( const LHCb::Particle *top); + + std::string m_BaseName; + //std::string m_BosonContainer; + std::vector m_PartContainer; + unsigned int m_MaxJets; + bool m_IsoJetAbsID; + // Tuples::Tuple* m_tuple; + std::string m_prefix; + const IJetMaker* m_AdditionalJetMaker; + const IJetMaker* m_IsoJetMaker; + const IParticleFilter* m_LokiAddJetFilter; + const IParticleFilter* m_LokiIsoJetFilter; + const LHCb::IParticlePropertySvc* m_ppSvc; + unsigned int m_magic; // magic number to identify the decay products in the jet + + LoKi::Types::Fun m_DPHI; + LoKi::Types::Fun m_DETA; + LoKi::Types::Fun m_DR2; + + LHCb::Particles& GetParticles(); + void AddDecProducts(LHCb::Particles&); + bool StoreAdditionalJets(const IJetMaker::Jets& AddJets); + bool MatchAndStoreIsoJets(const IJetMaker::Jets& IsoJets); + bool WriteJetComparisonToTuple(const LHCb::Particle*jet,std::string prefix); + void addBasicParticles(std::map& particleCharges, LHCb::Particles& myParts, LHCb::Particle::ConstVector parts); +}; + +#endif // TUPLETOOLWZJETS_H diff --git a/first-analysis-steps/TupleTools.md b/first-analysis-steps/TupleTools.md new file mode 100644 index 00000000..4d9d1531 --- /dev/null +++ b/first-analysis-steps/TupleTools.md @@ -0,0 +1,1126 @@ +# List of TupleTool Variables + +{% objectives "Learning Objectives" %} +* What are each TupleTool's variables? +{% endobjectives %} + +{% callout "List of DecayTreeTuples - General Categories" %} +DecayTreeTuples: + +- DecayTreeTuple - for the more general tools. +- DecayTreeTupleANNPID - for the NeuralNet-based PID tools. [Class Reference here.](http://lhcb-doxygen.web.cern.ch/lhcb-doxygen/analysis/latest/dc/dd6/class_tuple_tool_a_n_n_p_i_d.html) +- DecayTreeTupleDalitz - for Dalitz analysis. [Class Reference here.](http://lhcb-doxygen.web.cern.ch/lhcb-doxygen/analysis/latest/df/d6a/class_tuple_tool_dalitz.html) +- DecayTreeTupleJets - for obtaining information on jets. [Class Reference here.](http://lhcb-doxygen.web.cern.ch/lhcb-doxygen/analysis/latest/d9/d48/class_tuple_tool_jets.html) +- DecayTreeTupleMC - gives us access to MC-level information. [Class Reference here.](http://lhcb-doxygen.web.cern.ch/lhcb-doxygen/analysis/latest/da/dd6/class_tuple_tool_m_c_truth.html) +- DecayTreeTupleMuonCalib - for muon calibration tools. [Class Reference here.](http://lhcb-doxygen.web.cern.ch/lhcb-doxygen/analysis/latest/d4/de9/class_tuple_tool_muon_i_d_calib.html) +- DecayTreeTupleReco - for reconstruction-level information, such as TupleToolTrackInfo. [Class Reference here.](http://lhcb-doxygen.web.cern.ch/lhcb-doxygen/analysis/latest/da/ddd/class_tuple_tool_track_info.html) +- DecayTreeTupleTracking - for more detailed tools regarding tracking. [Class Reference here.](http://lhcb-doxygen.web.cern.ch/lhcb-doxygen/analysis/latest/d4/d31/class_tuple_tool_cone_isolation.html) +- DecayTreeTupleTrigger - for accessing to the trigger information of the candidates. [Class Reference here.](http://lhcb-doxygen.web.cern.ch/lhcb-doxygen/analysis/latest/d3/dd1/class_tuple_tool_trigger.html) +{% endcallout %} + +The class references and descriptions of each of the individual tuple tools can be found [here](http://lhcb-doxygen.web.cern.ch/lhcb-doxygen/analysis/latest/annotated.html), (scroll down to T). + +Below you will find links to the source code and header files for each of the TupleTools, with each variable beneath. + +{% callout "DecayTreeTuple - for the more general tools" %} + * [TupleToolAllTracks.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolAllTracks.cpp) + * [TupleToolAllTracks.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolAllTracks.h) + * H_M, _n_Particles + * H_M_pion, _n_Particles + * H_M_kaon, _n_Particles + * H_M_proton, _n_Particles + * _dauH_CorrM, _n_Particles + * _dauH_CorrM_pion, _n_Particles + * _dauH_CorrM_kaon, _n_Particles + * _dauH_CorrM_proton, _n_Particles + * _dauH_CorrMErr, _n_Particles + * _dauH_CorrMErr_pion, _n_Particles + * _dauH_CorrMErr_kaon, _n_Particles + * _dauH_CorrMErr_proton, _n_Particles + * H_PT, _n_Particles + * H_ETA, _n_Particles + * H_PHI, _n_Particles + * H_PX, _n_Particles + * H_PY, _n_Particles + * H_PZ, _n_Particles + * H_FDCHI2_OLD, _n_Particles + * H_FDCHI2_NEW, _n_Particles + * H_FD_OLD, _n_Particles + * H_FD_NEW, _n_Particles + * H_VERTEXCHI2_OLD, _n_Particles + * H_VERTEXCHI2_NEW, _n_Particles + * H_VERTEX_X_NEW, _n_Particles + * H_VERTEX_Y_NEW, _n_Particles + * H_VERTEX_Z_NEW, _n_Particles + * H_PV_X_NEW, _n_Particles + * H_PV_Y_NEW, _n_Particles + * H_PV_Z_NEW, _n_Particles + * H_VERTEX_COV_, _n_Particles + * H_PV_COV_, _n_Particles + * H_VertexRefitStatus, _n_Particles + * H_IPCHI2_OLD, _n_Particles + * H_IP_OLD, _n_Particles + * H_IPCHI2_NEW, _n_Particles + * H_IP_NEW, _n_Particles + * H_MINIPCHI2, _n_Particles + * _H_OPENING, _n_Particles + * _H_PX, _n_Particles + * _H_PY, _n_Particles + * _H_PZ, _n_Particles + * _H_PT, _n_Particles + * _H_ETA, _n_Particles + * _H_PHI, _n_Particles + * _H_THETA, _n_Particles + * _H_DELTAPHI, _n_Particles + * _H_PID, _n_Particles + * _H_PROBNNPID, _n_Tracks + * _H_GHOST, _n_Tracks + * _H_TRACKCHI2, _n_Tracks + * _H_TRACKTYPE, _n_Tracks + * _H_PIDe, _n_Tracks + * _H_PIDK, _n_Tracks + * _H_PIDmu, _n_Tracks + * _H_PIDp, _n_Tracks + * _H_ProbNNpi, _n_Tracks + * _H_ProbNNk, _n_Tracks + * _H_ProbNNp, _n_Tracks + * _H_ProbNNe, _n_Tracks + * _H_ProbNNmu, _n_Tracks + * [TupleToolAngles.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolAngles.cpp) + * [TupleToolAngles.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolAngles.h) + * _CosTheta + * _Theta + * [TupleToolBeamSpot.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolBeamSpot.cpp) + * [TupleToolBeamSpot.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolBeamSpot.h) + * _BeamX + * _BeamY + * [TupleToolBremInfo.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolBremInfo.cpp) + * [TupleToolBremInfo.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolBremInfo.h) + * _DiEBremMultiplicity + * _DiEBremP + * _BremOrigin + * _BremP + * _HasBremAdded + * [TupleToolCaloDigits.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolCaloDigits.cpp) + * [TupleToolCaloDigits.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolCaloDigits.h) + * DigitIndex, DigitNi + * DigitCalo, DigitNc + * DigitArea, DigitNa + * DigitRow, DigitNr + * DigitColumn, DigitNco + * Digit_X, DigitNx + * Digit_Y, DigitNy + * Digit_Z, DigitNz + * DigitEnergy, DigitNe + * [TupleToolCaloHypo.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolCaloHypo.cpp) + * [TupleToolCaloHypo.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolCaloHypo.h) + * _hasCaloHypo + * _hasBremCaloHypo + * _CaloHypo_E + * _CaloHypo_X + * _CaloHypo_Y + * _CaloHypo_Z + * _CaloHypo_DeltaTheta + * _CaloHypoDaugh0_E + * _CaloHypoDaugh0_X + * _CaloHypoDaugh0_Y + * _CaloHypoDaugh0_Z + * _CaloHypoDaugh1_E + * _CaloHypoDaugh1_X + * _CaloHypoDaugh1_Y + * _CaloHypoDaugh1_Z + * _CaloHypoPileUpEnergy + * _CaloHypo + * _BremCaloHypo + * _CaloHypoDaugh0 + * _CaloHypoDaugh1 + * [TupleToolCorrectedMass.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolCorrectedMass.cpp) + * [TupleToolCorrectedMass.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolCorrectedMass.h) + * _MCORR + * _MCORRERR + * _MCORRVERTEXERR + * [TupleToolDecayTreeFitter.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolDecayTreeFitter.cpp) + * [TupleToolDecayTreeFitter.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolDecayTreeFitter.h) + * _nPV + * [TupleToolDira.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolDira.cpp) + * [TupleToolDira.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolDira.h) + * _DiraAngleError + * _DiraCosError + * _DiraAngle + * _DiraCos + * [TupleToolGeometry.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolGeometry.cpp) + * [TupleToolGeometry.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolGeometry.h) + * _AllIP, nPV + * _AllIPchi2, nPV + * _AllDIRA, nPV + * _MINIP + * _MINIPCHI2 + * _MINIPNEXTBEST + * _MINIPCHI2NEXTBEST + * _XERR + * _YERR + * _ZERR + * _CHI2 + * _NDOF + * [TupleToolHOP.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolHOP.cpp) + * [TupleToolHOP.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolHOP.h) + * _HOP + * _HOP_ELECTRON_MASS + * [TupleToolIsolationTwoBody.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolIsolationTwoBody.cpp) + * [TupleToolIsolationTwoBody.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolIsolationTwoBody.h) + * _test + * _MuonChi2DOF + * _MuonChi2DOF + * _P1_massiso + * _P2_massiso + * _P1_Q + * _P2_Q + * _P1_chi2iso + * _P2_chi2iso + * _P1_iso5 + * _P2_iso5 + * [TupleToolKinematic.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolKinematic.cpp) + * [TupleToolKinematic.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolKinematic.h) + * _test + * _MuonChi2DOF + * _MuonChi2DOF + * _P1_massiso + * _P2_massiso + * _P1_Q + * _P2_Q + * _P1_chi2iso + * _P2_chi2iso + * _P1_iso5 + * _P2_iso5 + * [TupleToolMassHypo.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolMassHypo.cpp) + * [TupleToolMassHypo.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolMassHypo.h) + * _M_with + * [TupleToolNeutrinoReco.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolNeutrinoReco.cpp) + * [TupleToolNeutrinoReco.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolNeutrinoReco.h) + * _Nu_Parl + * _Nu_Perp + * _Nu_a + * _Nu_X + * _Nu_Y + * _Nu_pb + * _Nu_pd + * _Nu_Hi + * _Nu_Lo + * [TupleToolP2VV.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolP2VV.cpp) + * [TupleToolP2VV.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolP2VV.h) + * _ThetaL + * _ThetaK + * _Phi + * _ThetaTr + * _PhiTr + * _ThetaVtr + * [TupleToolParticleReFit.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolParticleReFit.cpp) + * [TupleToolParticleReFit.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolParticleReFit.h) + * _status + * _ENDVERTEX_NDOF + * _ENDVERTEX_CHI2 + * _MM + * _MMERR + * _P + * _PT + * _P + * _TAU + * _TAUERR + * _TAUCHI2 + * [TupleToolParticleStats.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolParticleStats.cpp) + * [TupleToolParticleStats.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolParticleStats.h) + * [TupleToolPhotonInfo.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolPhotonInfo.cpp) + * [TupleToolPhotonInfo.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolPhotonInfo.h) + * _Converted + * _Prs + * _Matching + * _PID + * _CL + * _ShowerShape + * [TupleToolPi0Info.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolPi0Info.cpp) + * [TupleToolPi0Info.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolPi0Info.h) + * _Type + * _CL + * _gamma0_PT + * _gamma1_PT + * _MCPi0_id + * _MCPi0_key + * _MCPi0Mother_id + * _MCPi0Mother_key + * _MCPi0GrandMother_id + * _MCPi0GrandMother_key + * _MCPi0GrandGrandMother_id + * _MCPi0GrandGrandMother_key + * [TupleToolPid.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolPid.cpp) + * [TupleToolPid.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolPid.h) + * _hasRich + * _UsedRichAerogel + * _UsedRich1Gas + * _UsedRich2Gas + * _RichAboveElThres + * _RichAboveMuThres + * _RichAbovePiThres + * _RichAboveKaThres + * _RichAbovePrThres + * _hasCalo + * _RichDLLe + * _RichDLLmu + * _RichDLLpi + * _RichDLLk + * _RichDLLp + * _RichDLLbt + * _InAccMuon + * _isMuonLoose + * _isMuonTight + * _MuonMuLL + * _MuonBkgLL + * _MuonNShared + * _MuonChi2Corr + * _InAccEcal + * _CaloEcalE + * _EcalPIDe + * _EcalPIDmu + * _InAccHcal + * _CaloHcalE + * _HcalPIDe + * _HcalPIDmu + * _InAccPrs + * _PrsPIDe + * _CaloPrsE + * _InAccSpd + * _CaloSpdE + * _InAccBrem + * _BremPIDe + * _VeloCharge + * [TupleToolPropertime.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolPropertime.cpp) + * [TupleToolPropertime.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolPropertime.h) + * _TAU + * _TAUERR + * _TAUCHI2 + * [TupleToolSelResults.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolSelResults.cpp) + * [TupleToolSelResults.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolSelResults.h) + * _M + * \_VtxChi2\_+flag + * _VtxnDoF+flag + * _VtxM+flag + * _IP+flag + * \_IPChi2\_+flag + * [TupleToolSubMass.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolSubMass.cpp) + * [TupleToolSubMass.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolSubMass.h) + * [TupleToolSwimmingInfo.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolSwimmingInfo.cpp) + * [TupleToolSwimmingInfo.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolSwimmingInfo.h) + * _TP_RAW, _nTP + * _TP_DEC, _nTP + * _TP_TAU, _nTP + * _TP_IP, _nTP + * _TP_DEC_, _nTP + * _TP_, _nTP + * _TP_DEC_ + * [TupleToolTagging.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolTagging.cpp) + * [TupleToolTagging.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolTagging.h) + * _TagPartsFeature_ + * _TAGDECISION + * _TAGOMEGA + * _TAGDECISION_OS + * _TAGOMEGA_OS + * _TAGGER + * _DEC + * _PROB + * [TupleToolTwoParticleMatching.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolTwoParticleMatching.cpp) + * [TupleToolTwoParticleMatching.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolTwoParticleMatching.h) + * \_NMatchingCand\_+fullName(head)+m\_headSuffix + * \_Overlap_loaded\_+fullName(head)+m\_headSuffix + * \_Overlap_original\_+fullName(head)+m\_headSuffix + * [TupleToolVeto.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolVeto.cpp) + * [TupleToolVeto.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolVeto.h) + * _Veto+flag + * _VetoOther+flag + * [TupleToolVtxIsoln.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolVtxIsoln.cpp) + * [TupleToolVtxIsoln.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTuple/src/TupleToolVtxIsoln.h) + * \_VtxIsoln.m\_varNames[index] + * _VtxIsoln.name +{% endcallout %} + +{% callout "DecayTreeTupleANNPID - for the NeuralNet-based PID tools" %} + * [TupleToolANNPID.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleANNPID/src/TupleToolANNPID.cpp) + * [TupleToolANNPID.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleANNPID/src/TupleToolANNPID.h) + * _prefix+_ProbNNe + * _prefix+_ProbNNmu + * _prefix+_ProbNNpi + * _prefix+_ProbNNk + * _prefix+_ProbNNp + * _prefix+_ProbNNd + * _prefix+_ProbNNghost + * [TupleToolANNPIDTraining.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleANNPID/src/TupleToolANNPIDTraining.cpp) + * [TupleToolANNPIDTraining.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleANNPID/src/TupleToolANNPIDTraining.h) +{% endcallout %} + +{% callout "DecayTreeTupleDalitz - for Dalitz analysis" %} + * [TupleToolDalitz.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleDalitz/src/TupleToolDalitz.cpp) + * [MCTupleToolDalitz.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleDalitz/src/MCTupleToolDalitz.h) + * [TupleToolDalitz.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleDalitz/src/TupleToolDalitz.cpp) + * [TupleToolDalitz.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleDalitz/src/TupleToolDalitz.h) + * [TupleToolDalitz.icpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleDalitz/src/TupleToolDalitz.icpp) +{% endcallout %} + +{% callout "DecayTreeTupleHerschel" %} + * [TupleToolHerschel.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleHerschel/src/TupleToolHerschel.cpp) + * [TupleToolHerschel.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleHerschel/src/TupleToolHerschel.h) +{% endcallout %} + +{% callout "DecayTreeTupleJets - for obtaining information on jets" %} + * [TupleToolJetRelations.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleJets/src/TupleToolJetRelations.cpp) + * [TupleToolJetRelations.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleJets/src/TupleToolJetRelations.h) + * [TupleToolJetsBase.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleJets/src/TupleToolJetsBase.cpp) + * [TupleToolJetsBase.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleJets/src/TupleToolJetsBase.h) + * _PX + * _PY + * _PZ + * _PE + * _PT + * _P + * _Eta + * _Phi + * _M + * _MLoKi + * _MMLoKi + * _NTrk + * _N90 + * _MTF + * _NSatCells + * _NHasPVInfo + * _JEC_Cor + * _JEC_PV + * _JEC_Error + * _w + * _CPF + * _JetWidth + * _NSatECAL + * _NSatHCAL + * _NIPChi2Inf4 + * _EfCharged + * _EfChargedHadron + * _EfMuon + * _EfElectron + * _EfNeutral + * _EfPhoton + * _EfPi0 + * _EfMPi0 + * _EfRPi0 + * _EfNHad + * _EfNReco + * _EfCompo + * _EfV0 + * _EfD + * _EfB + * _EfBadParticle + * [TupleToolJets.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleJets/src/TupleToolJets.cpp) + * [TupleToolJets.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleJets/src/TupleToolJets.h) + * [TupleToolJetsForB.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleJets/src/TupleToolJetsForB.cpp) + * [TupleToolJetsForB.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleJets/src/TupleToolJetsForB.h) + * _JETNOMU1PX + * _JETNOMU1PY + * _JETNOMU1PZ + * _JETNOMU1PT + * _JETNOMU1JETWIDTH + * _JETNOMU1NNTAG + * _JETNOMU1MNF + * _JETNOMU2PX + * _JETNOMU2PY + * _JETNOMU2PZ + * _JETNOMU2PT + * _JETNOMU2JETWIDTH + * _JETNOMU2NNTAG + * _JETNOMU2MNF + * _JETNOMU3PX + * _JETNOMU3PY + * _JETNOMU3PZ + * _JETNOMU3PT + * _JETNOMU3JETWIDTH + * _JETNOMU3NNTAG + * _JETNOMU3MNF + * _JETMU1PX + * _JETMU1PY + * _JETMU1PZ + * _JETMU1PT + * _JETMU1JETWIDTH + * _JETMU1NNTAG + * _JETMU1MNF + * _JETMU2PX + * _JETMU2PY + * _JETMU2PZ + * _JETMU2PT + * _JETMU2JETWIDTH + * _JETMU2NNTAG + * _JETMU2MNF + * _JETBPX + * _JETBPY + * _JETBPZ + * _JETBPT + * _JETBJETWIDTH + * _JETBNNTAG + * [TupleToolJetTag.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleJets/src/TupleToolJetTag.cpp) + * [TupleToolJetTag.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleJets/src/TupleToolJetTag.h) + * _fdrMin, _NbTag + * _ptSvrJet, _NbTag + * _nTrk, _NbTag + * _nTrkJet, _NbTag + * _drSvrJet, _NbTag + * _absQSum, _NbTag + * _m, _NbTag + * _mCor, _NbTag + * _fdChi2, _NbTag + * _ipChi2Sum, _NbTag + * _bdt0, _NbTag + * _bdt1, _NbTag + * _pass, _NbTag + * _tau, _NbTag + * _z, _NbTag + * _pt, _NbTag + * _backwards, _NbTag + * [TupleToolWZJets.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleJets/src/TupleToolWZJets.cpp) + * [TupleToolWZJets.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleJets/src/TupleToolWZJets.h) + * _ m_prefix+_ChargedTracksUsed + * _ m_prefix+_NeutralObjectsUsed + * _ m_prefix+_PositiveTracksUsed + * _ m_prefix+_NegativeTracksUsed + * _NumJets + * _DETA + * _DPHI + * _DR +{% endcallout %} + +{% callout "DecayTreeTupleMC - gives us access to MC-level information" %} + * [MCTupleToolAngles.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolAngles.cpp) + * [MCTupleToolAngles.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolAngles.h) + * _TRUECosTheta + * _TRUETheta + * [MCTupleToolDecayType.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolDecayType.cpp) + * [MCTupleToolDecayType.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolDecayType.h) + * found + * _MCP_FoundTypes, _FoundLen + * found + * _MatchingTypes, _MatchLen + * found + * _PseudoTypes, _MCP_PseudoLen + * found + * _MatchingPseudoTypes + * _numFoundTypes + * _numMatchingTypes + * _numPseudoTypes + * _numMatchingPseudoTypes + * _hasGivenDecay + * [MCTupleToolEventType.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolEventType.cpp) + * [MCTupleToolEventType.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolEventType.h) + * found + * FoundTypes, FoundLen + * found + * MatchingTypes, MatchLen + * found + * PseudoTypes, PseudoLen + * found + * MatchingPseudoTypes, MatchPseudoLen + * _GenEvent + * _hasGenEvent + * _hasPseudoGenEvent + * _numFoundTypes + * _numMatchingTypes + * _numPseudoTypes + * _numMatchingPseudoTypes + * _hasGivenDecay + * [MCTupleToolHierarchy.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolHierarchy.cpp) + * [MCTupleToolHierarchy.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolHierarchy.h) + * _MC_MOTHER_ID + * _MC_MOTHER_KEY + * _MC_GD_MOTHER_ID + * _MC_GD_MOTHER_KEY + * _MC_GD_GD_MOTHER_ID + * _MC_GD_GD_MOTHER_KEY + * [MCTupleToolInteractions.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolInteractions.cpp) + * [MCTupleToolInteractions.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolInteractions.h) + * _I + * _Mean + * _Prob + * _AdjustMean + * _AdjustProb + * _AdjustWeight + * _NormalisedAt + * _NormalisedTo + * _nMCI + * _nMCPV + * _nRecPV + * [MCTupleToolKinematic.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolKinematic.cpp) + * [MCTupleToolKinematic.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolKinematic.h) + * _TRUEID + * \_TRUEP\_ + * _TRUEPT + * \_TRUEORIGINVERTEX\_ + * \_TRUEENDVERTEX\_ + * _TRUEISSTABLE + * _TRUETAU + * _OSCIL + * [MCTupleToolP2VV.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolP2VV.cpp) + * [MCTupleToolP2VV.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolP2VV.h) + * _TRUEThetaL + * _TRUEThetaK + * _TRUEPhi + * _TRUEThetaTr + * _TRUEPhiTr + * _TRUEThetaVtr + * [MCTupleToolPID.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolPID.cpp) + * [MCTupleToolPID.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolPID.h) + * _ID + * [MCTupleToolPrimaries.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolPrimaries.cpp) + * [MCTupleToolPrimaries.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolPrimaries.h) + * [MCTupleToolPrompt.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolPrompt.cpp) + * [MCTupleToolPrompt.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolPrompt.h) + * MCPVX, MCPVs + * MCPVY, MCPVs + * MCPVZ, MCPVs + * MCPVT, MCPVs + * _MC_ISPROMPT + * _MC_LONGLIVED_ID + * _MC_LONGLIVED_KEY + * [MCTupleToolReconstructed.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolReconstructed.cpp) + * [MCTupleToolReconstructed.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolReconstructed.h) + * _PP_PX, _ProtoParticles + * _PP_PY, _ProtoParticles + * _PP_PZ, _ProtoParticles + * _PP_Weight, _ProtoParticles + * _PP_tr_pchi2, _ProtoParticles + * _PP_DLLe, _ProtoParticles + * _PP_DLLk, _ProtoParticles + * _PP_DLLp, _ProtoParticles + * _PP_DLLmu, _ProtoParticles + * _Reconstructible + * _Reconstructed + * [MCTupleToolRedecay.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolRedecay.cpp) + * [MCTupleToolRedecay.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/MCTupleToolRedecay.h) + * _prefix + RD_org_eventNumber + * _prefix + RD_org_runNumber + * _prefix + RD_i_event + * [TupleToolGeneration.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/TupleToolGeneration.cpp) + * [TupleToolGeneration.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/TupleToolGeneration.h) + * ProcessType, Collisions + * HeaviestQuark, Collisions + * [TupleToolMCBackgroundInfo.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/TupleToolMCBackgroundInfo.cpp) + * [TupleToolMCBackgroundInfo.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/TupleToolMCBackgroundInfo.h) + * _prefix+_BKGCAT + * [TupleToolMCTruth.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/TupleToolMCTruth.cpp) + * [TupleToolMCTruth.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMC/src/TupleToolMCTruth.h) + * _TRUEID +{%endcallout %} + +{% callout "DecayTreeTupleMuonCalib - for muon calibration tools" %} + * [TupleToolMuonIDCalib.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMuonCalib/src/TupleToolMuonIDCalib.cpp) + * [TupleToolMuonIDCalib.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMuonCalib/src/TupleToolMuonIDCalib.h) + * _LHCbID_X, _n + * _LHCbID_Y, _n + * _LHCbID_Z, _n + * _hitInFOI_X, _n_InFOI + * _hitInFOI_dX, _n_InFOI + * _hitInFOI_Y, _n_InFOI + * _hitInFOI_dY, _n_InFOI + * _hitInFOI_Z, _n_InFOI + * _hitInFOI_dZ, _n_InFOI + * _hitInFOI_ID, _n_InFOI + * _hitInFOI_uncrossed, _n_InFOI + * _hitInFOI_TDC1, _n_InFOI + * _hitInFOI_TDC2, _n_InFOI + * _allMuonHits_X, _n_AllHits + * _allMuonHits_dX, _n_AllHits + * _allMuonHits_Y, _n_AllHits + * _allMuonHits_dY, _n_AllHits + * _allMuonHits_Z, _n_AllHits + * _allMuonHits_dZ, _n_AllHits + * _allMuonHits_ID, _n_AllHits + * _allMuonHits_uncrossed, _n_AllHits + * _allMuonHits_TDC1, _n_AllHits + * _allMuonHits_TDC2, _n_AllHits + * _m_trackX[station] + * _m_trackY[station] + * _m_TextraX[station] + * _m_TextraY[station] + * _m_ms2X[station] + * _m_ms2Y[station] + * _m_TextraReg[station] + * _X + * _Y + * _Z + * _5pZM1 + * _5qOverP + * _5sigmaQOverP2 + * _5pXvtx + * _5pYvtx + * _5pZvtx + * _4pZM1 + * _4qOverP + * _4sigmaQOverP2 + * _4pXvtx + * _4pYvtx + * _4pZvtx + * _DistAve + * [TupleToolMuonPid.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMuonCalib/src/TupleToolMuonPid.cpp) + * [TupleToolMuonPid.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleMuonCalib/src/TupleToolMuonPid.h) + * _ID + * _CombDLLMu + * _ProbNNmu + * _ProbNNghost + * _InMuonAcc + * _MuonDist2 + * _regionInM2 + * _hasMuon + * _isMuon + * _isMuonLoose + * _isMuonTight + * _NShared + * _MuonLLmu + * _MuonLLbg + * _isMuonFromProto + * _MuonDist2 +{% endcallout %} + +{% callout "DecayTreeTupleReco - for reconstruction-level information, such as TupleToolTrackInfo" %} + * [TupleToolAllPhotons.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolAllPhotons.cpp) + * [TupleToolAllPhotons.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolAllPhotons.h) + * AllPhotons_PID, nParts + * AllPhotons_TPID, nParts + * AllPhotons_PX, nParts + * AllPhotons_PY, nParts + * AllPhotons_PZ, nParts + * AllPhotons_PE, nParts + * AllPhotons_CaloTrMatch + * AllPhotons_CaloDepositID + * AllPhotons_ShowerShape + * AllPhotons_ClusterMass + * AllPhotons_CaloNeutralSpd + * AllPhotons_CaloNeutralPrs + * AllPhotons_CaloNeutralEcal + * AllPhotons_CaloNeutralHcal2Ecal + * AllPhotons_CaloNeutralE49 + * AllPhotons_CaloNeutralID + * AllPhotons_PhotonID + * AllPhotons_IsPhoton + * [TupleToolAllVeloTracks.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolAllVeloTracks.cpp) + * [TupleToolAllVeloTracks.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolAllVeloTracks.h) + * VeloSegTr_slopeX + * VeloSegTr_slopeY + * VeloSegTr_pointX + * VeloSegTr_pointY + * VeloSegTr_pointZ + * VeloSegTr_chi2pdof + * VeloSegTr_type + * VeloSegTr_key, nVeloSegTracks + * [TupleToolCPU.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolCPU.cpp) + * [TupleToolCPU.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolCPU.h) + * _Memory + * _CPUTime + * [TupleToolPrimaries.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolPrimaries.cpp) + * [TupleToolPrimaries.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolPrimaries.h) + * PVX, nPV + * PVY, nPV + * PVZ, nPV + * PVXERR, nPV + * PVYERR, nPV + * PVZERR, nPV + * PVCHI2, nPV + * PVNDOF, nPV + * PVNTRACKS, nPV + * PVsumPT, nPV + * [TupleToolProtoPData.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolProtoPData.cpp) + * [TupleToolProtoPData.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolProtoPData.h) + * _PP_+var + * [TupleToolRecoStats.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolRecoStats.cpp) + * [TupleToolRecoStats.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolRecoStats.h) + * _nPVs + * _nTracks + * _nLongTracks + * _nDownstreamTracks + * _nUpstreamTracks + * _nVeloTracks + * _nTTracks + * _nBackTracks + * _nRich1Hits + * _nRich2Hits + * _nVeloClusters + * _nITClusters + * _nTTClusters + * _nOTClusters + * _nSPDHits + * _nMuonCoordsS0 + * _nMuonCoordsS1 + * _nMuonCoordsS2 + * _nMuonCoordsS3 + * _nMuonCoordsS4 + * _nMuonTracks + * [TupleToolRICHPid.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolRICHPid.cpp) + * [TupleToolRICHPid.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolRICHPid.h) + * _RICHDLLe + * _RICHDLLmu + * _RICHDLLpi + * _RICHDLLK + * _RICHDLLp + * _RICHDLLbt + * _prefix+_RICHBestID + * _prefix+_RICHThreshold + * _prefix+_RICHThresholdEl + * _prefix+_RICHThresholdMu + * _prefix+_RICHThresholdPi + * _prefix+_RICHThresholdKa + * _prefix+_RICHThresholdPr + * _prefix+_RICHAerogelUsed + * _prefix+_RICH1GasUsed + * _prefix+_RICH2GasUsed + * _prefix+_TRACK_Eta + * _prefix+_TRACK_Phi + * [TupleToolTrackInfo.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolTrackInfo.cpp) + * [TupleToolTrackInfo.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleReco/src/TupleToolTrackInfo.h) + * _TRACK_Type + * _TRACK_Key + * _TRACK_CHI2 + * _TRACK_NDOF + * _TRACK_CHI2NDOF + * _TRACK_PCHI2 + * _TRACK_VeloCHI2NDOF", + * _TRACK_VeloCHI2NDOF + * _TRACK_TCHI2NDOF", + * _TRACK_TCHI2NDOF + * _TRACK_PCHI2 + * _TRACK_CHI2NDOF + * _TRACK_VeloCHI2NDOF + * _TRACK_TCHI2NDOF + * _TRACK_VELO_UTID + * _TRACK_TT_UTID + * _TRACK_IT_UTID + * _TRACK_OT_UTID + * _TRACK_VP_UTID + * _TRACK_UT_UTID + * _TRACK_FT_UTID + * _TRACK_nVeloHits + * _TRACK_nVeloRHits + * _TRACK_nVeloPhiHits + * _TRACK_nVeloPileUpHits + * _TRACK_nTTHits + * _TRACK_nITHits + * _TRACK_nOTHits + * _TRACK_nVPHits + * _TRACK_nUTHits + * _TRACK_nFTHits + * _TRACK_History + * _TRACK_FirstMeasurementX + * _TRACK_FirstMeasurementY + * _TRACK_FirstMeasurementZ + * _TRACK_FirstMeasurementQOverP + * _TRACK_FirstMeasurementTx + * _TRACK_FirstMeasurementTy + * _TRACK_MatchCHI2 + * _TRACK_GhostProb + * _TRACK_CloneDist + * _TRACK_Likelihood +{% endcallout %} + +{% callout "DecayTreeTupleTracking - for more detailed tools regarding tracking" %} + * [TupleToolConeIsolation.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolConeIsolation.cpp) + * [TupleToolConeIsolation.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolConeIsolation.h) + * _MasshPi0, _Pi0_ArrayLength + * _Pi0_PX, _Pi0_ArrayLength + * _Pi0_PY, _Pi0_ArrayLength + * _Pi0_PZ, _Pi0_ArrayLength + * _Pi0_E, _Pi0_ArrayLength + * _Pi0_M, _Pi0_ArrayLength + * _Pi0_DeltaR, _Pi0_ArrayLength + * _Pi0Ph1_CL, _Pi0_ArrayLength + * _Pi0Ph2_CL, _Pi0_ArrayLength + * _MasshPi0, _Pi0_ArrayLength + * _Pi0_PX, _Pi0_ArrayLength + * _Pi0_PY, _Pi0_ArrayLength + * _Pi0_PZ, _Pi0_ArrayLength + * _Pi0_E, _Pi0_ArrayLength + * _Pi0_M, _Pi0_ArrayLength + * _Pi0_DeltaR, _Pi0_ArrayLength + * _Pi0Ph1_CL, _Pi0_ArrayLength + * _Pi0Ph2_CL, _Pi0_ArrayLength + * _MasshMergPi0, _MergPi0_ArrayLength + * _MergPi0_PX, _MergPi0_ArrayLength + * _MergPi0_PY, _MergPi0_ArrayLength + * _MergPi0_PZ, _MergPi0_ArrayLength + * _MergPi0_E, _MergPi0_ArrayLength + * _MergPi0_M, _MergPi0_ArrayLength + * _MergPi0_DeltaR, _MergPi0_ArrayLength + * _MergPi0Ph1_CL, _MergPi0_ArrayLength + * _MergPi0Ph2_CL, _MergPi0_ArrayLength + * _MasshMergPi0, _MergPi0_ArrayLength + * _MergPi0_PX, _MergPi0_ArrayLength + * _MergPi0_PY, _MergPi0_ArrayLength + * _MergPi0_PZ, _MergPi0_ArrayLength + * _MergPi0_E, _MergPi0_ArrayLength + * _MergPi0_M, _MergPi0_ArrayLength + * _MergPi0_DeltaR, _MergPi0_ArrayLength + * _MergPi0Ph1_CL, _MergPi0_ArrayLength + * _MergPi0Ph2_CL, _MergPi0_ArrayLength + * _cc_mult + * _cc_sPT + * _cc_vPT + * _cc_PX + * _cc_PY + * _cc_PZ + * _cc_asy_P + * _cc_asy_PT + * _cc_asy_PX + * _cc_asy_PY + * _cc_asy_PZ + * _cc_deltaEta + * _cc_deltaPhi + * _cc_IT + * _cc_maxPt_Q + * _cc_maxPt_PT + * _cc_maxPt_PX + * _cc_maxPt_PY + * _cc_maxPt_PZ + * _cc_maxPt_PE + * _cc_mult + * _cc_sPT + * _cc_vPT + * _cc_PX + * _cc_PY + * _cc_PZ + * _cc_asy_P + * _cc_asy_PT + * _cc_asy_PX + * _cc_asy_PY + * _cc_asy_PZ + * _cc_deltaEta + * _cc_deltaPhi + * _cc_IT + * _cc_maxPt_Q + * _cc_maxPt_PT + * _cc_maxPt_PX + * _cc_maxPt_PY + * _cc_maxPt_PZ + * _cc_maxPt_PE + * _nc_mult + * [TupleToolDEDX.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolDEDX.cpp) + * [TupleToolDEDX.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolDEDX.h) + * _DEDX_protoCaloHypothesis, CaloHypoLength + * _DEDX_protoCaloLh, CaloHypoLength + * _DEDX_ADCValues, _DEDX_ArrayLength + * _DEDX_CorrectedADCValues + * _DEDX._Q + * _DEDX._Q + * _DEDX._eta + * _EventNumber + * _TrackNumber + * _phi + * _TrackID + * _head+_DEDX_theta + * _momentum + * _momentumTRUE + * _head+_DEDX_pt + * _head+_DEDX_px + * _head+_DEDX_py + * _head+_DEDX_pz + * _head+_DEDX_pseudoRapidity + * _head+_DEDX_trackType + * _head+_DEDX_trackKey + * _head+_DEDX_trackVeloKey + * _head+_DEDX_trackChi2 + * _head+_DEDX_trackProbChi2 + * _head+_DEDX_trackLikelihood + * _head+_DEDX_trackGhostProb + * _head+_DEDX_trackChi2PerDoF + * _head+_DEDX_tracknDoF + * _head+_DEDX_protoMuBkgLL + * _head+_DEDX_protoMuLL + * _head+_DEDX_protoRichDLLe + * _head+_DEDX_protoRichDLLmu + * _head+_DEDX_protoRichDLLpi + * _head+_DEDX_protoRichDLLk + * _head+_DEDX_protoRichDLLp + * _head+_DEDX_protoRichBestPID + * _head+_DEDX_MPV_Mean + * _head+_DEDX_MPV_Median + * _head+_DEDX_MPV_Corrected_Median + * _head+_DEDX_MPV_Trunc20 + * _head+_DEDX_MPV_Trunc40 + * _head+_DEDX_MPV_GenMean_2 + * _head+_DEDX_MPV_GenMean_4 + * _head+_DEDX_MPV_GenMean_6 + * _head+_DEDX_MPV_GenMean_0_5 + * _head+_DEDX_nClustersPerTrack + * [TupleToolMCAssociatedClusters.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolMCAssociatedClusters.cpp) + * [TupleToolMCAssociatedClusters.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolMCAssociatedClusters.h) + * _prefix+_MC_nUsedOTClusters + * _prefix+_MC_nUsedITClusters + * _prefix+_MC_nUsedTTClusters + * _prefix+_MC_nUsedVeloClusters + * _prefix+_MC_nUsedUniqueOTClusters + * _prefix+_MC_nUsedUniqueITClusters + * _prefix+_MC_nUsedUniqueTTClusters + * _prefix+_MC_nUsedUniqueVeloClusters + * _prefix+_MC_nOTClusters + * _prefix+_MC_nITClusters + * _prefix+_MC_nTTClusters + * _prefix+_MC_nVeloClusters + * [TupleToolTrackIsolation.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolTrackIsolation.cpp) + * [TupleToolTrackIsolation.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolTrackIsolation.h) + * _conePx + * _conePy + * _conePz + * _conePt + * _coneP + * _myPair.second + * _deltaEta + * _deltaPhi + * [TupleToolTrackKink.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolTrackKink.cpp) + * [TupleToolTrackKink.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolTrackKink.h) + * _TRACK_kinkChi2 + * _TRACK_kinkChi2z + * _TRACK_kinkFitChi2 + * _TRACK_kinkFitDeltaR + * _TRACK_kinkFitDeltaRE + * _TRACK_kinkFitDeltaRZ + * [TupleToolTrackPosition.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolTrackPosition.cpp) + * [TupleToolTrackPosition.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolTrackPosition.h) + * _X + * _Y + * [TupleToolTrackTime.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolTrackTime.cpp) + * [TupleToolTrackTime.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolTrackTime.h) + * _TRACK_time + * _TRACK_time_err + * [TupleToolVELOClusters.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolVELOClusters.cpp) + * [TupleToolVELOClusters.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolVELOClusters.h) + * UNUSED_VELO_STATION_ADC, nClusters + * UNUSED_VELO_STATION_VECTOR, nClusters + * _nUnusedVeloClusters + * [TupleToolVeloTrackClusterInfo.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolVeloTrackClusterInfo.cpp) + * [TupleToolVeloTrackClusterInfo.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolVeloTrackClusterInfo.h) + * _TRACK_VELO_STATION_ADC, nClusters + * _TRACK_VELO_STATION_VECTOR, nClusters + * _TRACK_TCHI2NDOF + * _TRACK_VELO_TOTALCHARGE + * _TRACK_VELO_AVERAGECHARGE + * _TRACK_VELO_CLUSTERSONTRACK + * [TupleToolVeloTrackMatch.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolVeloTrackMatch.cpp) + * [TupleToolVeloTrackMatch.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTracking/src/TupleToolVeloTrackMatch.h) + * _VM_array_fpos_X, _VM_nTP + * _VM_array_fpos_Y, _VM_nTP + * _VM_array_fpos_Z, _VM_nTP + * _VM_array_fpos_err_XX, _VM_nTP + * _VM_array_fpos_err_YY, _VM_nTP + * _VM_array_fpos_err_XY, _VM_nTP + * _VM_array_slope_X, _VM_nTP + * _VM_array_slope_Y, _VM_nTP + * _VM_array_slope_err_XX, _VM_nTP + * _VM_array_slope_err_YY, _VM_nTP + * _VM_array_slope_err_XY, _VM_nTP + * _VM_array_sloperatio_X, _VM_nTP + * _VM_array_sloperatio_Y, _VM_nTP + * _VM_array_R, _VM_nTP + * _VM_array_IP, _VM_nTP + * _VM_array_CD, _VM_nTP + * _VM_cand_slope_X + * _VM_cand_slope_Y + * _VM_nvelotracks + * _VM_R + * _VM_IP + * _VM_CD + * _VM_index + * _VM_fpos_X + * _VM_fpos_Y + * _VM_fpos_Z + * _VM_fpos_err_XX + * _VM_fpos_err_YY + * _VM_fpos_err_XY + * _VM_sloperatio_X + * _VM_sloperatio_Y + * _VM_slope_X + * _VM_slope_Y + * _VM_slope_err_XX + * _VM_slope_err_YY + * _VM_slope_err_XY +{% endcallout %} + +{% callout "DecayTreeTupleTrigger - for access to the trigger information of the candidates" %} + * [TupleToolEventInfo.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolEventInfo.cpp) + * [TupleToolEventInfo.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolEventInfo.h) + * _Mu + * _runNumber + * _eventNumber + * _BCID + * _BCType + * _OdinTCK + * _L0DUTCK + * _HLT1TCK + * _HLT2TCK + * _GpsTime + * _GpsYear + * _GpsMonth + * _GpsDay + * _GpsHour + * _GpsMinute + * _TriggerType + * _Polarity + * [TupleToolFillingScheme.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolFillingScheme.cpp) + * [TupleToolFillingScheme.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolFillingScheme.h) + * _fill + * _CrossingsAfterToEE + * _CrossingsAfterToBB + * _CrossingsAfterToBE + * _CrossingsAfterToEB + * _CrossingsBeforeToEE + * _CrossingsBeforeToBB + * _CrossingsBeforeToBE + * _CrossingsBeforeToEB + * _IsBeamBeam + * _Prev1 + * _Prev2 + * _Next1 + * _Next2 + * _isSpillOver + * _isEmpty + * _isPreSpill + * [TupleToolL0Calo.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolL0Calo.cpp) + * [TupleToolL0Calo.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolL0Calo.h) + * _L0Calo_HCAL_realET + * _L0Calo_HCAL_xProjection + * _L0Calo_HCAL_yProjection + * _L0Calo_HCAL_region + * _L0Calo_HCAL_TriggerET + * _L0Calo_HCAL_TriggerHCALET + * _L0Calo_HCAL_xTrigger + * _L0Calo_HCAL_yTrigger + * _L0Calo_ECAL_realET + * _L0Calo_ECAL_xProjection + * _L0Calo_ECAL_yProjection + * _L0Calo_ECAL_region + * _L0Calo_ECAL_TriggerET + * _L0Calo_ECAL_xTrigger + * _L0Calo_ECAL_yTrigger + * [TupleToolL0Data.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolL0Data.cpp) + * [TupleToolL0Data.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolL0Data.h) + * \_prefix+L0Data\_+rename(name) + * \_prefix+L0Data\_+rename(name) + * \_prefix+L0Emu\_TCK+stck + * [TupleToolStripping.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolStripping.cpp) + * [TupleToolStripping.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolStripping.h) + * [TupleToolTISTOS.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolTISTOS.cpp) + * [TupleToolTISTOS.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolTISTOS.h) + * _Dec, + * _TIS, + * _TOS, + * _TUS, + * _TPS, + * _prefix+L0Global + * _prefix+Hlt1Global + * _prefix+Hlt2Global + * _prefix+*n, + * _prefix+level+nSelections + * [TupleToolTriggerBase.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolTriggerBase.cpp) + * [TupleToolTriggerBase.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolTriggerBase.h) + * [TupleToolTrigger.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolTrigger.cpp) + * [TupleToolTrigger.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolTrigger.h) + * RoutingBits, MaxRoutingBits + * [TupleToolTriggerRecoStats.cpp](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolTriggerRecoStats.cpp) + * [TupleToolTriggerRecoStats.h](https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/DecayTreeTupleTrigger/src/TupleToolTriggerRecoStats.h) + * _TriggerRecoStats./Particles +{% endcallout %} diff --git a/first-analysis-steps/TupleTools.md~ b/first-analysis-steps/TupleTools.md~ new file mode 100644 index 00000000..bdd2d42b --- /dev/null +++ b/first-analysis-steps/TupleTools.md~ @@ -0,0 +1,34 @@ + + + +this is where the tuple tool is gunna go! + +# Title goes here + +{% objectives "Learning Objectives" %} +* Lauren do something +{% endobjectives %} + +{% callout "Nice list bro" %} +Different ways of writing: + + - `Code looks fun` + - *Italic shit* +{% endcallout %} + +```python +Write code here +``` + +{% challenge "Challenging" %} + +This the tuple tool for MCTupleToolAngles.md +[.cpp](DecayTrees/MCTupleToolAngles.html) +[.h](DecayTrees/MCTupleToolAngles2.html) + +{% endchallenge %} + +Numbered list coming up: + + 1. We are number 1 +