CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/RecoTracker/FinalTrackSelectors/src/AnalyticalTrackSelector.cc

Go to the documentation of this file.
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 ),  // as this is what you expect from a well behaved selector
00018   setQualityBit_( false ),
00019   qualityToSet_( TrackBase::undefQuality ),
00020   // parameters for vertex selection
00021   vtxNumber_( cfg.getParameter<int32_t>("vtxNumber") ),
00022   vertexCut_(cfg.getParameter<std::string>("vertexCut")),
00023   //  parameters for adapted optimal cuts on chi2 and primary vertex compatibility
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   // Boolean indicating if adapted primary vertex compatibility cuts are to be applied.
00031   applyAdaptedPVCuts_(cfg.getParameter<bool>("applyAdaptedPVCuts")),
00032   // Impact parameter absolute cuts.
00033   max_d0_(cfg.getParameter<double>("max_d0")),
00034   max_z0_(cfg.getParameter<double>("max_z0")),
00035   nSigmaZ_(cfg.getParameter<double>("nSigmaZ")),
00036   // Cuts on numbers of layers with hits/3D hits/lost hits.
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   // Flag to apply absolute cuts if no PV passes the selection
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   // looking for the beam spot
00087   edm::Handle<reco::BeamSpot> hBsp;
00088   evt.getByLabel(beamspot_, hBsp);
00089   reco::BeamSpot vertexBeamSpot;
00090   vertexBeamSpot = *hBsp;
00091         
00092   // Select good primary vertices for use in subsequent track selection
00093   edm::Handle<reco::VertexCollection> hVtx;
00094   evt.getByLabel(vertices_, hVtx);
00095   std::vector<Point> points;
00096   selectVertices(*hVtx, points);
00097   // Debug 
00098   LogDebug("SelectVertex") << points.size() << " good pixel vertices";
00099 
00100   // Get tracks 
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   // Loop over tracks
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     // Check if this track passes cuts
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 ) ); // clone and store
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       // TrackExtras
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       // TrackingRecHits
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   // Decide if the given track passes selection cuts.
00196 
00197   using namespace std; 
00198 
00199   if ( tk.ndof() < 1E-5 ) return false;
00200 
00201   // Cuts on numbers of layers with hits/3D hits/lost hits.
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   // For each 1D rechit, the chi^2 and ndof is increased by one.  This is a way of retaining approximately
00229   // the same normalized chi^2 distribution as with 2D rechits.
00230   if (chi2n > chi2n_par_*nlayers) return false;
00231 
00232   // Get track parameters
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   // parametrized d0 resolution for the track pt
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   // parametrized z0 resolution for the track pt and eta
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   // ---- PrimaryVertex compatibility cut
00249   bool primaryVertexZCompatibility(false);   
00250   bool primaryVertexD0Compatibility(false);   
00251 
00252   if (points.empty()) { //If not primaryVertices are reconstructed, check just the compatibility with the BS
00253     //z0 within (n sigma + dzCut) of the beam spot z, if no good vertex is found
00254     if ( abs(dz) < hypot(vertexBeamSpot.sigmaZ()*nSigmaZ_,dzCut) ) primaryVertexZCompatibility = true;  
00255     // d0 compatibility with beam line
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); //re-evaluate the dz with respect to the vertex position
00263     double d0PV = tk.dxy(*point); //re-evaluate the dxy with respect to the vertex position
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     // Absolute cuts on all tracks impact parameters with respect to beam-spot.
00273     // If BS is not compatible, verify if at least the reco-vertex is compatible (useful for incorrect BS settings)
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   // Select good primary vertices
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 }