CMS 3D CMS Logo

PFDisplacedVertexHelper.cc
Go to the documentation of this file.
2 
3 #include "TVector3.h"
5 
6 #include "TMath.h"
7 
8 using namespace std;
9 using namespace reco;
10 
11 
12 const double PFDisplacedVertexHelper::pion_mass2 = 0.0194;
13 const double PFDisplacedVertexHelper::muon_mass2 = 0.106*0.106;
14 const double PFDisplacedVertexHelper::proton_mass2 = 0.938*0.938;
15 
16 //for debug only
17 //#define PFLOW_DEBUG
18 
20  tracksSelector_(),
21  vertexIdentifier_(),
22  pvtx_(math::XYZPoint(0,0,0)) {}
23 
25 
27  edm::Handle< reco::VertexCollection > mainVertexHandle,
28  edm::Handle< reco::BeamSpot > beamSpotHandle){
29 
30  const math::XYZPoint beamSpot = beamSpotHandle.isValid() ?
31  math::XYZPoint(beamSpotHandle->x0(), beamSpotHandle->y0(), beamSpotHandle->z0()) :
32  math::XYZPoint(0, 0, 0);
33 
34  // The primary vertex is taken from the refitted list,
35  // if does not exist from the average offline beam spot position
36  // if does not exist (0,0,0) is used
37  pvtx_ = mainVertexHandle.isValid() ?
38  math::XYZPoint(mainVertexHandle->begin()->x(),
39  mainVertexHandle->begin()->y(),
40  mainVertexHandle->begin()->z()) :
41  beamSpot;
42 }
43 
44 bool
46  const reco::PFDisplacedVertex::VertexTrackType vertexTrackType) const {
47 
48 
49  if (!tracksSelector_.selectTracks()) return true;
50 
51  bool isGoodTrack = false;
52 
53  bool isHighPurity = trk.quality( trk.qualityByName(tracksSelector_.quality().data()) );
54 
55  double nChi2 = trk.normalizedChi2();
56  double pt = trk.pt();
57  int nHits = trk.numberOfValidHits();
58 
59  bool bIsPrimary =
60  (
61  (vertexTrackType == reco::PFDisplacedVertex::T_TO_VERTEX)
62  ||
63  (vertexTrackType == reco::PFDisplacedVertex::T_MERGED)
64  );
65 
66 
67  if (bIsPrimary) {
68  // Primary or merged track selection
69  isGoodTrack =
70  ( ( nChi2 > tracksSelector_.nChi2_min()
71  && nChi2 < tracksSelector_.nChi2_max())
72  || isHighPurity )
73  && pt > tracksSelector_.pt_min();
74  } else {
75  // Secondary tracks selection
76  int nOuterHits = trk.hitPattern().numberOfHits(HitPattern::MISSING_OUTER_HITS);
77 
78  double dxy = trk.dxy(pvtx_);
79 
80  isGoodTrack =
81  nChi2 < tracksSelector_.nChi2_max()
82  && pt > tracksSelector_.pt_min()
83  && fabs(dxy) > tracksSelector_.dxy_min()
84  && nHits >= tracksSelector_.nHits_min()
85  && nOuterHits <= tracksSelector_.nOuterHits_max();
86 
87  }
88 
89  return isGoodTrack;
90 
91 }
92 
95 
97 
98  PFDisplacedVertex::M_Hypo massElec = PFDisplacedVertex::M_MASSLESS;
99  PFDisplacedVertex::M_Hypo massPion = PFDisplacedVertex::M_PION;
100 
101  math::XYZTLorentzVector mom_ee = v.secondaryMomentum(massElec, true);
102  math::XYZTLorentzVector mom_pipi = v.secondaryMomentum(massPion, true);
103 
104  // ===== (1) Identify fake and looper vertices ===== //
105 
106  double ang = v.angle_io();
107  double pt_ee = mom_ee.Pt();
108  double eta_vtx = v.position().eta();
109 
110  //cout << "Angle = " << ang << endl;
111 
112  bool bDirectionFake = ang > vertexIdentifier_.angle_max();
113  bool bLowPt = pt_ee < vertexIdentifier_.pt_min();
114  bool bLooperEta = fabs(eta_vtx) < vertexIdentifier_.looper_eta_max();
115 
116  bool isFake = bDirectionFake ||(bLowPt && !bLooperEta);
117  bool isLooper = !bDirectionFake && bLowPt && bLooperEta;
118 
119  if (isFake) return PFDisplacedVertex::FAKE;
120  if (isLooper) return PFDisplacedVertex::LOOPER;
121 
122  // ===== (2) Identify Decays and Conversions ===== //
123 
124  int c1 = v.originalTrack(v.refittedTracks()[0])->charge();
125  int c2 = v.originalTrack(v.refittedTracks()[1])->charge();
126  double mass_ee = mom_ee.M();
127 
128  int nTracks = v.nTracks();
129  int nSecondaryTracks = v.nSecondaryTracks();
130  bool bPrimaryTracks = v.isTherePrimaryTracks();
131  bool bMergedTracks = v.isThereMergedTracks();
132 
133  bool bPair = (nTracks == nSecondaryTracks) && (nTracks == 2);
134  bool bOpposite = (c1*c2 < -0.1);
135  bool bDirection = ang < vertexIdentifier_.angle_V0Conv_max();
136  bool bConvMass = mass_ee < vertexIdentifier_.mConv_max();
137 
138  bool bV0Conv = bPair && bOpposite && bDirection;
139 
140  // If the basic configuration of conversions and V0 decays is respected
141  // pair of secondary track with opposite charge and going in the right direction
142  // the selection is then based on mass limits
143  if (bV0Conv){
144 
145  // == (2.1) Identify Conversions == //
146 
147  bool isConv = bConvMass;
148 
149  if (isConv) return PFDisplacedVertex::CONVERSION_LOOSE;
150 
151  // == (2.2) Identify K0 == //
152 
153  double mass_pipi = mom_pipi.M();
154 
155  bool bK0Mass =
156  mass_pipi < vertexIdentifier_.mK0_max()
157  && mass_pipi > vertexIdentifier_.mK0_min();
158 
159  bool isK0 = bK0Mass;
160 
161  if (isK0) return PFDisplacedVertex::K0_DECAY;
162 
163  // == (2.3) Identify Lambda == //
164 
165  int lambdaKind = lambdaCP(v);
166 
167 
168  bool isLambda = (lambdaKind == 1);
169  bool isLambdaBar = (lambdaKind == -1);
170 
171  if (isLambda) return PFDisplacedVertex::LAMBDA_DECAY;
172  if (isLambdaBar) return PFDisplacedVertex::LAMBDABAR_DECAY;
173 
174  }
175 
176  // == (2.4) Identify K- and K+ ==
177  bool bK =
178  (nSecondaryTracks == 1) && bPrimaryTracks && !bMergedTracks
179  && !bOpposite;
180 
181  if(bK){
182 
183  bool bKMass = isKaonMass(v);
184 
185  bool isKPlus = bKMass && c1 > 0;
186  bool isKMinus = bKMass && c1 < 0;
187 
188  if(isKMinus) return PFDisplacedVertex::KMINUS_DECAY_LOOSE;
189  if(isKPlus) return PFDisplacedVertex::KPLUS_DECAY_LOOSE;
190 
191  }
192 
193  // ===== (3) Identify Nuclears, Kinks and Remaining Fakes ===== //
194 
195  math::XYZTLorentzVector mom_prim = v.primaryMomentum(massPion, true);
196 
197  double p_prim = mom_prim.P();
198  double p_sec = mom_pipi.P();
199  double pt_prim = mom_prim.Pt();
200 
201  bool bLog = false;
202  if (p_prim > 0.05 && p_sec > 0.05) bLog = log10(p_prim/p_sec) > vertexIdentifier_.logPrimSec_min();
203  bool bPtMin = pt_prim > vertexIdentifier_.pt_kink_min();
204 
205  // A vertex with at least 3 tracks is considered as high purity nuclear interaction
206  // the only exception is K- decay into 3 prongs. To be studied.
207  bool isNuclearHighPurity = nTracks > 2 && mass_ee > vertexIdentifier_.mNucl_min();
208  bool isFakeHighPurity = nTracks > 2 && mass_ee < vertexIdentifier_.mNucl_min();
209  // Two secondary tracks with some minimal tracks angular opening are still accepted
210  // as nuclear interactions
211  bool isNuclearLowPurity =
212  (nTracks == nSecondaryTracks)
213  && (nTracks == 2)
214  && mass_ee > vertexIdentifier_.mNucl_min();
215 
216  bool isFakeNucl =
217  (nTracks == nSecondaryTracks)
218  && (nTracks == 2)
219  && mass_ee < vertexIdentifier_.mNucl_min();
220 
221  // Kinks: 1 primary + 1 secondary is accepted only if the primary tracks
222  // has more energy than the secondary and primary have some minimal pT
223  // to produce a nuclear interaction
224  bool isNuclearKink =
225  (nSecondaryTracks == 1) && bPrimaryTracks && !bMergedTracks
226  && bLog && bPtMin;
227 
228  // Here some loopers may hide appearing in Particle Isolation plots. To be studied...
229  bool isFakeKink =
230  ( (nSecondaryTracks == 1) && bMergedTracks && !bPrimaryTracks )
231  ||
232  ( (nSecondaryTracks == 1) && bPrimaryTracks && !bMergedTracks
233  && (!bLog || !bPtMin) );
234 
235  if (isNuclearHighPurity) return PFDisplacedVertex::NUCL;
236  if (isNuclearLowPurity) return PFDisplacedVertex::NUCL_LOOSE;
237  if (isFakeKink || isFakeNucl || isFakeHighPurity) return PFDisplacedVertex::FAKE;
238  if (isNuclearKink) return PFDisplacedVertex::NUCL_KINK;
239 
240 
241  return PFDisplacedVertex::ANY;
242 
243 }
244 
245 
247 
248  int lambdaCP = 0;
249 
250  vector <Track> refittedTracks = v.refittedTracks();
251 
252  math::XYZTLorentzVector totalMomentumDcaRefit_lambda;
253  math::XYZTLorentzVector totalMomentumDcaRefit_lambdabar;
254 
255 
256  reco::Track tMomentumDcaRefit_0 = refittedTracks[0];
257  reco::Track tMomentumDcaRefit_1 = refittedTracks[1];
258 
259  double mass2_0 = 0, mass2_1 = 0;
260 
261  int c1 = v.originalTrack(v.refittedTracks()[1])->charge();
262 
263  // --------------------------- lambda --------------------
264 
265 
266  if (c1 > 0.1) mass2_0 = pion_mass2, mass2_1 = proton_mass2;
267  else mass2_0 = proton_mass2, mass2_1 = pion_mass2;
268 
269  double E = sqrt(tMomentumDcaRefit_0.p()*tMomentumDcaRefit_0.p() + mass2_0);
270 
271  math::XYZTLorentzVector momentumDcaRefit_0(tMomentumDcaRefit_0.px(), tMomentumDcaRefit_0.py(),
272  tMomentumDcaRefit_0.pz(), E);
273 
274 
275 
276  E = sqrt(tMomentumDcaRefit_1.p()*tMomentumDcaRefit_1.p() + mass2_1);
277 
278  math::XYZTLorentzVector momentumDcaRefit_1(tMomentumDcaRefit_1.px(), tMomentumDcaRefit_1.py(),
279  tMomentumDcaRefit_1.pz(), E);
280 
281 
282  totalMomentumDcaRefit_lambda = momentumDcaRefit_0 + momentumDcaRefit_1;
283 
284 
285 
286  // --------------------------- anti - lambda --------------------
287 
288  if (c1 > 0.1) mass2_1 = pion_mass2, mass2_0 = proton_mass2;
289  else mass2_1 = proton_mass2, mass2_0 = pion_mass2;
290 
291 
292  E = sqrt(tMomentumDcaRefit_0.p()*tMomentumDcaRefit_0.p() + mass2_0);
293 
294  math::XYZTLorentzVector momentumDcaRefit_01(tMomentumDcaRefit_0.px(), tMomentumDcaRefit_0.py(),
295  tMomentumDcaRefit_0.pz(), E);
296 
297 
298 
299  E = sqrt(tMomentumDcaRefit_1.p()*tMomentumDcaRefit_1.p() + mass2_1);
300 
301  math::XYZTLorentzVector momentumDcaRefit_11(tMomentumDcaRefit_1.px(), tMomentumDcaRefit_1.py(),
302  tMomentumDcaRefit_1.pz(), E);
303 
304 
305  totalMomentumDcaRefit_lambdabar = momentumDcaRefit_01 + momentumDcaRefit_11;
306 
307  double mass_l = totalMomentumDcaRefit_lambda.M();
308  double mass_lbar = totalMomentumDcaRefit_lambdabar.M();
309 
310  // cout << "mass_l = " << mass_l << " mass_lbar = " << mass_lbar << endl;
311 
312 
313  if (
314  mass_l < mass_lbar
315  && mass_l > vertexIdentifier_.mLambda_min()
316  && mass_l < vertexIdentifier_.mLambda_max())
317  lambdaCP = 1;
318  else if (mass_lbar < mass_l
319  && mass_lbar > vertexIdentifier_.mLambda_min()
320  && mass_lbar < vertexIdentifier_.mLambda_max())
321  lambdaCP = -1;
322  else
323  lambdaCP = 0;
324 
325  //cout << "lambdaCP = " << lambdaCP << endl;
326 
327  return lambdaCP;
328 
329 }
330 
331 
332 
334 
335  math::XYZVector trkInit = v.refittedTracks()[1].momentum();
336  math::XYZVector trkFinal = v.refittedTracks()[0].momentum();
337 
338  if (v.trackTypes()[0] == PFDisplacedVertex::T_TO_VERTEX) {
339  trkInit = v.refittedTracks()[0].momentum();
340  trkFinal = v.refittedTracks()[1].momentum();
341  }
342 
343 
344  math::XYZVector trkNeutre(trkInit.x()-trkFinal.x(), trkInit.y()-trkFinal.y(),
345  trkInit.z()-trkFinal.z());
346 
347  double Ec = sqrt(muon_mass2 + trkFinal.Mag2());
348  double En = sqrt(0*0 + trkNeutre.Mag2());
349 
350 
351 
352  math::XYZTLorentzVectorD trkMuNu(trkInit.x(), trkInit.y(), trkInit.z(), Ec+En);
353  double massMuNu = trkMuNu.M();
354 
355  bool bKMass =
356  massMuNu > vertexIdentifier_.mK_min()
357  && massMuNu < vertexIdentifier_.mK_max();
358 
359  return bKMass;
360 
361 }
362 
363 
364 
365 void PFDisplacedVertexHelper::Dump(std::ostream& out) const {
368  out << " pvtx_ = " << pvtx_ << std::endl;
369  }
double p() const
momentum vector magnitude
Definition: TrackBase.h:615
double z0() const
z coordinate
Definition: BeamSpot.h:68
const unsigned int nTracks(const reco::Vertex &sv)
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double > > XYZTLorentzVectorD
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:14
const double angle_io() const
const bool isTherePrimaryTracks() const
--—— Provide useful information --—— ///
double normalizedChi2() const
chi-squared divided by n.d.o.f. (or chi-squared * 1e6 if n.d.o.f. is zero)
Definition: TrackBase.h:561
TrackBaseRef originalTrack(const Track &refTrack) const
Definition: Vertex.cc:108
const math::XYZTLorentzVector secondaryMomentum(std::string massHypo="PI", bool useRefitted=true, double mass=0.0) const
void Dump(std::ostream &out=std::cout) const
static const double proton_mass2
void Dump(std::ostream &out=std::cout) const
double px() const
x coordinate of momentum vector
Definition: TrackBase.h:627
void setPrimaryVertex(edm::Handle< reco::VertexCollection > mainVertexHandle, edm::Handle< reco::BeamSpot > beamSpotHandle)
Update the primary vertex information.
const std::vector< Track > & refittedTracks() const
Returns the container of refitted tracks.
Definition: Vertex.h:164
const Point & position() const
position
Definition: Vertex.h:109
bool isKaonMass(const reco::PFDisplacedVertex &v) const
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
bool isTrackSelected(const reco::Track &trk, const reco::PFDisplacedVertex::VertexTrackType vertexTrackType) const
Select tracks tool.
T sqrt(T t)
Definition: SSEVec.h:18
reco::PFDisplacedVertex::VertexType identifyVertex(const reco::PFDisplacedVertex &v) const
Vertex identification tool.
double pt() const
track transverse momentum
Definition: TrackBase.h:621
static const double pion_mass2
Masses2 taken from PDG.
int lambdaCP(const reco::PFDisplacedVertex &v) const
Tools used to calculate quantities for vertex identification.
const std::vector< VertexTrackType > trackTypes() const
unsigned short numberOfValidHits() const
number of valid hits found
Definition: TrackBase.h:820
bool isValid() const
Definition: HandleBase.h:74
Definition: Error.h:16
double pz() const
z coordinate of momentum vector
Definition: TrackBase.h:639
Block of elements.
static TrackQuality qualityByName(const std::string &name)
Definition: TrackBase.cc:125
const HitPattern & hitPattern() const
Access the hit pattern, indicating in which Tracker layers the track has hits.
Definition: TrackBase.h:446
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:30
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
const math::XYZTLorentzVector primaryMomentum(std::string massHypo="PI", bool useRefitted=true, double mass=0.0) const
Momentum of primary or merged track calculated with a mass hypothesis.
bool quality(const TrackQuality) const
Track quality.
Definition: TrackBase.h:510
void Dump(std::ostream &out=std::cout) const
fixed size matrix
math::XYZPoint pvtx_
Primary vertex information updated for each event.
double y0() const
y coordinate
Definition: BeamSpot.h:66
const bool isThereMergedTracks() const
If a merged track was identified.
double dxy() const
dxy parameter. (This is the transverse impact parameter w.r.t. to (0,0,0) ONLY if refPoint is close t...
Definition: TrackBase.h:591
const int nSecondaryTracks() const
Number of secondary tracks was identified.
M_Hypo
Mass hypothesis enum.
double py() const
y coordinate of momentum vector
Definition: TrackBase.h:633
int numberOfHits(HitCategory category) const
Definition: HitPattern.h:807
const int nTracks() const
Number of tracks.
double x0() const
x coordinate
Definition: BeamSpot.h:64