11 #include <boost/iterator/transform_iterator.hpp>
61 #include "fastjet/JetDefinition.hh"
62 #include "fastjet/ClusterSequence.hh"
63 #include "fastjet/PseudoJet.hh"
69 typedef std::shared_ptr<fastjet::JetDefinition>
JetDefPtr;
74 class VertexInfo :
public fastjet::PseudoJet::UserInfoBase {
76 VertexInfo(
const int vertexIndex) : m_vertexIndex(vertexIndex) {}
78 inline const int vertexIndex()
const {
return m_vertexIndex; }
85 struct RefToBaseLess {
87 return r1.
id() < r2.
id() || (r1.
id() == r2.
id() && r1.
key() < r2.
key());
101 template <
class IPTI,
class VTX>
107 typedef std::vector<TemplatedSecondaryVertexTagInfo<IPTI, VTX> >
Product;
115 template <
class CONTAINER>
117 const std::vector<fastjet::PseudoJet> &matchedJets,
118 std::vector<int> &matchedIndices,
122 std::vector<int> &matchedIndices);
123 void matchSubjets(
const std::vector<int> &groomedIndices,
140 CONSTRAINT_PV_PRIMARIES_IN_FIT
183 : pv(pv), direction(direction), withPVError(withPVError), minTrackWeight(minTrackWeight) {}
196 : filter(filter), pv(pv), direction(direction) {}
205 template <
class IPTI,
class VTX>
209 return CONSTRAINT_NONE;
210 else if (name ==
"BeamSpot")
211 return CONSTRAINT_BEAMSPOT;
212 else if (name ==
"BeamSpot+PVPosition")
213 return CONSTRAINT_PV_BEAMSPOT_SIZE;
214 else if (name ==
"BeamSpotZ+PVErrorScaledXY")
215 return CONSTRAINT_PV_BS_Z_ERRORS_SCALED;
216 else if (name ==
"PVErrorScaled")
217 return CONSTRAINT_PV_ERROR_SCALED;
218 else if (name ==
"BeamSpot+PVTracksInFit")
219 return CONSTRAINT_PV_PRIMARIES_IN_FIT;
221 throw cms::Exception(
"InvalidArgument") <<
"TemplatedSecondaryVertexProducer: ``constraint'' parameter "
223 << name <<
"\" not understood." << std::endl;
227 if (name ==
"AlwaysWithGhostTrack")
229 else if (name ==
"SingleTracksWithGhostTrack")
231 else if (name ==
"RefitGhostTrackWithVertices")
234 throw cms::Exception(
"InvalidArgument") <<
"TemplatedSecondaryVertexProducer: ``fitType'' "
238 "GhostTrackVertexFinder settings not "
243 template <
class IPTI,
class VTX>
245 : sortCriterium(TrackSorting::
getCriterium(params.getParameter<std::
string>(
"trackSort"))),
247 constraint(getConstraintType(params.getParameter<std::
string>(
"constraint"))),
248 constraintScaling(1.0),
249 vtxRecoPSet(params.getParameter<edm::
ParameterSet>(
"vertexReco")),
250 useGhostTrack(vtxRecoPSet.getParameter<std::
string>(
"finder") ==
"gtvr"),
251 withPVError(params.getParameter<bool>(
"usePVError")),
252 minTrackWeight(params.getParameter<double>(
"minimumTrackWeight")),
253 vertexFilter(params.getParameter<edm::
ParameterSet>(
"vertexCuts")),
254 vertexSorting(params.getParameter<edm::
ParameterSet>(
"vertexSelection")) {
263 if (params.
existsAs<
bool>(
"useExternalSV"))
281 (params.
existsAs<
double>(
"relPtTolerance")
294 <<
", use CambridgeAachen | Kt | AntiKt" << std::endl;
297 esConsumes<TransientTrackBuilder, TransientTrackRecord>(
edm::ESInputTag(
"",
"TransientTrackBuilder"));
302 if (!srcWeights.
label().empty())
312 template <
class IPTI,
class VTX>
315 template <
class IPTI,
class VTX>
320 typedef std::map<const Track *, TransientTrack> TransientTrackMap;
325 event.getByToken(token_trackIPTagInfo, trackIPTagInfos);
330 event.getByToken(token_extSVCollection, extSecVertex);
335 event.getByToken(token_fatJets, fatJetsHandle);
336 if (useGroomedFatJets) {
337 event.getByToken(token_groomedFatJets, groomedFatJetsHandle);
339 if (groomedFatJetsHandle->size() > fatJetsHandle->size())
341 <<
"There are more groomed (" << groomedFatJetsHandle->size() <<
") than original fat jets ("
342 << fatJetsHandle->size() <<
"). Please check that the two jet collections belong to each other.";
346 if (!token_weights.isUninitialized())
347 event.
getByToken(token_weights, weightsHandle);
350 unsigned int bsCovSrc[7] = {
353 double sigmaZ = 0.0, beamWidth = 0.0;
355 case CONSTRAINT_PV_BEAMSPOT_SIZE:
356 event.getByToken(token_BeamSpot, beamSpot);
357 bsCovSrc[3] = bsCovSrc[4] = bsCovSrc[5] = bsCovSrc[6] = 1;
358 sigmaZ = beamSpot->sigmaZ();
359 beamWidth = beamSpot->BeamWidthX();
362 case CONSTRAINT_PV_BS_Z_ERRORS_SCALED:
363 event.getByToken(token_BeamSpot, beamSpot);
364 bsCovSrc[0] = bsCovSrc[1] = 2;
365 bsCovSrc[3] = bsCovSrc[4] = bsCovSrc[5] = 1;
366 sigmaZ = beamSpot->sigmaZ();
369 case CONSTRAINT_PV_ERROR_SCALED:
370 bsCovSrc[0] = bsCovSrc[1] = bsCovSrc[2] = 2;
373 case CONSTRAINT_BEAMSPOT:
374 case CONSTRAINT_PV_PRIMARIES_IN_FIT:
375 event.getByToken(token_BeamSpot, beamSpot);
383 std::vector<std::vector<int> > clusteredSVs(trackIPTagInfos->size(), std::vector<int>());
384 if (
useExternalSV && useSVClustering && !trackIPTagInfos->empty()) {
386 std::vector<fastjet::PseudoJet> fjInputs;
390 std::vector<edm::Ptr<reco::Candidate> > constituents = it->getJetConstituents();
391 std::vector<edm::Ptr<reco::Candidate> >::const_iterator
m;
392 for (m = constituents.begin(); m != constituents.end(); ++
m) {
394 if (constit->pt() == 0) {
395 edm::LogWarning(
"NullTransverseMomentum") <<
"dropping input candidate with pt=0";
398 if (it->isWeighted()) {
399 if (token_weights.isUninitialized())
401 <<
"TemplatedSecondaryVertexProducer: No weights (e.g. PUPPI) given for weighted jet collection"
403 float w = (*weightsHandle)[constit];
405 fastjet::PseudoJet(constit->px() *
w, constit->py() *
w, constit->pz() *
w, constit->energy() *
w));
407 fjInputs.push_back(fastjet::PseudoJet(constit->px(), constit->py(), constit->pz(), constit->energy()));
412 for (
typename std::vector<IPTI>::const_iterator it = trackIPTagInfos->begin(); it != trackIPTagInfos->end();
414 std::vector<edm::Ptr<reco::Candidate> > constituents = it->jet()->getJetConstituents();
415 std::vector<edm::Ptr<reco::Candidate> >::const_iterator
m;
416 for (m = constituents.begin(); m != constituents.end(); ++
m) {
418 if (constit->pt() == 0) {
419 edm::LogWarning(
"NullTransverseMomentum") <<
"dropping input candidate with pt=0";
422 if (it->jet()->isWeighted()) {
423 if (token_weights.isUninitialized())
425 <<
"TemplatedSecondaryVertexProducer: No weights (e.g. PUPPI) given for weighted jet collection"
427 float w = (*weightsHandle)[constit];
429 fastjet::PseudoJet(constit->px() *
w, constit->py() *
w, constit->pz() *
w, constit->energy() *
w));
431 fjInputs.push_back(fastjet::PseudoJet(constit->px(), constit->py(), constit->pz(), constit->energy()));
438 const reco::Vertex &
pv = *(trackIPTagInfos->front().primaryVertex());
441 fastjet::PseudoJet
p(
442 dir.
x(), dir.
y(), dir.
z(), dir.
mag());
444 p = fastjet::PseudoJet(it->p4().px(), it->p4().py(), it->p4().pz(), it->p4().energy());
446 p.set_user_info(
new VertexInfo(it - extSecVertex->begin()));
447 fjInputs.push_back(p);
451 fjClusterSeq = std::make_shared<fastjet::ClusterSequence>(fjInputs, *fjJetDefinition);
453 std::vector<fastjet::PseudoJet> inclusiveJets = fastjet::sorted_by_pt(fjClusterSeq->inclusive_jets(
jetPtMin));
456 if (inclusiveJets.size() < fatJetsHandle->size())
458 <<
"There are fewer reclustered (" << inclusiveJets.size() <<
") than original fat jets ("
459 << fatJetsHandle->size()
460 <<
"). Please check that the jet algorithm and jet size match those used for the original jet collection.";
463 std::vector<int> reclusteredIndices;
464 matchReclusteredJets<edm::View<reco::Jet> >(fatJetsHandle, inclusiveJets, reclusteredIndices,
"fat");
467 std::vector<int> groomedIndices;
468 if (useGroomedFatJets)
469 matchGroomedJets(fatJetsHandle, groomedFatJetsHandle, groomedIndices);
472 std::vector<std::vector<int> > subjetIndices;
473 if (useGroomedFatJets)
474 matchSubjets(groomedIndices, groomedFatJetsHandle, trackIPTagInfos, subjetIndices);
476 matchSubjets(fatJetsHandle, trackIPTagInfos, subjetIndices);
479 for (
size_t i = 0;
i < fatJetsHandle->size(); ++
i) {
480 if (reclusteredIndices.at(
i) < 0)
483 if (fatJetsHandle->at(
i).pt() == 0)
486 <<
"The original fat jet " <<
i <<
" has Pt=0. This is not expected so the jet will be skipped.";
490 if (subjetIndices.at(
i).empty())
494 if ((
std::abs(inclusiveJets.at(reclusteredIndices.at(
i)).
pt() - fatJetsHandle->at(
i).pt()) /
495 fatJetsHandle->at(
i).pt()) > relPtTolerance) {
496 if (fatJetsHandle->at(
i).pt() < 10.)
498 <<
"The reclustered and original fat jet " <<
i <<
" have different Pt's ("
499 << inclusiveJets.at(reclusteredIndices.at(
i)).
pt() <<
" vs " << fatJetsHandle->at(
i).pt()
500 <<
" GeV, respectively).\n"
501 <<
"Please check that the jet algorithm and jet size match those used for the original fat jet "
502 "collection and also make sure the original fat jets are uncorrected. In addition, make sure you "
503 "are not using CaloJets which are presently not supported.\n"
504 <<
"Since the mismatch is at low Pt, it is ignored and only a warning is issued.\n"
505 <<
"\nIn extremely rare instances the mismatch could be caused by a difference in the machine "
506 "precision in which case make sure the original jet collection is produced and reclustering is "
507 "performed in the same job.";
510 <<
"The reclustered and original fat jet " <<
i <<
" have different Pt's ("
511 << inclusiveJets.at(reclusteredIndices.at(
i)).
pt() <<
" vs " << fatJetsHandle->at(
i).pt()
512 <<
" GeV, respectively).\n"
513 <<
"Please check that the jet algorithm and jet size match those used for the original fat jet "
514 "collection and also make sure the original fat jets are uncorrected. In addition, make sure you "
515 "are not using CaloJets which are presently not supported.\n"
516 <<
"\nIn extremely rare instances the mismatch could be caused by a difference in the machine "
517 "precision in which case make sure the original jet collection is produced and reclustering is "
518 "performed in the same job.";
522 std::vector<fastjet::PseudoJet> constituents = inclusiveJets.at(reclusteredIndices.at(
i)).constituents();
524 std::vector<int> svIndices;
526 for (std::vector<fastjet::PseudoJet>::const_iterator it = constituents.begin(); it != constituents.end();
528 if (!it->has_user_info())
531 svIndices.push_back(it->user_info<VertexInfo>().vertexIndex());
535 for (
size_t sv = 0; sv < svIndices.size(); ++sv) {
536 const reco::Vertex &
pv = *(trackIPTagInfos->front().primaryVertex());
537 const VTX &extSV = (*extSecVertex)[svIndices.at(sv)];
540 fastjet::PseudoJet
p(
541 dir.
x(), dir.
y(), dir.
z(), dir.
mag());
543 p = fastjet::PseudoJet(extSV.p4().px(), extSV.p4().py(), extSV.p4().pz(), extSV.p4().energy());
545 std::vector<double> dR2toSubjets;
547 for (
size_t sj = 0; sj < subjetIndices.at(
i).size(); ++sj)
550 trackIPTagInfos->at(subjetIndices.at(
i).at(sj)).
jet()->rapidity(),
551 trackIPTagInfos->at(subjetIndices.at(
i).at(sj)).
jet()->phi()));
554 int closestSubjetIdx =
555 std::distance(dR2toSubjets.begin(), std::min_element(dR2toSubjets.begin(), dR2toSubjets.end()));
557 clusteredSVs.at(subjetIndices.at(
i).at(closestSubjetIdx)).push_back(svIndices.at(sv));
561 if (inclusiveJets.size() < trackIPTagInfos->size())
563 <<
"There are fewer reclustered (" << inclusiveJets.size() <<
") than original jets ("
564 << trackIPTagInfos->size()
565 <<
"). Please check that the jet algorithm and jet size match those used for the original jet collection.";
568 std::vector<int> reclusteredIndices;
569 matchReclusteredJets<std::vector<IPTI> >(
trackIPTagInfos, inclusiveJets, reclusteredIndices);
572 for (
size_t i = 0;
i < trackIPTagInfos->size(); ++
i) {
573 if (reclusteredIndices.at(
i) < 0)
576 if (trackIPTagInfos->at(
i).jet()->pt() == 0)
579 <<
"The original jet " <<
i <<
" has Pt=0. This is not expected so the jet will be skipped.";
584 if ((
std::abs(inclusiveJets.at(reclusteredIndices.at(
i)).
pt() - trackIPTagInfos->at(
i).jet()->pt()) /
585 trackIPTagInfos->at(
i).jet()->pt()) > relPtTolerance) {
586 if (trackIPTagInfos->at(
i).jet()->pt() < 10.)
588 <<
"The reclustered and original jet " <<
i <<
" have different Pt's ("
589 << inclusiveJets.at(reclusteredIndices.at(
i)).
pt() <<
" vs " << trackIPTagInfos->at(
i).jet()->pt()
590 <<
" GeV, respectively).\n"
591 <<
"Please check that the jet algorithm and jet size match those used for the original jet collection "
592 "and also make sure the original jets are uncorrected. In addition, make sure you are not using "
593 "CaloJets which are presently not supported.\n"
594 <<
"Since the mismatch is at low Pt, it is ignored and only a warning is issued.\n"
595 <<
"\nIn extremely rare instances the mismatch could be caused by a difference in the machine "
596 "precision in which case make sure the original jet collection is produced and reclustering is "
597 "performed in the same job.";
600 <<
"The reclustered and original jet " <<
i <<
" have different Pt's ("
601 << inclusiveJets.at(reclusteredIndices.at(
i)).
pt() <<
" vs " << trackIPTagInfos->at(
i).jet()->pt()
602 <<
" GeV, respectively).\n"
603 <<
"Please check that the jet algorithm and jet size match those used for the original jet collection "
604 "and also make sure the original jets are uncorrected. In addition, make sure you are not using "
605 "CaloJets which are presently not supported.\n"
606 <<
"\nIn extremely rare instances the mismatch could be caused by a difference in the machine "
607 "precision in which case make sure the original jet collection is produced and reclustering is "
608 "performed in the same job.";
612 std::vector<fastjet::PseudoJet> constituents = inclusiveJets.at(reclusteredIndices.at(
i)).constituents();
615 for (std::vector<fastjet::PseudoJet>::const_iterator it = constituents.begin(); it != constituents.end();
617 if (!it->has_user_info())
620 clusteredSVs.at(
i).push_back(it->user_info<VertexInfo>().vertexIndex());
626 else if (
useExternalSV && !useSVClustering && !trackIPTagInfos->empty() && useFatJets) {
628 std::vector<int> groomedIndices;
629 if (useGroomedFatJets)
630 matchGroomedJets(fatJetsHandle, groomedFatJetsHandle, groomedIndices);
633 std::vector<std::vector<int> > subjetIndices;
634 if (useGroomedFatJets)
635 matchSubjets(groomedIndices, groomedFatJetsHandle, trackIPTagInfos, subjetIndices);
637 matchSubjets(fatJetsHandle, trackIPTagInfos, subjetIndices);
640 for (
size_t i = 0;
i < fatJetsHandle->size(); ++
i) {
641 if (fatJetsHandle->at(
i).pt() == 0)
644 <<
"The original fat jet " <<
i <<
" has Pt=0. This is not expected so the jet will be skipped.";
648 if (subjetIndices.at(
i).empty())
654 size_t sv = (it - extSecVertex->begin());
656 const reco::Vertex &
pv = *(trackIPTagInfos->front().primaryVertex());
657 const VTX &extSV = (*extSecVertex)[sv];
659 GlobalVector jetDir(fatJetsHandle->at(
i).px(), fatJetsHandle->at(
i).py(), fatJetsHandle->at(
i).pz());
665 fastjet::PseudoJet
p(
666 dir.
x(), dir.
y(), dir.
z(), dir.
mag());
668 p = fastjet::PseudoJet(extSV.p4().px(), extSV.p4().py(), extSV.p4().pz(), extSV.p4().energy());
670 std::vector<double> dR2toSubjets;
672 for (
size_t sj = 0; sj < subjetIndices.at(
i).size(); ++sj)
675 trackIPTagInfos->at(subjetIndices.at(
i).at(sj)).
jet()->rapidity(),
676 trackIPTagInfos->at(subjetIndices.at(
i).at(sj)).
jet()->phi()));
679 int closestSubjetIdx =
680 std::distance(dR2toSubjets.begin(), std::min_element(dR2toSubjets.begin(), dR2toSubjets.end()));
682 clusteredSVs.at(subjetIndices.at(
i).at(closestSubjetIdx)).push_back(sv);
688 std::unique_ptr<ConfigurableVertexReconstructor>
vertexReco;
689 std::unique_ptr<GhostTrackVertexFinder> vertexRecoGT;
691 vertexRecoGT = std::make_unique<GhostTrackVertexFinder>(
692 vtxRecoPSet.getParameter<
double>(
"maxFitChi2"),
693 vtxRecoPSet.getParameter<
double>(
"mergeThreshold"),
694 vtxRecoPSet.getParameter<
double>(
"primcut"),
695 vtxRecoPSet.getParameter<
double>(
"seccut"),
698 vertexReco = std::make_unique<ConfigurableVertexReconstructor>(vtxRecoPSet);
700 TransientTrackMap primariesMap;
704 auto tagInfos = std::make_unique<Product>();
706 for (
typename std::vector<IPTI>::const_iterator iterJets = trackIPTagInfos->begin();
707 iterJets != trackIPTagInfos->end();
712 const Vertex &
pv = *iterJets->primaryVertex();
714 std::set<TransientTrack> primaries;
715 if (
constraint == CONSTRAINT_PV_PRIMARIES_IN_FIT) {
717 TransientTrackMap::iterator pos = primariesMap.lower_bound(iter->get());
719 if (pos != primariesMap.end() && pos->first == iter->get())
720 primaries.insert(pos->second);
723 primariesMap.insert(pos, std::make_pair(iter->get(),
track));
724 primaries.insert(track);
731 GlobalVector jetDir(jetRef->momentum().x(), jetRef->momentum().y(), jetRef->momentum().z());
733 std::vector<std::size_t>
indices = iterJets->sortedIndexes(sortCriterium);
737 const std::vector<reco::btag::TrackIPData> &ipData = iterJets->impactParameterData();
741 std::vector<TransientTrack> fitTracks;
742 std::vector<GhostTrackState> gtStates;
743 std::unique_ptr<GhostTrackPrediction> gtPred;
745 gtPred = std::make_unique<GhostTrackPrediction>(*iterJets->ghostTrack());
747 for (
unsigned int i = 0;
i < indices.size();
i++) {
753 trackData.back().first = indices[
i];
763 TransientTrackMap::const_iterator pos = primariesMap.find(
reco::btag::toTrack((trackRef)));
765 if (pos != primariesMap.end()) {
766 primaries.erase(pos->second);
767 fitTrack = pos->second;
769 fitTrack = trackBuilder->build(trackRef);
770 fitTracks.push_back(fitTrack);
776 GlobalPoint pos = ipData[indices[
i]].closestToGhostTrack;
777 gtState.
linearize(*gtPred,
true, gtPred->lambda(pos));
778 gtState.
setWeight(ipData[indices[i]].ghostTrackWeight);
779 gtStates.push_back(gtState);
783 std::unique_ptr<GhostTrack> ghostTrack;
785 ghostTrack = std::make_unique<GhostTrack>(
789 GlobalVector(iterJets->ghostTrack()->px(), iterJets->ghostTrack()->py(), iterJets->ghostTrack()->pz()),
793 iterJets->ghostTrack()->chi2(),
794 iterJets->ghostTrack()->ndof());
798 std::vector<VTX> extAssoCollection;
799 std::vector<TransientVertex> fittedSVs;
800 std::vector<SecondaryVertex> SVs;
803 case CONSTRAINT_NONE:
805 fittedSVs = vertexRecoGT->vertices(pv, *ghostTrack);
807 fittedSVs = vertexReco->vertices(fitTracks);
810 case CONSTRAINT_BEAMSPOT:
812 fittedSVs = vertexRecoGT->vertices(pv, *beamSpot, *ghostTrack);
814 fittedSVs = vertexReco->vertices(fitTracks, *beamSpot);
817 case CONSTRAINT_PV_BEAMSPOT_SIZE:
818 case CONSTRAINT_PV_BS_Z_ERRORS_SCALED:
819 case CONSTRAINT_PV_ERROR_SCALED: {
821 for (
unsigned int i = 0;
i < 7;
i++) {
822 unsigned int covSrc = bsCovSrc[
i];
823 for (
unsigned int j = 0;
j < 7;
j++) {
825 if (!covSrc || bsCovSrc[
j] != covSrc)
827 else if (covSrc == 1)
828 v = beamSpot->covariance(
i,
j);
829 else if (
j < 3 &&
i < 3)
837 beamSpot.
isValid() ? beamSpot->dxdz() : 0.,
838 beamSpot.
isValid() ? beamSpot->dydz() : 0.,
844 fittedSVs = vertexRecoGT->vertices(pv,
bs, *ghostTrack);
846 fittedSVs = vertexReco->vertices(fitTracks,
bs);
849 case CONSTRAINT_PV_PRIMARIES_IN_FIT: {
850 std::vector<TransientTrack> primaries_(primaries.begin(), primaries.end());
852 fittedSVs = vertexRecoGT->vertices(pv, *beamSpot, primaries_, *ghostTrack);
854 fittedSVs = vertexReco->vertices(primaries_, fitTracks, *beamSpot);
858 SVBuilder svBuilder(pv, jetDir, withPVError, minTrackWeight);
859 std::remove_copy_if(boost::make_transform_iterator(fittedSVs.begin(), svBuilder),
860 boost::make_transform_iterator(fittedSVs.end(), svBuilder),
861 std::back_inserter(SVs),
862 SVFilter(vertexFilter, pv, jetDir));
865 if (useSVClustering || useFatJets) {
866 size_t jetIdx = (iterJets - trackIPTagInfos->begin());
868 for (
size_t iExtSv = 0; iExtSv < clusteredSVs.at(jetIdx).size(); iExtSv++) {
869 const VTX &extVertex = (*extSecVertex)[clusteredSVs.at(jetIdx).at(iExtSv)];
870 if (extVertex.p4().M() < 0.3)
872 extAssoCollection.push_back(extVertex);
875 for (
size_t iExtSv = 0; iExtSv < extSecVertex->size(); iExtSv++) {
876 const VTX &extVertex = (*extSecVertex)[iExtSv];
879 extVertex.p4().M() < 0.3)
881 extAssoCollection.push_back(extVertex);
885 SVBuilder svBuilder(pv, jetDir, withPVError, minTrackWeight);
886 std::remove_copy_if(boost::make_transform_iterator(extAssoCollection.begin(), svBuilder),
887 boost::make_transform_iterator(extAssoCollection.end(), svBuilder),
888 std::back_inserter(SVs),
889 SVFilter(vertexFilter, pv, jetDir));
897 extAssoCollection.clear();
901 std::vector<unsigned int> vtxIndices = vertexSorting(SVs);
903 std::vector<typename TemplatedSecondaryVertexTagInfo<IPTI, VTX>::VertexData> svData;
905 svData.resize(vtxIndices.size());
906 for (
unsigned int idx = 0; idx < vtxIndices.size(); idx++) {
909 svData[idx].vertex = sv;
911 svData[idx].dist2d = sv.
dist2d();
912 svData[idx].dist3d = sv.
dist3d();
915 markUsedTracks(trackData, trackRefs, sv, idx);
937 if (sv.trackWeight(*iter) < minTrackWeight)
940 typename input_container::const_iterator pos =
943 if (pos == trackRefs.end()) {
945 throw cms::Exception(
"TrackNotFound") <<
"Could not find track from secondary "
946 "vertex in original tracks."
949 unsigned int index = pos - trackRefs.begin();
950 trackData[
index].second.svStatus = (btag::TrackData::trackAssociatedToVertex + idx);
957 for (
typename input_container::const_iterator iter = sv.daughterPtrVector().begin();
958 iter != sv.daughterPtrVector().end();
960 typename input_container::const_iterator pos =
std::find(trackRefs.begin(), trackRefs.end(), *iter);
962 if (pos != trackRefs.end()) {
963 unsigned int index = pos - trackRefs.begin();
964 trackData[
index].second.svStatus = (btag::TrackData::trackAssociatedToVertex + idx);
975 edm::LogError(
"UnexpectedInputs") <<
"Building from Candidates, should not happen!";
985 edm::LogError(
"UnexpectedInputs") <<
"Building from Tracks, should not happen!";
1001 for (std::vector<reco::TransientTrack>::const_iterator
tt = sv.
originalTracks().begin();
1009 if (cptt ==
nullptr)
1010 edm::LogError(
"DynamicCastingFailed") <<
"Casting of TransientTrack to CandidatePtrTransientTrack failed!";
1016 vtxCompPtrCand.
setP4(p4);
1023 template <
class IPTI,
class VTX>
1024 template <
class CONTAINER>
1027 const std::vector<fastjet::PseudoJet> &reclusteredJets,
1028 std::vector<int> &matchedIndices,
1032 std::vector<bool> matchedLocks(reclusteredJets.size(),
false);
1034 for (
size_t j = 0;
j < jets->size(); ++
j) {
1035 double matchedDR2 = 1e9;
1036 int matchedIdx = -1;
1038 for (
size_t rj = 0; rj < reclusteredJets.size(); ++rj) {
1039 if (matchedLocks.at(rj))
1044 reclusteredJets.at(rj).rapidity(),
1045 reclusteredJets.at(rj).phi_std());
1046 if (tempDR2 < matchedDR2) {
1047 matchedDR2 = tempDR2;
1052 if (matchedIdx >= 0) {
1054 edm::LogError(
"JetMatchingFailed") <<
"Matched reclustered jet " << matchedIdx <<
" and original " << type
1055 <<
"jet " <<
j <<
" are separated by dR=" <<
sqrt(matchedDR2)
1056 <<
" which is greater than the jet size R=" << rParam <<
".\n"
1057 <<
"This is not expected so please check that the jet algorithm and jet "
1058 "size match those used for the original "
1059 << type <<
"jet collection.";
1061 matchedLocks.at(matchedIdx) =
true;
1064 <<
"Matching reclustered to original " << type
1065 <<
"jets failed. Please check that the jet algorithm and jet size match those used for the original " << type
1066 <<
"jet collection.";
1068 matchedIndices.push_back(matchedIdx);
1073 template <
class IPTI,
class VTX>
1076 std::vector<int> &matchedIndices) {
1077 std::vector<bool> jetLocks(
jets->size(),
false);
1078 std::vector<int> jetIndices;
1080 for (
size_t gj = 0; gj < groomedJets->size(); ++gj) {
1081 double matchedDR2 = 1e9;
1082 int matchedIdx = -1;
1084 if (groomedJets->at(gj).pt() > 0.)
1086 for (
size_t j = 0;
j <
jets->size(); ++
j) {
1091 jets->at(
j).rapidity(),
jets->at(
j).phi(), groomedJets->at(gj).rapidity(), groomedJets->at(gj).phi());
1092 if (tempDR2 < matchedDR2) {
1093 matchedDR2 = tempDR2;
1099 if (matchedIdx >= 0) {
1102 <<
"Matched groomed jet " << gj <<
" and original jet " << matchedIdx
1103 <<
" are separated by dR=" <<
sqrt(matchedDR2) <<
" which is greater than the jet size R=" << rParam
1105 <<
"This is not expected so the matching of these two jets has been discarded. Please check that the two "
1106 "jet collections belong to each other.";
1109 jetLocks.at(matchedIdx) =
true;
1111 jetIndices.push_back(matchedIdx);
1114 for (
size_t j = 0;
j <
jets->size(); ++
j) {
1115 std::vector<int>::iterator matchedIndex =
std::find(jetIndices.begin(), jetIndices.end(),
j);
1117 matchedIndices.push_back(matchedIndex != jetIndices.end() ?
std::distance(jetIndices.begin(), matchedIndex) : -1);
1122 template <
class IPTI,
class VTX>
1127 for (
size_t g = 0;
g < groomedIndices.size(); ++
g) {
1128 std::vector<int> subjetIndices;
1130 if (groomedIndices.at(
g) >= 0) {
1131 for (
size_t s = 0;
s < groomedJets->at(groomedIndices.at(
g)).numberOfDaughters(); ++
s) {
1134 for (
size_t sj = 0; sj < subjets->size(); ++sj) {
1137 subjetIndices.push_back(sj);
1143 if (subjetIndices.empty())
1144 edm::LogError(
"SubjetMatchingFailed") <<
"Matching subjets to original fat jets failed. Please check that the "
1145 "groomed fat jet and subjet collections belong to each other.";
1147 matchedIndices.push_back(subjetIndices);
1149 matchedIndices.push_back(subjetIndices);
1154 template <
class IPTI,
class VTX>
1158 for (
size_t fj = 0; fj < fatJets->size(); ++fj) {
1159 std::vector<int> subjetIndices;
1160 size_t nSubjetCollections = 0;
1161 size_t nSubjets = 0;
1163 const pat::Jet *fatJet =
dynamic_cast<const pat::Jet *
>(fatJets->ptrAt(fj).get());
1168 <<
"Wrong jet type for input fat jets. Please check that the input fat jets are of the pat::Jet type.";
1170 matchedIndices.push_back(subjetIndices);
1175 if (nSubjetCollections > 0) {
1176 for (
size_t coll = 0; coll < nSubjetCollections; ++coll) {
1179 for (
size_t fjsj = 0; fjsj < fatJetSubjets.size(); ++fjsj) {
1182 for (
size_t sj = 0; sj < subjets->size(); ++sj) {
1183 const pat::Jet *subJet =
dynamic_cast<const pat::Jet *
>(subjets->at(sj).jet().get());
1186 if (fj == 0 && coll == 0 && fjsj == 0 && sj == 0)
1187 edm::LogError(
"WrongJetType") <<
"Wrong jet type for input subjets. Please check that the input "
1188 "subjets are of the pat::Jet type.";
1192 if (subJet->
originalObjectRef() == fatJetSubjets.at(fjsj)->originalObjectRef()) {
1193 subjetIndices.push_back(sj);
1201 if (subjetIndices.empty() && nSubjets > 0)
1202 edm::LogError(
"SubjetMatchingFailed") <<
"Matching subjets to fat jets failed. Please check that the fat jet "
1203 "and subjet collections belong to each other.";
1205 matchedIndices.push_back(subjetIndices);
1207 matchedIndices.push_back(subjetIndices);
1213 template <
class IPTI,
class VTX>
1216 desc.
add<
double>(
"extSVDeltaRToJet", 0.3);
1220 vertexReco.
add<
double>(
"primcut", 1.8);
1221 vertexReco.
add<
double>(
"seccut", 6.0);
1236 vertexSelection.
add<
std::string>(
"sortCriterium",
"dist3dError");
1243 vertexCuts.
add<
double>(
"distSig3dMax", 99999.9);
1244 vertexCuts.
add<
double>(
"fracPV", 0.65);
1245 vertexCuts.
add<
double>(
"distVal2dMax", 2.5);
1246 vertexCuts.
add<
bool>(
"useTrackWeights",
true);
1247 vertexCuts.
add<
double>(
"maxDeltaRToJetAxis", 0.4);
1250 v0Filter.
add<
double>(
"k0sMassWindow", 0.05);
1253 vertexCuts.
add<
double>(
"distSig2dMin", 3.0);
1254 vertexCuts.
add<
unsigned int>(
"multiplicityMin", 2);
1255 vertexCuts.
add<
double>(
"distVal2dMin", 0.01);
1256 vertexCuts.
add<
double>(
"distSig2dMax", 99999.9);
1257 vertexCuts.
add<
double>(
"distVal3dMax", 99999.9);
1258 vertexCuts.
add<
double>(
"minimumTrackWeight", 0.5);
1259 vertexCuts.
add<
double>(
"distVal3dMin", -99999.9);
1260 vertexCuts.
add<
double>(
"massMax", 6.5);
1261 vertexCuts.
add<
double>(
"distSig3dMin", -99999.9);
1264 desc.
add<
bool>(
"useExternalSV",
false);
1265 desc.
add<
double>(
"minimumTrackWeight", 0.5);
1266 desc.
add<
bool>(
"usePVError",
true);
1269 trackSelection.
add<
double>(
"b_pT", 0.3684);
1270 trackSelection.
add<
double>(
"max_pT", 500);
1271 trackSelection.
add<
bool>(
"useVariableJTA",
false);
1272 trackSelection.
add<
double>(
"maxDecayLen", 99999.9);
1273 trackSelection.
add<
double>(
"sip3dValMin", -99999.9);
1274 trackSelection.
add<
double>(
"max_pT_dRcut", 0.1);
1275 trackSelection.
add<
double>(
"a_pT", 0.005263);
1276 trackSelection.
add<
unsigned int>(
"totalHitsMin", 8);
1277 trackSelection.
add<
double>(
"jetDeltaRMax", 0.3);
1278 trackSelection.
add<
double>(
"a_dR", -0.001053);
1279 trackSelection.
add<
double>(
"maxDistToAxis", 0.2);
1280 trackSelection.
add<
double>(
"ptMin", 1.0);
1282 trackSelection.
add<
unsigned int>(
"pixelHitsMin", 2);
1283 trackSelection.
add<
double>(
"sip2dValMax", 99999.9);
1284 trackSelection.
add<
double>(
"max_pT_trackPTcut", 3);
1285 trackSelection.
add<
double>(
"sip2dValMin", -99999.9);
1286 trackSelection.
add<
double>(
"normChi2Max", 99999.9);
1287 trackSelection.
add<
double>(
"sip3dValMax", 99999.9);
1288 trackSelection.
add<
double>(
"sip3dSigMin", -99999.9);
1289 trackSelection.
add<
double>(
"min_pT", 120);
1290 trackSelection.
add<
double>(
"min_pT_dRcut", 0.5);
1291 trackSelection.
add<
double>(
"sip2dSigMax", 99999.9);
1292 trackSelection.
add<
double>(
"sip3dSigMax", 99999.9);
1293 trackSelection.
add<
double>(
"sip2dSigMin", -99999.9);
1294 trackSelection.
add<
double>(
"b_dR", 0.6263);
std::shared_ptr< fastjet::JetDefinition > JetDefPtr
math::Error< dimension >::type CovarianceMatrix
reco::Vertex::Point convertPos(const GlobalPoint &p)
value_type const * get() const
edm::EDGetTokenT< edm::View< reco::Jet > > token_fatJets
edm::ESGetToken< TransientTrackBuilder, TransientTrackRecord > token_trackBuilder
reco::btag::SortCriteria getCriterium(const std::string &name)
TemplatedSecondaryVertex< reco::Vertex > SecondaryVertex
ParameterDescriptionBase * addOptional(U const &iLabel, T const &value)
TrackSelector trackSelector
bool existsAs(std::string const ¶meterName, bool trackiness=true) const
checks if a parameter exists as a given type
TemplatedSecondaryVertexProducer(const edm::ParameterSet ¶ms)
void produce(edm::Event &event, const edm::EventSetup &es) override
const GlobalVector & direction
bool getByToken(EDGetToken token, Handle< PROD > &result) const
ClusterSequencePtr fjClusterSeq
CandidatePtr candidate() const override
#define DEFINE_FWK_MODULE(type)
edm::EDGetTokenT< reco::BeamSpot > token_BeamSpot
const AlgebraicSymMatrix33 matrix() const
double y() const
y coordinate
Base class for all types of Jets.
float totalChiSquared() const
reco::Vertex::Error convertError(const GlobalError &ge)
Measurement1D dist3d() const
bool exists(std::string const ¶meterName) const
checks if a parameter exists
Measurement1D dist2d() const
void setWeight(double weight)
SVFilter(const VertexFilter &filter, const Vertex &pv, const GlobalVector &direction)
const Point & vertex() const override
vertex position (overwritten by PF...)
double covariance(int i, int j) const
(i, j)-th element of error matrix, i, j = 0, ... 2
VertexFilter vertexFilter
reco::btag::SortCriteria sortCriterium
Log< level::Error, false > LogError
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
const reco::Track * toTrack(const reco::TrackBaseRef &t)
const Point & position() const
position
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
TemplatedSecondaryVertexProducer< CandIPTagInfo, reco::VertexCompositePtrCandidate > CandSecondaryVertexProducer
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="")
ConstraintType constraint
edm::EDGetTokenT< std::vector< IPTI > > token_trackIPTagInfo
IPTI::input_container::value_type input_item
Container::value_type value_type
reco::btag::IndexedTrackData IndexedTrackData
void addDefault(ParameterSetDescription const &psetDescription)
std::vector< TemplatedSecondaryVertexTagInfo< IPTI, VTX > > Product
GlobalVector flightDirection(const reco::Vertex &pv, const reco::Vertex &sv)
std::vector< reco::TransientTrack > const & originalTracks() const
float degreesOfFreedom() const
const reco::Jet * toJet(const IPTI &j)
GlobalPoint position() const
std::vector< edm::Ptr< pat::Jet > > JetPtrCollection
edm::EDGetTokenT< edm::ValueMap< float > > token_weights
Abs< T >::type abs(const T &t)
trackRef_iterator tracks_end() const
last iterator over tracks
double z() const
z coordinate
Measurement1D dist1d() const
ParameterDescriptionNode * addOptionalNode(ParameterDescriptionNode const &node, bool writeToCfi)
VertexSorting< SecondaryVertex > vertexSorting
std::vector< std::string > const & subjetCollectionNames() const
Subjet collection names.
static ConstraintType getConstraintType(const std::string &name)
trackRef_iterator tracks_begin() const
first iterator over tracks
const edm::Ptr< reco::Candidate > & originalObjectRef() const
reference to original object. Returns a null reference if not available
ParameterDescriptionBase * add(U const &iLabel, T const &value)
float trackWeight(const reco::TransientTrack &track) const
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)
void markUsedTracks(TrackDataVector &trackData, const input_container &trackRefs, const SecondaryVertex &sv, size_t idx)
edm::EDGetTokenT< edm::View< VTX > > token_extSVCollection
Vector3DBase unit() const
SVBuilder(const reco::Vertex &pv, const GlobalVector &direction, bool withPVError, double minTrackWeight)
double x() const
x coordinate
std::shared_ptr< fastjet::ClusterSequence > ClusterSequencePtr
constexpr auto deltaR2(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
TemplatedSecondaryVertex< VTX > SecondaryVertex
edm::ParameterSet vtxRecoPSet
edm::EDGetTokenT< edm::View< reco::Jet > > token_groomedFatJets
bool linearize(const GhostTrackPrediction &pred, bool initial=false, double lambda=0.)
XYZPointD XYZPoint
point in space with cartesian internal representation
T getParameter(std::string const &) const
Analysis-level calorimeter jet class.
SecondaryVertex operator()(const TransientVertex &sv) const
Error error() const
return SMatrix
TemplatedSecondaryVertexProducer< TrackIPTagInfo, reco::Vertex > SecondaryVertexProducer
math::XYZTLorentzVector LorentzVector
Lorentz vector.
std::vector< reco::btag::IndexedTrackData > TrackDataVector
const GlobalVector & direction
boost::indirect_iterator< typename seq_t::const_iterator > const_iterator
static int position[264][3]
void setCovariance(const CovarianceMatrix &m)
set covariance matrix
void addDaughter(const CandidatePtr &)
add a daughter via a reference
const VertexFilter & filter
math::XYZPoint Point
point in the space
GlobalError error() const
void setChi2AndNdof(double chi2, double ndof)
set chi2 and ndof
ESHandle< T > getHandle(const ESGetToken< T, R > &iToken) const
Log< level::Warning, false > LogWarning
JetDefPtr fjJetDefinition
VertexState const & vertexState() const
~TemplatedSecondaryVertexProducer() override
bool operator()(const SecondaryVertex &sv) const
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)
std::vector< TrackBaseRef >::const_iterator trackRef_iterator
The iteratator for the vector<TrackRef>
SecondaryVertex operator()(const VTX &sv) const
std::pair< unsigned int, TrackData > IndexedTrackData
Global3DVector GlobalVector
IPTI::input_container input_container
tuple trackSelector
Tracks selection.