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