00001 #include <functional>
00002 #include <algorithm>
00003 #include <iterator>
00004 #include <cstddef>
00005 #include <string>
00006 #include <vector>
00007 #include <map>
00008 #include <set>
00009
00010 #include <boost/iterator/transform_iterator.hpp>
00011
00012 #include "FWCore/Framework/interface/EDProducer.h"
00013 #include "FWCore/Framework/interface/Event.h"
00014 #include "FWCore/Framework/interface/EventSetup.h"
00015 #include "FWCore/Framework/interface/MakerMacros.h"
00016 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00017 #include "FWCore/Utilities/interface/InputTag.h"
00018 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00019 #include "FWCore/Utilities/interface/Exception.h"
00020
00021 #include "DataFormats/TrackReco/interface/Track.h"
00022 #include "DataFormats/TrackReco/interface/TrackFwd.h"
00023 #include "DataFormats/VertexReco/interface/Vertex.h"
00024
00025 #include "DataFormats/GeometryCommonDetAlgo/interface/Measurement1D.h"
00026 #include "DataFormats/BTauReco/interface/TrackIPTagInfo.h"
00027 #include "DataFormats/BTauReco/interface/SecondaryVertexTagInfo.h"
00028
00029 #include "RecoVertex/VertexPrimitives/interface/VertexException.h"
00030 #include "RecoVertex/VertexPrimitives/interface/ConvertToFromReco.h"
00031 #include "RecoVertex/ConfigurableVertexReco/interface/ConfigurableVertexReconstructor.h"
00032 #include "RecoVertex/GhostTrackFitter/interface/GhostTrackVertexFinder.h"
00033 #include "RecoVertex/GhostTrackFitter/interface/GhostTrackPrediction.h"
00034 #include "RecoVertex/GhostTrackFitter/interface/GhostTrackState.h"
00035 #include "RecoVertex/GhostTrackFitter/interface/GhostTrack.h"
00036
00037 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
00038 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
00039 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
00040
00041 #include "RecoBTag/SecondaryVertex/interface/TrackSelector.h"
00042 #include "RecoBTag/SecondaryVertex/interface/TrackSorting.h"
00043 #include "RecoBTag/SecondaryVertex/interface/SecondaryVertex.h"
00044 #include "RecoBTag/SecondaryVertex/interface/VertexFilter.h"
00045 #include "RecoBTag/SecondaryVertex/interface/VertexSorting.h"
00046
00047 #include "DataFormats/GeometryVector/interface/VectorUtil.h"
00048
00049 using namespace reco;
00050
00051 namespace {
00052 template<typename T>
00053 struct RefToBaseLess : public std::binary_function<edm::RefToBase<T>,
00054 edm::RefToBase<T>,
00055 bool> {
00056 inline bool operator()(const edm::RefToBase<T> &r1,
00057 const edm::RefToBase<T> &r2) const
00058 {
00059 return r1.id() < r2.id() ||
00060 (r1.id() == r2.id() && r1.key() < r2.key());
00061 }
00062 };
00063 }
00064
00065 class SecondaryVertexProducer : public edm::EDProducer {
00066 public:
00067 explicit SecondaryVertexProducer(const edm::ParameterSet ¶ms);
00068 ~SecondaryVertexProducer();
00069
00070 virtual void produce(edm::Event &event, const edm::EventSetup &es);
00071
00072 private:
00073 enum ConstraintType {
00074 CONSTRAINT_NONE = 0,
00075 CONSTRAINT_BEAMSPOT,
00076 CONSTRAINT_PV_BEAMSPOT_SIZE,
00077 CONSTRAINT_PV_BS_Z_ERRORS_SCALED,
00078 CONSTRAINT_PV_ERROR_SCALED,
00079 CONSTRAINT_PV_PRIMARIES_IN_FIT
00080 };
00081
00082 static ConstraintType getConstraintType(const std::string &name);
00083
00084 const edm::InputTag trackIPTagInfoLabel;
00085 edm::InputTag beamSpotTag;
00086 TrackIPTagInfo::SortCriteria sortCriterium;
00087 TrackSelector trackSelector;
00088 ConstraintType constraint;
00089 double constraintScaling;
00090 edm::ParameterSet vtxRecoPSet;
00091 bool useGhostTrack;
00092 bool withPVError;
00093 double minTrackWeight;
00094 VertexFilter vertexFilter;
00095 VertexSorting vertexSorting;
00096 bool useExternalSV;
00097 double extSVDeltaRToJet;
00098 edm::InputTag extSVCollection;
00099 };
00100
00101 SecondaryVertexProducer::ConstraintType
00102 SecondaryVertexProducer::getConstraintType(const std::string &name)
00103 {
00104 if (name == "None")
00105 return CONSTRAINT_NONE;
00106 else if (name == "BeamSpot")
00107 return CONSTRAINT_BEAMSPOT;
00108 else if (name == "BeamSpot+PVPosition")
00109 return CONSTRAINT_PV_BEAMSPOT_SIZE;
00110 else if (name == "BeamSpotZ+PVErrorScaledXY")
00111 return CONSTRAINT_PV_BS_Z_ERRORS_SCALED;
00112 else if (name == "PVErrorScaled")
00113 return CONSTRAINT_PV_ERROR_SCALED;
00114 else if (name == "BeamSpot+PVTracksInFit")
00115 return CONSTRAINT_PV_PRIMARIES_IN_FIT;
00116 else
00117 throw cms::Exception("InvalidArgument")
00118 << "SecondaryVertexProducer: ``constraint'' parameter "
00119 "value \"" << name << "\" not understood."
00120 << std::endl;
00121 }
00122
00123 static GhostTrackVertexFinder::FitType
00124 getGhostTrackFitType(const std::string &name)
00125 {
00126 if (name == "AlwaysWithGhostTrack")
00127 return GhostTrackVertexFinder::kAlwaysWithGhostTrack;
00128 else if (name == "SingleTracksWithGhostTrack")
00129 return GhostTrackVertexFinder::kSingleTracksWithGhostTrack;
00130 else if (name == "RefitGhostTrackWithVertices")
00131 return GhostTrackVertexFinder::kRefitGhostTrackWithVertices;
00132 else
00133 throw cms::Exception("InvalidArgument")
00134 << "SecondaryVertexProducer: ``fitType'' "
00135 "parameter value \"" << name << "\" for "
00136 "GhostTrackVertexFinder settings not "
00137 "understood." << std::endl;
00138 }
00139
00140 SecondaryVertexProducer::SecondaryVertexProducer(
00141 const edm::ParameterSet ¶ms) :
00142 trackIPTagInfoLabel(params.getParameter<edm::InputTag>("trackIPTagInfos")),
00143 sortCriterium(TrackSorting::getCriterium(params.getParameter<std::string>("trackSort"))),
00144 trackSelector(params.getParameter<edm::ParameterSet>("trackSelection")),
00145 constraint(getConstraintType(params.getParameter<std::string>("constraint"))),
00146 constraintScaling(1.0),
00147 vtxRecoPSet(params.getParameter<edm::ParameterSet>("vertexReco")),
00148 useGhostTrack(vtxRecoPSet.getParameter<std::string>("finder") == "gtvr"),
00149 withPVError(params.getParameter<bool>("usePVError")),
00150 minTrackWeight(params.getParameter<double>("minimumTrackWeight")),
00151 vertexFilter(params.getParameter<edm::ParameterSet>("vertexCuts")),
00152 vertexSorting(params.getParameter<edm::ParameterSet>("vertexSelection"))
00153 {
00154 if (constraint == CONSTRAINT_PV_ERROR_SCALED ||
00155 constraint == CONSTRAINT_PV_BS_Z_ERRORS_SCALED)
00156 constraintScaling = params.getParameter<double>("pvErrorScaling");
00157
00158 if (constraint == CONSTRAINT_PV_BEAMSPOT_SIZE ||
00159 constraint == CONSTRAINT_PV_BS_Z_ERRORS_SCALED ||
00160 constraint == CONSTRAINT_BEAMSPOT ||
00161 constraint == CONSTRAINT_PV_PRIMARIES_IN_FIT )
00162 beamSpotTag = params.getParameter<edm::InputTag>("beamSpotTag");
00163 useExternalSV = false;
00164 if(params.existsAs<bool>("useExternalSV")) useExternalSV = params.getParameter<bool> ("useExternalSV");
00165 if(useExternalSV) {
00166 extSVCollection = params.getParameter<edm::InputTag>("extSVCollection");
00167 extSVDeltaRToJet = params.getParameter<double>("extSVDeltaRToJet");
00168 }
00169 produces<SecondaryVertexTagInfoCollection>();
00170 }
00171
00172 SecondaryVertexProducer::~SecondaryVertexProducer()
00173 {
00174 }
00175
00176 namespace {
00177 struct SVBuilder :
00178 public std::unary_function<const Vertex&, SecondaryVertex> {
00179
00180 SVBuilder(const reco::Vertex &pv,
00181 const GlobalVector &direction,
00182 bool withPVError) :
00183 pv(pv), direction(direction),
00184 withPVError(withPVError) {}
00185
00186 SecondaryVertex operator () (const reco::Vertex &sv) const
00187 { return SecondaryVertex(pv, sv, direction, withPVError); }
00188
00189 const Vertex &pv;
00190 const GlobalVector &direction;
00191 bool withPVError;
00192 };
00193
00194 struct SVFilter :
00195 public std::unary_function<const SecondaryVertex&, bool> {
00196
00197 SVFilter(const VertexFilter &filter, const Vertex &pv,
00198 const GlobalVector &direction) :
00199 filter(filter), pv(pv), direction(direction) {}
00200
00201 inline bool operator () (const SecondaryVertex &sv) const
00202 { return !filter(pv, sv, direction); }
00203
00204 const VertexFilter &filter;
00205 const Vertex &pv;
00206 const GlobalVector &direction;
00207 };
00208
00209 }
00210
00211 void SecondaryVertexProducer::produce(edm::Event &event,
00212 const edm::EventSetup &es)
00213 {
00214 typedef std::map<TrackBaseRef, TransientTrack,
00215 RefToBaseLess<Track> > TransientTrackMap;
00216
00217 edm::ESHandle<TransientTrackBuilder> trackBuilder;
00218 es.get<TransientTrackRecord>().get("TransientTrackBuilder",
00219 trackBuilder);
00220
00221 edm::Handle<TrackIPTagInfoCollection> trackIPTagInfos;
00222 event.getByLabel(trackIPTagInfoLabel, trackIPTagInfos);
00223
00224
00225 edm::Handle<reco::VertexCollection> extSecVertex;
00226 if(useExternalSV) event.getByLabel(extSVCollection,extSecVertex);
00227
00228
00229 edm::Handle<BeamSpot> beamSpot;
00230 unsigned int bsCovSrc[7] = { 0, };
00231 double sigmaZ = 0.0, beamWidth = 0.0;
00232 switch(constraint) {
00233 case CONSTRAINT_PV_BEAMSPOT_SIZE:
00234 event.getByLabel(beamSpotTag,beamSpot);
00235 bsCovSrc[3] = bsCovSrc[4] = bsCovSrc[5] = bsCovSrc[6] = 1;
00236 sigmaZ = beamSpot->sigmaZ();
00237 beamWidth = beamSpot->BeamWidthX();
00238 break;
00239
00240 case CONSTRAINT_PV_BS_Z_ERRORS_SCALED:
00241 event.getByLabel(beamSpotTag,beamSpot);
00242 bsCovSrc[0] = bsCovSrc[1] = 2;
00243 bsCovSrc[3] = bsCovSrc[4] = bsCovSrc[5] = 1;
00244 sigmaZ = beamSpot->sigmaZ();
00245 break;
00246
00247 case CONSTRAINT_PV_ERROR_SCALED:
00248 bsCovSrc[0] = bsCovSrc[1] = bsCovSrc[2] = 2;
00249 break;
00250
00251 case CONSTRAINT_BEAMSPOT:
00252 case CONSTRAINT_PV_PRIMARIES_IN_FIT:
00253 event.getByLabel(beamSpotTag,beamSpot);
00254 break;
00255
00256 default:
00257 ;
00258 }
00259
00260 std::auto_ptr<ConfigurableVertexReconstructor> vertexReco;
00261 std::auto_ptr<GhostTrackVertexFinder> vertexRecoGT;
00262 if (useGhostTrack)
00263 vertexRecoGT.reset(new GhostTrackVertexFinder(
00264 vtxRecoPSet.getParameter<double>("maxFitChi2"),
00265 vtxRecoPSet.getParameter<double>("mergeThreshold"),
00266 vtxRecoPSet.getParameter<double>("primcut"),
00267 vtxRecoPSet.getParameter<double>("seccut"),
00268 getGhostTrackFitType(vtxRecoPSet.getParameter<std::string>("fitType"))));
00269 else
00270 vertexReco.reset(
00271 new ConfigurableVertexReconstructor(vtxRecoPSet));
00272
00273 TransientTrackMap primariesMap;
00274
00275
00276
00277 std::auto_ptr<SecondaryVertexTagInfoCollection>
00278 tagInfos(new SecondaryVertexTagInfoCollection);
00279
00280 for(TrackIPTagInfoCollection::const_iterator iterJets =
00281 trackIPTagInfos->begin(); iterJets != trackIPTagInfos->end();
00282 ++iterJets) {
00283 std::vector<SecondaryVertexTagInfo::IndexedTrackData> trackData;
00284
00285
00286 const Vertex &pv = *iterJets->primaryVertex();
00287
00288 std::set<TransientTrack> primaries;
00289 if (constraint == CONSTRAINT_PV_PRIMARIES_IN_FIT) {
00290 for(Vertex::trackRef_iterator iter = pv.tracks_begin();
00291 iter != pv.tracks_end(); ++iter) {
00292 TransientTrackMap::iterator pos =
00293 primariesMap.lower_bound(*iter);
00294
00295 if (pos != primariesMap.end() &&
00296 pos->first == *iter)
00297 primaries.insert(pos->second);
00298 else {
00299 TransientTrack track =
00300 trackBuilder->build(
00301 iter->castTo<TrackRef>());
00302 primariesMap.insert(pos,
00303 std::make_pair(*iter, track));
00304 primaries.insert(track);
00305 }
00306 }
00307 }
00308
00309 edm::RefToBase<Jet> jetRef = iterJets->jet();
00310
00311 GlobalVector jetDir(jetRef->momentum().x(),
00312 jetRef->momentum().y(),
00313 jetRef->momentum().z());
00314
00315 std::vector<std::size_t> indices =
00316 iterJets->sortedIndexes(sortCriterium);
00317
00318 TrackRefVector trackRefs = iterJets->sortedTracks(indices);
00319
00320 const std::vector<TrackIPTagInfo::TrackIPData> &ipData =
00321 iterJets->impactParameterData();
00322
00323
00324
00325 std::vector<TransientTrack> fitTracks;
00326 std::vector<GhostTrackState> gtStates;
00327 std::auto_ptr<GhostTrackPrediction> gtPred;
00328 if (useGhostTrack)
00329 gtPred.reset(new GhostTrackPrediction(
00330 *iterJets->ghostTrack()));
00331
00332 for(unsigned int i = 0; i < indices.size(); i++) {
00333 typedef SecondaryVertexTagInfo::IndexedTrackData IndexedTrackData;
00334
00335 const TrackRef &trackRef = trackRefs[i];
00336
00337 trackData.push_back(IndexedTrackData());
00338 trackData.back().first = indices[i];
00339
00340
00341
00342 if (!trackSelector(*trackRef, ipData[indices[i]], *jetRef,
00343 RecoVertex::convertPos(
00344 pv.position()))) {
00345 trackData.back().second.svStatus =
00346 SecondaryVertexTagInfo::TrackData::trackSelected;
00347 continue;
00348 }
00349
00350 TransientTrackMap::const_iterator pos =
00351 primariesMap.find(
00352 TrackBaseRef(trackRef));
00353 TransientTrack fitTrack;
00354 if (pos != primariesMap.end()) {
00355 primaries.erase(pos->second);
00356 fitTrack = pos->second;
00357 } else
00358 fitTrack = trackBuilder->build(trackRef);
00359 fitTracks.push_back(fitTrack);
00360
00361 trackData.back().second.svStatus =
00362 SecondaryVertexTagInfo::TrackData::trackUsedForVertexFit;
00363
00364 if (useGhostTrack) {
00365 GhostTrackState gtState(fitTrack);
00366 GlobalPoint pos =
00367 ipData[indices[i]].closestToGhostTrack;
00368 gtState.linearize(*gtPred, true,
00369 gtPred->lambda(pos));
00370 gtState.setWeight(ipData[indices[i]].ghostTrackWeight);
00371 gtStates.push_back(gtState);
00372 }
00373 }
00374
00375 std::auto_ptr<GhostTrack> ghostTrack;
00376 if (useGhostTrack)
00377 ghostTrack.reset(new GhostTrack(
00378 GhostTrackPrediction(
00379 RecoVertex::convertPos(pv.position()),
00380 RecoVertex::convertError(pv.error()),
00381 GlobalVector(
00382 iterJets->ghostTrack()->px(),
00383 iterJets->ghostTrack()->py(),
00384 iterJets->ghostTrack()->pz()),
00385 0.05),
00386 *gtPred, gtStates,
00387 iterJets->ghostTrack()->chi2(),
00388 iterJets->ghostTrack()->ndof()));
00389
00390
00391
00392
00393 std::vector<reco::Vertex> extAssoCollection;
00394 std::vector<TransientVertex> fittedSVs;
00395 std::vector<SecondaryVertex> SVs;
00396 if(!useExternalSV){
00397 switch(constraint) {
00398 case CONSTRAINT_NONE:
00399 if (useGhostTrack)
00400 fittedSVs = vertexRecoGT->vertices(
00401 pv, *ghostTrack);
00402 else
00403 fittedSVs = vertexReco->vertices(fitTracks);
00404 break;
00405
00406 case CONSTRAINT_BEAMSPOT:
00407 if (useGhostTrack)
00408 fittedSVs = vertexRecoGT->vertices(
00409 pv, *beamSpot, *ghostTrack);
00410 else
00411 fittedSVs = vertexReco->vertices(fitTracks,
00412 *beamSpot);
00413 break;
00414
00415 case CONSTRAINT_PV_BEAMSPOT_SIZE:
00416 case CONSTRAINT_PV_BS_Z_ERRORS_SCALED:
00417 case CONSTRAINT_PV_ERROR_SCALED: {
00418 BeamSpot::CovarianceMatrix cov;
00419 for(unsigned int i = 0; i < 7; i++) {
00420 unsigned int covSrc = bsCovSrc[i];
00421 for(unsigned int j = 0; j < 7; j++) {
00422 double v=0.0;
00423 if (!covSrc || bsCovSrc[j] != covSrc)
00424 v = 0.0;
00425 else if (covSrc == 1)
00426 v = beamSpot->covariance(i, j);
00427 else if (j<3 && i<3)
00428 v = pv.covariance(i, j) *
00429 constraintScaling;
00430 cov(i, j) = v;
00431 }
00432 }
00433
00434 BeamSpot bs(pv.position(), sigmaZ,
00435 beamSpot.isValid() ? beamSpot->dxdz() : 0.,
00436 beamSpot.isValid() ? beamSpot->dydz() : 0.,
00437 beamWidth, cov, BeamSpot::Unknown);
00438
00439 if (useGhostTrack)
00440 fittedSVs = vertexRecoGT->vertices(
00441 pv, bs, *ghostTrack);
00442 else
00443 fittedSVs = vertexReco->vertices(fitTracks, bs);
00444 } break;
00445
00446 case CONSTRAINT_PV_PRIMARIES_IN_FIT: {
00447 std::vector<TransientTrack> primaries_(
00448 primaries.begin(), primaries.end());
00449 if (useGhostTrack)
00450 fittedSVs = vertexRecoGT->vertices(
00451 pv, *beamSpot, primaries_,
00452 *ghostTrack);
00453 else
00454 fittedSVs = vertexReco->vertices(
00455 primaries_, fitTracks,
00456 *beamSpot);
00457 } break;
00458 }
00459
00460
00461
00462 SVBuilder svBuilder(pv, jetDir, withPVError);
00463 std::remove_copy_if(boost::make_transform_iterator(
00464 fittedSVs.begin(), svBuilder),
00465 boost::make_transform_iterator(
00466 fittedSVs.end(), svBuilder),
00467 std::back_inserter(SVs),
00468 SVFilter(vertexFilter, pv, jetDir));
00469
00470
00471 }else{
00472 for(size_t iExtSv = 0; iExtSv < extSecVertex->size(); iExtSv++){
00473 const reco::Vertex & extVertex = (*extSecVertex)[iExtSv];
00474
00475
00476
00477 if( Geom::deltaR( ( extVertex.position() - pv.position() ), jetDir ) > extSVDeltaRToJet || extVertex.p4().M() < 0.3)
00478 continue;
00479
00480 extAssoCollection.push_back( extVertex );
00481 }
00482 SVBuilder svBuilder(pv, jetDir, withPVError);
00483 std::remove_copy_if(boost::make_transform_iterator( extAssoCollection.begin(), svBuilder),
00484 boost::make_transform_iterator(extAssoCollection.end(), svBuilder),
00485 std::back_inserter(SVs),
00486 SVFilter(vertexFilter, pv, jetDir));
00487
00488
00489 }
00490
00491 gtPred.reset();
00492 ghostTrack.reset();
00493 gtStates.clear();
00494 fitTracks.clear();
00495 fittedSVs.clear();
00496 extAssoCollection.clear();
00497
00498
00499
00500 std::vector<unsigned int> vtxIndices = vertexSorting(SVs);
00501
00502 std::vector<SecondaryVertexTagInfo::VertexData> svData;
00503
00504 svData.resize(vtxIndices.size());
00505 for(unsigned int idx = 0; idx < vtxIndices.size(); idx++) {
00506 const SecondaryVertex &sv = SVs[vtxIndices[idx]];
00507
00508 svData[idx].vertex = sv;
00509 svData[idx].dist2d = sv.dist2d();
00510 svData[idx].dist3d = sv.dist3d();
00511 svData[idx].direction =
00512 GlobalVector(sv.x() - pv.x(),
00513 sv.y() - pv.y(),
00514 sv.z() - pv.z());
00515
00516
00517
00518 for(Vertex::trackRef_iterator iter = sv.tracks_begin();
00519 iter != sv.tracks_end(); iter++) {
00520 if (sv.trackWeight(*iter) < minTrackWeight)
00521 continue;
00522
00523 TrackRefVector::const_iterator pos =
00524 std::find(trackRefs.begin(), trackRefs.end(),
00525 iter->castTo<TrackRef>());
00526
00527 if (pos == trackRefs.end() ) {
00528 if(!useExternalSV)
00529 throw cms::Exception("TrackNotFound")
00530 << "Could not find track from secondary "
00531 "vertex in original tracks."
00532 << std::endl;
00533 } else {
00534 unsigned int index = pos - trackRefs.begin();
00535 trackData[index].second.svStatus =
00536 (SecondaryVertexTagInfo::TrackData::Status)
00537 ((unsigned int)SecondaryVertexTagInfo::TrackData::trackAssociatedToVertex + idx);
00538 }
00539 }
00540 }
00541
00542
00543
00544 tagInfos->push_back(
00545 SecondaryVertexTagInfo(
00546 trackData, svData, SVs.size(),
00547 TrackIPTagInfoRef(trackIPTagInfos,
00548 iterJets - trackIPTagInfos->begin())));
00549 }
00550
00551 event.put(tagInfos);
00552 }
00553
00554
00555 DEFINE_FWK_MODULE(SecondaryVertexProducer);