00001 #include "RecoTracker/FinalTrackSelectors/interface/AnalyticalTrackSelector.h"
00002
00003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00004 #include <Math/DistFunc.h>
00005 #include "TMath.h"
00006
00007 using reco::modules::AnalyticalTrackSelector;
00008
00009 AnalyticalTrackSelector::AnalyticalTrackSelector( const edm::ParameterSet & cfg ) :
00010 src_( cfg.getParameter<edm::InputTag>( "src" ) ),
00011 beamspot_( cfg.getParameter<edm::InputTag>( "beamspot" ) ),
00012 vertices_( cfg.getParameter<edm::InputTag>( "vertices" ) ),
00013 copyExtras_(cfg.getUntrackedParameter<bool>("copyExtras", false)),
00014 copyTrajectories_(cfg.getUntrackedParameter<bool>("copyTrajectories", false)),
00015 keepAllTracks_( cfg.exists("keepAllTracks") ?
00016 cfg.getParameter<bool>("keepAllTracks") :
00017 false ),
00018 setQualityBit_( false ),
00019 qualityToSet_( TrackBase::undefQuality ),
00020
00021 vtxNumber_( cfg.getParameter<int32_t>("vtxNumber") ),
00022 vertexCut_(cfg.getParameter<std::string>("vertexCut")),
00023
00024 res_par_(cfg.getParameter< std::vector<double> >("res_par") ),
00025 chi2n_par_( cfg.getParameter<double>("chi2n_par") ),
00026 d0_par1_(cfg.getParameter< std::vector<double> >("d0_par1")),
00027 dz_par1_(cfg.getParameter< std::vector<double> >("dz_par1")),
00028 d0_par2_(cfg.getParameter< std::vector<double> >("d0_par2")),
00029 dz_par2_(cfg.getParameter< std::vector<double> >("dz_par2")),
00030
00031 applyAdaptedPVCuts_(cfg.getParameter<bool>("applyAdaptedPVCuts")),
00032
00033 max_d0_(cfg.getParameter<double>("max_d0")),
00034 max_z0_(cfg.getParameter<double>("max_z0")),
00035 nSigmaZ_(cfg.getParameter<double>("nSigmaZ")),
00036
00037 min_layers_(cfg.getParameter<uint32_t>("minNumberLayers") ),
00038 min_3Dlayers_(cfg.getParameter<uint32_t>("minNumber3DLayers") ),
00039 max_lostLayers_(cfg.getParameter<uint32_t>("maxNumberLostLayers")),
00040
00041 applyAbsCutsIfNoPV_(cfg.getParameter<bool>("applyAbsCutsIfNoPV"))
00042 {
00043 if (cfg.exists("qualityBit")) {
00044 std::string qualityStr = cfg.getParameter<std::string>("qualityBit");
00045 if (qualityStr != "") {
00046 setQualityBit_ = true;
00047 qualityToSet_ = TrackBase::qualityByName(cfg.getParameter<std::string>("qualityBit"));
00048 }
00049 }
00050 if (keepAllTracks_ && !setQualityBit_) throw cms::Exception("Configuration") <<
00051 "If you set 'keepAllTracks' to true, you must specify which qualityBit to set.\n";
00052 if (setQualityBit_ && (qualityToSet_ == TrackBase::undefQuality)) throw cms::Exception("Configuration") <<
00053 "You can't set the quality bit " << cfg.getParameter<std::string>("qualityBit") << " as it is 'undefQuality' or unknown.\n";
00054 if (applyAbsCutsIfNoPV_) {
00055 max_d0NoPV_ = cfg.getParameter<double>("max_d0NoPV");
00056 max_z0NoPV_ = cfg.getParameter<double>("max_z0NoPV");
00057 }
00058
00059 std::string alias( cfg.getParameter<std::string>( "@module_label" ) );
00060 produces<reco::TrackCollection>().setBranchAlias( alias + "Tracks");
00061 if (copyExtras_) {
00062 produces<reco::TrackExtraCollection>().setBranchAlias( alias + "TrackExtras");
00063 produces<TrackingRecHitCollection>().setBranchAlias( alias + "RecHits");
00064 }
00065 if (copyTrajectories_) {
00066 produces< std::vector<Trajectory> >().setBranchAlias( alias + "Trajectories");
00067 produces< TrajTrackAssociationCollection >().setBranchAlias( alias + "TrajectoryTrackAssociations");
00068 }
00069
00070 }
00071
00072 AnalyticalTrackSelector::~AnalyticalTrackSelector() {
00073 }
00074
00075 void AnalyticalTrackSelector::produce( edm::Event& evt, const edm::EventSetup& es )
00076 {
00077 using namespace std;
00078 using namespace edm;
00079 using namespace reco;
00080
00081 Handle<TrackCollection> hSrcTrack;
00082 Handle< vector<Trajectory> > hTraj;
00083 Handle< vector<Trajectory> > hTrajP;
00084 Handle< TrajTrackAssociationCollection > hTTAss;
00085
00086
00087 edm::Handle<reco::BeamSpot> hBsp;
00088 evt.getByLabel(beamspot_, hBsp);
00089 reco::BeamSpot vertexBeamSpot;
00090 vertexBeamSpot = *hBsp;
00091
00092
00093 edm::Handle<reco::VertexCollection> hVtx;
00094 evt.getByLabel(vertices_, hVtx);
00095 std::vector<Point> points;
00096 selectVertices(*hVtx, points);
00097
00098 LogDebug("SelectVertex") << points.size() << " good pixel vertices";
00099
00100
00101 evt.getByLabel( src_, hSrcTrack );
00102
00103 selTracks_ = auto_ptr<TrackCollection>(new TrackCollection());
00104 rTracks_ = evt.getRefBeforePut<TrackCollection>();
00105 if (copyExtras_) {
00106 selTrackExtras_ = auto_ptr<TrackExtraCollection>(new TrackExtraCollection());
00107 selHits_ = auto_ptr<TrackingRecHitCollection>(new TrackingRecHitCollection());
00108 rHits_ = evt.getRefBeforePut<TrackingRecHitCollection>();
00109 rTrackExtras_ = evt.getRefBeforePut<TrackExtraCollection>();
00110 }
00111
00112 if (copyTrajectories_) trackRefs_.resize(hSrcTrack->size());
00113
00114
00115 size_t current = 0;
00116 for (TrackCollection::const_iterator it = hSrcTrack->begin(), ed = hSrcTrack->end(); it != ed; ++it, ++current) {
00117 const Track & trk = * it;
00118
00119
00120 LogTrace("TrackSelection") << "ready to check track with pt="<< trk.pt() ;
00121
00122 bool ok = select(vertexBeamSpot, trk, points);
00123 if (!ok) {
00124
00125 LogTrace("TrackSelection") << "track with pt="<< trk.pt() << " NOT selected";
00126
00127 if (copyTrajectories_) trackRefs_[current] = reco::TrackRef();
00128 if (!keepAllTracks_) continue;
00129 }
00130 LogTrace("TrackSelection") << "track with pt="<< trk.pt() << " selected";
00131 selTracks_->push_back( Track( trk ) );
00132 if (ok && setQualityBit_) {
00133 selTracks_->back().setQuality(qualityToSet_);
00134 if (!points.empty()) {
00135 if (qualityToSet_==TrackBase::loose) selTracks_->back().setQuality(TrackBase::looseSetWithPV);
00136 else if (qualityToSet_==TrackBase::highPurity) selTracks_->back().setQuality(TrackBase::highPuritySetWithPV);
00137 }
00138 }
00139 if (copyExtras_) {
00140
00141 selTrackExtras_->push_back( TrackExtra( trk.outerPosition(), trk.outerMomentum(), trk.outerOk(),
00142 trk.innerPosition(), trk.innerMomentum(), trk.innerOk(),
00143 trk.outerStateCovariance(), trk.outerDetId(),
00144 trk.innerStateCovariance(), trk.innerDetId(),
00145 trk.seedDirection(), trk.seedRef() ) );
00146 selTracks_->back().setExtra( TrackExtraRef( rTrackExtras_, selTrackExtras_->size() - 1) );
00147 TrackExtra & tx = selTrackExtras_->back();
00148 tx.setResiduals(trk.residuals());
00149
00150 for( trackingRecHit_iterator hit = trk.recHitsBegin(); hit != trk.recHitsEnd(); ++ hit ) {
00151 selHits_->push_back( (*hit)->clone() );
00152 tx.add( TrackingRecHitRef( rHits_, selHits_->size() - 1) );
00153 }
00154 }
00155 if (copyTrajectories_) {
00156 trackRefs_[current] = TrackRef(rTracks_, selTracks_->size() - 1);
00157 }
00158 }
00159 if ( copyTrajectories_ ) {
00160 Handle< vector<Trajectory> > hTraj;
00161 Handle< TrajTrackAssociationCollection > hTTAss;
00162 evt.getByLabel(src_, hTTAss);
00163 evt.getByLabel(src_, hTraj);
00164 selTrajs_ = auto_ptr< vector<Trajectory> >(new vector<Trajectory>());
00165 rTrajectories_ = evt.getRefBeforePut< vector<Trajectory> >();
00166 selTTAss_ = auto_ptr< TrajTrackAssociationCollection >(new TrajTrackAssociationCollection());
00167 for (size_t i = 0, n = hTraj->size(); i < n; ++i) {
00168 Ref< vector<Trajectory> > trajRef(hTraj, i);
00169 TrajTrackAssociationCollection::const_iterator match = hTTAss->find(trajRef);
00170 if (match != hTTAss->end()) {
00171 const Ref<TrackCollection> &trkRef = match->val;
00172 short oldKey = static_cast<short>(trkRef.key());
00173 if (trackRefs_[oldKey].isNonnull()) {
00174 selTrajs_->push_back( Trajectory(*trajRef) );
00175 selTTAss_->insert ( Ref< vector<Trajectory> >(rTrajectories_, selTrajs_->size() - 1), trackRefs_[oldKey] );
00176 }
00177 }
00178 }
00179 }
00180
00181 static const std::string emptyString;
00182 evt.put(selTracks_);
00183 if (copyExtras_ ) {
00184 evt.put(selTrackExtras_);
00185 evt.put(selHits_);
00186 }
00187 if ( copyTrajectories_ ) {
00188 evt.put(selTrajs_);
00189 evt.put(selTTAss_);
00190 }
00191 }
00192
00193
00194 bool AnalyticalTrackSelector::select(const reco::BeamSpot &vertexBeamSpot, const reco::Track &tk, const std::vector<Point> &points) {
00195
00196
00197 using namespace std;
00198
00199 if ( tk.ndof() < 1E-5 ) return false;
00200
00201
00202 uint32_t nlayers = tk.hitPattern().trackerLayersWithMeasurement();
00203 uint32_t nlayers3D = tk.hitPattern().pixelLayersWithMeasurement() +
00204 tk.hitPattern().numberOfValidStripLayersWithMonoAndStereo();
00205 uint32_t nlayersLost = tk.hitPattern().trackerLayersWithoutMeasurement();
00206 LogDebug("TrackSelection") << "cuts on nlayers: " << nlayers << " " << nlayers3D << " " << nlayersLost << " vs "
00207 << min_layers_ << " " << min_3Dlayers_ << " " << max_lostLayers_;
00208 if (nlayers < min_layers_) return false;
00209 if (nlayers3D < min_3Dlayers_) return false;
00210 if (nlayersLost > max_lostLayers_) return false;
00211 LogTrace("TrackSelection") << "cuts on nlayers passed";
00212
00213 double chi2n = tk.normalizedChi2();
00214
00215 int count1dhits = 0;
00216 for (trackingRecHit_iterator ith = tk.recHitsBegin(), edh = tk.recHitsEnd(); ith != edh; ++ith) {
00217 const TrackingRecHit * hit = ith->get();
00218 DetId detid = hit->geographicalId();
00219 if (hit->isValid()) {
00220 if (typeid(*hit) == typeid(SiStripRecHit1D)) ++count1dhits;
00221 }
00222 }
00223 if (count1dhits > 0) {
00224 double chi2 = tk.chi2();
00225 double ndof = tk.ndof();
00226 chi2n = (chi2+count1dhits)/double(ndof+count1dhits);
00227 }
00228
00229
00230 if (chi2n > chi2n_par_*nlayers) return false;
00231
00232
00233 double pt = tk.pt(), eta = tk.eta();
00234 double d0 = -tk.dxy(vertexBeamSpot.position()), d0E = tk.d0Error(),
00235 dz = tk.dz(vertexBeamSpot.position()), dzE = tk.dzError();
00236
00237
00238 double nomd0E = sqrt(res_par_[0]*res_par_[0]+(res_par_[1]/max(pt,1e-9))*(res_par_[1]/max(pt,1e-9)));
00239
00240 double nomdzE = nomd0E*(std::cosh(eta));
00241
00242 double dzCut = min( pow(dz_par1_[0]*nlayers,dz_par1_[1])*nomdzE,
00243 pow(dz_par2_[0]*nlayers,dz_par2_[1])*dzE );
00244 double d0Cut = min( pow(d0_par1_[0]*nlayers,d0_par1_[1])*nomd0E,
00245 pow(d0_par2_[0]*nlayers,d0_par2_[1])*d0E );
00246
00247
00248
00249 bool primaryVertexZCompatibility(false);
00250 bool primaryVertexD0Compatibility(false);
00251
00252 if (points.empty()) {
00253
00254 if ( abs(dz) < hypot(vertexBeamSpot.sigmaZ()*nSigmaZ_,dzCut) ) primaryVertexZCompatibility = true;
00255
00256 if (abs(d0) < d0Cut) primaryVertexD0Compatibility = true;
00257 }
00258
00259 for (std::vector<Point>::const_iterator point = points.begin(), end = points.end(); point != end; ++point) {
00260 LogTrace("TrackSelection") << "Test track w.r.t. vertex with z position " << point->z();
00261 if(primaryVertexZCompatibility && primaryVertexD0Compatibility) break;
00262 double dzPV = tk.dz(*point);
00263 double d0PV = tk.dxy(*point);
00264 if (abs(dzPV) < dzCut) primaryVertexZCompatibility = true;
00265 if (abs(d0PV) < d0Cut) primaryVertexD0Compatibility = true;
00266 LogTrace("TrackSelection") << "distances " << dzPV << " " << d0PV << " vs " << dzCut << " " << d0Cut;
00267 }
00268
00269 if (points.empty() && applyAbsCutsIfNoPV_) {
00270 if ( abs(dz) > max_z0NoPV_ || abs(d0) > max_d0NoPV_) return false;
00271 } else {
00272
00273
00274 if (abs(d0) > max_d0_ && !primaryVertexD0Compatibility) return false;
00275 LogTrace("TrackSelection") << "absolute cuts on d0 passed";
00276 if (abs(dz) > max_z0_ && !primaryVertexZCompatibility) return false;
00277 LogTrace("TrackSelection") << "absolute cuts on dz passed";
00278 }
00279
00280 LogTrace("TrackSelection") << "cuts on PV: apply adapted PV cuts? " << applyAdaptedPVCuts_
00281 << " d0 compatibility? " << primaryVertexD0Compatibility
00282 << " z compatibility? " << primaryVertexZCompatibility ;
00283
00284 if (applyAdaptedPVCuts_) {
00285 return (primaryVertexD0Compatibility && primaryVertexZCompatibility);
00286 } else {
00287 return true;
00288 }
00289
00290 }
00291
00292 void AnalyticalTrackSelector::selectVertices(const reco::VertexCollection &vtxs, std::vector<Point> &points) {
00293
00294 using namespace reco;
00295 int32_t toTake = vtxNumber_;
00296 for (VertexCollection::const_iterator it = vtxs.begin(), ed = vtxs.end(); it != ed; ++it) {
00297
00298 LogDebug("SelectVertex") << " select vertex with z position " << it->z() << " "
00299 << it->chi2() << " " << it->ndof() << " " << TMath::Prob(it->chi2(), static_cast<int32_t>(it->ndof()));
00300 Vertex vtx = *it;
00301 bool pass = vertexCut_( vtx );
00302 if( pass ) {
00303 points.push_back(it->position());
00304 LogTrace("SelectVertex") << " SELECTED vertex with z position " << it->z();
00305 toTake--; if (toTake == 0) break;
00306 }
00307 }
00308 }