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 {
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) {}
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>
248 constraintScaling(1.0),
250 useGhostTrack(vtxRecoPSet.getParameter<
std::
string>(
"finder") ==
"gtvr"),
251 withPVError(
params.getParameter<
bool>(
"usePVError")),
252 minTrackWeight(
params.getParameter<double>(
"minimumTrackWeight")),
263 if (
params.existsAs<
bool>(
"useExternalSV"))
279 (
params.existsAs<
double>(
"ghostRescaling") ?
params.getParameter<
double>(
"ghostRescaling") : 1
e-18);
281 (
params.existsAs<
double>(
"relPtTolerance")
282 ?
params.getParameter<
double>(
"relPtTolerance")
294 <<
", use CambridgeAachen | Kt | AntiKt" << std::endl;
297 esConsumes<TransientTrackBuilder, TransientTrackRecord>(
edm::ESInputTag(
"",
"TransientTrackBuilder"));
312 template <
class IPTI,
class VTX>
315 template <
class IPTI,
class VTX>
320 typedef std::map<const Track *, TransientTrack> TransientTrackMap;
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;
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;
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>());
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()));
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()));
441 fastjet::PseudoJet
p(
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);
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) {
537 const VTX &extSV = (*extSecVertex)[svIndices.at(
sv)];
540 fastjet::PseudoJet
p(
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)
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));
563 <<
"There are fewer reclustered (" << inclusiveJets.size() <<
") than original jets ("
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);
573 if (reclusteredIndices.at(
i) < 0)
579 <<
"The original jet " <<
i <<
" has Pt=0. This is not expected so the jet will be skipped.";
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());
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);
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());
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(
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)
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();
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());
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];
765 if (
pos != primariesMap.end()) {
766 primaries.erase(
pos->second);
767 fitTrack =
pos->second;
769 fitTrack = trackBuilder->
build(trackRef);
770 fitTracks.push_back(fitTrack);
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);
810 case CONSTRAINT_BEAMSPOT:
812 fittedSVs = vertexRecoGT->vertices(
pv, *
beamSpot, *ghostTrack);
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)
829 else if (
j < 3 &&
i < 3)
830 v =
pv.covariance(
i,
j) * constraintScaling;
844 fittedSVs = vertexRecoGT->vertices(
pv,
bs, *ghostTrack);
849 case CONSTRAINT_PV_PRIMARIES_IN_FIT: {
850 std::vector<TransientTrack> primaries_(primaries.begin(), primaries.end());
852 fittedSVs = vertexRecoGT->vertices(
pv, *
beamSpot, primaries_, *ghostTrack);
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),
865 if (useSVClustering || useFatJets) {
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),
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;
910 svData[
idx].dist1d =
sv.dist1d();
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 =
958 for (
typename input_container::const_iterator iter =
sv.daughterPtrVector().begin();
959 iter !=
sv.daughterPtrVector().end();
961 typename input_container::const_iterator
pos =
std::find(trackRefs.begin(), trackRefs.end(), *iter);
963 if (
pos != trackRefs.end()) {
964 unsigned int index =
pos - trackRefs.begin();
965 trackData[
index].second.svStatus =
974 if (!
sv.originalTracks().empty() &&
sv.originalTracks()[0].trackBaseRef().isNonnull())
977 edm::LogError(
"UnexpectedInputs") <<
"Building from Candidates, should not happen!";
986 if (!
sv.originalTracks().empty() &&
sv.originalTracks()[0].trackBaseRef().isNonnull()) {
987 edm::LogError(
"UnexpectedInputs") <<
"Building from Tracks, should not happen!";
1003 for (std::vector<reco::TransientTrack>::const_iterator
tt =
sv.originalTracks().begin();
1004 tt !=
sv.originalTracks().end();
1010 dynamic_cast<const CandidatePtrTransientTrack *>(
tt->basicTransientTrack());
1011 if (cptt ==
nullptr)
1012 edm::LogError(
"DynamicCastingFailed") <<
"Casting of TransientTrack to CandidatePtrTransientTrack failed!";
1025 template <
class IPTI,
class VTX>
1026 template <
class CONTAINER>
1029 const std::vector<fastjet::PseudoJet> &reclusteredJets,
1030 std::vector<int> &matchedIndices,
1034 std::vector<bool> matchedLocks(reclusteredJets.size(),
false);
1036 for (
size_t j = 0;
j <
jets->size(); ++
j) {
1037 double matchedDR2 = 1e9;
1038 int matchedIdx = -1;
1040 for (
size_t rj = 0; rj < reclusteredJets.size(); ++rj) {
1041 if (matchedLocks.at(rj))
1046 reclusteredJets.at(rj).rapidity(),
1047 reclusteredJets.at(rj).phi_std());
1048 if (tempDR2 < matchedDR2) {
1049 matchedDR2 = tempDR2;
1054 if (matchedIdx >= 0) {
1056 edm::LogError(
"JetMatchingFailed") <<
"Matched reclustered jet " << matchedIdx <<
" and original " <<
type
1057 <<
"jet " <<
j <<
" are separated by dR=" <<
sqrt(matchedDR2)
1058 <<
" which is greater than the jet size R=" <<
rParam <<
".\n"
1059 <<
"This is not expected so please check that the jet algorithm and jet "
1060 "size match those used for the original "
1061 <<
type <<
"jet collection.";
1063 matchedLocks.at(matchedIdx) =
true;
1066 <<
"Matching reclustered to original " <<
type
1067 <<
"jets failed. Please check that the jet algorithm and jet size match those used for the original " <<
type
1068 <<
"jet collection.";
1070 matchedIndices.push_back(matchedIdx);
1075 template <
class IPTI,
class VTX>
1078 std::vector<int> &matchedIndices) {
1079 std::vector<bool> jetLocks(
jets->size(),
false);
1080 std::vector<int> jetIndices;
1082 for (
size_t gj = 0; gj < groomedJets->size(); ++gj) {
1083 double matchedDR2 = 1e9;
1084 int matchedIdx = -1;
1086 if (groomedJets->at(gj).pt() > 0.)
1088 for (
size_t j = 0;
j <
jets->size(); ++
j) {
1093 jets->at(
j).rapidity(),
jets->at(
j).phi(), groomedJets->at(gj).rapidity(), groomedJets->at(gj).phi());
1094 if (tempDR2 < matchedDR2) {
1095 matchedDR2 = tempDR2;
1101 if (matchedIdx >= 0) {
1104 <<
"Matched groomed jet " << gj <<
" and original jet " << matchedIdx
1105 <<
" are separated by dR=" <<
sqrt(matchedDR2) <<
" which is greater than the jet size R=" <<
rParam
1107 <<
"This is not expected so the matching of these two jets has been discarded. Please check that the two "
1108 "jet collections belong to each other.";
1111 jetLocks.at(matchedIdx) =
true;
1113 jetIndices.push_back(matchedIdx);
1116 for (
size_t j = 0;
j <
jets->size(); ++
j) {
1117 std::vector<int>::iterator matchedIndex =
std::find(jetIndices.begin(), jetIndices.end(),
j);
1119 matchedIndices.push_back(matchedIndex != jetIndices.end() ?
std::distance(jetIndices.begin(), matchedIndex) : -1);
1124 template <
class IPTI,
class VTX>
1129 for (
size_t g = 0;
g < groomedIndices.size(); ++
g) {
1130 std::vector<int> subjetIndices;
1132 if (groomedIndices.at(
g) >= 0) {
1133 for (
size_t s = 0;
s < groomedJets->at(groomedIndices.at(
g)).numberOfDaughters(); ++
s) {
1136 for (
size_t sj = 0; sj < subjets->size(); ++sj) {
1139 subjetIndices.push_back(sj);
1145 if (subjetIndices.empty())
1146 edm::LogError(
"SubjetMatchingFailed") <<
"Matching subjets to original fat jets failed. Please check that the "
1147 "groomed fat jet and subjet collections belong to each other.";
1149 matchedIndices.push_back(subjetIndices);
1151 matchedIndices.push_back(subjetIndices);
1156 template <
class IPTI,
class VTX>
1160 for (
size_t fj = 0; fj < fatJets->size(); ++fj) {
1161 std::vector<int> subjetIndices;
1162 size_t nSubjetCollections = 0;
1163 size_t nSubjets = 0;
1165 const pat::Jet *fatJet = dynamic_cast<const pat::Jet *>(fatJets->ptrAt(fj).get());
1170 <<
"Wrong jet type for input fat jets. Please check that the input fat jets are of the pat::Jet type.";
1172 matchedIndices.push_back(subjetIndices);
1177 if (nSubjetCollections > 0) {
1178 for (
size_t coll = 0; coll < nSubjetCollections; ++coll) {
1181 for (
size_t fjsj = 0; fjsj < fatJetSubjets.size(); ++fjsj) {
1184 for (
size_t sj = 0; sj < subjets->size(); ++sj) {
1185 const pat::Jet *subJet = dynamic_cast<const pat::Jet *>(subjets->at(sj).jet().get());
1188 if (fj == 0 && coll == 0 && fjsj == 0 && sj == 0)
1189 edm::LogError(
"WrongJetType") <<
"Wrong jet type for input subjets. Please check that the input "
1190 "subjets are of the pat::Jet type.";
1194 if (subJet->
originalObjectRef() == fatJetSubjets.at(fjsj)->originalObjectRef()) {
1195 subjetIndices.push_back(sj);
1203 if (subjetIndices.empty() && nSubjets > 0)
1204 edm::LogError(
"SubjetMatchingFailed") <<
"Matching subjets to fat jets failed. Please check that the fat jet "
1205 "and subjet collections belong to each other.";
1207 matchedIndices.push_back(subjetIndices);
1209 matchedIndices.push_back(subjetIndices);
1215 template <
class IPTI,
class VTX>
1218 desc.add<
double>(
"extSVDeltaRToJet", 0.3);
1245 vertexCuts.add<
double>(
"distSig3dMax", 99999.9);
1248 vertexCuts.add<
bool>(
"useTrackWeights",
true);
1249 vertexCuts.add<
double>(
"maxDeltaRToJetAxis", 0.4);
1252 v0Filter.add<
double>(
"k0sMassWindow", 0.05);
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);
1263 vertexCuts.add<
double>(
"distSig3dMin", -99999.9);
1266 desc.add<
bool>(
"useExternalSV",
false);
1267 desc.add<
double>(
"minimumTrackWeight", 0.5);
1268 desc.add<
bool>(
"usePVError",
true);
1305 desc.addOptional<
bool>(
"useSVMomentum",
false);
1306 desc.addOptional<
double>(
"ghostRescaling", 1
e-18);
1307 desc.addOptional<
double>(
"relPtTolerance", 1
e-03);