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
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
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
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
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
0105
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
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
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
0177 if (fRecoveryIteration) {
0178 auto const& oldVertices = iEvent.get(recoveryVtxToken);
0179
0180 for (auto const& old : oldVertices) {
0181 if (!(old.isFake())) {
0182
0183
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
0193
0194 edm::Handle<reco::TrackCollection> tks;
0195 iEvent.getByToken(trkToken, tks);
0196
0197
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;
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
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
0261 std::vector<reco::TransientTrack>&& seltks = theTrackFilter->select(t_tks);
0262
0263
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
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
0288 if (pvs.size() > 1) {
0289 sort(pvs.begin(), pvs.end(), VertexHigherPtSquared());
0290 }
0291
0292
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", "");
0371
0372
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
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);
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"));
0430 desc.add<edm::InputTag>("TrackTimesLabel", edm::InputTag("dummy_default"));
0431 desc.add<edm::InputTag>("trackMTDTimeQualityVMapTag", edm::InputTag("mtdTrackQualityMVA:mtdQualMVA"));
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
0464 DEFINE_FWK_MODULE(PrimaryVertexProducer);