Go to the documentation of this file.00001 #include "RecoParticleFlow/PFTracking/interface/PFDisplacedVertexHelper.h"
00002
00003 #include "TVector3.h"
00004 #include "DataFormats/VertexReco/interface/Vertex.h"
00005
00006 #include "TMath.h"
00007
00008 using namespace std;
00009 using namespace reco;
00010
00011
00012 const double PFDisplacedVertexHelper::pion_mass2 = 0.0194;
00013 const double PFDisplacedVertexHelper::muon_mass2 = 0.106*0.106;
00014 const double PFDisplacedVertexHelper::proton_mass2 = 0.938*0.938;
00015
00016
00017
00018
00019 PFDisplacedVertexHelper::PFDisplacedVertexHelper() :
00020 tracksSelector_(),
00021 vertexIdentifier_(),
00022 pvtx_(math::XYZPoint(0,0,0)) {}
00023
00024 PFDisplacedVertexHelper::~PFDisplacedVertexHelper() {}
00025
00026 void PFDisplacedVertexHelper::setPrimaryVertex(
00027 edm::Handle< reco::VertexCollection > mainVertexHandle,
00028 edm::Handle< reco::BeamSpot > beamSpotHandle){
00029
00030 const math::XYZPoint beamSpot = beamSpotHandle.isValid() ?
00031 math::XYZPoint(beamSpotHandle->x0(), beamSpotHandle->y0(), beamSpotHandle->z0()) :
00032 math::XYZPoint(0, 0, 0);
00033
00034
00035
00036
00037 pvtx_ = mainVertexHandle.isValid() ?
00038 math::XYZPoint(mainVertexHandle->begin()->x(),
00039 mainVertexHandle->begin()->y(),
00040 mainVertexHandle->begin()->z()) :
00041 beamSpot;
00042 }
00043
00044 bool
00045 PFDisplacedVertexHelper::isTrackSelected(const reco::Track& trk,
00046 const reco::PFDisplacedVertex::VertexTrackType vertexTrackType) const {
00047
00048
00049 if (!tracksSelector_.selectTracks()) return true;
00050
00051 bool isGoodTrack = false;
00052
00053 bool isHighPurity = trk.quality( trk.qualityByName(tracksSelector_.quality().data()) );
00054
00055 double nChi2 = trk.normalizedChi2();
00056 double pt = trk.pt();
00057 int nHits = trk.numberOfValidHits();
00058
00059 bool bIsPrimary =
00060 (
00061 (vertexTrackType == reco::PFDisplacedVertex::T_TO_VERTEX)
00062 ||
00063 (vertexTrackType == reco::PFDisplacedVertex::T_MERGED)
00064 );
00065
00066
00067 if (bIsPrimary) {
00068
00069 isGoodTrack =
00070 ( ( nChi2 > tracksSelector_.nChi2_min()
00071 && nChi2 < tracksSelector_.nChi2_max())
00072 || isHighPurity )
00073 && pt > tracksSelector_.pt_min();
00074 } else {
00075
00076 int nOuterHits = trk.trackerExpectedHitsOuter().numberOfHits();
00077
00078 double dxy = trk.dxy(pvtx_);
00079
00080 isGoodTrack =
00081 nChi2 < tracksSelector_.nChi2_max()
00082 && pt > tracksSelector_.pt_min()
00083 && fabs(dxy) > tracksSelector_.dxy_min()
00084 && nHits >= tracksSelector_.nHits_min()
00085 && nOuterHits <= tracksSelector_.nOuterHits_max();
00086
00087 }
00088
00089 return isGoodTrack;
00090
00091 }
00092
00093 reco::PFDisplacedVertex::VertexType
00094 PFDisplacedVertexHelper::identifyVertex(const reco::PFDisplacedVertex& v) const{
00095
00096 if (!vertexIdentifier_.identifyVertices()) return PFDisplacedVertex::ANY;
00097
00098 PFDisplacedVertex::M_Hypo massElec = PFDisplacedVertex::M_MASSLESS;
00099 PFDisplacedVertex::M_Hypo massPion = PFDisplacedVertex::M_PION;
00100
00101 math::XYZTLorentzVector mom_ee = v.secondaryMomentum(massElec, true);
00102 math::XYZTLorentzVector mom_pipi = v.secondaryMomentum(massPion, true);
00103
00104
00105
00106 double ang = v.angle_io();
00107 double pt_ee = mom_ee.Pt();
00108 double eta_vtx = v.position().eta();
00109
00110
00111
00112 bool bDirectionFake = ang > vertexIdentifier_.angle_max();
00113 bool bLowPt = pt_ee < vertexIdentifier_.pt_min();
00114 bool bLooperEta = fabs(eta_vtx) < vertexIdentifier_.looper_eta_max();
00115
00116 bool isFake = bDirectionFake ||(bLowPt && !bLooperEta);
00117 bool isLooper = !bDirectionFake && bLowPt && bLooperEta;
00118
00119 if (isFake) return PFDisplacedVertex::FAKE;
00120 if (isLooper) return PFDisplacedVertex::LOOPER;
00121
00122
00123
00124 int c1 = v.originalTrack(v.refittedTracks()[0])->charge();
00125 int c2 = v.originalTrack(v.refittedTracks()[1])->charge();
00126 double mass_ee = mom_ee.M();
00127
00128 int nTracks = v.nTracks();
00129 int nSecondaryTracks = v.nSecondaryTracks();
00130 bool bPrimaryTracks = v.isTherePrimaryTracks();
00131 bool bMergedTracks = v.isThereMergedTracks();
00132
00133 bool bPair = (nTracks == nSecondaryTracks) && (nTracks == 2);
00134 bool bOpposite = (c1*c2 < -0.1);
00135 bool bDirection = ang < vertexIdentifier_.angle_V0Conv_max();
00136 bool bConvMass = mass_ee < vertexIdentifier_.mConv_max();
00137
00138 bool bV0Conv = bPair && bOpposite && bDirection;
00139
00140
00141
00142
00143 if (bV0Conv){
00144
00145
00146
00147 bool isConv = bConvMass;
00148
00149 if (isConv) return PFDisplacedVertex::CONVERSION_LOOSE;
00150
00151
00152
00153 double mass_pipi = mom_pipi.M();
00154
00155 bool bK0Mass =
00156 mass_pipi < vertexIdentifier_.mK0_max()
00157 && mass_pipi > vertexIdentifier_.mK0_min();
00158
00159 bool isK0 = bK0Mass;
00160
00161 if (isK0) return PFDisplacedVertex::K0_DECAY;
00162
00163
00164
00165 int lambdaKind = lambdaCP(v);
00166
00167
00168 bool isLambda = (lambdaKind == 1);
00169 bool isLambdaBar = (lambdaKind == -1);
00170
00171 if (isLambda) return PFDisplacedVertex::LAMBDA_DECAY;
00172 if (isLambdaBar) return PFDisplacedVertex::LAMBDABAR_DECAY;
00173
00174 }
00175
00176
00177 bool bK =
00178 (nSecondaryTracks == 1) && bPrimaryTracks && !bMergedTracks
00179 && !bOpposite;
00180
00181 if(bK){
00182
00183 bool bKMass = isKaonMass(v);
00184
00185 bool isKPlus = bKMass && c1 > 0;
00186 bool isKMinus = bKMass && c1 < 0;
00187
00188 if(isKMinus) return PFDisplacedVertex::KMINUS_DECAY_LOOSE;
00189 if(isKPlus) return PFDisplacedVertex::KPLUS_DECAY_LOOSE;
00190
00191 }
00192
00193
00194
00195 math::XYZTLorentzVector mom_prim = v.primaryMomentum(massPion, true);
00196
00197 double p_prim = mom_prim.P();
00198 double p_sec = mom_pipi.P();
00199 double pt_prim = mom_prim.Pt();
00200
00201 bool bLog = log10(p_prim/p_sec) > vertexIdentifier_.logPrimSec_min();
00202 bool bPtMin = pt_prim > vertexIdentifier_.pt_kink_min();
00203
00204
00205
00206 bool isNuclearHighPurity = nTracks > 2 && mass_ee > vertexIdentifier_.mNucl_min();
00207 bool isFakeHighPurity = nTracks > 2 && mass_ee < vertexIdentifier_.mNucl_min();
00208
00209
00210 bool isNuclearLowPurity =
00211 (nTracks == nSecondaryTracks)
00212 && (nTracks == 2)
00213 && mass_ee > vertexIdentifier_.mNucl_min();
00214
00215 bool isFakeNucl =
00216 (nTracks == nSecondaryTracks)
00217 && (nTracks == 2)
00218 && mass_ee < vertexIdentifier_.mNucl_min();
00219
00220
00221
00222
00223 bool isNuclearKink =
00224 (nSecondaryTracks == 1) && bPrimaryTracks && !bMergedTracks
00225 && bLog && bPtMin;
00226
00227
00228 bool isFakeKink =
00229 ( (nSecondaryTracks == 1) && bMergedTracks && !bPrimaryTracks )
00230 ||
00231 ( (nSecondaryTracks == 1) && bPrimaryTracks && !bMergedTracks
00232 && (!bLog || !bPtMin) );
00233
00234 if (isNuclearHighPurity) return PFDisplacedVertex::NUCL;
00235 if (isNuclearLowPurity) return PFDisplacedVertex::NUCL_LOOSE;
00236 if (isFakeKink || isFakeNucl || isFakeHighPurity) return PFDisplacedVertex::FAKE;
00237 if (isNuclearKink) return PFDisplacedVertex::NUCL_KINK;
00238
00239
00240 return PFDisplacedVertex::ANY;
00241
00242 }
00243
00244
00245 int PFDisplacedVertexHelper::lambdaCP(const PFDisplacedVertex& v) const {
00246
00247 int lambdaCP = 0;
00248
00249 vector <Track> refittedTracks = v.refittedTracks();
00250
00251 math::XYZTLorentzVector totalMomentumDcaRefit_lambda;
00252 math::XYZTLorentzVector totalMomentumDcaRefit_lambdabar;
00253
00254
00255 reco::Track tMomentumDcaRefit_0 = refittedTracks[0];
00256 reco::Track tMomentumDcaRefit_1 = refittedTracks[1];
00257
00258 double mass2_0 = 0, mass2_1 = 0;
00259
00260 int c1 = v.originalTrack(v.refittedTracks()[1])->charge();
00261
00262
00263
00264
00265 if (c1 > 0.1) mass2_0 = pion_mass2, mass2_1 = proton_mass2;
00266 else mass2_0 = proton_mass2, mass2_1 = pion_mass2;
00267
00268 double E = sqrt(tMomentumDcaRefit_0.p()*tMomentumDcaRefit_0.p() + mass2_0);
00269
00270 math::XYZTLorentzVector momentumDcaRefit_0(tMomentumDcaRefit_0.px(), tMomentumDcaRefit_0.py(),
00271 tMomentumDcaRefit_0.pz(), E);
00272
00273
00274
00275 E = sqrt(tMomentumDcaRefit_1.p()*tMomentumDcaRefit_1.p() + mass2_1);
00276
00277 math::XYZTLorentzVector momentumDcaRefit_1(tMomentumDcaRefit_1.px(), tMomentumDcaRefit_1.py(),
00278 tMomentumDcaRefit_1.pz(), E);
00279
00280
00281 totalMomentumDcaRefit_lambda = momentumDcaRefit_0 + momentumDcaRefit_1;
00282
00283
00284
00285
00286
00287 if (c1 > 0.1) mass2_1 = pion_mass2, mass2_0 = proton_mass2;
00288 else mass2_1 = proton_mass2, mass2_0 = pion_mass2;
00289
00290
00291 E = sqrt(tMomentumDcaRefit_0.p()*tMomentumDcaRefit_0.p() + mass2_0);
00292
00293 math::XYZTLorentzVector momentumDcaRefit_01(tMomentumDcaRefit_0.px(), tMomentumDcaRefit_0.py(),
00294 tMomentumDcaRefit_0.pz(), E);
00295
00296
00297
00298 E = sqrt(tMomentumDcaRefit_1.p()*tMomentumDcaRefit_1.p() + mass2_1);
00299
00300 math::XYZTLorentzVector momentumDcaRefit_11(tMomentumDcaRefit_1.px(), tMomentumDcaRefit_1.py(),
00301 tMomentumDcaRefit_1.pz(), E);
00302
00303
00304 totalMomentumDcaRefit_lambdabar = momentumDcaRefit_01 + momentumDcaRefit_11;
00305
00306 double mass_l = totalMomentumDcaRefit_lambda.M();
00307 double mass_lbar = totalMomentumDcaRefit_lambdabar.M();
00308
00309
00310
00311
00312 if (
00313 mass_l < mass_lbar
00314 && mass_l > vertexIdentifier_.mLambda_min()
00315 && mass_l < vertexIdentifier_.mLambda_max())
00316 lambdaCP = 1;
00317 else if (mass_lbar < mass_l
00318 && mass_lbar > vertexIdentifier_.mLambda_min()
00319 && mass_lbar < vertexIdentifier_.mLambda_max())
00320 lambdaCP = -1;
00321 else
00322 lambdaCP = 0;
00323
00324
00325
00326 return lambdaCP;
00327
00328 }
00329
00330
00331
00332 bool PFDisplacedVertexHelper::isKaonMass(const PFDisplacedVertex& v) const {
00333
00334 math::XYZVector trkInit = v.refittedTracks()[1].momentum(),
00335 trkFinal = v.refittedTracks()[0].momentum();
00336
00337 if (v.trackTypes()[0] == PFDisplacedVertex::T_TO_VERTEX)
00338 trkInit = v.refittedTracks()[0].momentum(),
00339 trkFinal = v.refittedTracks()[1].momentum();
00340
00341
00342 math::XYZVector trkNeutre(trkInit.x()-trkFinal.x(), trkInit.y()-trkFinal.y(),
00343 trkInit.z()-trkFinal.z());
00344
00345 double Ec = sqrt(muon_mass2 + trkFinal.Mag2());
00346 double En = sqrt(0*0 + trkNeutre.Mag2());
00347
00348
00349
00350 math::XYZTLorentzVectorD trkMuNu(trkInit.x(), trkInit.y(), trkInit.z(), Ec+En);
00351 double massMuNu = trkMuNu.M();
00352
00353 bool bKMass =
00354 massMuNu > vertexIdentifier_.mK_min()
00355 && massMuNu < vertexIdentifier_.mK_max();
00356
00357 return bKMass;
00358
00359 }
00360
00361
00362
00363 void PFDisplacedVertexHelper::Dump(std::ostream& out) const {
00364 tracksSelector_.Dump();
00365 vertexIdentifier_.Dump();
00366 out << " pvtx_ = " << pvtx_ << std::endl;
00367 }