CMS 3D CMS Logo

TemplatedSecondaryVertexProducer.cc
Go to the documentation of this file.
1 #include <functional>
2 #include <algorithm>
3 #include <iterator>
4 #include <cstddef>
5 #include <string>
6 #include <vector>
7 #include <map>
8 #include <set>
9 
10 #include <boost/iterator/transform_iterator.hpp>
11 
23 
28 
33 
41 
46 
52 
54 
55 #include "fastjet/JetDefinition.hh"
56 #include "fastjet/ClusterSequence.hh"
57 #include "fastjet/PseudoJet.hh"
58 
59 //
60 // constants, enums and typedefs
61 //
62 typedef boost::shared_ptr<fastjet::ClusterSequence> ClusterSequencePtr;
63 typedef boost::shared_ptr<fastjet::JetDefinition> JetDefPtr;
64 
65 
66 using namespace reco;
67 
68 namespace {
69  class VertexInfo : public fastjet::PseudoJet::UserInfoBase{
70  public:
71  VertexInfo(const int vertexIndex) :
72  m_vertexIndex(vertexIndex) { }
73 
74  inline const int vertexIndex() const { return m_vertexIndex; }
75 
76  protected:
77  int m_vertexIndex;
78  };
79 
80  template<typename T>
81  struct RefToBaseLess {
82  inline bool operator()(const edm::RefToBase<T> &r1,
83  const edm::RefToBase<T> &r2) const
84  {
85  return r1.id() < r2.id() ||
86  (r1.id() == r2.id() && r1.key() < r2.key());
87  }
88  };
89 }
90 
92 return GlobalVector(sv.x() - pv.x(), sv.y() - pv.y(),sv.z() - pv.z());
93 }
95 return GlobalVector(sv.vertex().x() - pv.x(), sv.vertex().y() - pv.y(),sv.vertex().z() - pv.z());
96 }
98 {return sv.position();}
100 {return sv.vertex();}
101 
102 
103 template <class IPTI,class VTX>
105  public:
106  explicit TemplatedSecondaryVertexProducer(const edm::ParameterSet &params);
108  static void fillDescriptions(edm::ConfigurationDescriptions & descriptions);
109  typedef std::vector<TemplatedSecondaryVertexTagInfo<IPTI,VTX> > Product;
111  typedef typename IPTI::input_container input_container;
113  typedef typename std::vector<reco::btag::IndexedTrackData> TrackDataVector;
114  void produce(edm::Event &event, const edm::EventSetup &es) override;
115 
116  private:
117  template<class CONTAINER>
118  void matchReclusteredJets(const edm::Handle<CONTAINER>& jets,
119  const std::vector<fastjet::PseudoJet>& matchedJets,
120  std::vector<int>& matchedIndices,
121  const std::string& jetType="");
122  void matchGroomedJets(const edm::Handle<edm::View<reco::Jet> >& jets,
123  const edm::Handle<edm::View<reco::Jet> >& matchedJets,
124  std::vector<int>& matchedIndices);
125  void matchSubjets(const std::vector<int>& groomedIndices,
126  const edm::Handle<edm::View<reco::Jet> >& groomedJets,
127  const edm::Handle<std::vector<IPTI> >& subjets,
128  std::vector<std::vector<int> >& matchedIndices);
129  void matchSubjets(const edm::Handle<edm::View<reco::Jet> >& fatJets,
130  const edm::Handle<std::vector<IPTI> >& subjets,
131  std::vector<std::vector<int> >& matchedIndices);
132 
133  const reco::Jet * toJet(const reco::Jet & j) { return &j; }
134  const reco::Jet * toJet(const IPTI & j) { return &(*(j.jet())); }
135 
137  CONSTRAINT_NONE = 0,
142  CONSTRAINT_PV_PRIMARIES_IN_FIT
143  };
144  static ConstraintType getConstraintType(const std::string &name);
145 
164  double rParam;
165  double jetPtMin;
172 
175 
176  void markUsedTracks(TrackDataVector & trackData, const input_container & trackRefs, const SecondaryVertex & sv,size_t idx);
177 
178  struct SVBuilder {
179 
181  const GlobalVector &direction,
182  bool withPVError,
183  double minTrackWeight) :
184  pv(pv), direction(direction),
185  withPVError(withPVError),
186  minTrackWeight(minTrackWeight) {}
187  SecondaryVertex operator () (const TransientVertex &sv) const;
188 
189  SecondaryVertex operator () (const VTX &sv) const
190  { return SecondaryVertex(pv, sv, direction, withPVError); }
191 
192 
193  const Vertex &pv;
197  };
198 
199  struct SVFilter {
200 
202  const GlobalVector &direction) :
203  filter(filter), pv(pv), direction(direction) {}
204 
205  inline bool operator () (const SecondaryVertex &sv) const
206  { return !filter(pv, sv, direction); }
207 
209  const Vertex &pv;
211  };
212 };
213 template <class IPTI,class VTX>
216 {
217  if (name == "None")
218  return CONSTRAINT_NONE;
219  else if (name == "BeamSpot")
220  return CONSTRAINT_BEAMSPOT;
221  else if (name == "BeamSpot+PVPosition")
222  return CONSTRAINT_PV_BEAMSPOT_SIZE;
223  else if (name == "BeamSpotZ+PVErrorScaledXY")
224  return CONSTRAINT_PV_BS_Z_ERRORS_SCALED;
225  else if (name == "PVErrorScaled")
226  return CONSTRAINT_PV_ERROR_SCALED;
227  else if (name == "BeamSpot+PVTracksInFit")
228  return CONSTRAINT_PV_PRIMARIES_IN_FIT;
229  else
230  throw cms::Exception("InvalidArgument")
231  << "TemplatedSecondaryVertexProducer: ``constraint'' parameter "
232  "value \"" << name << "\" not understood."
233  << std::endl;
234 }
235 
238 {
239  if (name == "AlwaysWithGhostTrack")
241  else if (name == "SingleTracksWithGhostTrack")
243  else if (name == "RefitGhostTrackWithVertices")
245  else
246  throw cms::Exception("InvalidArgument")
247  << "TemplatedSecondaryVertexProducer: ``fitType'' "
248  "parameter value \"" << name << "\" for "
249  "GhostTrackVertexFinder settings not "
250  "understood." << std::endl;
251 }
252 
253 template <class IPTI,class VTX>
255  const edm::ParameterSet &params) :
256  sortCriterium(TrackSorting::getCriterium(params.getParameter<std::string>("trackSort"))),
257  trackSelector(params.getParameter<edm::ParameterSet>("trackSelection")),
258  constraint(getConstraintType(params.getParameter<std::string>("constraint"))),
259  constraintScaling(1.0),
260  vtxRecoPSet(params.getParameter<edm::ParameterSet>("vertexReco")),
261  useGhostTrack(vtxRecoPSet.getParameter<std::string>("finder") == "gtvr"),
262  withPVError(params.getParameter<bool>("usePVError")),
263  minTrackWeight(params.getParameter<double>("minimumTrackWeight")),
264  vertexFilter(params.getParameter<edm::ParameterSet>("vertexCuts")),
265  vertexSorting(params.getParameter<edm::ParameterSet>("vertexSelection"))
266 {
267  token_trackIPTagInfo = consumes<std::vector<IPTI> >(params.getParameter<edm::InputTag>("trackIPTagInfos"));
270  constraintScaling = params.getParameter<double>("pvErrorScaling");
271 
276  token_BeamSpot = consumes<reco::BeamSpot>(params.getParameter<edm::InputTag>("beamSpotTag"));
277  useExternalSV = false;
278  if(params.existsAs<bool>("useExternalSV")) useExternalSV = params.getParameter<bool> ("useExternalSV");
279  if(useExternalSV) {
280  token_extSVCollection = consumes<edm::View<VTX> >(params.getParameter<edm::InputTag>("extSVCollection"));
281  extSVDeltaRToJet = params.getParameter<double>("extSVDeltaRToJet");
282  }
283  useSVClustering = ( params.existsAs<bool>("useSVClustering") ? params.getParameter<bool>("useSVClustering") : false );
284  useSVMomentum = ( params.existsAs<bool>("useSVMomentum") ? params.getParameter<bool>("useSVMomentum") : false );
285  useFatJets = ( useExternalSV && params.exists("fatJets") );
286  useGroomedFatJets = ( useExternalSV && params.exists("groomedFatJets") );
287  if( useSVClustering )
288  {
289  jetAlgorithm = params.getParameter<std::string>("jetAlgorithm");
290  rParam = params.getParameter<double>("rParam");
291  jetPtMin = 0.; // hardcoded to 0. since we simply want to recluster all input jets which already had some PtMin applied
292  ghostRescaling = ( params.existsAs<double>("ghostRescaling") ? params.getParameter<double>("ghostRescaling") : 1e-18 );
293  relPtTolerance = ( params.existsAs<double>("relPtTolerance") ? params.getParameter<double>("relPtTolerance") : 1e-03); // 0.1% relative difference in Pt should be sufficient to detect possible misconfigurations
294 
295  // set jet algorithm
296  if (jetAlgorithm=="Kt")
297  fjJetDefinition = JetDefPtr( new fastjet::JetDefinition(fastjet::kt_algorithm, rParam) );
298  else if (jetAlgorithm=="CambridgeAachen")
299  fjJetDefinition = JetDefPtr( new fastjet::JetDefinition(fastjet::cambridge_algorithm, rParam) );
300  else if (jetAlgorithm=="AntiKt")
301  fjJetDefinition = JetDefPtr( new fastjet::JetDefinition(fastjet::antikt_algorithm, rParam) );
302  else
303  throw cms::Exception("InvalidJetAlgorithm") << "Jet clustering algorithm is invalid: " << jetAlgorithm << ", use CambridgeAachen | Kt | AntiKt" << std::endl;
304  }
305  if( useFatJets )
306  token_fatJets = consumes<edm::View<reco::Jet> >(params.getParameter<edm::InputTag>("fatJets"));
307  if( useGroomedFatJets )
308  token_groomedFatJets = consumes<edm::View<reco::Jet> >(params.getParameter<edm::InputTag>("groomedFatJets"));
309  if( useFatJets && !useSVClustering )
310  rParam = params.getParameter<double>("rParam"); // will be used later as a dR cut
311 
312  produces<Product>();
313 }
314 template <class IPTI,class VTX>
316 {
317 }
318 
319 template <class IPTI,class VTX>
321  const edm::EventSetup &es)
322 {
323 // typedef std::map<TrackBaseRef, TransientTrack,
324 // RefToBaseLess<Track> > TransientTrackMap;
325  //How about good old pointers?
326  typedef std::map<const Track *, TransientTrack> TransientTrackMap;
327 
328 
330  es.get<TransientTrackRecord>().get("TransientTrackBuilder",
331  trackBuilder);
332 
334  event.getByToken(token_trackIPTagInfo, trackIPTagInfos);
335 
336  // External Sec Vertex collection (e.g. for IVF usage)
337  edm::Handle<edm::View<VTX> > extSecVertex;
338  if(useExternalSV) event.getByToken(token_extSVCollection,extSecVertex);
339 
340  edm::Handle<edm::View<reco::Jet> > fatJetsHandle;
341  edm::Handle<edm::View<reco::Jet> > groomedFatJetsHandle;
342  if( useFatJets )
343  {
344  event.getByToken(token_fatJets, fatJetsHandle);
345 
346  if( useGroomedFatJets )
347  {
348  event.getByToken(token_groomedFatJets, groomedFatJetsHandle);
349 
350  if( groomedFatJetsHandle->size() > fatJetsHandle->size() )
351  edm::LogError("TooManyGroomedJets") << "There are more groomed (" << groomedFatJetsHandle->size() << ") than original fat jets (" << fatJetsHandle->size() << "). Please check that the two jet collections belong to each other.";
352  }
353  }
354 
356  unsigned int bsCovSrc[7] = { 0, };
357  double sigmaZ = 0.0, beamWidth = 0.0;
358  switch(constraint) {
360  event.getByToken(token_BeamSpot,beamSpot);
361  bsCovSrc[3] = bsCovSrc[4] = bsCovSrc[5] = bsCovSrc[6] = 1;
362  sigmaZ = beamSpot->sigmaZ();
363  beamWidth = beamSpot->BeamWidthX();
364  break;
365 
367  event.getByToken(token_BeamSpot,beamSpot);
368  bsCovSrc[0] = bsCovSrc[1] = 2;
369  bsCovSrc[3] = bsCovSrc[4] = bsCovSrc[5] = 1;
370  sigmaZ = beamSpot->sigmaZ();
371  break;
372 
374  bsCovSrc[0] = bsCovSrc[1] = bsCovSrc[2] = 2;
375  break;
376 
377  case CONSTRAINT_BEAMSPOT:
379  event.getByToken(token_BeamSpot,beamSpot);
380  break;
381 
382  default:
383  /* nothing */;
384  }
385 
386  // ------------------------------------ SV clustering START --------------------------------------------
387  std::vector<std::vector<int> > clusteredSVs(trackIPTagInfos->size(),std::vector<int>());
388  if( useExternalSV && useSVClustering && !trackIPTagInfos->empty() )
389  {
390  // vector of constituents for reclustering jets and "ghost" SVs
391  std::vector<fastjet::PseudoJet> fjInputs;
392  // loop over all input jets and collect all their constituents
393  if( useFatJets )
394  {
395  for(edm::View<reco::Jet>::const_iterator it = fatJetsHandle->begin(); it != fatJetsHandle->end(); ++it)
396  {
397  std::vector<edm::Ptr<reco::Candidate> > constituents = it->getJetConstituents();
398  std::vector<edm::Ptr<reco::Candidate> >::const_iterator m;
399  for( m = constituents.begin(); m != constituents.end(); ++m )
400  {
401  reco::CandidatePtr constit = *m;
402  if(constit->pt() == 0)
403  {
404  edm::LogWarning("NullTransverseMomentum") << "dropping input candidate with pt=0";
405  continue;
406  }
407  fjInputs.push_back(fastjet::PseudoJet(constit->px(),constit->py(),constit->pz(),constit->energy()));
408  }
409  }
410  }
411  else
412  {
413  for(typename std::vector<IPTI>::const_iterator it = trackIPTagInfos->begin(); it != trackIPTagInfos->end(); ++it)
414  {
415  std::vector<edm::Ptr<reco::Candidate> > constituents = it->jet()->getJetConstituents();
416  std::vector<edm::Ptr<reco::Candidate> >::const_iterator m;
417  for( m = constituents.begin(); m != constituents.end(); ++m )
418  {
419  reco::CandidatePtr constit = *m;
420  if(constit->pt() == 0)
421  {
422  edm::LogWarning("NullTransverseMomentum") << "dropping input candidate with pt=0";
423  continue;
424  }
425  fjInputs.push_back(fastjet::PseudoJet(constit->px(),constit->py(),constit->pz(),constit->energy()));
426  }
427  }
428  }
429  // insert "ghost" SVs in the vector of constituents
430  for(typename edm::View<VTX>::const_iterator it = extSecVertex->begin(); it != extSecVertex->end(); ++it)
431  {
432  const reco::Vertex &pv = *(trackIPTagInfos->front().primaryVertex());
433  GlobalVector dir = flightDirection(pv, *it);
434  dir = dir.unit();
435  fastjet::PseudoJet p(dir.x(),dir.y(),dir.z(),dir.mag()); // using SV flight direction so treating SV as massless
436  if( useSVMomentum )
437  p = fastjet::PseudoJet(it->p4().px(),it->p4().py(),it->p4().pz(),it->p4().energy());
438  p*=ghostRescaling; // rescale SV direction/momentum
439  p.set_user_info(new VertexInfo( it - extSecVertex->begin() ));
440  fjInputs.push_back(p);
441  }
442 
443  // define jet clustering sequence
444  fjClusterSeq = ClusterSequencePtr( new fastjet::ClusterSequence( fjInputs, *fjJetDefinition ) );
445  // recluster jet constituents and inserted "ghosts"
446  std::vector<fastjet::PseudoJet> inclusiveJets = fastjet::sorted_by_pt( fjClusterSeq->inclusive_jets(jetPtMin) );
447 
448  if( useFatJets )
449  {
450  if( inclusiveJets.size() < fatJetsHandle->size() )
451  edm::LogError("TooFewReclusteredJets") << "There are fewer reclustered (" << inclusiveJets.size() << ") than original fat jets (" << fatJetsHandle->size() << "). Please check that the jet algorithm and jet size match those used for the original jet collection.";
452 
453  // match reclustered and original fat jets
454  std::vector<int> reclusteredIndices;
455  matchReclusteredJets<edm::View<reco::Jet> >(fatJetsHandle,inclusiveJets,reclusteredIndices,"fat");
456 
457  // match groomed and original fat jets
458  std::vector<int> groomedIndices;
459  if( useGroomedFatJets )
460  matchGroomedJets(fatJetsHandle,groomedFatJetsHandle,groomedIndices);
461 
462  // match subjets and original fat jets
463  std::vector<std::vector<int> > subjetIndices;
464  if( useGroomedFatJets )
465  matchSubjets(groomedIndices,groomedFatJetsHandle,trackIPTagInfos,subjetIndices);
466  else
467  matchSubjets(fatJetsHandle,trackIPTagInfos,subjetIndices);
468 
469  // collect clustered SVs
470  for(size_t i=0; i<fatJetsHandle->size(); ++i)
471  {
472  if( reclusteredIndices.at(i) < 0 ) continue; // continue if matching reclustered to original jets failed
473 
474  if( fatJetsHandle->at(i).pt() == 0 ) // continue if the original jet has Pt=0
475  {
476  edm::LogWarning("NullTransverseMomentum") << "The original fat jet " << i << " has Pt=0. This is not expected so the jet will be skipped.";
477  continue;
478  }
479 
480  if( subjetIndices.at(i).empty() ) continue; // continue if the original jet does not have subjets assigned
481 
482  // since the "ghosts" are extremely soft, the configuration and ordering of the reclustered and original fat jets should in principle stay the same
483  if( ( std::abs( inclusiveJets.at(reclusteredIndices.at(i)).pt() - fatJetsHandle->at(i).pt() ) / fatJetsHandle->at(i).pt() ) > relPtTolerance )
484  {
485  if( fatJetsHandle->at(i).pt() < 10. ) // special handling for low-Pt jets (Pt<10 GeV)
486  edm::LogWarning("JetPtMismatchAtLowPt") << "The reclustered and original fat jet " << i << " have different Pt's (" << inclusiveJets.at(reclusteredIndices.at(i)).pt() << " vs " << fatJetsHandle->at(i).pt() << " GeV, respectively).\n"
487  << "Please check that the jet algorithm and jet size match those used for the original fat jet collection and also make sure the original fat jets are uncorrected. In addition, make sure you are not using CaloJets which are presently not supported.\n"
488  << "Since the mismatch is at low Pt, it is ignored and only a warning is issued.\n"
489  << "\nIn extremely rare instances the mismatch could be caused by a difference in the machine precision in which case make sure the original jet collection is produced and reclustering is performed in the same job.";
490  else
491  edm::LogError("JetPtMismatch") << "The reclustered and original fat jet " << i << " have different Pt's (" << inclusiveJets.at(reclusteredIndices.at(i)).pt() << " vs " << fatJetsHandle->at(i).pt() << " GeV, respectively).\n"
492  << "Please check that the jet algorithm and jet size match those used for the original fat jet collection and also make sure the original fat jets are uncorrected. In addition, make sure you are not using CaloJets which are presently not supported.\n"
493  << "\nIn extremely rare instances the mismatch could be caused by a difference in the machine precision in which case make sure the original jet collection is produced and reclustering is performed in the same job.";
494  }
495 
496  // get jet constituents
497  std::vector<fastjet::PseudoJet> constituents = inclusiveJets.at(reclusteredIndices.at(i)).constituents();
498 
499  std::vector<int> svIndices;
500  // loop over jet constituents and try to find "ghosts"
501  for(std::vector<fastjet::PseudoJet>::const_iterator it = constituents.begin(); it != constituents.end(); ++it)
502  {
503  if( !it->has_user_info() ) continue; // skip if not a "ghost"
504 
505  svIndices.push_back( it->user_info<VertexInfo>().vertexIndex() );
506  }
507 
508  // loop over clustered SVs and assign them to different subjets based on smallest dR
509  for(size_t sv=0; sv<svIndices.size(); ++sv)
510  {
511  const reco::Vertex &pv = *(trackIPTagInfos->front().primaryVertex());
512  const VTX &extSV = (*extSecVertex)[ svIndices.at(sv) ];
513  GlobalVector dir = flightDirection(pv, extSV);
514  dir = dir.unit();
515  fastjet::PseudoJet p(dir.x(),dir.y(),dir.z(),dir.mag()); // using SV flight direction so treating SV as massless
516  if( useSVMomentum )
517  p = fastjet::PseudoJet(extSV.p4().px(),extSV.p4().py(),extSV.p4().pz(),extSV.p4().energy());
518 
519  std::vector<double> dR2toSubjets;
520 
521  for(size_t sj=0; sj<subjetIndices.at(i).size(); ++sj)
522  dR2toSubjets.push_back( Geom::deltaR2( p.rapidity(), p.phi_std(), trackIPTagInfos->at(subjetIndices.at(i).at(sj)).jet()->rapidity(), trackIPTagInfos->at(subjetIndices.at(i).at(sj)).jet()->phi() ) );
523 
524  // find the closest subjet
525  int closestSubjetIdx = std::distance( dR2toSubjets.begin(), std::min_element(dR2toSubjets.begin(), dR2toSubjets.end()) );
526 
527  clusteredSVs.at(subjetIndices.at(i).at(closestSubjetIdx)).push_back( svIndices.at(sv) );
528  }
529  }
530  }
531  else
532  {
533  if( inclusiveJets.size() < trackIPTagInfos->size() )
534  edm::LogError("TooFewReclusteredJets") << "There are fewer reclustered (" << inclusiveJets.size() << ") than original jets (" << trackIPTagInfos->size() << "). Please check that the jet algorithm and jet size match those used for the original jet collection.";
535 
536  // match reclustered and original jets
537  std::vector<int> reclusteredIndices;
538  matchReclusteredJets<std::vector<IPTI> >(trackIPTagInfos,inclusiveJets,reclusteredIndices);
539 
540  // collect clustered SVs
541  for(size_t i=0; i<trackIPTagInfos->size(); ++i)
542  {
543  if( reclusteredIndices.at(i) < 0 ) continue; // continue if matching reclustered to original jets failed
544 
545  if( trackIPTagInfos->at(i).jet()->pt() == 0 ) // continue if the original jet has Pt=0
546  {
547  edm::LogWarning("NullTransverseMomentum") << "The original jet " << i << " has Pt=0. This is not expected so the jet will be skipped.";
548  continue;
549  }
550 
551  // since the "ghosts" are extremely soft, the configuration and ordering of the reclustered and original jets should in principle stay the same
552  if( ( std::abs( inclusiveJets.at(reclusteredIndices.at(i)).pt() - trackIPTagInfos->at(i).jet()->pt() ) / trackIPTagInfos->at(i).jet()->pt() ) > relPtTolerance )
553  {
554  if( trackIPTagInfos->at(i).jet()->pt() < 10. ) // special handling for low-Pt jets (Pt<10 GeV)
555  edm::LogWarning("JetPtMismatchAtLowPt") << "The reclustered and original jet " << i << " have different Pt's (" << inclusiveJets.at(reclusteredIndices.at(i)).pt() << " vs " << trackIPTagInfos->at(i).jet()->pt() << " GeV, respectively).\n"
556  << "Please check that the jet algorithm and jet size match those used for the original jet collection and also make sure the original jets are uncorrected. In addition, make sure you are not using CaloJets which are presently not supported.\n"
557  << "Since the mismatch is at low Pt, it is ignored and only a warning is issued.\n"
558  << "\nIn extremely rare instances the mismatch could be caused by a difference in the machine precision in which case make sure the original jet collection is produced and reclustering is performed in the same job.";
559  else
560  edm::LogError("JetPtMismatch") << "The reclustered and original jet " << i << " have different Pt's (" << inclusiveJets.at(reclusteredIndices.at(i)).pt() << " vs " << trackIPTagInfos->at(i).jet()->pt() << " GeV, respectively).\n"
561  << "Please check that the jet algorithm and jet size match those used for the original jet collection and also make sure the original jets are uncorrected. In addition, make sure you are not using CaloJets which are presently not supported.\n"
562  << "\nIn extremely rare instances the mismatch could be caused by a difference in the machine precision in which case make sure the original jet collection is produced and reclustering is performed in the same job.";
563  }
564 
565  // get jet constituents
566  std::vector<fastjet::PseudoJet> constituents = inclusiveJets.at(reclusteredIndices.at(i)).constituents();
567 
568  // loop over jet constituents and try to find "ghosts"
569  for(std::vector<fastjet::PseudoJet>::const_iterator it = constituents.begin(); it != constituents.end(); ++it)
570  {
571  if( !it->has_user_info() ) continue; // skip if not a "ghost"
572  // push back clustered SV indices
573  clusteredSVs.at(i).push_back( it->user_info<VertexInfo>().vertexIndex() );
574  }
575  }
576  }
577  }
578  // case where fat jets are used to associate SVs to subjets but no SV clustering is performed
579  else if( useExternalSV && !useSVClustering && !trackIPTagInfos->empty() && useFatJets )
580  {
581  // match groomed and original fat jets
582  std::vector<int> groomedIndices;
583  if( useGroomedFatJets )
584  matchGroomedJets(fatJetsHandle,groomedFatJetsHandle,groomedIndices);
585 
586  // match subjets and original fat jets
587  std::vector<std::vector<int> > subjetIndices;
588  if( useGroomedFatJets )
589  matchSubjets(groomedIndices,groomedFatJetsHandle,trackIPTagInfos,subjetIndices);
590  else
591  matchSubjets(fatJetsHandle,trackIPTagInfos,subjetIndices);
592 
593  // loop over fat jets
594  for(size_t i=0; i<fatJetsHandle->size(); ++i)
595  {
596  if( fatJetsHandle->at(i).pt() == 0 ) // continue if the original jet has Pt=0
597  {
598  edm::LogWarning("NullTransverseMomentum") << "The original fat jet " << i << " has Pt=0. This is not expected so the jet will be skipped.";
599  continue;
600  }
601 
602  if( subjetIndices.at(i).empty() ) continue; // continue if the original jet does not have subjets assigned
603 
604  // loop over SVs, associate them to fat jets based on dR cone and
605  // then assign them to the closets subjet in dR
606  for(typename edm::View<VTX>::const_iterator it = extSecVertex->begin(); it != extSecVertex->end(); ++it)
607  {
608  size_t sv = ( it - extSecVertex->begin() );
609 
610  const reco::Vertex &pv = *(trackIPTagInfos->front().primaryVertex());
611  const VTX &extSV = (*extSecVertex)[sv];
612  GlobalVector dir = flightDirection(pv, extSV);
613  GlobalVector jetDir(fatJetsHandle->at(i).px(),
614  fatJetsHandle->at(i).py(),
615  fatJetsHandle->at(i).pz());
616  // skip SVs outside the dR cone
617  if( Geom::deltaR2( dir, jetDir ) > rParam*rParam ) // here using the jet clustering rParam as a dR cut
618  continue;
619 
620  dir = dir.unit();
621  fastjet::PseudoJet p(dir.x(),dir.y(),dir.z(),dir.mag()); // using SV flight direction so treating SV as massless
622  if( useSVMomentum )
623  p = fastjet::PseudoJet(extSV.p4().px(),extSV.p4().py(),extSV.p4().pz(),extSV.p4().energy());
624 
625  std::vector<double> dR2toSubjets;
626 
627  for(size_t sj=0; sj<subjetIndices.at(i).size(); ++sj)
628  dR2toSubjets.push_back( Geom::deltaR2( p.rapidity(), p.phi_std(), trackIPTagInfos->at(subjetIndices.at(i).at(sj)).jet()->rapidity(), trackIPTagInfos->at(subjetIndices.at(i).at(sj)).jet()->phi() ) );
629 
630  // find the closest subjet
631  int closestSubjetIdx = std::distance( dR2toSubjets.begin(), std::min_element(dR2toSubjets.begin(), dR2toSubjets.end()) );
632 
633  clusteredSVs.at(subjetIndices.at(i).at(closestSubjetIdx)).push_back(sv);
634  }
635  }
636  }
637  // ------------------------------------ SV clustering END ----------------------------------------------
638 
639  std::unique_ptr<ConfigurableVertexReconstructor> vertexReco;
640  std::unique_ptr<GhostTrackVertexFinder> vertexRecoGT;
641  if (useGhostTrack)
642  vertexRecoGT.reset(new GhostTrackVertexFinder(
643  vtxRecoPSet.getParameter<double>("maxFitChi2"),
644  vtxRecoPSet.getParameter<double>("mergeThreshold"),
645  vtxRecoPSet.getParameter<double>("primcut"),
646  vtxRecoPSet.getParameter<double>("seccut"),
648  else
649  vertexReco.reset(
651 
652  TransientTrackMap primariesMap;
653 
654  // result secondary vertices
655 
656  auto tagInfos = std::make_unique<Product>();
657 
658  for(typename std::vector<IPTI>::const_iterator iterJets =
659  trackIPTagInfos->begin(); iterJets != trackIPTagInfos->end();
660  ++iterJets) {
661  TrackDataVector trackData;
662 // std::cout << "Jet " << iterJets-trackIPTagInfos->begin() << std::endl;
663 
664  const Vertex &pv = *iterJets->primaryVertex();
665 
666  std::set<TransientTrack> primaries;
668  for(Vertex::trackRef_iterator iter = pv.tracks_begin();
669  iter != pv.tracks_end(); ++iter) {
670  TransientTrackMap::iterator pos =
671  primariesMap.lower_bound(iter->get());
672 
673  if (pos != primariesMap.end() &&
674  pos->first == iter->get())
675  primaries.insert(pos->second);
676  else {
678  trackBuilder->build(
679  iter->castTo<TrackRef>());
680  primariesMap.insert(pos,
681  std::make_pair(iter->get(), track));
682  primaries.insert(track);
683  }
684  }
685  }
686 
687  edm::RefToBase<Jet> jetRef = iterJets->jet();
688 
689  GlobalVector jetDir(jetRef->momentum().x(),
690  jetRef->momentum().y(),
691  jetRef->momentum().z());
692 
693  std::vector<std::size_t> indices =
694  iterJets->sortedIndexes(sortCriterium);
695 
696  input_container trackRefs = iterJets->sortedTracks(indices);
697 
698  const std::vector<reco::btag::TrackIPData> &ipData =
699  iterJets->impactParameterData();
700 
701  // build transient tracks used for vertex reconstruction
702 
703  std::vector<TransientTrack> fitTracks;
704  std::vector<GhostTrackState> gtStates;
705  std::unique_ptr<GhostTrackPrediction> gtPred;
706  if (useGhostTrack)
707  gtPred.reset(new GhostTrackPrediction(
708  *iterJets->ghostTrack()));
709 
710  for(unsigned int i = 0; i < indices.size(); i++) {
712 
713  const input_item &trackRef = trackRefs[i];
714 
715  trackData.push_back(IndexedTrackData());
716  trackData.back().first = indices[i];
717 
718  // select tracks for SV finder
719 
720  if (!trackSelector(*reco::btag::toTrack(trackRef), ipData[indices[i]], *jetRef,
722  pv.position()))) {
723  trackData.back().second.svStatus =
725  continue;
726  }
727 
728  TransientTrackMap::const_iterator pos =
729  primariesMap.find(reco::btag::toTrack((trackRef)));
730  TransientTrack fitTrack;
731  if (pos != primariesMap.end()) {
732  primaries.erase(pos->second);
733  fitTrack = pos->second;
734  } else
735  fitTrack = trackBuilder->build(trackRef);
736  fitTracks.push_back(fitTrack);
737 
738  trackData.back().second.svStatus =
740 
741  if (useGhostTrack) {
742  GhostTrackState gtState(fitTrack);
743  GlobalPoint pos =
744  ipData[indices[i]].closestToGhostTrack;
745  gtState.linearize(*gtPred, true,
746  gtPred->lambda(pos));
747  gtState.setWeight(ipData[indices[i]].ghostTrackWeight);
748  gtStates.push_back(gtState);
749  }
750  }
751 
752  std::unique_ptr<GhostTrack> ghostTrack;
753  if (useGhostTrack)
754  ghostTrack.reset(new GhostTrack(
758  GlobalVector(
759  iterJets->ghostTrack()->px(),
760  iterJets->ghostTrack()->py(),
761  iterJets->ghostTrack()->pz()),
762  0.05),
763  *gtPred, gtStates,
764  iterJets->ghostTrack()->chi2(),
765  iterJets->ghostTrack()->ndof()));
766 
767  // perform actual vertex finding
768 
769 
770  std::vector<VTX> extAssoCollection;
771  std::vector<TransientVertex> fittedSVs;
772  std::vector<SecondaryVertex> SVs;
773  if(!useExternalSV){
774  switch(constraint) {
775  case CONSTRAINT_NONE:
776  if (useGhostTrack)
777  fittedSVs = vertexRecoGT->vertices(
778  pv, *ghostTrack);
779  else
780  fittedSVs = vertexReco->vertices(fitTracks);
781  break;
782 
783  case CONSTRAINT_BEAMSPOT:
784  if (useGhostTrack)
785  fittedSVs = vertexRecoGT->vertices(
786  pv, *beamSpot, *ghostTrack);
787  else
788  fittedSVs = vertexReco->vertices(fitTracks,
789  *beamSpot);
790  break;
791 
796  for(unsigned int i = 0; i < 7; i++) {
797  unsigned int covSrc = bsCovSrc[i];
798  for(unsigned int j = 0; j < 7; j++) {
799  double v=0.0;
800  if (!covSrc || bsCovSrc[j] != covSrc)
801  v = 0.0;
802  else if (covSrc == 1)
803  v = beamSpot->covariance(i, j);
804  else if (j<3 && i<3)
805  v = pv.covariance(i, j) *
807  cov(i, j) = v;
808  }
809  }
810 
811  BeamSpot bs(pv.position(), sigmaZ,
812  beamSpot.isValid() ? beamSpot->dxdz() : 0.,
813  beamSpot.isValid() ? beamSpot->dydz() : 0.,
814  beamWidth, cov, BeamSpot::Unknown);
815 
816  if (useGhostTrack)
817  fittedSVs = vertexRecoGT->vertices(
818  pv, bs, *ghostTrack);
819  else
820  fittedSVs = vertexReco->vertices(fitTracks, bs);
821  } break;
822 
824  std::vector<TransientTrack> primaries_(
825  primaries.begin(), primaries.end());
826  if (useGhostTrack)
827  fittedSVs = vertexRecoGT->vertices(
828  pv, *beamSpot, primaries_,
829  *ghostTrack);
830  else
831  fittedSVs = vertexReco->vertices(
832  primaries_, fitTracks,
833  *beamSpot);
834  } break;
835  }
836  // build combined SV information and filter
837  SVBuilder svBuilder(pv, jetDir, withPVError, minTrackWeight);
838  std::remove_copy_if(boost::make_transform_iterator(
839  fittedSVs.begin(), svBuilder),
840  boost::make_transform_iterator(
841  fittedSVs.end(), svBuilder),
842  std::back_inserter(SVs),
843  SVFilter(vertexFilter, pv, jetDir));
844 
845  }else{
846  if( useSVClustering || useFatJets ) {
847  size_t jetIdx = ( iterJets - trackIPTagInfos->begin() );
848 
849  for(size_t iExtSv = 0; iExtSv < clusteredSVs.at(jetIdx).size(); iExtSv++){
850  const VTX & extVertex = (*extSecVertex)[ clusteredSVs.at(jetIdx).at(iExtSv) ];
851  if( extVertex.p4().M() < 0.3 )
852  continue;
853  extAssoCollection.push_back( extVertex );
854  }
855  }
856  else {
857  for(size_t iExtSv = 0; iExtSv < extSecVertex->size(); iExtSv++){
858  const VTX & extVertex = (*extSecVertex)[iExtSv];
859  if( Geom::deltaR2( ( position(extVertex) - pv.position() ), (extSVDeltaRToJet > 0) ? jetDir : -jetDir ) > extSVDeltaRToJet*extSVDeltaRToJet || extVertex.p4().M() < 0.3 )
860  continue;
861  extAssoCollection.push_back( extVertex );
862 
863  }
864  }
865  // build combined SV information and filter
866  SVBuilder svBuilder(pv, jetDir, withPVError, minTrackWeight);
867  std::remove_copy_if(boost::make_transform_iterator( extAssoCollection.begin(), svBuilder),
868  boost::make_transform_iterator(extAssoCollection.end(), svBuilder),
869  std::back_inserter(SVs),
870  SVFilter(vertexFilter, pv, jetDir));
871  }
872  // clean up now unneeded collections
873  gtPred.reset();
874  ghostTrack.reset();
875  gtStates.clear();
876  fitTracks.clear();
877  fittedSVs.clear();
878  extAssoCollection.clear();
879 
880  // sort SVs by importance
881 
882  std::vector<unsigned int> vtxIndices = vertexSorting(SVs);
883 
884  std::vector<typename TemplatedSecondaryVertexTagInfo<IPTI,VTX>::VertexData> svData;
885 
886  svData.resize(vtxIndices.size());
887  for(unsigned int idx = 0; idx < vtxIndices.size(); idx++) {
888  const SecondaryVertex &sv = SVs[vtxIndices[idx]];
889 
890  svData[idx].vertex = sv;
891  svData[idx].dist1d = sv.dist1d();
892  svData[idx].dist2d = sv.dist2d();
893  svData[idx].dist3d = sv.dist3d();
894  svData[idx].direction = flightDirection(pv,sv);
895  // mark tracks successfully used in vertex fit
896  markUsedTracks(trackData,trackRefs,sv,idx);
897  }
898 
899  // fill result into tag infos
900 
901  tagInfos->push_back(
903  trackData, svData, SVs.size(),
905  iterJets - trackIPTagInfos->begin())));
906  }
907 
908  event.put(std::move(tagInfos));
909 }
910 
911 //Need specialized template because reco::Vertex iterators are TrackBase and it is a mess to make general
912 template <>
914 {
915  for(Vertex::trackRef_iterator iter = sv.tracks_begin(); iter != sv.tracks_end(); ++iter) {
916  if (sv.trackWeight(*iter) < minTrackWeight)
917  continue;
918 
919  typename input_container::const_iterator pos =
920  std::find(trackRefs.begin(), trackRefs.end(),
921  iter->castTo<input_item>());
922 
923  if (pos == trackRefs.end() ) {
924  if(!useExternalSV)
925  throw cms::Exception("TrackNotFound")
926  << "Could not find track from secondary "
927  "vertex in original tracks."
928  << std::endl;
929  } else {
930  unsigned int index = pos - trackRefs.begin();
931  trackData[index].second.svStatus =
933  ((unsigned int)btag::TrackData::trackAssociatedToVertex + idx);
934  }
935  }
936 }
937 template <>
939 {
940  for(typename input_container::const_iterator iter = sv.daughterPtrVector().begin(); iter != sv.daughterPtrVector().end(); ++iter)
941  {
942  typename input_container::const_iterator pos =
943  std::find(trackRefs.begin(), trackRefs.end(), *iter);
944 
945  if (pos != trackRefs.end() )
946  {
947  unsigned int index = pos - trackRefs.begin();
948  trackData[index].second.svStatus =
950  ((unsigned int)btag::TrackData::trackAssociatedToVertex + idx);
951  }
952  }
953 }
954 
955 
956 template <>
959 {
960  if(!sv.originalTracks().empty() && sv.originalTracks()[0].trackBaseRef().isNonnull())
961  return SecondaryVertex(pv, sv, direction, withPVError);
962  else
963  {
964  edm::LogError("UnexpectedInputs") << "Building from Candidates, should not happen!";
965  return SecondaryVertex(pv, sv, direction, withPVError);
966  }
967 }
968 
969 template <>
972 {
973  if(!sv.originalTracks().empty() && sv.originalTracks()[0].trackBaseRef().isNonnull())
974  {
975  edm::LogError("UnexpectedInputs") << "Building from Tracks, should not happen!";
976  VertexCompositePtrCandidate vtxCompPtrCand;
977 
978  vtxCompPtrCand.setCovariance(sv.vertexState().error().matrix());
979  vtxCompPtrCand.setChi2AndNdof(sv.totalChiSquared(), sv.degreesOfFreedom());
980  vtxCompPtrCand.setVertex(Candidate::Point(sv.position().x(),sv.position().y(),sv.position().z()));
981 
982  return SecondaryVertex(pv, vtxCompPtrCand, direction, withPVError);
983  }
984  else
985  {
986  VertexCompositePtrCandidate vtxCompPtrCand;
987 
988  vtxCompPtrCand.setCovariance(sv.vertexState().error().matrix());
989  vtxCompPtrCand.setChi2AndNdof(sv.totalChiSquared(), sv.degreesOfFreedom());
990  vtxCompPtrCand.setVertex(Candidate::Point(sv.position().x(),sv.position().y(),sv.position().z()));
991 
993  for(std::vector<reco::TransientTrack>::const_iterator tt = sv.originalTracks().begin(); tt != sv.originalTracks().end(); ++tt)
994  {
995  if (sv.trackWeight(*tt) < minTrackWeight)
996  continue;
997 
998  const CandidatePtrTransientTrack* cptt = dynamic_cast<const CandidatePtrTransientTrack*>(tt->basicTransientTrack());
999  if ( cptt==nullptr )
1000  edm::LogError("DynamicCastingFailed") << "Casting of TransientTrack to CandidatePtrTransientTrack failed!";
1001  else
1002  {
1003  p4 += cptt->candidate()->p4();
1004  vtxCompPtrCand.addDaughter(cptt->candidate());
1005  }
1006  }
1007  vtxCompPtrCand.setP4(p4);
1008 
1009  return SecondaryVertex(pv, vtxCompPtrCand, direction, withPVError);
1010  }
1011 }
1012 
1013 // ------------ method that matches reclustered and original jets based on minimum dR ------------
1014 template<class IPTI,class VTX>
1015 template<class CONTAINER>
1017  const std::vector<fastjet::PseudoJet>& reclusteredJets,
1018  std::vector<int>& matchedIndices,
1019  const std::string& jetType)
1020 {
1021  std::string type = ( !jetType.empty() ? jetType + " " : jetType );
1022 
1023  std::vector<bool> matchedLocks(reclusteredJets.size(),false);
1024 
1025  for(size_t j=0; j<jets->size(); ++j)
1026  {
1027  double matchedDR2 = 1e9;
1028  int matchedIdx = -1;
1029 
1030  for(size_t rj=0; rj<reclusteredJets.size(); ++rj)
1031  {
1032  if( matchedLocks.at(rj) ) continue; // skip jets that have already been matched
1033 
1034  double tempDR2 = Geom::deltaR2( toJet(jets->at(j))->rapidity(), toJet(jets->at(j))->phi(), reclusteredJets.at(rj).rapidity(), reclusteredJets.at(rj).phi_std() );
1035  if( tempDR2 < matchedDR2 )
1036  {
1037  matchedDR2 = tempDR2;
1038  matchedIdx = rj;
1039  }
1040  }
1041 
1042  if( matchedIdx>=0 )
1043  {
1044  if ( matchedDR2 > rParam*rParam )
1045  {
1046  edm::LogError("JetMatchingFailed") << "Matched reclustered jet " << matchedIdx << " and original " << type << "jet " << j <<" are separated by dR=" << sqrt(matchedDR2) << " which is greater than the jet size R=" << rParam << ".\n"
1047  << "This is not expected so please check that the jet algorithm and jet size match those used for the original " << type << "jet collection.";
1048  }
1049  else
1050  matchedLocks.at(matchedIdx) = true;
1051  }
1052  else
1053  edm::LogError("JetMatchingFailed") << "Matching reclustered to original " << type << "jets failed. Please check that the jet algorithm and jet size match those used for the original " << type << "jet collection.";
1054 
1055  matchedIndices.push_back(matchedIdx);
1056  }
1057 }
1058 
1059 // ------------ method that matches groomed and original jets based on minimum dR ------------
1060 template<class IPTI,class VTX>
1062  const edm::Handle<edm::View<reco::Jet> >& groomedJets,
1063  std::vector<int>& matchedIndices)
1064 {
1065  std::vector<bool> jetLocks(jets->size(),false);
1066  std::vector<int> jetIndices;
1067 
1068  for(size_t gj=0; gj<groomedJets->size(); ++gj)
1069  {
1070  double matchedDR2 = 1e9;
1071  int matchedIdx = -1;
1072 
1073  if( groomedJets->at(gj).pt()>0. ) // skip pathological cases of groomed jets with Pt=0
1074  {
1075  for(size_t j=0; j<jets->size(); ++j)
1076  {
1077  if( jetLocks.at(j) ) continue; // skip jets that have already been matched
1078 
1079  double tempDR2 = Geom::deltaR2( jets->at(j).rapidity(), jets->at(j).phi(), groomedJets->at(gj).rapidity(), groomedJets->at(gj).phi() );
1080  if( tempDR2 < matchedDR2 )
1081  {
1082  matchedDR2 = tempDR2;
1083  matchedIdx = j;
1084  }
1085  }
1086  }
1087 
1088  if( matchedIdx>=0 )
1089  {
1090  if ( matchedDR2 > rParam*rParam )
1091  {
1092  edm::LogWarning("MatchedJetsFarApart") << "Matched groomed jet " << gj << " and original jet " << matchedIdx <<" are separated by dR=" << sqrt(matchedDR2) << " which is greater than the jet size R=" << rParam << ".\n"
1093  << "This is not expected so the matching of these two jets has been discarded. Please check that the two jet collections belong to each other.";
1094  matchedIdx = -1;
1095  }
1096  else
1097  jetLocks.at(matchedIdx) = true;
1098  }
1099  jetIndices.push_back(matchedIdx);
1100  }
1101 
1102  for(size_t j=0; j<jets->size(); ++j)
1103  {
1104  std::vector<int>::iterator matchedIndex = std::find( jetIndices.begin(), jetIndices.end(), j );
1105 
1106  matchedIndices.push_back( matchedIndex != jetIndices.end() ? std::distance(jetIndices.begin(),matchedIndex) : -1 );
1107  }
1108 }
1109 
1110 // ------------ method that matches subjets and original fat jets ------------
1111 template<class IPTI,class VTX>
1112 void TemplatedSecondaryVertexProducer<IPTI,VTX>::matchSubjets(const std::vector<int>& groomedIndices,
1113  const edm::Handle<edm::View<reco::Jet> >& groomedJets,
1114  const edm::Handle<std::vector<IPTI> >& subjets,
1115  std::vector<std::vector<int> >& matchedIndices)
1116 {
1117  for(size_t g=0; g<groomedIndices.size(); ++g)
1118  {
1119  std::vector<int> subjetIndices;
1120 
1121  if( groomedIndices.at(g)>=0 )
1122  {
1123  for(size_t s=0; s<groomedJets->at(groomedIndices.at(g)).numberOfDaughters(); ++s)
1124  {
1125  const edm::Ptr<reco::Candidate> & subjet = groomedJets->at(groomedIndices.at(g)).daughterPtr(s);
1126 
1127  for(size_t sj=0; sj<subjets->size(); ++sj)
1128  {
1129  const edm::RefToBase<reco::Jet> &subjetRef = subjets->at(sj).jet();
1130  if( subjet == edm::Ptr<reco::Candidate>( subjetRef.id(), subjetRef.get(), subjetRef.key() ) )
1131  {
1132  subjetIndices.push_back(sj);
1133  break;
1134  }
1135  }
1136  }
1137 
1138  if( subjetIndices.empty() )
1139  edm::LogError("SubjetMatchingFailed") << "Matching subjets to original fat jets failed. Please check that the groomed fat jet and subjet collections belong to each other.";
1140 
1141  matchedIndices.push_back(subjetIndices);
1142  }
1143  else
1144  matchedIndices.push_back(subjetIndices);
1145  }
1146 }
1147 
1148 // ------------ method that matches subjets and original fat jets ------------
1149 template<class IPTI,class VTX>
1151  const edm::Handle<std::vector<IPTI> >& subjets,
1152  std::vector<std::vector<int> >& matchedIndices)
1153 {
1154  for(size_t fj=0; fj<fatJets->size(); ++fj)
1155  {
1156  std::vector<int> subjetIndices;
1157  size_t nSubjetCollections = 0;
1158  size_t nSubjets = 0;
1159 
1160  const pat::Jet * fatJet = dynamic_cast<const pat::Jet *>( fatJets->ptrAt(fj).get() );
1161 
1162  if( !fatJet )
1163  {
1164  if( fj==0 ) edm::LogError("WrongJetType") << "Wrong jet type for input fat jets. Please check that the input fat jets are of the pat::Jet type.";
1165 
1166  matchedIndices.push_back(subjetIndices);
1167  continue;
1168  }
1169  else
1170  {
1171  nSubjetCollections = fatJet->subjetCollectionNames().size();
1172 
1173  if( nSubjetCollections>0 )
1174  {
1175  for(size_t coll=0; coll<nSubjetCollections; ++coll)
1176  {
1177  const pat::JetPtrCollection & fatJetSubjets = fatJet->subjets(coll);
1178 
1179  for(size_t fjsj=0; fjsj<fatJetSubjets.size(); ++fjsj)
1180  {
1181  ++nSubjets;
1182 
1183  for(size_t sj=0; sj<subjets->size(); ++sj)
1184  {
1185  const pat::Jet * subJet = dynamic_cast<const pat::Jet *>( subjets->at(sj).jet().get() );
1186 
1187  if( !subJet )
1188  {
1189  if( fj==0 && coll==0 && fjsj==0 && sj==0 ) edm::LogError("WrongJetType") << "Wrong jet type for input subjets. Please check that the input subjets are of the pat::Jet type.";
1190 
1191  break;
1192  }
1193  else
1194  {
1195  if( subJet->originalObjectRef() == fatJetSubjets.at(fjsj)->originalObjectRef() )
1196  {
1197  subjetIndices.push_back(sj);
1198  break;
1199  }
1200  }
1201  }
1202  }
1203  }
1204 
1205  if( subjetIndices.empty() && nSubjets > 0)
1206  edm::LogError("SubjetMatchingFailed") << "Matching subjets to fat jets failed. Please check that the fat jet and subjet collections belong to each other.";
1207 
1208  matchedIndices.push_back(subjetIndices);
1209  }
1210  else
1211  matchedIndices.push_back(subjetIndices);
1212  }
1213  }
1214 }
1215 
1216 // ------------ method fills 'descriptions' with the allowed parameters for the module ------------
1217 template<class IPTI,class VTX>
1219 
1221  desc.add<double>("extSVDeltaRToJet",0.3);
1222  desc.add<edm::InputTag>("beamSpotTag",edm::InputTag("offlineBeamSpot"));
1223  {
1225  vertexReco.add<double>("primcut",1.8);
1226  vertexReco.add<double>("seccut",6.0);
1227  vertexReco.add<std::string>("finder","avr");
1228  vertexReco.addOptionalNode( edm::ParameterDescription<double>("minweight",0.5, true) and
1229  edm::ParameterDescription<double>("weightthreshold",0.001, true) and
1230  edm::ParameterDescription<bool>("smoothing",false, true), true );
1231  vertexReco.addOptionalNode( edm::ParameterDescription<double>("maxFitChi2",10.0, true) and
1232  edm::ParameterDescription<double>("mergeThreshold",3.0, true) and
1233  edm::ParameterDescription<std::string>("fitType","RefitGhostTrackWithVertices", true), true );
1234  desc.add<edm::ParameterSetDescription>("vertexReco",vertexReco);
1235  }
1236  {
1238  vertexSelection.add<std::string>("sortCriterium","dist3dError");
1239  desc.add<edm::ParameterSetDescription>("vertexSelection",vertexSelection);
1240  }
1241  desc.add<std::string>("constraint","BeamSpot");
1242  desc.add<edm::InputTag>("trackIPTagInfos",edm::InputTag("impactParameterTagInfos"));
1243  {
1245  vertexCuts.add<double>("distSig3dMax",99999.9);
1246  vertexCuts.add<double>("fracPV",0.65);
1247  vertexCuts.add<double>("distVal2dMax",2.5);
1248  vertexCuts.add<bool>("useTrackWeights",true);
1249  vertexCuts.add<double>("maxDeltaRToJetAxis",0.4);
1250  {
1252  v0Filter.add<double>("k0sMassWindow",0.05);
1253  vertexCuts.add<edm::ParameterSetDescription>("v0Filter",v0Filter);
1254  }
1255  vertexCuts.add<double>("distSig2dMin",3.0);
1256  vertexCuts.add<unsigned int>("multiplicityMin",2);
1257  vertexCuts.add<double>("distVal2dMin",0.01);
1258  vertexCuts.add<double>("distSig2dMax",99999.9);
1259  vertexCuts.add<double>("distVal3dMax",99999.9);
1260  vertexCuts.add<double>("minimumTrackWeight",0.5);
1261  vertexCuts.add<double>("distVal3dMin",-99999.9);
1262  vertexCuts.add<double>("massMax",6.5);
1263  vertexCuts.add<double>("distSig3dMin",-99999.9);
1264  desc.add<edm::ParameterSetDescription>("vertexCuts",vertexCuts);
1265  }
1266  desc.add<bool>("useExternalSV",false);
1267  desc.add<double>("minimumTrackWeight",0.5);
1268  desc.add<bool>("usePVError",true);
1269  {
1271  trackSelection.add<double>("b_pT",0.3684);
1272  trackSelection.add<double>("max_pT",500);
1273  trackSelection.add<bool>("useVariableJTA",false);
1274  trackSelection.add<double>("maxDecayLen",99999.9);
1275  trackSelection.add<double>("sip3dValMin",-99999.9);
1276  trackSelection.add<double>("max_pT_dRcut",0.1);
1277  trackSelection.add<double>("a_pT",0.005263);
1278  trackSelection.add<unsigned int>("totalHitsMin",8);
1279  trackSelection.add<double>("jetDeltaRMax",0.3);
1280  trackSelection.add<double>("a_dR",-0.001053);
1281  trackSelection.add<double>("maxDistToAxis",0.2);
1282  trackSelection.add<double>("ptMin",1.0);
1283  trackSelection.add<std::string>("qualityClass","any");
1284  trackSelection.add<unsigned int>("pixelHitsMin",2);
1285  trackSelection.add<double>("sip2dValMax",99999.9);
1286  trackSelection.add<double>("max_pT_trackPTcut",3);
1287  trackSelection.add<double>("sip2dValMin",-99999.9);
1288  trackSelection.add<double>("normChi2Max",99999.9);
1289  trackSelection.add<double>("sip3dValMax",99999.9);
1290  trackSelection.add<double>("sip3dSigMin",-99999.9);
1291  trackSelection.add<double>("min_pT",120);
1292  trackSelection.add<double>("min_pT_dRcut",0.5);
1293  trackSelection.add<double>("sip2dSigMax",99999.9);
1294  trackSelection.add<double>("sip3dSigMax",99999.9);
1295  trackSelection.add<double>("sip2dSigMin",-99999.9);
1296  trackSelection.add<double>("b_dR",0.6263);
1297  desc.add<edm::ParameterSetDescription>("trackSelection",trackSelection);
1298  }
1299  desc.add<std::string>("trackSort","sip3dSig");
1300  desc.add<edm::InputTag>("extSVCollection",edm::InputTag("secondaryVertices"));
1301  desc.addOptionalNode( edm::ParameterDescription<bool>("useSVClustering",false, true) and
1302  edm::ParameterDescription<std::string>("jetAlgorithm", true) and
1303  edm::ParameterDescription<double>("rParam", true), true );
1304  desc.addOptional<bool>("useSVMomentum",false);
1305  desc.addOptional<double>("ghostRescaling",1e-18);
1306  desc.addOptional<double>("relPtTolerance",1e-03);
1307  desc.addOptional<edm::InputTag>("fatJets");
1308  desc.addOptional<edm::InputTag>("groomedFatJets");
1309  descriptions.addDefault(desc);
1310 }
1311 
1312 //define this as a plug-in
1315 
1318 
std::shared_ptr< fastjet::JetDefinition > JetDefPtr
type
Definition: HCALResponse.h:21
math::Error< dimension >::type CovarianceMatrix
Definition: BeamSpot.h:31
reco::Vertex::Point convertPos(const GlobalPoint &p)
value_type const * get() const
Definition: RefToBase.h:234
T getParameter(std::string const &) const
edm::EDGetTokenT< edm::View< reco::Jet > > token_fatJets
const math::XYZPoint & position(const reco::Vertex &sv)
reco::btag::SortCriteria getCriterium(const std::string &name)
Definition: TrackSorting.cc:11
boost::shared_ptr< fastjet::JetDefinition > JetDefPtr
virtual double pz() const =0
z coordinate of momentum vector
TemplatedSecondaryVertex< reco::Vertex > SecondaryVertex
ParameterDescriptionBase * addOptional(U const &iLabel, T const &value)
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:161
trackRef_iterator tracks_end() const
last iterator over tracks
Definition: Vertex.cc:81
TemplatedSecondaryVertexProducer(const edm::ParameterSet &params)
void produce(edm::Event &event, const edm::EventSetup &es) override
edm::EDGetTokenT< reco::BeamSpot > token_BeamSpot
const AlgebraicSymMatrix33 matrix() const
double y() const
y coordinate
Definition: Vertex.h:113
Base class for all types of Jets.
Definition: Jet.h:20
float totalChiSquared() const
reco::Vertex::Error convertError(const GlobalError &ge)
Definition: ConvertError.h:8
reco::TransientTrack build(const reco::Track *p) const
T y() const
Definition: PV3DBase.h:63
bool exists(std::string const &parameterName) const
checks if a parameter exists
void setWeight(double weight)
SVFilter(const VertexFilter &filter, const Vertex &pv, const GlobalVector &direction)
double covariance(int i, int j) const
(i, j)-th element of error matrix, i, j = 0, ... 2
Definition: Vertex.h:130
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:20
const reco::Track * toTrack(const reco::TrackBaseRef &t)
Definition: IPTagInfo.h:24
const Point & position() const
position
Definition: Vertex.h:109
ProductID id() const
Definition: RefToBase.h:242
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
TemplatedSecondaryVertexProducer< TrackIPTagInfo, reco::Vertex > SecondaryVertexProducer
void setVertex(const Point &vertex) override
set vertex
static GhostTrackVertexFinder::FitType getGhostTrackFitType(const std::string &name)
void matchReclusteredJets(const edm::Handle< CONTAINER > &jets, const std::vector< fastjet::PseudoJet > &matchedJets, std::vector< int > &matchedIndices, const std::string &jetType="")
double dydz() const
dydz slope
Definition: BeamSpot.h:84
edm::EDGetTokenT< std::vector< IPTI > > token_trackIPTagInfo
IPTI::input_container::value_type input_item
virtual double energy() const =0
energy
virtual double py() const =0
y coordinate of momentum vector
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
T mag() const
Definition: PV3DBase.h:67
void addDefault(ParameterSetDescription const &psetDescription)
GlobalVector flightDirection(const reco::Vertex &pv, const reco::Vertex &sv)
std::vector< reco::TransientTrack > const & originalTracks() const
virtual const LorentzVector & p4() const =0
four-momentum Lorentz vector
float degreesOfFreedom() const
size_t key() const
Definition: RefToBase.h:250
T sqrt(T t)
Definition: SSEVec.h:18
double p4[4]
Definition: TauolaWrapper.h:92
GlobalPoint position() const
vector< PseudoJet > jets
std::vector< edm::Ptr< pat::Jet > > JetPtrCollection
Definition: Jet.h:77
T z() const
Definition: PV3DBase.h:64
const Point & vertex() const override
vertex position (overwritten by PF...)
boost::shared_ptr< fastjet::ClusterSequence > ClusterSequencePtr
def pv(vc)
Definition: MetAnalyzer.py:7
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double z() const
z coordinate
Definition: Vertex.h:115
ParameterDescriptionNode * addOptionalNode(ParameterDescriptionNode const &node, bool writeToCfi)
double BeamWidthX() const
beam width X
Definition: BeamSpot.h:86
VertexSorting< SecondaryVertex > vertexSorting
std::vector< std::string > const & subjetCollectionNames() const
Subjet collection names.
Definition: Jet.h:527
static ConstraintType getConstraintType(const std::string &name)
const edm::Ptr< reco::Candidate > & originalObjectRef() const
reference to original object. Returns a null reference if not available
Definition: PATObject.h:500
ParameterDescriptionBase * add(U const &iLabel, T const &value)
bool isValid() const
Definition: HandleBase.h:74
float trackWeight(const reco::TransientTrack &track) const
CandidatePtr candidate() const override
void matchGroomedJets(const edm::Handle< edm::View< reco::Jet > > &jets, const edm::Handle< edm::View< reco::Jet > > &matchedJets, std::vector< int > &matchedIndices)
void matchSubjets(const std::vector< int > &groomedIndices, const edm::Handle< edm::View< reco::Jet > > &groomedJets, const edm::Handle< std::vector< IPTI > > &subjets, std::vector< std::vector< int > > &matchedIndices)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
double dxdz() const
dxdz slope
Definition: BeamSpot.h:82
void markUsedTracks(TrackDataVector &trackData, const input_container &trackRefs, const SecondaryVertex &sv, size_t idx)
edm::EDGetTokenT< edm::View< VTX > > token_extSVCollection
Vector3DBase unit() const
Definition: Vector3DBase.h:57
SVBuilder(const reco::Vertex &pv, const GlobalVector &direction, bool withPVError, double minTrackWeight)
double x() const
x coordinate
Definition: Vertex.h:111
std::shared_ptr< fastjet::ClusterSequence > ClusterSequencePtr
constexpr auto deltaR2(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:16
JetCorrectorParametersCollection coll
Definition: classes.h:10
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
TemplatedSecondaryVertex< VTX > SecondaryVertex
edm::EDGetTokenT< edm::View< reco::Jet > > token_groomedFatJets
virtual double pt() const =0
transverse momentum
bool linearize(const GhostTrackPrediction &pred, bool initial=false, double lambda=0.)
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
double sigmaZ() const
sigma z
Definition: BeamSpot.h:80
Analysis-level calorimeter jet class.
Definition: Jet.h:80
SecondaryVertex operator()(const TransientVertex &sv) const
Error error() const
return SMatrix
Definition: Vertex.h:139
TemplatedSecondaryVertexProducer< CandIPTagInfo, reco::VertexCompositePtrCandidate > CandSecondaryVertexProducer
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:37
double covariance(int i, int j) const
(i,j)-th element of error matrix
Definition: BeamSpot.h:112
std::vector< reco::btag::IndexedTrackData > TrackDataVector
fixed size matrix
HLT enums.
boost::indirect_iterator< typename seq_t::const_iterator > const_iterator
Definition: View.h:86
std::vector< TemplatedSecondaryVertexTagInfo< IPTI, VTX > > Product
T get() const
Definition: EventSetup.h:71
void setCovariance(const CovarianceMatrix &m)
set covariance matrix
std::vector< TrackBaseRef >::const_iterator trackRef_iterator
The iteratator for the vector<TrackRef>
Definition: Vertex.h:37
void addDaughter(const CandidatePtr &)
add a daughter via a reference
math::XYZPoint Point
point in the space
Definition: Candidate.h:41
GlobalError error() const
Definition: VertexState.h:74
dbl *** dir
Definition: mlp_gen.cc:35
void setChi2AndNdof(double chi2, double ndof)
set chi2 and ndof
trackRef_iterator tracks_begin() const
first iterator over tracks
Definition: Vertex.cc:76
virtual double px() const =0
x coordinate of momentum vector
VertexState const & vertexState() const
T x() const
Definition: PV3DBase.h:62
pat::JetPtrCollection const & subjets(unsigned int index=0) const
Access to subjet list.
void setP4(const LorentzVector &p4) final
set 4-momentum
const reco::Jet * toJet(const reco::Jet &j)
def move(src, dest)
Definition: eostools.py:511
std::pair< unsigned int, TrackData > IndexedTrackData
Definition: event.py:1
Global3DVector GlobalVector
Definition: GlobalVector.h:10