diff --git a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/InDetVKalVxInJetTool/InDetTrkInJetType.h b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/InDetVKalVxInJetTool/InDetTrkInJetType.h index 85cf7b30328ee21fa27d89e69491786703fbc302..3f947855d42c3b2c49b761dcbb504b8026c9aca7 100644 --- a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/InDetVKalVxInJetTool/InDetTrkInJetType.h +++ b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/InDetVKalVxInJetTool/InDetTrkInJetType.h @@ -79,11 +79,14 @@ namespace InDet { private: TMVA::Reader* m_tmvaReader; - double m_trkMinPtCut; - float m_d0_limLow; - float m_d0_limUpp; - float m_Z0_limLow; - float m_Z0_limUpp; + int m_trkSctHitsCut{}; + int m_trkPixelHitsCut{}; + float m_trkChi2Cut{}; + float m_trkMinPtCut{}; + float m_d0_limLow{}; + float m_d0_limUpp{}; + float m_Z0_limLow{}; + float m_Z0_limUpp{}; std::string m_calibFileName; ToolHandle < Trk::IVertexFitter > m_fitterSvc; Trk::TrkVKalVrtFitter* m_fitSvc{}; diff --git a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/InDetVKalVxInJetTool/InDetVKalVxInJetTool.h b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/InDetVKalVxInJetTool/InDetVKalVxInJetTool.h index cfb8d0c68ede6af5645d378815a310a5d245551b..e6da7b7d5b417d5653faf99813c4d0a46da699f4 100755 --- a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/InDetVKalVxInJetTool/InDetVKalVxInJetTool.h +++ b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/InDetVKalVxInJetTool/InDetVKalVxInJetTool.h @@ -48,6 +48,7 @@ // #include "Particle/TrackParticle.h" #include "xAODTracking/TrackParticleContainer.h" +#include "xAODTruth/TruthEventContainer.h" // // #include "InDetRecToolInterfaces/ISecVertexInJetFinder.h" @@ -120,17 +121,6 @@ namespace InDet { const TLorentzVector & jetMomentum, const std::vector<const xAOD::IParticle*> & inputTracks) const; -//--------------------------------------------- For package debugging - public: - void setVBTrk(std::vector<const xAOD::TrackParticle*> * BTrk) const { m_dbgVBTrk=BTrk; }; - private: - int isBTrk(const xAOD::TrackParticle* prt) const - { if(!m_dbgVBTrk) return 0; - if(std::find((*m_dbgVBTrk).begin(),(*m_dbgVBTrk).end(), prt) != (*m_dbgVBTrk).end()) return 1; - return 0; - } - int isBTrk(const Rec::TrackParticle*) const { return 0; } - mutable std::vector<const xAOD::TrackParticle*> *m_dbgVBTrk=nullptr; //------------------------------------------------------------------------------------------------------------------ // Private data and functions // @@ -212,6 +202,8 @@ namespace InDet { double m_zTrkErrorCut{}; double m_cutHFClass{}; double m_antiGarbageCut{}; + double m_antiFragmentCut{}; + double m_Vrt2TrMassLimit{}; bool m_fillHist{}; @@ -261,6 +253,10 @@ namespace InDet { //------------------------------------------- //For ntuples (only for development/tuning!) + int notFromBC(int PDGID) const; + const xAOD::TruthParticle * getPreviousParent(const xAOD::TruthParticle * child, int & ParentPDG) const; + int getIdHF(const Rec::TrackParticle* TP ) const; + int getIdHF(const xAOD::TrackParticle* TP ) const; int getG4Inter( const Rec::TrackParticle* TP ) const; int getG4Inter( const xAOD::TrackParticle* TP ) const; int getMCPileup(const Rec::TrackParticle* TP ) const; @@ -269,6 +265,7 @@ namespace InDet { struct DevTuple { static const int maxNTrk=100; + static const int maxNVrt=100; int nTrkInJet; float ptjet; float etajet; @@ -288,19 +285,31 @@ namespace InDet { float Sig3D[maxNTrk]; int chg[maxNTrk]; int nVrtT[maxNTrk]; - int nVrt; - float VrtDist2D[maxNTrk]; - float VrtSig3D[maxNTrk]; - float VrtSig2D[maxNTrk]; - float mass[maxNTrk]; - float Chi2[maxNTrk]; - int itrk[maxNTrk]; - int jtrk[maxNTrk]; - int badVrt[maxNTrk]; - int ibl[maxNTrk]; - int bl[maxNTrk]; + float TotM; + int nVrt; + float VrtDist2D[maxNVrt]; + float VrtSig3D[maxNVrt]; + float VrtSig2D[maxNVrt]; + float VrtDR[maxNVrt]; + float mass[maxNVrt]; + float Chi2[maxNVrt]; + int itrk[maxNVrt]; + int jtrk[maxNVrt]; + int badVrt[maxNVrt]; + int ibl[maxNVrt]; + int bl[maxNVrt]; int NTHF; - int itHF[maxNTrk]; + int itHF[maxNVrt]; + //--- + int nNVrt; + float NVrtDist2D[maxNVrt]; + int NVrtNT[maxNVrt]; + int NVrtTrkI[maxNVrt]; + float NVrtM[maxNVrt]; + float NVrtChi2[maxNVrt]; + float NVrtMaxW[maxNVrt]; + float NVrtAveW[maxNVrt]; + float NVrtDR[maxNVrt]; }; DevTuple* m_curTup; @@ -317,6 +326,7 @@ namespace InDet { double Signif3DProj=0.; double Signif2D=0.; double Chi2=0.; + double dRSVPV=-1.; }; @@ -326,7 +336,7 @@ namespace InDet { float m_chiScale[11]{}; VKalVxInJetTemp* m_WorkArray{}; struct WrkVrt - { bool Good{}; + { bool Good=true; std::deque<long int> SelTrk; Amg::Vector3D vertex; TLorentzVector vertexMom; @@ -335,9 +345,9 @@ namespace InDet { std::vector<double> Chi2PerTrk; std::vector< std::vector<double> > TrkAtVrt; double Chi2{}; - int nCloseVrt{}; - double dCloseVrt{}; - double ProjectedVrt{}; + int nCloseVrt=0; + double dCloseVrt=1000000.; + double ProjectedVrt=0.; int detachedTrack=-1; }; @@ -411,7 +421,9 @@ namespace InDet { double VrtRadiusError(const Amg::Vector3D & SecVrt, const std::vector<double> & VrtErr) const; bool insideMatLayer(float ,float ) const; - void fillVrtNTup( std::vector<Vrt2Tr> & all2TrVrt) const; + void fillVrtNTup( std::vector<Vrt2Tr> & all2TrVrt) const; + void fillNVrtNTup(std::vector<WrkVrt> & VrtSet, std::vector< std::vector<float> > & trkScore, + const xAOD::Vertex & PrimVrt, const TLorentzVector & JetDir)const; TLorentzVector GetBDir( const xAOD::TrackParticle* trk1, const xAOD::TrackParticle* trk2, @@ -482,6 +494,9 @@ namespace InDet { template <class Particle> double mergeAndRefitVertices( std::vector<WrkVrt> *WrkVrtSet, int V1, int V2, WrkVrt & newvrt, std::vector<const Particle*> & AllTrackList) const; + template <class Particle> + void mergeAndRefitOverlapVertices( std::vector<WrkVrt> *WrkVrtSet, int V1, int V2, + std::vector<const Particle*> & AllTrackList) const; template <class Particle> double improveVertexChi2( std::vector<WrkVrt> *WrkVrtSet, int V, std::vector<const Particle*> & AllTracks)const; diff --git a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/Root/README b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/Root/README new file mode 100644 index 0000000000000000000000000000000000000000..73266aa7a361a4a6c8b15ee9f63027a099356eaf --- /dev/null +++ b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/Root/README @@ -0,0 +1,11 @@ +Tool calibration data can be obtained by running the InDetVKalVxInJetTool with the following jobO: + +FillHist = 1 +AntiGarbageCut = 1.0 + +Produce calibation files using different MC samples (ttbar, Zp, dijet,...) +Edit Train.C to provide correct pathes to all this calibration files +Run corrected Train.C using root 6.12 or above. + +Use HF tracks from b-jets +Use fragmentation tracks from L+HF jets diff --git a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/BTagVrtSec.cxx b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/BTagVrtSec.cxx index ecf1ccae1066ee6bad93e1b4659568b50b1b87ad..104fb338a7223343bd1d62803a82f80142df04a5 100755 --- a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/BTagVrtSec.cxx +++ b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/BTagVrtSec.cxx @@ -36,10 +36,20 @@ namespace InDet{ float median(std::vector<float> &Vec){ int N=Vec.size(); if(N==1) return Vec[0]; - if(N>1){ + if(N==2) return (Vec[0]+Vec[1])/2.; + if(N==3) return Vec[1]; + if(N>3){ std::vector<float> tmp(Vec); - std::sort(tmp.begin(),tmp.end()); //can use nth_element instead of completely sorting, it's quicker - return (tmp[(N-1)/2]+tmp[N/2])/2.; //only true if the number of elements is even? + int N05m=(N-1)/2, N05p=N/2; + //std::sort(tmp.begin(),tmp.end()); //can use nth_element instead of completely sorting, it's quicker + if(N05m==N05p){ + std::nth_element(tmp.begin(),tmp.begin()+N05m,tmp.end()); + return tmp[N05m]; + } else { + std::nth_element(tmp.begin(),tmp.begin()+N05m,tmp.end()); + std::nth_element(tmp.begin(),tmp.begin()+N05p,tmp.end()); + return (tmp[N05m]+tmp[N05p])/2.; + } } return 0.; } @@ -508,6 +518,7 @@ namespace InDet{ float R=JetDir.DeltaR(TLorentzVector(FitVertex.x()-PrimVrt.x(),FitVertex.y()-PrimVrt.y(), FitVertex.z()-PrimVrt.z(), 1.e4)); m_hb_deltaRSVPV->Fill( R, m_w_1); + if(m_curTup)m_curTup->TotM=Momentum.M(); } //------------------------------------------------------------------------------------- @@ -713,7 +724,6 @@ namespace InDet{ // std::vector<float> covPV=PrimVrt.covariance(); double SignifR=0.,SignifZ=0.; - int nTrkHF=0; std::vector<int> hitIBL(NTracks,0), hitBL(NTracks,0); std::vector<double> TrackSignif(NTracks),TrkSig3D(NTracks); std::vector< std::vector<float> > trkScore(NTracks); @@ -731,7 +741,6 @@ namespace InDet{ int hL1=0, nLays=0; getPixelLayers(SelectedTracks[i] , hitIBL[i] , hitBL[i], hL1, nLays ); //---- trkScore[i]=m_trackClassificator->trkTypeWgts(SelectedTracks[i], PrimVrt, JetDir); - if( trkScore[i][0]>trkScore[i][1] && trkScore[i][0]>trkScore[i][2] ) nTrkHF++; //Good HF track if(m_fillHist){ m_hb_impactR->Fill( SignifR, m_w_1); m_hb_impactZ->Fill( SignifZ, m_w_1); @@ -743,7 +752,7 @@ namespace InDet{ m_curTup->SigR[i]=SignifR; m_curTup->SigZ[i]=SignifZ; m_curTup->d0[i]=Impact[0]; m_curTup->Z0[i]=Impact[1]; m_curTup->idMC[i]=getG4Inter(SelectedTracks[i]); - if(isBTrk(SelectedTracks[i]))m_curTup->idMC[i]=2; + if(getIdHF(SelectedTracks[i]))m_curTup->idMC[i]=2; if(getMCPileup(SelectedTracks[i]))m_curTup->idMC[i]=3; m_curTup->wgtB[i]=trkScore[i][0]; m_curTup->wgtL[i]=trkScore[i][1]; m_curTup->wgtG[i]=trkScore[i][2]; m_curTup->Sig3D[i]=TrkSig3D[i]; @@ -759,10 +768,8 @@ namespace InDet{ } } } - if (not m_curTup) return; //something very wrong if(m_fillHist){ m_curTup->ptjet=JetDir.Perp(); m_curTup->etajet=fabs(JetDir.Eta()); m_curTup->phijet=JetDir.Phi(); m_curTup->nTrkInJet=std::min(NTracks,DevTuple::maxNTrk); }; - if(nTrkHF==0) return; //====== No at all good HF tracks ListSecondTracks.reserve(2*NTracks); // Reserve memory for single vertex @@ -776,8 +783,13 @@ namespace InDet{ if(trkScore[i][0]==0.)continue; if(trkScore[j][0]==0.)continue; if(!m_multiWithPrimary) { // Not used for multi-vertex with primary one search - if( trkScore[i][0]<m_cutHFClass )continue; //Not classified HF tracks - if( trkScore[j][0]<m_cutHFClass )continue; //Not classified HF tracks + if( std::max(trkScore[i][1],trkScore[j][1]) > m_antiFragmentCut ) continue; // Remove definite fragmentation tracks + bool goodPair=false; + float minWgtB=std::min(trkScore[i][0],trkScore[j][0]); + float maxWgtB=std::max(trkScore[i][0],trkScore[j][0]); + if( minWgtB>m_cutHFClass ) goodPair=true; + if( maxWgtB>0.5 && minWgtB>m_cutHFClass/2. )goodPair=true; + if( !goodPair ) continue; } int BadTracks = 0; //Bad tracks identification TracksForFit.resize(2); @@ -805,12 +817,15 @@ namespace InDet{ Dist2D=tmpVrt.FitVertex.perp(); if(Dist2D > 180. ) continue; // can't be from B decay double mass_PiPi = tmpVrt.Momentum.M(); - if(mass_PiPi > c_vrtBCMassLimit) continue; // can't be from B decay + if(mass_PiPi > m_Vrt2TrMassLimit) continue; // can't be from B decay VrtVrtDist(PrimVrt, tmpVrt.FitVertex, tmpVrt.ErrorMatrix, Signif3D); tmpVrt.Signif3D=Signif3D; VrtVrtDist2D(PrimVrt, tmpVrt.FitVertex, tmpVrt.ErrorMatrix, tmpVrt.Signif2D); //--- TVector3 SVmPV(tmpVrt.FitVertex.x()-PrimVrt.x(),tmpVrt.FitVertex.y()-PrimVrt.y(),tmpVrt.FitVertex.z()-PrimVrt.z()); + tmpVrt.dRSVPV=JetDir.DeltaR(TLorentzVector(SVmPV, 1.)); //DeltaR SV-PV vs jet + if(tmpVrt.dRSVPV > m_coneForTag ) continue; // SV is outside of the jet cone +//--- JetVrtDir = SVmPV.Dot(JetDir.Vect()); double vPos=SVmPV.Dot(tmpVrt.Momentum.Vect())/tmpVrt.Momentum.Rho(); if((!m_multiWithPrimary) &&(!m_getNegativeTail) && (!m_getNegativeTag) && JetVrtDir<0. ) continue; /* secondary vertex behind primary*/ @@ -972,18 +987,27 @@ namespace InDet{ // { if( trkTypeSV[all2TrVrt[iv].i]>0 && trkTypeSV[all2TrVrt[iv].j]>0) all2TrVrt.erase(all2TrVrt.begin()+iv); else iv++; } // */ +//-- Cleaning. Remove small wgtB tracks attached to one vertex only. +// std::vector<int> inVrt(NTracks,0); +// for( auto vv : all2TrVrt){ inVrt[vv.i]++; inVrt[vv.j]++; } +// ////std::map<float,int> trkInOneV; for( int kt=0; kt<NTracks; kt++) if(inVrt[kt]==1) trkInOneV[trkScore[kt][0]]=kt; +// for(int kk=0; kk<NTracks; kk++){ +// if( inVrt[kk]==1 && trkScore[kk][0]<2.5*m_cutHFClass ) { +// int iv=0; while (iv<(int)all2TrVrt.size()){ if( all2TrVrt[iv].i==kk || all2TrVrt[iv].j==kk ) { all2TrVrt.erase(all2TrVrt.begin()+iv); break;} else iv++; } +// } } +//============================================================================ //-- Save results ListSecondTracks.clear(); std::map<float,int> trkHF; - for( auto vv : all2TrVrt){ + for( auto &vv : all2TrVrt){ if( m_multiWithPrimary || m_multiVertex) add_edge(vv.i,vv.j,*m_compatibilityGraph); trkHF[trkScore[vv.i][0]]=vv.i; trkHF[trkScore[vv.j][0]]=vv.j; } for( auto it : trkHF) { ListSecondTracks.push_back(SelectedTracks[it.second]); } //-Debug if( m_fillHist && m_curTup ){ - for( auto it : trkHF) { m_curTup->itHF[m_curTup->NTHF++]=it.second; } - for( auto vv : all2TrVrt){ m_curTup->nVrtT[vv.i]++; m_curTup->nVrtT[vv.j]++; } + for( auto &it : trkHF) { m_curTup->itHF[m_curTup->NTHF++]=it.second; } + for( auto &vv : all2TrVrt){ m_curTup->nVrtT[vv.i]++; m_curTup->nVrtT[vv.j]++; } fillVrtNTup(all2TrVrt); } // diff --git a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/BTagVrtSecMulti.cxx b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/BTagVrtSecMulti.cxx index 0a73eb71e87e7eb1a6e7b96e77c5e3ea70c2ea91..368e41ff99e85bf41f806575c921a8315be57905 100755 --- a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/BTagVrtSecMulti.cxx +++ b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/BTagVrtSecMulti.cxx @@ -56,8 +56,7 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com const { - const double probVrtMergeLimit=0.04; - const int useMaterialRejection=1; + const double probVrtMergeLimit=0.01; m_NRefPVTrk=0; int inpNPart=0; @@ -74,7 +73,7 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com if(msgLvl(MSG::DEBUG))msg(MSG::DEBUG) << "InDet GetVrtSecMulti() called with NPart=" <<inpNPart<< endmsg; //std::vector<const Rec::TrackParticle*> listJetTracks, tmpListTracks, listSecondTracks, TracksForFit; - std::vector<xAOD::Vertex*> finalVertices; + std::vector<xAOD::Vertex*> finalVertices(0); if( inpNPart < 2 ) { return finalVertices;} // 0,1 track => nothing to do! @@ -205,7 +204,7 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com newvrt.Good = true; newvrt.nCloseVrt = 0; newvrt.dCloseVrt = 1000000.; - newvrt.ProjectedVrt=JetProjDist(newvrt.vertex, PrimVrt, JetDir); + newvrt.ProjectedVrt=JetProjDist(newvrt.vertex, PrimVrt, JetDir); //3D SV-PV distance WrkVrtSet->push_back(newvrt); } //================================================================================== @@ -220,45 +219,23 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com // std::vector<const xAOD::TrackParticle*> tempTrk(0); // for(auto & iv : (*WrkVrtSet)){ if(iv.Good){for(auto & it : iv.SelTrk)tempTrk.push_back(xAODwrk->listJetTracks.at(it));}} // RemoveDoubleEntries(tempTrk); -//--- Initial cleaning of solutions // -//- Try to merge vertices with 3 and more tracks which have at least 2 common tracks - int NSoluI=(*WrkVrtSet).size(); - for(int iv=0; iv<NSoluI-1; iv++ ){ - if(!(*WrkVrtSet)[iv].Good ) continue; - int nTrk1=(*WrkVrtSet)[iv].SelTrk.size(); - for(int jv=iv+1; jv<NSoluI; jv++){ - if(!(*WrkVrtSet)[jv].Good ) continue; - int nTrk2=(*WrkVrtSet)[jv].SelTrk.size(); - if( nTrk1<3 || nTrk2<3 || nTrk1+nTrk2<7) continue; - int nTCom=nTrkCommon( WrkVrtSet, iv, jv); - if( nTrk1-nTCom==1 || nTrk2-nTCom==1){ - double probV=-1.; - if (xAODwrk)probV=mergeAndRefitVertices( WrkVrtSet, iv, jv, newvrt, xAODwrk->listJetTracks); - else if(RECwork)probV=mergeAndRefitVertices( WrkVrtSet, iv, jv, newvrt, RECwork->listJetTracks); - if(probV<probVrtMergeLimit)continue; - newvrt.Good = true; - newvrt.ProjectedVrt=JetProjDist(newvrt.vertex, PrimVrt, JetDir); - (*WrkVrtSet).push_back(newvrt); - (*WrkVrtSet)[iv].Good=false; - (*WrkVrtSet)[jv].Good=false; - } - } - } +//========= Initial cleaning of solutions //-Remove worst track from vertices with very bad Chi2 - NSoluI=(*WrkVrtSet).size(); - for(int iv=0; iv<NSoluI; iv++){ - if(!(*WrkVrtSet)[iv].Good ) continue; - if( (*WrkVrtSet)[iv].SelTrk.size() == 2 ) continue; - //if( (*WrkVrtSet)[iv].Chi2 > (5.*(*WrkVrtSet)[iv].SelTrk.size()) ){ - if( TMath::Prob( (*WrkVrtSet)[iv].Chi2, 2*(*WrkVrtSet)[iv].SelTrk.size()-3) <1.e-2){ + bool disassembled=false; + int NSoluI=0; + do{ + disassembled=false; + NSoluI=(*WrkVrtSet).size(); + for(int iv=0; iv<NSoluI; iv++){ + if(!(*WrkVrtSet)[iv].Good || (*WrkVrtSet)[iv].SelTrk.size() == 2 ) continue; + if( TMath::Prob( (*WrkVrtSet)[iv].Chi2, 2*(*WrkVrtSet)[iv].SelTrk.size()-3) <1.e-3){ + //printWrkSet(WrkVrtSet,"BigChi2Vertex present"); if (xAODwrk)DisassembleVertex(WrkVrtSet,iv,xAODwrk->listJetTracks); else if(RECwork)DisassembleVertex(WrkVrtSet,iv,RECwork->listJetTracks); - (*WrkVrtSet)[iv].ProjectedVrt=JetProjDist((*WrkVrtSet)[iv].vertex, PrimVrt, JetDir); - int kpp=(*WrkVrtSet).size()-1; - (*WrkVrtSet)[kpp].ProjectedVrt=JetProjDist((*WrkVrtSet)[kpp].vertex, PrimVrt, JetDir); - } - } + disassembled=true; + } } + }while(disassembled); //-Remove vertices fully contained in other vertices while( (*WrkVrtSet).size()>1 ){ int tmpN=(*WrkVrtSet).size(); int iv=0; @@ -272,32 +249,50 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com } if(jv!=tmpN) break; // One vertex is erased. Restart check } if(iv==tmpN-1) break; // No vertex deleted } - if(m_fillHist){ int cvgood=0; for(int iv=0; iv<(int)(*WrkVrtSet).size(); iv++) if((*WrkVrtSet)[iv].Good)cvgood++; - m_hb_rawVrtN->Fill( (float)cvgood, m_w_1); } -//- Try to merge all vertices which have at least 2 common track - for(int iv=0; iv<(int)(*WrkVrtSet).size()-1; iv++ ){ - if(!(*WrkVrtSet)[iv].Good ) continue; - for(int jv=iv+1; jv<(int)(*WrkVrtSet).size(); jv++){ - if(!(*WrkVrtSet)[jv].Good ) continue; - if(nTrkCommon( WrkVrtSet, iv, jv)<2) continue; - if( VrtVrtDist((*WrkVrtSet)[iv].vertex,(*WrkVrtSet)[iv].vertexCov, - (*WrkVrtSet)[jv].vertex,(*WrkVrtSet)[jv].vertexCov) < m_vertexMergeCut) { - double probV=0.; - if (xAODwrk)probV=mergeAndRefitVertices( WrkVrtSet, iv, jv, newvrt, xAODwrk->listJetTracks); - else if(RECwork)probV=mergeAndRefitVertices( WrkVrtSet, iv, jv, newvrt, RECwork->listJetTracks); - if(probV>probVrtMergeLimit){ // Good merged vertex found - double tstDst=JetProjDist(newvrt.vertex, PrimVrt, JetDir); - if(tstDst>0.){ // only positive vertex directions are accepted as merging result - newvrt.ProjectedVrt=tstDst; - (*WrkVrtSet).push_back(newvrt); - (*WrkVrtSet)[iv].Good=false; - (*WrkVrtSet)[jv].Good=false; - break; - } +// +//- Try to merge all vertices with common tracks + std::multimap<int,std::pair<int,int>> vrtWithCommonTrk; + std::multimap<int,std::pair<int,int>>::reverse_iterator icvrt; + do{ + NSoluI=(*WrkVrtSet).size(); + vrtWithCommonTrk.clear(); + for(int iv=0; iv<NSoluI-1; iv++ ){ for(int jv=iv+1; jv<NSoluI; jv++){ + if(!(*WrkVrtSet)[iv].Good || !(*WrkVrtSet)[jv].Good) continue; + int nTCom=nTrkCommon( WrkVrtSet, iv, jv); if(!nTCom)continue; + vrtWithCommonTrk.emplace(nTCom,std::make_pair(iv,jv)); + } } + //============================== DEBUG output + //printWrkSet(WrkVrtSet,"InitialVrts"); + //for(auto ku : vrtWithCommonTrk)std::cout<<" nCom="<<ku.first<<" v1="<<ku.second.first<<" v2="<<ku.second.second<<'\n'; + //=========================================== + for(icvrt=vrtWithCommonTrk.rbegin(); icvrt!=vrtWithCommonTrk.rend(); icvrt++){ + int nTCom=(*icvrt).first; + int iv=(*icvrt).second.first; + int jv=(*icvrt).second.second; + int nTrkI=(*WrkVrtSet)[iv].SelTrk.size(); + int nTrkJ=(*WrkVrtSet)[jv].SelTrk.size(); + double probV=-1.; + if (xAODwrk)probV=mergeAndRefitVertices( WrkVrtSet, iv, jv, newvrt, xAODwrk->listJetTracks); + else if(RECwork)probV=mergeAndRefitVertices( WrkVrtSet, iv, jv, newvrt, RECwork->listJetTracks); + ////std::cout<<" ntcommon="<<(*icvrt).first<<" prb="<<probV<<" itrk="<<nTrkI<<" jtrk="<<nTrkJ<<'\n'; + if(probV<probVrtMergeLimit){ + if(nTrkI==2 || nTrkJ==2 || nTCom<2) continue; + if((nTCom>nTrkI-nTCom || nTCom>nTrkJ-nTCom)){ //2 and more common tracks for NTr>=3 vertices. Merge anyway. + if (xAODwrk)mergeAndRefitOverlapVertices( WrkVrtSet, iv, jv, xAODwrk->listJetTracks); + else if(RECwork)mergeAndRefitOverlapVertices( WrkVrtSet, iv, jv, RECwork->listJetTracks); + break; //Vertex list is changed. Restart merging from scratch. } - } + continue; //Continue merging loop + } + newvrt.Good = true; + (*WrkVrtSet).push_back(newvrt); + (*WrkVrtSet)[iv].Good=false; + (*WrkVrtSet)[jv].Good=false; + break; //Merging successful. Break merging loop and remake list of connected vertices } - } + } while( icvrt != vrtWithCommonTrk.rend() ); + if(m_fillHist){ int cvgood=0; for(int iv=0; iv<(int)(*WrkVrtSet).size(); iv++) if((*WrkVrtSet)[iv].Good)cvgood++; + m_hb_rawVrtN->Fill( (float)cvgood, m_w_1); } //-Identify/remove vertices behind the PV wrt jet direction //-Identify remaining 2-track vertices with very bad Chi2 and mass (b-tagging) // for(int iv=0; iv<(int)(*WrkVrtSet).size(); iv++ ){ @@ -308,9 +303,24 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com // if( (*WrkVrtSet)[iv].Chi2 > 10.) (*WrkVrtSet)[iv].Good=false; // if( (*WrkVrtSet)[iv].vertexMom.M()>c_vrtBCMassLimit) (*WrkVrtSet)[iv].Good=false; //VK B-tagging specific requirement // } +// //-Remove all bad vertices from the working set + for( auto &tmpV : (*WrkVrtSet) ) { + if(tmpV.vertex.perp()>m_rLayer3+10.)tmpV.Good=false; //Vertices outside Pixel detector + TLorentzVector SVPV(tmpV.vertex.x()-PrimVrt.x(),tmpV.vertex.y()-PrimVrt.y(),tmpV.vertex.z()-PrimVrt.z(),1.); + if(JetDir.DeltaR(SVPV)>m_coneForTag)tmpV.Good=false; // SV is outside of the jet cone + } int tmpV=0; while( tmpV<(int)(*WrkVrtSet).size() )if( !(*WrkVrtSet)[tmpV].Good ) { (*WrkVrtSet).erase((*WrkVrtSet).begin()+tmpV);} else {tmpV++;} + if((*WrkVrtSet).size()==0){ // No vertices at all + delete WrkVrtSet; + return finalVertices; + } + //------ //printWrkSet(WrkVrtSet,"Interm"); + //------ + std::vector< std::vector<float> > trkScore(0); + if(xAODwrk){ for(auto &trk : xAODwrk->listJetTracks) trkScore.push_back(m_trackClassificator->trkTypeWgts(trk, PrimVrt, JetDir)); } + for( auto &tmpV : (*WrkVrtSet) ) tmpV.ProjectedVrt=JetProjDist(tmpV.vertex, PrimVrt, JetDir); //Setup ProjectedVrt //---------------------------------------------------------------------------- // Add primary vertex // @@ -342,11 +352,13 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com // } // //---------------------------------------------------------------------------- -// Here we have the overlapping solutions +// Here we have the overlapping solutions. +// Vertices may have only 1 common track. // Now solution cleaning int nGoodVertices=0; // Final number of good vertices - int n2trVrt=0; // N vertices with 2 and more tracks + int n2trVrt=0; // N of vertices with 2 tracks + int nNtrVrt=0; // N vertices with 3 and more tracks std::vector< std::deque<long int> > *TrkInVrt =new std::vector< std::deque<long int> >(NTracks); double foundMaxT; long int SelectedTrack, SelectedVertex; int foundV1, foundV2; @@ -425,7 +437,7 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com minDistVV=minVrtVrtDistNext( WrkVrtSet, foundV1, foundV2); } // -// Try to improve vertices with big Chi2 +// Try to improve vertices with big Chi2 if something went wrong. Just precaution. for(int iv=0; iv<(int)WrkVrtSet->size(); iv++) { if(!(*WrkVrtSet)[iv].Good ) continue; //don't work on vertex which is already bad if( (*WrkVrtSet)[iv].SelTrk.size()<3 ) continue; @@ -541,23 +553,7 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com } // //--- Check interactions on pixel layers -// - //if( curVrt.vertex.perp()>m_beampipeR-2. && curVrt.detachedTrack<0) { - if( curVrt.vertex.perp()>m_beampipeR-2.) { - double minPt=1.e9; for(int ti=0; ti<nth; ti++) minPt=TMath::Min(minPt,MomAtVrt(curVrt.TrkAtVrt[ti]).Pt()); - if(m_fillHist){ - m_hb_totmass2T0->Fill( curVrt.vertexMom.M()-nth*m_massPi, m_w_1); - m_hb_r2d->Fill( curVrt.vertex.perp(), m_w_1); - } - if(useMaterialRejection){ - if( insideMatLayer(curVrt.vertex.x(),curVrt.vertex.y()) ) continue; - } - //double dR=0; for(int mi=0;mi<nth-1;mi++)for(int mj=mi+1;mj<nth;mj++) - // dR=TMath::Max(dR,MomAtVrt(curVrt.TrkAtVrt[mi]).DeltaR(MomAtVrt(curVrt.TrkAtVrt[mj]))); - //if(m_fillHist)m_hb_deltaRSVPV->Fill(dR,m_w_1); - //if( m_killHighPtIBLFakes && curVrt.vertex.perp()<m_rLayer1 && dR<0.015)continue; - if(Signif3D<20.) continue; - } + if(m_fillHist && nth==2){ m_hb_r2d->Fill( curVrt.vertex.perp(), m_w_1); } // //--- Check V0s and conversions if(nth==2 && curVrt.vertexCharge==0 && curVrt.detachedTrack<0){ @@ -574,19 +570,9 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com //--- if(m_fillHist){m_hb_sig3DTot->Fill( Signif3D, m_w_1); } if(Signif3D<m_sel2VrtSigCut)continue; //Main PV-SV distance quality cut -//----- -// float Dist2D= (*WrkVrtSet)[iv].vertex.perp(); -// if(Dist2D<2.){ -// double tmpProb=0.; -// if (xAODwrk)tmpProb=FitVertexWithPV( WrkVrtSet, iv, PrimVrt, xAODwrk->listJetTracks); -// else if(RECwork)tmpProb=FitVertexWithPV( WrkVrtSet, iv, PrimVrt, RECwork->listJetTracks); -// if(m_fillHist){m_hb_trkPtMax->Fill( tmpProb*1.e5, m_w_1); } -// if(tmpProb>0.01)continue; // Vertex can be associated with PV -// } //--- curVrt.Good = true; /* Vertex is absolutely good */ nGoodVertices++; - if(nth>=2)n2trVrt++; } // //--Final cleaning of the 1-track vertices set. Must be behind all other cleanings. @@ -599,13 +585,9 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com //Checks std::vector<WrkVrt> GoodVertices(0); nGoodVertices=0; // Final number of good vertices - n2trVrt=0; // N vertices with 2 and more tracks - int nNtrVrt=0; // N vertices with 3 and more tracks + n2trVrt=nNtrVrt=0; // N of vertices with different amount of tracks for(auto & iv : (*WrkVrtSet) ) { nth=iv.SelTrk.size(); if(nth == 0) continue; /* Definitely bad vertices */ - Amg::Vector3D tmpVec=iv.vertex-PrimVrt.position(); - TLorentzVector Momentum(tmpVec.x(),tmpVec.y(),tmpVec.z(),m_massPi); - //if(Momentum.DeltaR(JetDir)>m_coneForTag) iv.Good=false; /* Vertex outside jet cone??? Very bad cut*/ if( iv.Good) { nGoodVertices++; GoodVertices.emplace_back(iv); /* add it */ @@ -657,8 +639,10 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com double Signif=0.; std::vector<double> Impact,ImpactError; for(int it=0; it<(int)nonusedTrk.size(); it++){ MatchedSV tmpV = {0, 1.e9}; - for(int iv=0; iv<(int)GoodVertices.size(); iv++){ - if(GoodVertices[iv].SelTrk.size()<2) continue; + for(int iv=0; iv<(int)GoodVertices.size(); iv++){ //--Find vertex closest to the given track + if(!GoodVertices[iv].Good) continue; + if(GoodVertices[iv].SelTrk.size()<2) continue; + if( VrtVrtDist(PrimVrt, GoodVertices[iv].vertex, GoodVertices[iv].vertexCov, JetDir) < 10.) continue; //--Too close to PV if (RECwork)Signif = m_fitSvc->VKalGetImpact(RECwork->listJetTracks[nonusedTrk[it]], GoodVertices[iv].vertex, 1, Impact, ImpactError); else if(xAODwrk)Signif = m_fitSvc->VKalGetImpact(xAODwrk->listJetTracks[nonusedTrk[it]], GoodVertices[iv].vertex, 1, Impact, ImpactError); if(Signif<tmpV.Signif3D){tmpV.Signif3D=Signif; tmpV.indVrt=iv;} @@ -674,7 +658,7 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com if(addTrk.size()>1){atrk++;if(atrk->first<4.){newV.SelTrk.push_back(nonusedTrk[atrk->second]);}} if(addedT){ if (xAODwrk)vProb = RefitVertex( newV, xAODwrk->listJetTracks); else if(RECwork)vProb = RefitVertex( newV, RECwork->listJetTracks); - if(vProb>0.01)GoodVertices[iv]=newV; + if(vProb>0.01)GoodVertices[iv]=newV; else{ std::vector<WrkVrt> TestVertices(1,newV); if (xAODwrk)vProb=improveVertexChi2( &TestVertices, 0, xAODwrk->listJetTracks); else if(RECwork)vProb=improveVertexChi2( &TestVertices, 0, RECwork->listJetTracks); @@ -682,44 +666,24 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com } } } -//------------------------------------------------------------- -// Check if very close vertices are present and merge them. Not big effect in ttbar -// - bool vrtMerged=false; //to check whether something is really merged - for(int iv=0; iv<(int)GoodVertices.size()-1; iv++ ){ if(!GoodVertices[iv].Good) continue; - for(int jv=iv+1; jv<(int)GoodVertices.size(); jv++){ if(!GoodVertices[jv].Good) continue; - if(GoodVertices[iv].SelTrk.size()>2 && GoodVertices[jv].SelTrk.size()>2)continue; - double probV=-1.; - if (xAODwrk)probV=mergeAndRefitVertices( &GoodVertices, iv, jv, newvrt, xAODwrk->listJetTracks); - else if(RECwork)probV=mergeAndRefitVertices( &GoodVertices, iv, jv, newvrt, RECwork->listJetTracks); - if(probV>0.1){ // Merged vertex is very good - std::swap(GoodVertices[iv],newvrt); - GoodVertices[iv].ProjectedVrt=JetProjDist(GoodVertices[iv].vertex, PrimVrt, JetDir); - GoodVertices[jv].Good=false; //Drop vertex - vrtMerged=true; - } } } - if(vrtMerged){ //-Remove all bad vertices from the good vertex set - int iV=0; while( iV<(int)GoodVertices.size() ) - { if( !GoodVertices[iV].Good ) { GoodVertices.erase(GoodVertices.begin()+iV);} else {iV++;} } - } -//-- -// printWrkSet(&GoodVertices,"FinalVrtSet"); +///// + //if(GoodVertices.size()>=4) + //printWrkSet(&GoodVertices,"FinalVrtSet"); //------------------------------------------- // Saving and final cleaning // nGoodVertices=0; // Final number of good vertices int n1trVrt=0; // Final number of good 1-track vertices TLorentzVector VertexMom; - double trackPt, trackPtMax=0.; for(int iv=0; iv<(int)GoodVertices.size(); iv++) { nth=GoodVertices[iv].SelTrk.size(); if(xAODwrk)xAODwrk->tmpListTracks.clear(); else if(RECwork)RECwork->tmpListTracks.clear(); + float vrtSumW=0.; for(i=0;i<nth;i++) { j=GoodVertices[iv].SelTrk[i]; /*Track number*/ if (xAODwrk)xAODwrk->tmpListTracks.push_back( xAODwrk->listJetTracks[j] ); else if(RECwork)RECwork->tmpListTracks.push_back( RECwork->listJetTracks[j] ); - trackPt=pTvsDir(Amg::Vector3D(JetDir.Vect().X(),JetDir.Vect().X(),JetDir.Vect().Z()), GoodVertices[iv].TrkAtVrt[i]); - if(trackPt>trackPtMax)trackPtMax=trackPt; + if(xAODwrk)vrtSumW+=trkScore[j][0]; } if( m_fillHist ){ if(nth==1)m_hb_r1dc->Fill( GoodVertices[iv].vertex.perp(), m_w_1); @@ -732,7 +696,8 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com else { m_hb_totmass2T2->Fill( GoodVertices[iv].vertexMom.M(), m_w_1);} m_hb_sig3D2tr->Fill( Signif3D , m_w_1); if(GoodVertices[iv].vertexCharge==0)m_hb_totmassEE->Fill(massV0(GoodVertices[iv].TrkAtVrt,m_massE,m_massE),m_w_1); - } else if( nth==1){ + //} else if( nth==1){ + } else if( GoodVertices[iv].vertexMom.M()>6000.){ m_hb_sig3D1tr->Fill( Signif3D, m_w_1); } else { m_hb_sig3DNtr->Fill( Signif3D, m_w_1); @@ -785,7 +750,9 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com //============================================== if(m_fillHist){m_hb_goodvrtN->Fill( nGoodVertices+0.1, m_w_1); - m_hb_goodvrtN->Fill( n1trVrt+15., m_w_1);} + if(n1trVrt)m_hb_goodvrtN->Fill( n1trVrt+15., m_w_1); + fillNVrtNTup( GoodVertices, trkScore, PrimVrt, JetDir); + } if(nGoodVertices == 0){ delete WrkVrtSet; delete TrkInVrt; @@ -854,12 +821,18 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com WrkVrt newvrt; newvrt.Good=true; std::vector<const Particle*> ListBaseTracks; int NTrk=(*WrkVrtSet)[iv].SelTrk.size(), SelT=-1; + if(NTrk<3)return; + StatusCode sc; sc.setChecked(); +//=== To get robust definition of most bad outlier + m_fitSvc->setRobustness(5); + sc = RefitVertex( WrkVrtSet, iv, AllTracks); + if(sc.isFailure()){ (*WrkVrtSet)[iv].Good=false; return; } + m_fitSvc->setRobustness(0); +//-------------------------------------------------- double Chi2Max=0.; for(int i=0; i<NTrk; i++){ if( (*WrkVrtSet)[iv].Chi2PerTrk[i]>Chi2Max) { Chi2Max=(*WrkVrtSet)[iv].Chi2PerTrk[i]; SelT=i;} } - if(SelT==-1)return; - StatusCode sc; int NVrtCur=WrkVrtSet->size(); for(int i=0; i<NTrk; i++){ if(i==SelT)continue; @@ -925,24 +898,19 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com for(int mtv=0; mtv<(int)WrkVrtSet->size(); mtv++) { if( (*WrkVrtSet)[mtv].SelTrk.size()<2 ) continue; if(!(*WrkVrtSet)[mtv].Good ) continue; - if( countVT[mtv] < 2 ) continue; - double distM=1000000.; + if( countVT[mtv] < 1 ) continue; + double distM=1.e9; int best1TVrt=-1; for(int i1tv=0; i1tv<(int)WrkVrtSet->size(); i1tv++) { if( (*WrkVrtSet)[i1tv].SelTrk.size()!=1 ) continue; if(!(*WrkVrtSet)[i1tv].Good ) continue; if( linkedVrt[i1tv] != mtv ) continue; - double dist=((*WrkVrtSet)[mtv].vertex - (*WrkVrtSet)[i1tv].vertex).mag(); + //double dist=((*WrkVrtSet)[mtv].vertex - (*WrkVrtSet)[i1tv].vertex).mag(); + double dist=((*WrkVrtSet)[mtv].vertexMom+(*WrkVrtSet)[i1tv].vertexMom).M(); //Use if( dist < distM ) {distM=dist; best1TVrt=i1tv;} (*WrkVrtSet)[i1tv].Good=false; } - if(best1TVrt>-1)(*WrkVrtSet)[best1TVrt].Good=true; - } -// -//--- Final Chi2 (last 2track vertex with the given track) - for(int i1tv=0; i1tv<(int)WrkVrtSet->size(); i1tv++) { - if( (*WrkVrtSet)[i1tv].SelTrk.size()!=1 || !(*WrkVrtSet)[i1tv].Good ) continue; - if( (*WrkVrtSet)[i1tv].Chi2>8.) (*WrkVrtSet)[i1tv].Good=false; + if(best1TVrt>-1 && distM<c_vrtBCMassLimit)(*WrkVrtSet)[best1TVrt].Good=true; } } @@ -951,12 +919,13 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com std::vector< std::deque<long int> > *TrkInVrt) const { - int NSet=WrkVrtSet->size(); int iv, jt, NTrkAtVrt, tracknum; - for( iv=0; iv<NSet; iv++) { - NTrkAtVrt=(*WrkVrtSet)[iv].SelTrk.size(); + int NSet=WrkVrtSet->size(); + for(int iv=0; iv<NSet; iv++) { + if(!(*WrkVrtSet)[iv].Good) continue; + int NTrkAtVrt=(*WrkVrtSet)[iv].SelTrk.size(); if(NTrkAtVrt<2) continue; - for( jt=0; jt<NTrkAtVrt; jt++){ - tracknum=(*WrkVrtSet)[iv].SelTrk[jt]; + for(int jt=0; jt<NTrkAtVrt; jt++){ + int tracknum=(*WrkVrtSet)[iv].SelTrk[jt]; (*TrkInVrt).at(tracknum).push_back(iv); } } @@ -969,29 +938,34 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com long int & SelectedVertex) const { - long int NTrack=TrkInVrt->size(); int it, jv, itmp, NVrt, VertexNumber; + long int NTrack=TrkInVrt->size(); + int it, jv, itmp, NVrt, VertexNumber; - double MaxOf=-999999999; double Chi2Red; double SelectedProb=-1.; + double MaxOf=-999999999, Chi2Red=0., SelectedProb=-1.; // - long int NShMax=0; + int NShareMax=0; for( it=0; it<NTrack; it++) { NVrt=(*TrkInVrt)[it].size(); /*Number of vertices for this track*/ - if( NVrt > NShMax ) NShMax=NVrt; + if( NVrt > NShareMax ) NShareMax=NVrt; } - if(NShMax<=1)return MaxOf; /* No shared tracks */ + if(NShareMax<=1)return MaxOf; /* No shared tracks */ // for( it=0; it<NTrack; it++) { NVrt=(*TrkInVrt)[it].size(); /*Number of vertices for this track*/ if( NVrt <= 1 ) continue; /*Should ALWAYS be checked for safety*/ - if( NVrt < NShMax ) continue; /*Not a shared track with maximal sharing*/ + if( NVrt < NShareMax ) continue; /*Not a shared track with maximal sharing*/ + int N2trVrt=0; + for(auto &vrtn :(*TrkInVrt)[it] ){ if((*WrkVrtSet).at(vrtn).SelTrk.size()==2)N2trVrt++; } //count number of 2-track vertices for( jv=0; jv<NVrt; jv++ ){ VertexNumber=(*TrkInVrt)[it][jv]; - int NTrkInVrt=(*WrkVrtSet).at(VertexNumber).SelTrk.size(); - if( NTrkInVrt <= 1) continue; // one track vertex - nothing to do + if(!(*WrkVrtSet).at(VertexNumber).Good)continue; + int NTrkInVrt=(*WrkVrtSet)[VertexNumber].SelTrk.size(); + if( NTrkInVrt <= 1) continue; // one track vertex - nothing to do + if( N2trVrt>0 && N2trVrt<NShareMax && NTrkInVrt>2) continue; // Mixture of multi-track and 2-track vrts. Skip multi-track then. for( itmp=0; itmp<NTrkInVrt; itmp++){ if( (*WrkVrtSet)[VertexNumber].SelTrk[itmp] == it ) { /* Track found*/ //Chi2Red=(*WrkVrtSet)[VertexNumber].Chi2PerTrk.at(itmp)/m_chiScale[(NTrkInVrt<10?NTrkInVrt:10)]; // Reduced Chi2 - //if(NTrkInVrt==2){ Chi2Red += 30./((*WrkVrtSet)[VertexNumber].vertex.perp()+5.);} //VK Reduce vrt multiplicity. May decrease fake rate + //if(NTrkInVrt==2){ Chi2Red += 30./((*WrkVrtSet)[VertexNumber].vertex.perp()+5.);} //VK Reduce vrt multiplicity. Chi2Red=(*WrkVrtSet)[VertexNumber].Chi2PerTrk.at(itmp); // Normal Chi2 seems the best if(NTrkInVrt==2){ Chi2Red=(*WrkVrtSet)[VertexNumber].Chi2/2.; //VK 2track vertices with Normal Chi2Red @@ -999,7 +973,7 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com } double prob_vrt = TMath::Prob( (*WrkVrtSet)[VertexNumber].Chi2, 2*(*WrkVrtSet)[VertexNumber].SelTrk.size()-3); if( MaxOf < Chi2Red ){ - if(MaxOf>0 && prob_vrt>0.01 && SelectedProb<0.01 ) continue; // Don't disassemble good vertices is a bad one is present + if(MaxOf>0 && prob_vrt>0.01 && SelectedProb<0.01 ) continue; // Don't disassemble good vertices if a bad one is present MaxOf = Chi2Red; SelectedTrack=it; SelectedVertex=VertexNumber; SelectedProb = prob_vrt; @@ -1064,6 +1038,7 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com (*TrkInVrt)[LeftTrack].erase(it); break; } } + if( TMath::Prob( (*WrkVrtSet)[SelectedVertex].Chi2, 1) < 0.05 ) (*WrkVrtSet)[SelectedVertex].Good=false; // Not really good Chi2 for one-track vertex if( (*WrkVrtSet)[SelectedVertex].vertexMom.M()>c_vrtBCMassLimit)(*WrkVrtSet)[SelectedVertex].Good=false; // Vertex is too heavy int ipos=0; if(posInVrtFit==0)ipos=1; // Position of remaining track in previous 2track vertex fit (*WrkVrtSet)[SelectedVertex].vertexMom=MomAtVrt((*WrkVrtSet)[SelectedVertex].TrkAtVrt[ipos]); //Redefine vertexMom using remaining track @@ -1188,6 +1163,95 @@ const double c_vrtBCMassLimit=5500.; // Mass limit to consider a vertex not com if( newvrt.Chi2PerTrk.size()==2) newvrt.Chi2PerTrk[0]=newvrt.Chi2PerTrk[1]=newvrt.Chi2/2.; return TMath::Prob( newvrt.Chi2, 2*newvrt.SelTrk.size()-3); } + //================== Intelligent merge of multitrack vertices with 2 and more common tracks + template <class Particle> + void InDetVKalVxInJetTool::mergeAndRefitOverlapVertices( std::vector<WrkVrt> *WrkVrtSet, int V1, int V2, + std::vector<const Particle*> & AllTrackList) + const + { + if(!(*WrkVrtSet).at(V1).Good)return; //bad vertex + if(!(*WrkVrtSet).at(V2).Good)return; //bad vertex + WrkVrt newvrt; + newvrt.Good=true; + if( nTrkCommon( WrkVrtSet, V1, V2)<2 )return; //No overlap + //- V1 should become ref. vertex. Another Vrt tracks will be added to it. + if( (*WrkVrtSet)[V1].SelTrk.size() < (*WrkVrtSet)[V2].SelTrk.size() ) + {int itmp=V2; V2=V1; V1=itmp;} //Vertex with NTrk=max is chosen + else if( (*WrkVrtSet)[V1].SelTrk.size() == (*WrkVrtSet)[V2].SelTrk.size() ) + { if( (*WrkVrtSet)[V1].Chi2 > (*WrkVrtSet)[V2].Chi2 ) {int itmp=V2; V2=V1; V1=itmp;} } // Vertex with minimal Chi2 is chosen + //- Fill base track list for new vertex + newvrt.SelTrk.resize( (*WrkVrtSet)[V1].SelTrk.size() ); + std::copy((*WrkVrtSet)[V1].SelTrk.begin(),(*WrkVrtSet)[V1].SelTrk.end(), newvrt.SelTrk.begin()); + //- Identify non-common tracks in second vertex + std::vector<int> noncommonTrk(0); + for(auto &it : (*WrkVrtSet)[V2].SelTrk){ + if( std::find((*WrkVrtSet)[V1].SelTrk.begin(), (*WrkVrtSet)[V1].SelTrk.end(), it) == (*WrkVrtSet)[V1].SelTrk.end() ) + noncommonTrk.push_back(it); + } + // + // Try to add non-common tracks one by one + std::vector<const Particle*> fitTrackList(0); + std::vector<int> detachedTrk(0); + StatusCode sc; sc.setChecked(); + WrkVrt bestVrt; + bool foundMerged=false; + for( auto nct : noncommonTrk){ + fitTrackList.clear(); + for(int it=0; it<(int)newvrt.SelTrk.size(); it++)fitTrackList.push_back( AllTrackList[newvrt.SelTrk[it]] ); + fitTrackList.push_back( AllTrackList.at(nct) ); + m_fitSvc->setApproximateVertex( (*WrkVrtSet)[V1].vertex[0],(*WrkVrtSet)[V1].vertex[1],(*WrkVrtSet)[V1].vertex[2]); + sc=VKalVrtFitBase(fitTrackList, newvrt.vertex, newvrt.vertexMom, newvrt.vertexCharge, newvrt.vertexCov, + newvrt.Chi2PerTrk, newvrt.TrkAtVrt, newvrt.Chi2); + if( sc.isFailure() || TMath::Prob( newvrt.Chi2, 2*newvrt.SelTrk.size()+2-3)<0.001 ) { + detachedTrk.push_back(nct); + continue; + } + newvrt.SelTrk.push_back(nct); // Compatible track. Add to common vertex. + bestVrt=newvrt; + foundMerged=true; + } + if(foundMerged)(*WrkVrtSet)[V1]=bestVrt; + (*WrkVrtSet)[V2].Good=false; + // + // Now detached tracks + if(detachedTrk.size()>1){ + WrkVrt nVrt; + fitTrackList.clear(); nVrt.SelTrk.clear(); + for(auto nct : detachedTrk){ fitTrackList.push_back( AllTrackList[nct] ); nVrt.SelTrk.push_back(nct); } + m_fitSvc->setApproximateVertex( (*WrkVrtSet)[V2].vertex[0],(*WrkVrtSet)[V2].vertex[1],(*WrkVrtSet)[V2].vertex[2]); + sc=VKalVrtFitBase(fitTrackList, nVrt.vertex, nVrt.vertexMom, nVrt.vertexCharge, nVrt.vertexCov, + nVrt.Chi2PerTrk, nVrt.TrkAtVrt, nVrt.Chi2); + if(sc.isSuccess()) (*WrkVrtSet).push_back(nVrt); + } else if( detachedTrk.size()==1 ){ + bool tFound=false; + for( auto &vrt : (*WrkVrtSet) ){ + if( !vrt.Good || vrt.SelTrk.size()<2 )continue; + if( std::find(vrt.SelTrk.begin(), vrt.SelTrk.end(), detachedTrk[0]) != vrt.SelTrk.end() ) { tFound=true; break; } + } + if( !tFound ) { //Track is not present in other vertices. + double Chi2min=1.e9; int selectedTrk=-1; + WrkVrt saveVrt; + fitTrackList.resize(2); + fitTrackList[0]= AllTrackList[detachedTrk[0]]; + for(auto trk : (*WrkVrtSet)[V2].SelTrk){ + if(trk==detachedTrk[0])continue; + WrkVrt nVrt; nVrt.Good=true; + fitTrackList[1]=AllTrackList[trk]; + m_fitSvc->setApproximateVertex( (*WrkVrtSet)[V2].vertex[0],(*WrkVrtSet)[V2].vertex[1],(*WrkVrtSet)[V2].vertex[2]); + sc=VKalVrtFitBase(fitTrackList, nVrt.vertex, nVrt.vertexMom, nVrt.vertexCharge, nVrt.vertexCov, + nVrt.Chi2PerTrk, nVrt.TrkAtVrt, nVrt.Chi2); + if(sc.isSuccess() && nVrt.Chi2<Chi2min) {Chi2min=nVrt.Chi2; saveVrt=nVrt; selectedTrk=trk; } + } + if(Chi2min<1.e9){ + saveVrt.SelTrk.resize(1); saveVrt.SelTrk[0]=detachedTrk[0]; + saveVrt.detachedTrack=selectedTrk; + saveVrt.vertexMom=MomAtVrt(saveVrt.TrkAtVrt[0]); //redefine vertex momentum + (*WrkVrtSet).push_back(saveVrt); + } + } + } + return ; + } // // Iterate track removal until vertex get good Chi2 diff --git a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/CutTrk.cxx b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/CutTrk.cxx index f813ae45f756a2fc42c43b5efde7ea39e64e7b25..935a4abc3710720144ff3abd6252f09ab771d79c 100755 --- a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/CutTrk.cxx +++ b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/CutTrk.cxx @@ -127,7 +127,7 @@ namespace InDet{ std::vector<const xAOD::TrackParticle*>::const_iterator i_ntrk; std::vector<double> Impact,ImpactError; - std::map<double,const xAOD::TrackParticle*> orderedTrk; + std::multimap<double,const xAOD::TrackParticle*> orderedTrk; int NPrimTrk=0; for (i_ntrk = InpTrk.begin(); i_ntrk < InpTrk.end(); ++i_ntrk) { // @@ -215,7 +215,7 @@ namespace InDet{ if( sc.isFailure() ) continue; //double rankBTrk=RankBTrk((*i_ntrk)->pt(),JetDir.Perp(),ImpactSignif); if(trkRank[1]>0.5)NPrimTrk += 1; - orderedTrk[trkRank[0]]= *i_ntrk; + orderedTrk.emplace(trkRank[0],*i_ntrk); } //---- Order tracks according to ranks std::map<double,const xAOD::TrackParticle*>::reverse_iterator rt=orderedTrk.rbegin(); diff --git a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/InDetTrkInJetType.cxx b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/InDetTrkInJetType.cxx index c7b07e5d15b497b2c384617740ec6c7199e15ada..3da8d5e80ab0c21570b7ea84ed1c6b15c0aa0c29 100644 --- a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/InDetTrkInJetType.cxx +++ b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/InDetTrkInJetType.cxx @@ -20,6 +20,9 @@ InDetTrkInJetType::InDetTrkInJetType(const std::string& type, const IInterface* parent): AthAlgTool(type,name,parent), m_tmvaReader(0), + m_trkSctHitsCut(4), + m_trkPixelHitsCut(1), + m_trkChi2Cut(5.), m_trkMinPtCut(700.), m_d0_limLow(-3.), m_d0_limUpp( 5.), @@ -29,6 +32,9 @@ InDetTrkInJetType::InDetTrkInJetType(const std::string& type, m_fitterSvc("Trk::TrkVKalVrtFitter/VertexFitterTool",this) { declareInterface<IInDetTrkInJetType>(this); + declareProperty("trkSctHits", m_trkSctHitsCut , "Cut on track SCT hits number" ); + declareProperty("trkPixelHits", m_trkPixelHitsCut , "Cut on track Pixel hits number" ); + declareProperty("trkChi2", m_trkChi2Cut , "Cut on track Chi2/Ndf" ); declareProperty("trkMinPt", m_trkMinPtCut , "Minimal track Pt cut" ); declareProperty("d0_limLow", m_d0_limLow , "Low d0 impact cut" ); declareProperty("d0_limUpp", m_d0_limUpp , "Upper d0 impact cut" ); @@ -97,9 +103,21 @@ InDetTrkInJetType::InDetTrkInJetType(const std::string& type, std::vector<float> InDetTrkInJetType::trkTypeWgts(const xAOD::TrackParticle * Trk, const xAOD::Vertex & PV, const TLorentzVector & Jet) { +//-- Track quality checks std::vector<float> safeReturn(3,0.); - if( !m_initialised ) return safeReturn; - if(Jet.Perp()>2500000.)return safeReturn; + if( !m_initialised ) return safeReturn; + if(Jet.Perp() > 2500000.) return safeReturn; + if(Trk->pt() < m_trkMinPtCut) return safeReturn; + if(Trk->pt() > Jet.Pt()) return safeReturn; + if(Trk->numberDoF() == 0) return safeReturn; //Safety + if(Trk->chiSquared()/Trk->numberDoF() > m_trkChi2Cut) return safeReturn; + uint8_t PixelHits,SctHits; + if( !(Trk->summaryValue(PixelHits,xAOD::numberOfPixelHits)) ) return safeReturn; // No Pixel hits. Bad. + if( !(Trk->summaryValue( SctHits,xAOD::numberOfSCTHits)) ) return safeReturn; // No SCT hits. Bad. + if( PixelHits < m_trkPixelHitsCut ) return safeReturn; + if( SctHits < m_trkSctHitsCut ) return safeReturn; + + std::vector<double> Impact,ImpactError; m_Sig3D=m_fitSvc->VKalGetImpact(Trk, PV.position(), 1, Impact, ImpactError); AmgVector(5) tmpPerigee = Trk->perigeeParameters().parameters(); @@ -110,7 +128,7 @@ InDetTrkInJetType::InDetTrkInJetType(const std::string& type, double SignifR = Impact[0]/ sqrt(ImpactError[0]); double SignifZ = Impact[1]/ sqrt(ImpactError[2]); double trkSignif = sqrt( (SignifR+0.6)*(SignifR+0.6) + (SignifZ+0.0)*(SignifZ+0.0) ); -//--- +//---Calibrated range selection if(Impact[0]<m_d0_limLow || Impact[0]>m_d0_limUpp) return safeReturn; if(Impact[0]<m_Z0_limLow || Impact[0]>m_Z0_limUpp) return safeReturn; if( sqrt(SignifR*SignifR +SignifZ*SignifZ) < 1.) return safeReturn; diff --git a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/InDetVKalVxInJetTool.cxx b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/InDetVKalVxInJetTool.cxx index b947561ad208c494f40304a845dba9f2b627ec26..4fd96f2179c2338dc6b008409aed5fc4ff822431 100755 --- a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/InDetVKalVxInJetTool.cxx +++ b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/InDetVKalVxInJetTool.cxx @@ -51,7 +51,9 @@ InDetVKalVxInJetTool::InDetVKalVxInJetTool(const std::string& type, m_a0TrkErrorCut(1.0), m_zTrkErrorCut(5.0), m_cutHFClass(0.1), - m_antiGarbageCut(0.85), + m_antiGarbageCut(0.80), + m_antiFragmentCut(0.80), + m_Vrt2TrMassLimit(4000.), m_fillHist(false), m_existIBL(true), m_RobustFit(1), @@ -105,7 +107,9 @@ InDetVKalVxInJetTool::InDetVKalVxInJetTool(const std::string& type, declareProperty("A0TrkErrorCut", m_a0TrkErrorCut, "Track A0 error cut" ); declareProperty("ZTrkErrorCut", m_zTrkErrorCut, "Track Z impact error cut" ); declareProperty("CutHFClass", m_cutHFClass, "Cut on HF classification weight" ); - declareProperty("AntiGarbageCut", m_antiGarbageCut, "Cut on Garbage classification weight for removal" ); + declareProperty("AntiGarbageCut", m_antiGarbageCut, "Cut on Garbage classification weight for track removal" ); + declareProperty("AntiFragmentCut",m_antiFragmentCut, "Cut on Fragmentation classification weight for track removal" ); + declareProperty("Vrt2TrMassLimit",m_Vrt2TrMassLimit, "Maximal allowed mass for 2-track vertices" ); declareProperty("Sel2VrtChi2Cut", m_sel2VrtChi2Cut, "Cut on Chi2 of 2-track vertex for initial selection" ); declareProperty("Sel2VrtSigCut", m_sel2VrtSigCut, "Cut on significance of 3D distance between initial 2-track vertex and PV" ); @@ -339,7 +343,9 @@ InDetVKalVxInJetTool::InDetVKalVxInJetTool(const std::string& type, //------------------------------------------------------- m_curTup=new DevTuple(); m_tuple = new TTree("Tracks","Tracks"); - std::string TreeDir("/file1/stat/SVrtInJet"+m_instanceName+"/"); + std::string TreeDir; + if(m_multiVertex) TreeDir="/file1/stat/MSVrtInJet"+m_instanceName+"/"; + else TreeDir="/file1/stat/SVrtInJet"+m_instanceName+"/"; sc = hist_root->regTree(TreeDir,m_tuple); if (sc.isSuccess()) { m_tuple->Branch("ptjet", &m_curTup->ptjet, "ptjet/F"); @@ -363,17 +369,32 @@ InDetVKalVxInJetTool::InDetVKalVxInJetTool(const std::string& type, m_tuple->Branch("prodTJ", &m_curTup->prodTJ, "prodTJ[ntrk]/F"); m_tuple->Branch("nVrtT", &m_curTup->nVrtT, "nVrtT[ntrk]/I"); m_tuple->Branch("chg", &m_curTup->chg, "chg[ntrk]/I"); + //----- + m_tuple->Branch("TotM", &m_curTup->TotM, "TotM/F"); + //----- m_tuple->Branch("nvrt", &m_curTup->nVrt, "nvrt/I"); m_tuple->Branch("VrtDist2D", &m_curTup->VrtDist2D, "VrtDist2D[nvrt]/F"); m_tuple->Branch("VrtSig3D", &m_curTup->VrtSig3D, "VrtSig3D[nvrt]/F"); m_tuple->Branch("VrtSig2D", &m_curTup->VrtSig2D, "VrtSig2D[nvrt]/F"); + m_tuple->Branch("VrtDR", &m_curTup->VrtDR, "VrtDR[nvrt]/F"); m_tuple->Branch("itrk", &m_curTup->itrk, "itrk[nvrt]/I"); m_tuple->Branch("jtrk", &m_curTup->jtrk, "jtrk[nvrt]/I"); m_tuple->Branch("badV", &m_curTup->badVrt, "badV[nvrt]/I"); m_tuple->Branch("mass", &m_curTup->mass, "mass[nvrt]/F"); m_tuple->Branch("Chi2", &m_curTup->Chi2, "Chi2[nvrt]/F"); + //----- m_tuple->Branch("ntHF", &m_curTup->NTHF, "ntHF/I"); m_tuple->Branch("itHF", &m_curTup->itHF, "itHF[ntHF]/I"); + //----- + m_tuple->Branch("nNVrt", &m_curTup->nNVrt, "nNVrt/I"); + m_tuple->Branch("NVrtDist2D", &m_curTup->NVrtDist2D, "NVrtDist2D[nNVrt]/F"); + m_tuple->Branch("NVrtNT", &m_curTup->NVrtNT, "NVrtNT[nNVrt]/I"); + m_tuple->Branch("NVrtTrkI", &m_curTup->NVrtTrkI, "NVrttrkI[nNVrt]/I"); + m_tuple->Branch("NVrtM", &m_curTup->NVrtM, "NVrtM[nNVrt]/F"); + m_tuple->Branch("NVrtChi2", &m_curTup->NVrtChi2, "NVrtChi2[nNVrt]/F"); + m_tuple->Branch("NVrtMaxW", &m_curTup->NVrtMaxW, "NVrtMaxW[nNVrt]/F"); + m_tuple->Branch("NVrtAveW", &m_curTup->NVrtAveW, "NVrtAveW[nNVrt]/F"); + m_tuple->Branch("NVrtDR", &m_curTup->NVrtDR, "NVrtDR[nNVrt]/F"); } } @@ -425,7 +446,7 @@ InDetVKalVxInJetTool::InDetVKalVxInJetTool(const std::string& type, double EnergyJet = 0.; int N2trVertices = 0 ; int NBigImpTrk = 0 ; - if(m_curTup){ m_curTup->nVrt=0; m_curTup->nTrkInJet=0; m_curTup->NTHF=0; } + if(m_curTup){ m_curTup->nVrt=0; m_curTup->nTrkInJet=0; m_curTup->NTHF=0; m_curTup->nNVrt=0;} int pseudoVrt = 0; @@ -498,7 +519,7 @@ InDetVKalVxInJetTool::InDetVKalVxInJetTool(const std::string& type, double RatioE = 0.; double EnergyJet = 0.; int N2trVertices = 0 ; - if(m_curTup){ m_curTup->nVrt=0; m_curTup->nTrkInJet=0; } + if(m_curTup){ m_curTup->nVrt=0; m_curTup->nTrkInJet=0; m_curTup->nNVrt=0; m_curTup->NTHF=0; } xAOD::Vertex xaodPrimVrt; xaodPrimVrt.setPosition(PrimVrt.position()); diff --git a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/Utilities.cxx b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/Utilities.cxx index 5c322d61c54f76eaeb1226dc026a40559d98e2aa..bd65a75f02d475ccfa2d3274e9d30846848c2fe0 100755 --- a/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/Utilities.cxx +++ b/InnerDetector/InDetRecTools/InDetVKalVxInJetTool/src/Utilities.cxx @@ -7,7 +7,6 @@ #include "TrkNeutralParameters/NeutralParameters.h" #include "TrkTrackSummary/TrackSummary.h" #include "TrkVKalVrtFitter/TrkVKalVrtFitter.h" -#include "xAODTruth/TruthParticleContainer.h" //------------------------------------------------- // Other stuff #include <cmath> @@ -742,8 +741,8 @@ namespace InDet{ const { if(!m_curTup)return; int ipnt=0; - for(auto vrt : all2TrVrt) { - if(ipnt==100)break; + for(auto & vrt : all2TrVrt) { + if(ipnt==DevTuple::maxNTrk)break; m_curTup->VrtDist2D[ipnt]=vrt.FitVertex.perp(); m_curTup->VrtSig3D[ipnt]=vrt.Signif3D; m_curTup->VrtSig2D[ipnt]=vrt.Signif2D; @@ -752,10 +751,83 @@ namespace InDet{ m_curTup->mass[ipnt]=vrt.Momentum.M(); m_curTup->Chi2[ipnt]=vrt.Chi2; m_curTup->badVrt[ipnt]=vrt.badVrt; + m_curTup->VrtDR[ipnt]=vrt.dRSVPV; ipnt++; m_curTup->nVrt=ipnt; } } + void InDetVKalVxInJetTool::fillNVrtNTup(std::vector<WrkVrt> & VrtSet, std::vector< std::vector<float> > & trkScore, + const xAOD::Vertex & PV, const TLorentzVector & JetDir) + const + { if(!m_curTup)return; + int ipnt=0; + TLorentzVector VertexMom; + for(auto & vrt : VrtSet) { + if(ipnt==DevTuple::maxNVrt)break; + m_curTup->NVrtDist2D[ipnt]=vrt.vertex.perp(); + m_curTup->NVrtNT[ipnt]=vrt.SelTrk.size(); + m_curTup->NVrtTrkI[ipnt]=vrt.SelTrk[0]; + m_curTup->NVrtM[ipnt]=vrt.vertexMom.M(); + m_curTup->NVrtChi2[ipnt]=vrt.Chi2; + float maxW=0., sumW=0.; + for(auto trk : vrt.SelTrk){ sumW+=trkScore[trk][0]; maxW=std::max(trkScore[trk][0], maxW);} + m_curTup->NVrtMaxW[ipnt]=maxW; + m_curTup->NVrtAveW[ipnt]=sumW/vrt.SelTrk.size(); + TLorentzVector SVPV(vrt.vertex.x()-PV.x(),vrt.vertex.y()-PV.y(),vrt.vertex.z()-PV.z(),1.); + m_curTup->NVrtDR[ipnt]=JetDir.DeltaR(SVPV); + VertexMom += vrt.vertexMom; + ipnt++; m_curTup->nNVrt=ipnt; + } + m_curTup->TotM=VertexMom.M(); + } + + + int InDetVKalVxInJetTool::getIdHF(const xAOD::TrackParticle* TP ) const { + if( TP->isAvailable< ElementLink< xAOD::TruthParticleContainer> >( "truthParticleLink") ) { + const ElementLink<xAOD::TruthParticleContainer>& tplink = + TP->auxdata< ElementLink< xAOD::TruthParticleContainer > >("truthParticleLink"); + if( !tplink.isValid() ) return 0; + if( TP->auxdata< float >( "truthMatchProbability" ) < 0.75 ) return 0; + if( (*tplink)->barcode() > 200000) return 0; + if( (*tplink)->hasProdVtx()){ + if( (*tplink)->prodVtx()->nIncomingParticles()==1){ + int PDGID1=0, PDGID2=0, PDGID3=0; + const xAOD::TruthParticle * parTP1=getPreviousParent(*tplink, PDGID1); + const xAOD::TruthParticle * parTP2=0; + int noBC1=notFromBC(PDGID1); + if(noBC1) parTP2 = getPreviousParent(parTP1, PDGID2); + int noBC2=notFromBC(PDGID2); + if(noBC2 && parTP2) getPreviousParent(parTP2, PDGID3); + int noBC3=notFromBC(PDGID3); + if(noBC1 && noBC2 && noBC3)return 0; + return 1; //This is a reconstructed track from B/C decays + } } } + return 0; + } + + int InDetVKalVxInJetTool::notFromBC(int PDGID) const { + int noBC=0; + if(PDGID<=0)return 1; + if(PDGID>600 && PDGID<4000)noBC=1; + if(PDGID<400 || PDGID>5600)noBC=1; + if(PDGID==513 || PDGID==523 || PDGID==533 || PDGID==543)noBC=1; //Remove tracks from B* (they are in PV) + if(PDGID==5114 || PDGID==5214 || PDGID==5224 || PDGID==5314 || PDGID==5324)noBC=1; //Remove tracks from B_Barions* (they are in PV) + //if(PDGID==413 || PDGID==423 || PDGID==433 )continue; //Keep tracks from D* (they are from B vertex) + //if(PDGID==4114 || PDGID==4214 || PDGID==4224 || PDGID==4314 || PDGID==4324)continue; + return noBC; + } + const xAOD::TruthParticle * InDetVKalVxInJetTool::getPreviousParent(const xAOD::TruthParticle * child, int & ParentPDG) const { + ParentPDG=0; + if( child->hasProdVtx() ){ + if( child->prodVtx()->nIncomingParticles()==1 ){ + ParentPDG = abs((*(child->prodVtx()->incomingParticleLinks())[0])->pdgId()); + return *(child->prodVtx()->incomingParticleLinks())[0]; + } + } + return 0; + } + + int InDetVKalVxInJetTool::getG4Inter(const xAOD::TrackParticle* TP ) const { if( TP->isAvailable< ElementLink< xAOD::TruthParticleContainer> >( "truthParticleLink") ) { const ElementLink<xAOD::TruthParticleContainer>& tplink = @@ -772,6 +844,7 @@ namespace InDet{ } else { return 1; } return 0; } + int InDetVKalVxInJetTool::getIdHF(const Rec::TrackParticle*) const { return 0; } int InDetVKalVxInJetTool::getG4Inter(const Rec::TrackParticle* ) const { return 0; } int InDetVKalVxInJetTool::getMCPileup(const Rec::TrackParticle* ) const { return 0; }