Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
#include "Alignment/CommonAlignmentProducer/interface/AlignmentTracksFromVertexSelector.h"

#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"

#include "FWCore/Framework/interface/Event.h"
#include "DataFormats/TrackReco/interface/Track.h"

#include "RecoVertex/VertexPrimitives/interface/TransientVertex.h"
#include "RecoVertex/KalmanVertexFit/interface/KalmanVertexFitter.h"

// vertices
#include "RecoVertex/VertexTools/interface/VertexDistanceXY.h"
#include "RecoVertex/VertexTools/interface/VertexDistance3D.h"

// constructor ----------------------------------------------------------------
AlignmentTrackFromVertexSelector::AlignmentTrackFromVertexSelector(const edm::ParameterSet& cfg,
                                                                   edm::ConsumesCollector& iC)
    : ttbESToken_(
          iC.esConsumes<TransientTrackBuilder, TransientTrackRecord>(edm::ESInputTag("", "TransientTrackBuilder"))),
      vertexToken_(iC.consumes<reco::VertexCollection>(cfg.getParameter<edm::InputTag>("vertices"))),
      diLeptonToken_(iC.consumes<reco::TrackCollection>(cfg.getParameter<edm::InputTag>("leptonTracks"))),
      useClosestVertex_(cfg.getParameter<bool>("useClosestVertexToDilepton")),
      vertexIndex_(cfg.getParameter<unsigned int>("vertexIndex")) {}

// destructor -----------------------------------------------------------------
AlignmentTrackFromVertexSelector::~AlignmentTrackFromVertexSelector() {}

// compute the closest vertex to di-lepton ------------------------------------
const reco::Vertex* AlignmentTrackFromVertexSelector::findClosestVertex(const reco::TrackCollection& leptonTracks,
                                                                        const reco::VertexCollection* vertices,
                                                                        const edm::EventSetup& setup) const {
  reco::Vertex* defaultVtx = nullptr;

  // fill the transient track collection with the lepton tracks
  const TransientTrackBuilder* theB = &setup.getData(ttbESToken_);
  std::vector<reco::TransientTrack> tks;
  for (const auto& track : leptonTracks) {
    reco::TransientTrack trajectory = theB->build(track);
    tks.push_back(trajectory);
  }

  // compute the secondary vertex
  TransientVertex aTransVtx;
  KalmanVertexFitter kalman(true);
  aTransVtx = kalman.vertex(tks);

  if (!aTransVtx.isValid())
    return defaultVtx;

  // find the closest vertex to the secondary vertex in 3D
  VertexDistance3D vertTool3D;
  float minD = 9999.;
  int closestVtxIndex = 0;
  int counter = 0;
  for (const auto& vtx : *vertices) {
    double dist3D = vertTool3D.distance(aTransVtx, vtx).value();
    if (dist3D < minD) {
      minD = dist3D;
      closestVtxIndex = counter;
    }
    counter++;
  }
  if ((*vertices).at(closestVtxIndex).isValid()) {
    return &(vertices->at(closestVtxIndex));
  } else {
    return defaultVtx;
  }
}

// do selection ---------------------------------------------------------------
AlignmentTrackFromVertexSelector::Tracks AlignmentTrackFromVertexSelector::select(
    const edm::Handle<reco::TrackCollection>& tc, const edm::Event& evt, const edm::EventSetup& setup) const {
  Tracks result;

  std::vector<unsigned int> thePVkeys;

  // get collection of reconstructed vertices from event
  edm::Handle<reco::VertexCollection> vertexHandle = evt.getHandle(vertexToken_);

  // get collection of the di-lepton traxks
  const auto& leptonTracks = evt.get(diLeptonToken_);

  // fill the vector of keys
  if (vertexHandle.isValid()) {
    const reco::VertexCollection* vertices = vertexHandle.product();
    const reco::Vertex* theVtx = nullptr;

    if (useClosestVertex_) {
      theVtx = findClosestVertex(leptonTracks, vertices, setup);
    } else {
      if ((*vertices).at(vertexIndex_).isValid()) {
        theVtx = &(vertices->at(vertexIndex_));
      }
    }

    if (theVtx) {
      for (auto tv = theVtx->tracks_begin(); tv != theVtx->tracks_end(); tv++) {
        if (tv->isNonnull()) {
          const reco::TrackRef trackRef = tv->castTo<reco::TrackRef>();
          thePVkeys.push_back(trackRef.key());
        }
      }
    }
  }

  std::sort(thePVkeys.begin(), thePVkeys.end());

  LogDebug("AlignmentTrackFromVertexSelector")
      << "after collecting the PV keys: thePVkeys.size()" << thePVkeys.size() << std::endl;
  for (const auto& key : thePVkeys) {
    LogDebug("AlignmentTrackFromVertexSelector") << key << ", ";
  }
  LogDebug("AlignmentTrackFromVertexSelector") << std::endl;

  if (tc.isValid()) {
    int indx(0);
    // put the track in the collection is it was used for the vertex
    for (reco::TrackCollection::const_iterator tk = tc->begin(); tk != tc->end(); ++tk, ++indx) {
      reco::TrackRef trackRef = reco::TrackRef(tc, indx);
      if (std::find(thePVkeys.begin(), thePVkeys.end(), trackRef.key()) != thePVkeys.end()) {
        LogDebug("AlignmentTrackFromVertexSelector") << "track index: " << indx << "filling result vector" << std::endl;
        result.push_back(&(*tk));
      }  // if a valid key is found
    }  // end loop over tracks
  }  // if the handle is valid
  return result;
}