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