CMS 3D CMS Logo

BtoCharmDecayVertexMerger.cc
Go to the documentation of this file.
1 // this code is partially taken from BCandidateProducer of L. Wehrli
2 
3 // first revised prototype version for CMSSW 29.Aug.2012
4 
10 
20 
22 
23 #include <algorithm>
24 
27  const std::vector<reco::CandidatePtr> & tracks = vtx.daughterPtrVector();
28 
29  for(std::vector<reco::CandidatePtr>::const_iterator track = tracks.begin(); track != tracks.end(); ++track) {
30  ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> > vec;
31  vec.SetPx((*track)->px());
32  vec.SetPy((*track)->py());
33  vec.SetPz((*track)->pz());
35  sum += vec;
36  }
37  return sum;
38 }
39 
40 template<typename VTX>
42  public:
44 
45  virtual void produce(edm::Event &event, const edm::EventSetup &es);
46 
48 
49  private:
53  // double maxFraction;
54  // double minSignificance;
55 
57 
58  // a vertex proxy for sorting using stl
59  struct VertexProxy{
60  VTX vert;
61  double invm;
62  size_t ntracks;
63  };
64 
65  // comparison operator for VertexProxy, used in sorting
66  friend bool operator<(VertexProxy v1, VertexProxy v2){
67  if(v1.ntracks>2 && v2.ntracks<3) return true;
68  if(v1.ntracks<3 && v2.ntracks>2) return false;
69  return (v1.invm>v2.invm);
70  }
71 
72  VertexProxy buildVertexProxy(const VTX & vtx);
73 
74  void resolveBtoDchain(std::vector<VertexProxy>& coll, unsigned int i, unsigned int k);
78 };
79 
80 
81 template<typename VTX>
83  token_primaryVertex(consumes<reco::VertexCollection>(params.getParameter<edm::InputTag>("primaryVertices"))),
84  token_secondaryVertex(consumes<edm::View<VTX> >(params.getParameter<edm::InputTag>("secondaryVertices"))),
85  maxDRForUnique(params.getParameter<double>("maxDRUnique")),
86  maxvecSumIMCUTForUnique(params.getParameter<double>("maxvecSumIMifsmallDRUnique")),
87  minCosPAtomerge(params.getParameter<double>("minCosPAtomerge")),
88  maxPtreltomerge(params.getParameter<double>("maxPtreltomerge"))
89  // maxFraction(params.getParameter<double>("maxFraction")),
90  // minSignificance(params.getParameter<double>("minSignificance"))
91 {
92  produces<std::vector<VTX> >();
93 }
94 //------------------------------------
95 template<typename VTX>
97 
98  using namespace reco;
99  // PV
101  iEvent.getByToken(token_primaryVertex, PVcoll);
102 
103  if(PVcoll->size()!=0) {
104 
105  const reco::VertexCollection pvc = *( PVcoll.product());
106  pv = pvc[0];
107 
108  // get the IVF collection
110  iEvent.getByToken(token_secondaryVertex, secondaryVertices);
111 
112 
113 
114  //loop over vertices, fill into own collection for sorting
115  std::vector<VertexProxy> vertexProxyColl;
116  for(typename edm::View<VTX>::const_iterator sv = secondaryVertices->begin();
117  sv != secondaryVertices->end(); ++sv) {
118  vertexProxyColl.push_back( buildVertexProxy(*sv) );
119  }
120 
121  // sort the vertices by mass and track multiplicity
122  sort( vertexProxyColl.begin(), vertexProxyColl.end());
123 
124 
125  // loop forward over all vertices
126  for(unsigned int iVtx=0; iVtx < vertexProxyColl.size(); ++iVtx){
127 
128  // nested loop backwards (in order to start from light masses)
129  // check all vertices against each other for B->D chain
130  for(unsigned int kVtx=vertexProxyColl.size()-1; kVtx>iVtx; --kVtx){
131  // remove D vertices from the collection and add the tracks to the original one
132  resolveBtoDchain(vertexProxyColl, iVtx, kVtx);
133  }
134  }
135 
136  // now create new vertex collection and add to event
137  auto bvertColl = std::make_unique<std::vector<VTX>>();
138  for(typename std::vector<VertexProxy>::const_iterator it=vertexProxyColl.begin(); it!=vertexProxyColl.end(); ++it) bvertColl->push_back((*it).vert);
139  iEvent.put(std::move(bvertColl));
140  }
141  else{
142  iEvent.put(std::make_unique<std::vector<VTX>>());
143  }
144 }
145 //------------------------------------
146 template<typename VTX>
149  return GlobalVector(v2.x() - v1.x(),
150  v2.y() - v1.y(),
151  v2.z() - v1.z());
152 }
153 
154 template<typename VTX>
157  return GlobalVector(v2.vertex().x() - v1.x(),
158  v2.vertex().y() - v1.y(),
159  v2.vertex().z() - v1.z());
160 }
161 
162 template<typename VTX>
165  return GlobalVector(v2.vertex().x() - v1.vertex().x(),
166  v2.vertex().y() - v1.vertex().y(),
167  v2.vertex().z() - v1.vertex().z());
168 }
169 //-------------- template specializations --------------------
170 
171 // -------------- buildVertexProxy ----------------
172 template<>
175  VertexProxy vtxProxy = {vtx,vtx.p4().M(),vtx.tracksSize()};
176  return vtxProxy;
177 }
178 
179 template<>
182  VertexProxy vtxProxy = {vtx,vtxP4(vtx).M(),vtx.numberOfSourceCandidatePtrs()};
183  return vtxProxy;
184 }
185 
186 // -------------- resolveBtoDchain ----------------
187 template<>
188 void BtoCharmDecayVertexMergerT<reco::Vertex>::resolveBtoDchain(std::vector<VertexProxy>& coll, unsigned int i, unsigned int k){
189  using namespace reco;
190 
191  GlobalVector momentum1 = GlobalVector(coll[i].vert.p4().X(), coll[i].vert.p4().Y(), coll[i].vert.p4().Z());
192  GlobalVector momentum2 = GlobalVector(coll[k].vert.p4().X(), coll[k].vert.p4().Y(), coll[k].vert.p4().Z());
193 
194  SecondaryVertex sv1(pv, coll[i].vert, momentum1 , true);
195  SecondaryVertex sv2(pv, coll[k].vert, momentum2 , true);
196 
197 
198  // find out which one is near and far
199  SecondaryVertex svNear = sv1;
200  SecondaryVertex svFar = sv2;
201  GlobalVector momentumNear = momentum1;
202  GlobalVector momentumFar = momentum2;
203 
204  // swap if it is the other way around
205  if(sv1.dist3d().value() >= sv2.dist3d().value()){
206  svNear = sv2;
207  svFar = sv1;
208  momentumNear = momentum2;
209  momentumFar = momentum1;
210  }
211  GlobalVector nearToFar = flightDirection( svNear, svFar);
212  GlobalVector pvToNear = flightDirection( pv, svNear);
213  GlobalVector pvToFar = flightDirection( pv, svFar);
214 
215  double cosPA = nearToFar.dot(momentumFar) / momentumFar.mag()/ nearToFar.mag();
216  double cosa = pvToNear. dot(momentumFar) / pvToNear.mag() / momentumFar.mag();
217  double ptrel = sqrt(1.0 - cosa*cosa)* momentumFar.mag();
218 
219  double vertexDeltaR = Geom::deltaR(pvToNear, pvToFar);
220 
221  // create a set of all tracks from both vertices, avoid double counting by using a std::set<>
222  std::set<reco::TrackRef> trackrefs;
223  // first vertex
224  for(reco::Vertex::trackRef_iterator ti = sv1.tracks_begin(); ti!=sv1.tracks_end(); ++ti){
225  if(sv1.trackWeight(*ti)>0.5){
226  reco::TrackRef t = ti->castTo<reco::TrackRef>();
227  trackrefs.insert(t);
228  }
229  }
230  // second vertex
231  for(reco::Vertex::trackRef_iterator ti = sv2.tracks_begin(); ti!=sv2.tracks_end(); ++ti){
232  if(sv2.trackWeight(*ti)>0.5){
233  reco::TrackRef t = ti->castTo<reco::TrackRef>();
234  trackrefs.insert(t);
235  }
236  }
237 
238  // now calculate one LorentzVector from the track momenta
239  ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> > mother;
240  for(std::set<reco::TrackRef>::const_iterator it = trackrefs.begin(); it!= trackrefs.end(); ++it){
241  ROOT::Math::LorentzVector<ROOT::Math::PxPyPzM4D<double> > temp ( (*it)->px(),(*it)->py(),(*it)->pz(), ParticleMasses::piPlus );
242  mother += temp;
243  }
244 
245 
246  // check if criteria for merging are fulfilled
247  if(vertexDeltaR<maxDRForUnique && mother.M()<maxvecSumIMCUTForUnique && cosPA>minCosPAtomerge && std::abs(ptrel)<maxPtreltomerge ) {
248 
249 
250  // add tracks of second vertex which are missing to first vertex
251  // loop over the second
252  bool bFoundDuplicate=false;
253  for(reco::Vertex::trackRef_iterator ti = sv2.tracks_begin(); ti!=sv2.tracks_end(); ++ti){
254  reco::Vertex::trackRef_iterator it = find(sv1.tracks_begin(), sv1.tracks_end(), *ti);
255  if (it==sv1.tracks_end()) coll[i].vert.add( *ti, sv2.refittedTrack(*ti), sv2.trackWeight(*ti) );
256  else bFoundDuplicate=true;
257  }
258  // in case a duplicate track is found, need to create the full track list in the vertex from scratch because we need to modify the weight.
259  // the weight must be the larger one, otherwise we may have outliers which are not real outliers
260 
261  if(bFoundDuplicate){
262  // create backup track containers from main vertex
263  std::vector<TrackBaseRef > tracks_;
264  std::vector<Track> refittedTracks_;
265  std::vector<float> weights_;
266  for(reco::Vertex::trackRef_iterator it = coll[i].vert.tracks_begin(); it!=coll[i].vert.tracks_end(); ++it) {
267  tracks_.push_back( *it);
268  refittedTracks_.push_back( coll[i].vert.refittedTrack(*it));
269  weights_.push_back( coll[i].vert.trackWeight(*it) );
270  }
271  // delete tracks and add all tracks back, and check in which vertex the weight is larger
272  coll[i].vert.removeTracks();
273  std::vector<Track>::iterator it2 = refittedTracks_.begin();
274  std::vector<float>::iterator it3 = weights_.begin();
275  for(reco::Vertex::trackRef_iterator it = tracks_.begin(); it!=tracks_.end(); ++it, ++it2, ++it3){
276  float weight = *it3;
277  float weight2= sv2.trackWeight(*it);
278  Track refittedTrackWithLargerWeight = *it2;
279  if( weight2 >weight) {
280  weight = weight2;
281  refittedTrackWithLargerWeight = sv2.refittedTrack(*it);
282  }
283  coll[i].vert.add(*it , refittedTrackWithLargerWeight , weight);
284  }
285  }
286 
287  // remove the second vertex from the collection
288  coll.erase( coll.begin() + k );
289  }
290 
291 }
292 
293 template<>
294 void BtoCharmDecayVertexMergerT<reco::VertexCompositePtrCandidate>::resolveBtoDchain(std::vector<VertexProxy>& coll, unsigned int i, unsigned int k){
295  using namespace reco;
296 
297  Candidate::LorentzVector vtx1P4 = vtxP4(coll[i].vert);
298  Candidate::LorentzVector vtx2P4 = vtxP4(coll[k].vert);
299  GlobalVector momentum1 = GlobalVector(vtx1P4.X(), vtx1P4.Y(), vtx1P4.Z());
300  GlobalVector momentum2 = GlobalVector(vtx2P4.X(), vtx2P4.Y(), vtx2P4.Z());
301 
302  SecondaryVertex sv1(pv, coll[i].vert, momentum1 , true);
303  SecondaryVertex sv2(pv, coll[k].vert, momentum2 , true);
304 
305 
306  // find out which one is near and far
307  SecondaryVertex svNear = sv1;
308  SecondaryVertex svFar = sv2;
309  GlobalVector momentumNear = momentum1;
310  GlobalVector momentumFar = momentum2;
311 
312  // swap if it is the other way around
313  if(sv1.dist3d().value() >= sv2.dist3d().value()){
314  svNear = sv2;
315  svFar = sv1;
316  momentumNear = momentum2;
317  momentumFar = momentum1;
318  }
319  GlobalVector nearToFar = flightDirection( svNear, svFar);
320  GlobalVector pvToNear = flightDirection( pv, svNear);
321  GlobalVector pvToFar = flightDirection( pv, svFar);
322 
323  double cosPA = nearToFar.dot(momentumFar) / momentumFar.mag()/ nearToFar.mag();
324  double cosa = pvToNear. dot(momentumFar) / pvToNear.mag() / momentumFar.mag();
325  double ptrel = sqrt(1.0 - cosa*cosa)* momentumFar.mag();
326 
327  double vertexDeltaR = Geom::deltaR(pvToNear, pvToFar);
328 
329  // create a set of all tracks from both vertices, avoid double counting by using a std::set<>
330  std::set<reco::CandidatePtr> trackrefs;
331  // first vertex
332  for(size_t i=0; i < sv1.numberOfSourceCandidatePtrs(); ++i)
333  trackrefs.insert(sv1.daughterPtr(i));
334  // second vertex
335  for(size_t i=0; i < sv2.numberOfSourceCandidatePtrs(); ++i)
336  trackrefs.insert(sv2.daughterPtr(i));
337 
338  // now calculate one LorentzVector from the track momenta
340  for(std::set<reco::CandidatePtr>::const_iterator it = trackrefs.begin(); it!= trackrefs.end(); ++it){
341  Candidate::LorentzVector temp ( (*it)->px(),(*it)->py(),(*it)->pz(), ParticleMasses::piPlus );
342  mother += temp;
343  }
344 
345  // check if criteria for merging are fulfilled
346  if(vertexDeltaR<maxDRForUnique && mother.M()<maxvecSumIMCUTForUnique && cosPA>minCosPAtomerge && std::abs(ptrel)<maxPtreltomerge ) {
347 
348  // add tracks of second vertex which are missing to first vertex
349  // loop over the second
350  const std::vector<reco::CandidatePtr> & tracks1 = sv1.daughterPtrVector();
351  const std::vector<reco::CandidatePtr> & tracks2 = sv2.daughterPtrVector();
352  for(std::vector<reco::CandidatePtr>::const_iterator ti = tracks2.begin(); ti!=tracks2.end(); ++ti){
353  std::vector<reco::CandidatePtr>::const_iterator it = find(tracks1.begin(), tracks1.end(), *ti);
354  if (it==tracks1.end()) {
355  coll[i].vert.addDaughter( *ti );
356  coll[i].vert.setP4( (*ti)->p4() + coll[i].vert.p4() );
357  }
358  }
359 
360  // remove the second vertex from the collection
361  coll.erase( coll.begin() + k );
362  }
363 }
364 
365 
366 // define specific instances of the templated BtoCharmDecayVertexMergerT class
369 
370 // define plugins
const double piPlus
Definition: ParticleMasses.h:9
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:122
reco::TemplatedSecondaryVertex< VTX > SecondaryVertex
const std::vector< reco::PFCandidatePtr > & tracks_
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:460
virtual const Point & vertex() const
vertex position (overwritten by PF...)
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
double y() const
y coordinate
Definition: Vertex.h:113
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
PreciseFloatType< T, U >::Type dot(const Vector3DBase< U, FrameTag > &v) const
Definition: Vector3DBase.h:107
Definition: weight.py:1
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:20
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
BtoCharmDecayVertexMergerT< reco::Vertex > BtoCharmDecayVertexMerger
VertexProxy buildVertexProxy(const VTX &vtx)
int iEvent
Definition: GenABIO.cc:230
T mag() const
Definition: PV3DBase.h:67
friend bool operator<(VertexProxy v1, VertexProxy v2)
T sqrt(T t)
Definition: SSEVec.h:18
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double z() const
z coordinate
Definition: Vertex.h:115
virtual size_type numberOfSourceCandidatePtrs() const
int k[5][pyjets_maxn]
double deltaR(double eta1, double eta2, double phi1, double phi2)
Definition: TreeUtility.cc:17
double x() const
x coordinate
Definition: Vertex.h:111
JetCorrectorParametersCollection coll
Definition: classes.h:10
T const * product() const
Definition: Handle.h:81
BtoCharmDecayVertexMergerT(const edm::ParameterSet &params)
math::XYZTLorentzVectorD p4(float mass=0.13957018, float minWeight=0.5) const
Returns the four momentum of the sum of the tracks, assuming the given mass for the decay products...
Definition: Vertex.cc:135
void resolveBtoDchain(std::vector< VertexProxy > &coll, unsigned int i, unsigned int k)
GlobalVector flightDirection(const reco::Vertex &v1, const reco::Vertex &v2)
double value() const
Definition: Measurement1D.h:28
virtual void produce(edm::Event &event, const edm::EventSetup &es)
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:37
BtoCharmDecayVertexMergerT< reco::VertexCompositePtrCandidate > CandidateBtoCharmDecayVertexMerger
reco::Candidate::LorentzVector vtxP4(const reco::VertexCompositePtrCandidate &vtx)
fixed size matrix
HLT enums.
T dot(const Basic3DVector &v) const
Scalar product, or "dot" product, with a vector of same type.
boost::indirect_iterator< typename seq_t::const_iterator > const_iterator
Definition: View.h:86
edm::EDGetTokenT< edm::View< VTX > > token_secondaryVertex
const daughters & daughterPtrVector() const
references to daughtes
std::vector< TrackBaseRef >::const_iterator trackRef_iterator
The iteratator for the vector<TrackRef>
Definition: Vertex.h:37
edm::EDGetTokenT< reco::VertexCollection > token_primaryVertex
def move(src, dest)
Definition: eostools.py:510
size_t tracksSize() const
number of tracks
Definition: Vertex.cc:71
Definition: event.py:1
Global3DVector GlobalVector
Definition: GlobalVector.h:10