Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:29:16

0001 #include "RecoVertex/PrimaryVertexProducer/interface/PrimaryVertexProducer.h"
0002 #include "FWCore/Framework/interface/ConsumesCollector.h"
0003 #include "DataFormats/VertexReco/interface/VertexFwd.h"
0004 #include "DataFormats/TrackReco/interface/TrackFwd.h"
0005 #include "DataFormats/Common/interface/Handle.h"
0006 #include "FWCore/Framework/interface/MakerMacros.h"
0007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0008 #include "FWCore/Utilities/interface/InputTag.h"
0009 
0010 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
0011 #include "RecoVertex/VertexPrimitives/interface/TransientVertex.h"
0012 #include "RecoVertex/VertexTools/interface/VertexDistanceXY.h"
0013 
0014 #include "FWCore/Framework/interface/ESHandle.h"
0015 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
0016 
0017 #include "RecoVertex/VertexTools/interface/GeometricAnnealing.h"
0018 
0019 PrimaryVertexProducer::PrimaryVertexProducer(const edm::ParameterSet& conf)
0020     : theTTBToken(esConsumes(edm::ESInputTag("", "TransientTrackBuilder"))), theConfig(conf) {
0021   fVerbose = conf.getUntrackedParameter<bool>("verbose", false);
0022   useMVASelection_ = conf.getParameter<bool>("useMVACut");
0023 
0024   trkToken = consumes<reco::TrackCollection>(conf.getParameter<edm::InputTag>("TrackLabel"));
0025   bsToken = consumes<reco::BeamSpot>(conf.getParameter<edm::InputTag>("beamSpotLabel"));
0026   useTransientTrackTime_ = false;
0027 
0028   // select and configure the track selection
0029   std::string trackSelectionAlgorithm =
0030       conf.getParameter<edm::ParameterSet>("TkFilterParameters").getParameter<std::string>("algorithm");
0031   if (trackSelectionAlgorithm == "filter") {
0032     theTrackFilter = new TrackFilterForPVFinding(conf.getParameter<edm::ParameterSet>("TkFilterParameters"));
0033   } else if (trackSelectionAlgorithm == "filterWithThreshold") {
0034     theTrackFilter = new HITrackFilterForPVFinding(conf.getParameter<edm::ParameterSet>("TkFilterParameters"));
0035   } else {
0036     throw VertexException("PrimaryVertexProducer: unknown track selection algorithm: " + trackSelectionAlgorithm);
0037   }
0038 
0039   // select and configure the track clusterizer
0040   std::string clusteringAlgorithm =
0041       conf.getParameter<edm::ParameterSet>("TkClusParameters").getParameter<std::string>("algorithm");
0042   if (clusteringAlgorithm == "gap") {
0043     theTrackClusterizer = new GapClusterizerInZ(
0044         conf.getParameter<edm::ParameterSet>("TkClusParameters").getParameter<edm::ParameterSet>("TkGapClusParameters"));
0045   } else if (clusteringAlgorithm == "DA_vect") {
0046     theTrackClusterizer = new DAClusterizerInZ_vect(
0047         conf.getParameter<edm::ParameterSet>("TkClusParameters").getParameter<edm::ParameterSet>("TkDAClusParameters"));
0048   } else if (clusteringAlgorithm == "DA2D_vect") {
0049     theTrackClusterizer = new DAClusterizerInZT_vect(
0050         conf.getParameter<edm::ParameterSet>("TkClusParameters").getParameter<edm::ParameterSet>("TkDAClusParameters"));
0051     useTransientTrackTime_ = true;
0052   } else {
0053     throw VertexException("PrimaryVertexProducer: unknown clustering algorithm: " + clusteringAlgorithm);
0054   }
0055 
0056   if (useTransientTrackTime_) {
0057     trkTimesToken = consumes<edm::ValueMap<float> >(conf.getParameter<edm::InputTag>("TrackTimesLabel"));
0058     trkTimeResosToken = consumes<edm::ValueMap<float> >(conf.getParameter<edm::InputTag>("TrackTimeResosLabel"));
0059     trackMTDTimeQualityToken =
0060         consumes<edm::ValueMap<float> >(conf.getParameter<edm::InputTag>("trackMTDTimeQualityVMapTag"));
0061     minTrackTimeQuality_ = conf.getParameter<double>("minTrackTimeQuality");
0062   }
0063 
0064   // select and configure the vertex fitters
0065   std::vector<edm::ParameterSet> vertexCollections =
0066       conf.getParameter<std::vector<edm::ParameterSet> >("vertexCollections");
0067 
0068   for (std::vector<edm::ParameterSet>::const_iterator algoconf = vertexCollections.begin();
0069        algoconf != vertexCollections.end();
0070        algoconf++) {
0071     algo algorithm;
0072 
0073     algorithm.label = algoconf->getParameter<std::string>("label");
0074 
0075     // configure the fitter and selector
0076     std::string fitterAlgorithm = algoconf->getParameter<std::string>("algorithm");
0077     if (fitterAlgorithm == "KalmanVertexFitter") {
0078       algorithm.pv_fitter = new SequentialPrimaryVertexFitterAdapter(new KalmanVertexFitter());
0079     } else if (fitterAlgorithm == "AdaptiveVertexFitter") {
0080       auto fitter = new AdaptiveVertexFitter(GeometricAnnealing(algoconf->getParameter<double>("chi2cutoff")));
0081       algorithm.pv_fitter = new SequentialPrimaryVertexFitterAdapter(fitter);
0082     } else if (fitterAlgorithm.empty()) {
0083       algorithm.pv_fitter = nullptr;
0084     } else if (fitterAlgorithm == "AdaptiveChisquareVertexFitter") {
0085       algorithm.pv_fitter = new AdaptiveChisquarePrimaryVertexFitter(algoconf->getParameter<double>("chi2cutoff"),
0086                                                                      algoconf->getParameter<double>("zcutoff"),
0087                                                                      algoconf->getParameter<double>("mintrkweight"),
0088                                                                      false);
0089     } else if (fitterAlgorithm == "MultiPrimaryVertexFitter") {
0090       algorithm.pv_fitter = new AdaptiveChisquarePrimaryVertexFitter(algoconf->getParameter<double>("chi2cutoff"),
0091                                                                      algoconf->getParameter<double>("zcutoff"),
0092                                                                      algoconf->getParameter<double>("mintrkweight"),
0093                                                                      true);
0094     } else if (fitterAlgorithm == "WeightedMeanFitter") {
0095       algorithm.pv_fitter = new WeightedMeanPrimaryVertexEstimator();
0096     } else {
0097       throw VertexException("PrimaryVertexProducer: unknown algorithm: " + fitterAlgorithm);
0098     }
0099     algorithm.minNdof = algoconf->getParameter<double>("minNdof");
0100     algorithm.useBeamConstraint = algoconf->getParameter<bool>("useBeamConstraint");
0101     algorithm.vertexSelector =
0102         new VertexCompatibleWithBeam(VertexDistanceXY(), algoconf->getParameter<double>("maxDistanceToBeam"));
0103 
0104     // configure separate vertex time reconstruction if applicable
0105     // note that the vertex time could, in principle, also come from the clusterizer or the vertex fit
0106 
0107     const auto& pv_time_conf = algoconf->getParameter<edm::ParameterSet>("vertexTimeParameters");
0108     const std::string vertexTimeAlgorithm = pv_time_conf.getParameter<std::string>("algorithm");
0109     edm::ConsumesCollector&& collector = consumesCollector();
0110 
0111     if (vertexTimeAlgorithm.empty()) {
0112       algorithm.pv_time_estimator = nullptr;
0113     } else if (vertexTimeAlgorithm == "legacy4D") {
0114       useTransientTrackTime_ = true;
0115       algorithm.pv_time_estimator =
0116           new VertexTimeAlgorithmLegacy4D(pv_time_conf.getParameter<edm::ParameterSet>("legacy4D"), collector);
0117     } else if (vertexTimeAlgorithm == "fromTracksPID") {
0118       algorithm.pv_time_estimator = new VertexTimeAlgorithmFromTracksPID(
0119           pv_time_conf.getParameter<edm::ParameterSet>("fromTracksPID"), collector);
0120     } else {
0121       edm::LogWarning("MisConfiguration") << "unknown vertexTimeParameters.algorithm" << vertexTimeAlgorithm;
0122     }
0123     algorithms.push_back(algorithm);
0124 
0125     produces<reco::VertexCollection>(algorithm.label);
0126   }
0127 
0128   //check if this is a recovery iteration
0129   fRecoveryIteration = conf.getParameter<bool>("isRecoveryIteration");
0130   if (fRecoveryIteration) {
0131     if (algorithms.empty()) {
0132       throw VertexException("PrimaryVertexProducer: No algorithm specified. ");
0133     } else if (algorithms.size() > 1) {
0134       throw VertexException(
0135           "PrimaryVertexProducer: Running in Recovery mode and more than one algorithm specified.  Please "
0136           "only one algorithm.");
0137     }
0138     recoveryVtxToken = consumes<reco::VertexCollection>(conf.getParameter<edm::InputTag>("recoveryVtxCollection"));
0139   }
0140 }
0141 
0142 PrimaryVertexProducer::~PrimaryVertexProducer() {
0143   if (theTrackFilter)
0144     delete theTrackFilter;
0145   if (theTrackClusterizer)
0146     delete theTrackClusterizer;
0147   for (std::vector<algo>::const_iterator algorithm = algorithms.begin(); algorithm != algorithms.end(); algorithm++) {
0148     if (algorithm->pv_fitter)
0149       delete algorithm->pv_fitter;
0150     if (algorithm->pv_time_estimator)
0151       delete algorithm->pv_time_estimator;
0152     if (algorithm->vertexSelector)
0153       delete algorithm->vertexSelector;
0154   }
0155 }
0156 
0157 void PrimaryVertexProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0158   // get the BeamSpot, it will always be needed, even when not used as a constraint
0159   reco::BeamSpot beamSpot;
0160   edm::Handle<reco::BeamSpot> recoBeamSpotHandle;
0161   iEvent.getByToken(bsToken, recoBeamSpotHandle);
0162   if (recoBeamSpotHandle.isValid()) {
0163     beamSpot = *recoBeamSpotHandle;
0164   } else {
0165     edm::LogError("UnusableBeamSpot") << "No beam spot available from EventSetup";
0166   }
0167 
0168   bool validBS = true;
0169   VertexState beamVertexState(beamSpot);
0170   if ((beamVertexState.error().cxx() <= 0.) || (beamVertexState.error().cyy() <= 0.) ||
0171       (beamVertexState.error().czz() <= 0.)) {
0172     edm::LogError("UnusableBeamSpot") << "Beamspot with invalid errors " << beamVertexState.error().matrix();
0173     validBS = false;
0174   }
0175 
0176   //if this is a recovery iteration, check if we already have a valid PV
0177   if (fRecoveryIteration) {
0178     auto const& oldVertices = iEvent.get(recoveryVtxToken);
0179     //look for the first valid (not-BeamSpot) vertex
0180     for (auto const& old : oldVertices) {
0181       if (!(old.isFake())) {
0182         //found a valid vertex, write the first one to the collection and return
0183         //otherwise continue with regular vertexing procedure
0184         auto result = std::make_unique<reco::VertexCollection>();
0185         result->push_back(old);
0186         iEvent.put(std::move(result), algorithms.begin()->label);
0187         return;
0188       }
0189     }
0190   }
0191 
0192   // get RECO tracks from the event
0193   // `tks` can be used as a ptr to a reco::TrackCollection
0194   edm::Handle<reco::TrackCollection> tks;
0195   iEvent.getByToken(trkToken, tks);
0196 
0197   // mechanism to put the beamspot if the track collection is empty
0198   if (!tks.isValid()) {
0199     for (std::vector<algo>::const_iterator algorithm = algorithms.begin(); algorithm != algorithms.end(); algorithm++) {
0200       auto result = std::make_unique<reco::VertexCollection>();
0201       reco::VertexCollection& vColl = (*result);
0202 
0203       GlobalError bse(beamSpot.rotatedCovariance3D());
0204       if ((bse.cxx() <= 0.) || (bse.cyy() <= 0.) || (bse.czz() <= 0.)) {
0205         AlgebraicSymMatrix33 we;
0206         we(0, 0) = 10000;
0207         we(1, 1) = 10000;
0208         we(2, 2) = 10000;
0209         vColl.push_back(reco::Vertex(beamSpot.position(), we, 0., 0., 0));
0210         if (fVerbose) {
0211           std::cout << "RecoVertex/PrimaryVertexProducer: "
0212                     << "Beamspot with invalid errors " << bse.matrix() << std::endl;
0213           std::cout << "Will put Vertex derived from dummy-fake BeamSpot into Event.\n";
0214         }
0215       } else {
0216         vColl.push_back(reco::Vertex(beamSpot.position(), beamSpot.rotatedCovariance3D(), 0., 0., 0));
0217         if (fVerbose) {
0218           std::cout << "RecoVertex/PrimaryVertexProducer: "
0219                     << " will put Vertex derived from BeamSpot into Event.\n";
0220         }
0221       }
0222       iEvent.put(std::move(result), algorithm->label);
0223     }
0224 
0225     return;  // early return
0226   }
0227 
0228   for (auto& algo : algorithms) {
0229     if (algo.pv_time_estimator) {
0230       algo.pv_time_estimator->setEvent(iEvent, iSetup);
0231     }
0232   }
0233 
0234   // interface RECO tracks to vertex reconstruction
0235   const auto& theB = &iSetup.getData(theTTBToken);
0236   std::vector<reco::TransientTrack> t_tks;
0237 
0238   if (useTransientTrackTime_) {
0239     auto const& trackTimeResos_ = iEvent.get(trkTimeResosToken);
0240     auto trackTimes_ = iEvent.get(trkTimesToken);
0241 
0242     if (useMVASelection_) {
0243       trackMTDTimeQualities_ = iEvent.get(trackMTDTimeQualityToken);
0244 
0245       for (unsigned int i = 0; i < (*tks).size(); i++) {
0246         const reco::TrackRef ref(tks, i);
0247         auto const trkTimeQuality = trackMTDTimeQualities_[ref];
0248         if (trkTimeQuality < minTrackTimeQuality_) {
0249           trackTimes_[ref] = std::numeric_limits<double>::max();
0250         }
0251       }
0252       t_tks = (*theB).build(tks, beamSpot, trackTimes_, trackTimeResos_);
0253     } else {
0254       t_tks = (*theB).build(tks, beamSpot, trackTimes_, trackTimeResos_);
0255     }
0256   } else {
0257     t_tks = (*theB).build(tks, beamSpot);
0258   }
0259 
0260   // select tracks
0261   std::vector<reco::TransientTrack>&& seltks = theTrackFilter->select(t_tks);
0262 
0263   // clusterize tracks in Z
0264   std::vector<TransientVertex>&& clusters = theTrackClusterizer->vertices(seltks);
0265 
0266   if (fVerbose) {
0267     edm::LogPrint("PrimaryVertexProducer")
0268         << "Clustering returned " << clusters.size() << " clusters from " << seltks.size() << " selected tracks";
0269   }
0270 
0271   // vertex fits
0272   for (std::vector<algo>::const_iterator algorithm = algorithms.begin(); algorithm != algorithms.end(); algorithm++) {
0273     auto result = std::make_unique<reco::VertexCollection>();
0274     reco::VertexCollection& vColl = (*result);
0275     std::vector<TransientVertex> pvs;
0276 
0277     if (algorithm->pv_fitter == nullptr) {
0278       pvs = clusters;
0279     } else {
0280       pvs = algorithm->pv_fitter->fit(seltks, clusters, beamSpot, algorithm->useBeamConstraint);
0281     }
0282 
0283     if (algorithm->pv_time_estimator != nullptr) {
0284       algorithm->pv_time_estimator->fill_vertex_times(pvs);
0285     }
0286 
0287     // sort vertices by pt**2  vertex
0288     if (pvs.size() > 1) {
0289       sort(pvs.begin(), pvs.end(), VertexHigherPtSquared());
0290     }
0291 
0292     // select and convert transient vertices to (reco) vertices
0293     for (std::vector<TransientVertex>::const_iterator iv = pvs.begin(); iv != pvs.end(); iv++) {
0294       if (iv->isValid() && (iv->degreesOfFreedom() >= algorithm->minNdof)) {
0295         reco::Vertex v = *iv;
0296         if (!validBS || ((*(algorithm->vertexSelector))(v, beamVertexState))) {
0297           vColl.push_back(v);
0298         }
0299       }
0300     }
0301 
0302     if (fVerbose) {
0303       edm::LogPrint("PrimaryVertexProducer") << "PrimaryVertexProducer \"" << algorithm->label << "\" contains "
0304                                              << pvs.size() << " reco::Vertex candidates";
0305     }
0306 
0307     if (clusters.size() > 2 && clusters.size() > 2 * pvs.size()) {
0308       edm::LogWarning("PrimaryVertexProducer")
0309           << "More than 50% of candidate vertices lost (" << pvs.size() << " out of " << clusters.size() << ")";
0310     }
0311 
0312     if (pvs.empty() && seltks.size() > 5) {
0313       edm::LogWarning("PrimaryVertexProducer")
0314           << "No vertex found with " << seltks.size() << " tracks and " << clusters.size() << " vertex candidates";
0315     }
0316 
0317     if (vColl.empty()) {
0318       GlobalError bse(beamSpot.rotatedCovariance3D());
0319       if ((bse.cxx() <= 0.) || (bse.cyy() <= 0.) || (bse.czz() <= 0.)) {
0320         AlgebraicSymMatrix33 we;
0321         we(0, 0) = 10000;
0322         we(1, 1) = 10000;
0323         we(2, 2) = 10000;
0324         vColl.push_back(reco::Vertex(beamSpot.position(), we, 0., 0., 0));
0325         edm::LogWarning("PrimaryVertexProducer") << "Zero recostructed vertices, will put reco::Vertex derived from "
0326                                                     "dummy/fake BeamSpot into Event, BeamSpot has invalid errors: "
0327                                                  << bse.matrix();
0328       } else {
0329         vColl.push_back(reco::Vertex(beamSpot.position(), beamSpot.rotatedCovariance3D(), 0., 0., 0));
0330         if (fVerbose) {
0331           edm::LogWarning("PrimaryVertexProducer")
0332               << "Zero recostructed vertices, will put reco::Vertex derived from BeamSpot into Event.";
0333         }
0334       }
0335     }
0336 
0337     if (fVerbose) {
0338       int ivtx = 0;
0339       for (reco::VertexCollection::const_iterator v = vColl.begin(); v != vColl.end(); ++v) {
0340         edm::LogPrint("PrimaryVertexProducer")
0341             << "recvtx " << std::setw(3) << std::fixed << ivtx++ << " #trk " << std::setw(3) << v->tracksSize()
0342             << " chi2 " << std::setw(5) << std::setprecision(1) << v->chi2() << " ndof " << std::setw(5)
0343             << std::setprecision(1) << v->ndof() << " x " << std::setw(7) << std::setprecision(4) << v->position().x()
0344             << " dx " << std::setw(6) << std::setprecision(4) << v->xError() << " y " << std::setw(7)
0345             << std::setprecision(4) << v->position().y() << " dy " << std::setw(6) << std::setprecision(4)
0346             << v->yError() << " z " << std::setw(8) << std::setprecision(4) << v->position().z() << " dz "
0347             << std::setw(6) << std::setprecision(4) << v->zError();
0348         if (v->tError() > 0) {
0349           edm::LogPrint("PrimaryVertexProducer") << " t " << std::setw(6) << std::setprecision(3) << v->t() << " dt "
0350                                                  << std::setw(6) << std::setprecision(3) << v->tError();
0351         }
0352       }
0353     }
0354 
0355     iEvent.put(std::move(result), algorithm->label);
0356   }
0357 }
0358 
0359 void PrimaryVertexProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0360   edm::ParameterSetDescription psd_pv_time;
0361   {
0362     edm::ParameterSetDescription psd1;
0363     VertexTimeAlgorithmFromTracksPID::fillPSetDescription(psd1);
0364     psd_pv_time.add<edm::ParameterSetDescription>("fromTracksPID", psd1);
0365 
0366     edm::ParameterSetDescription psd2;
0367     VertexTimeAlgorithmLegacy4D::fillPSetDescription(psd2);
0368     psd_pv_time.add<edm::ParameterSetDescription>("legacy4D", psd2);
0369   }
0370   psd_pv_time.add<std::string>("algorithm", "");  // default = none
0371 
0372   // vertex collections
0373   edm::ParameterSetDescription desc;
0374   {
0375     edm::ParameterSetDescription vpsd1;
0376     vpsd1.add<double>("maxDistanceToBeam", 1.0);
0377     vpsd1.add<std::string>("algorithm", "AdaptiveVertexFitter");
0378     vpsd1.add<bool>("useBeamConstraint", false);
0379     vpsd1.add<std::string>("label", "");
0380     vpsd1.add<double>("chi2cutoff", 2.5);
0381     vpsd1.add<double>("zcutoff", 1.0);
0382     vpsd1.add<double>("mintrkweight", 0.0);
0383     vpsd1.add<double>("minNdof", 0.0);
0384     vpsd1.add<edm::ParameterSetDescription>("vertexTimeParameters", psd_pv_time);
0385 
0386     // two default values : with- and without beam constraint
0387     std::vector<edm::ParameterSet> temp1;
0388     temp1.reserve(2);
0389     {
0390       edm::ParameterSet temp2;
0391       temp2.addParameter<double>("maxDistanceToBeam", 1.0);
0392       temp2.addParameter<std::string>("algorithm", "AdaptiveVertexFitter");
0393       temp2.addParameter<bool>("useBeamConstraint", false);
0394       temp2.addParameter<std::string>("label", "");
0395       temp2.addParameter<double>("chi2cutoff", 2.5);
0396       temp2.addParameter<double>("zcutoff", 1.0);
0397       temp2.addParameter<double>("mintrkweight", 0.);
0398       temp2.addParameter<double>("minNdof", 0.0);
0399       edm::ParameterSet temp_vertexTime;
0400       temp_vertexTime.addParameter<std::string>("algorithm", "");
0401       temp2.addParameter<edm::ParameterSet>("vertexTimeParameters", temp_vertexTime);
0402       temp1.push_back(temp2);
0403     }
0404     {
0405       edm::ParameterSet temp2;
0406       temp2.addParameter<double>("maxDistanceToBeam", 1.0);
0407       temp2.addParameter<std::string>("algorithm", "AdaptiveVertexFitter");
0408       temp2.addParameter<bool>("useBeamConstraint", true);
0409       temp2.addParameter<std::string>("label", "WithBS");
0410       temp2.addParameter<double>("chi2cutoff", 2.5);
0411       temp2.addParameter<double>("zcutoff", 1.0);
0412       temp2.addParameter<double>("mintrkweight", 0.);
0413       temp2.addParameter<double>("minNdof", 2.0);
0414       edm::ParameterSet temp_vertexTime;
0415       temp_vertexTime.addParameter<std::string>("algorithm", "");
0416       temp2.addParameter<edm::ParameterSet>("vertexTimeParameters", temp_vertexTime);
0417       temp1.push_back(temp2);
0418     }
0419     desc.addVPSet("vertexCollections", vpsd1, temp1);
0420   }
0421   desc.addUntracked<bool>("verbose", false);
0422   {
0423     edm::ParameterSetDescription psd0;
0424     HITrackFilterForPVFinding::fillPSetDescription(psd0);  // extension of TrackFilterForPVFinding
0425     desc.add<edm::ParameterSetDescription>("TkFilterParameters", psd0);
0426   }
0427   desc.add<edm::InputTag>("beamSpotLabel", edm::InputTag("offlineBeamSpot"));
0428   desc.add<edm::InputTag>("TrackLabel", edm::InputTag("generalTracks"));
0429   desc.add<edm::InputTag>("TrackTimeResosLabel", edm::InputTag("dummy_default"));                         // 4D only
0430   desc.add<edm::InputTag>("TrackTimesLabel", edm::InputTag("dummy_default"));                             // 4D only
0431   desc.add<edm::InputTag>("trackMTDTimeQualityVMapTag", edm::InputTag("mtdTrackQualityMVA:mtdQualMVA"));  // 4D only
0432 
0433   {
0434     edm::ParameterSetDescription psd0;
0435     {
0436       edm::ParameterSetDescription psd1;
0437       DAClusterizerInZ_vect::fillPSetDescription(psd1);
0438 
0439       edm::ParameterSetDescription psd2;
0440       DAClusterizerInZT_vect::fillPSetDescription(psd2);
0441 
0442       edm::ParameterSetDescription psd3;
0443       GapClusterizerInZ::fillPSetDescription(psd3);
0444 
0445       psd0.ifValue(
0446           edm::ParameterDescription<std::string>("algorithm", "DA_vect", true),
0447           "DA_vect" >> edm::ParameterDescription<edm::ParameterSetDescription>("TkDAClusParameters", psd1, true) or
0448               "DA2D_vect" >>
0449                   edm::ParameterDescription<edm::ParameterSetDescription>("TkDAClusParameters", psd2, true) or
0450               "gap" >> edm::ParameterDescription<edm::ParameterSetDescription>("TkGapClusParameters", psd3, true));
0451     }
0452     desc.add<edm::ParameterSetDescription>("TkClusParameters", psd0);
0453   }
0454 
0455   desc.add<bool>("isRecoveryIteration", false);
0456   desc.add<edm::InputTag>("recoveryVtxCollection", {""});
0457   desc.add<bool>("useMVACut", false);
0458   desc.add<double>("minTrackTimeQuality", 0.8);
0459 
0460   descriptions.addWithDefaultLabel(desc);
0461 }
0462 
0463 //define this as a plug-in
0464 DEFINE_FWK_MODULE(PrimaryVertexProducer);