CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/RecoVertex/NuclearInteractionProducer/src/NuclearVertexBuilder.cc

Go to the documentation of this file.
00001 #include "RecoVertex/NuclearInteractionProducer/interface/NuclearVertexBuilder.h"
00002 #include "TrackingTools/TrajectoryState/interface/FreeTrajectoryState.h"
00003 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00004 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
00005 #include "RecoVertex/VertexPrimitives/interface/TransientVertex.h"
00006 #include "RecoVertex/AdaptiveVertexFit/interface/AdaptiveVertexFitter.h"
00007 
00008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00009 
00010 void NuclearVertexBuilder::build( const reco::TrackRef& primTrack, std::vector<reco::TrackRef>& secTracks) {
00011 
00012      cleanTrackCollection(primTrack, secTracks); 
00013      std::sort(secTracks.begin(),secTracks.end(),cmpTracks());
00014      checkEnergy(primTrack, secTracks);
00015 
00016      if( secTracks.size() != 0) {
00017          if( FillVertexWithAdaptVtxFitter(primTrack, secTracks) ) return;
00018          else if( FillVertexWithCrossingPoint(primTrack, secTracks) ) return;
00019          else FillVertexWithLastPrimHit( primTrack, secTracks);
00020      }
00021      else {
00022        // if no secondary tracks : vertex position = position of last rechit of the primary track 
00023        FillVertexWithLastPrimHit( primTrack, secTracks);
00024      }
00025 }
00026           
00027 FreeTrajectoryState NuclearVertexBuilder::getTrajectory(const reco::TrackRef& track) const
00028 { 
00029   GlobalPoint position(track->vertex().x(),
00030                        track->vertex().y(),
00031                        track->vertex().z());
00032 
00033   GlobalVector momentum(track->momentum().x(),
00034                         track->momentum().y(),
00035                         track->momentum().z());
00036 
00037   GlobalTrajectoryParameters gtp(position,momentum,
00038                                  track->charge(),theMagField);
00039   
00040   FreeTrajectoryState fts(gtp);
00041 
00042   return fts; 
00043 } 
00044 
00045 void NuclearVertexBuilder::FillVertexWithLastPrimHit(const reco::TrackRef& primTrack, const std::vector<reco::TrackRef>& secTracks) {
00046    LogDebug("NuclearInteractionMaker") << "Vertex build from the end point of the primary track";
00047        the_vertex = reco::Vertex(reco::Vertex::Point(primTrack->outerPosition().x(),
00048                                          primTrack->outerPosition().y(),
00049                                          primTrack->outerPosition().z()),
00050                                          reco::Vertex::Error(), 0.,0.,0);
00051        the_vertex.add(reco::TrackBaseRef( primTrack ), 1.0);
00052        for( unsigned short i=0; i != secTracks.size(); i++) {
00053              the_vertex.add(reco::TrackBaseRef( secTracks[i] ), 0.0);
00054        }
00055 }
00056 
00057 bool NuclearVertexBuilder::FillVertexWithAdaptVtxFitter(const reco::TrackRef& primTrack, const std::vector<reco::TrackRef>& secTracks) {
00058          std::vector<reco::TransientTrack> transientTracks;
00059          transientTracks.push_back( theTransientTrackBuilder->build(primTrack));
00060          // get the secondary track with the max number of hits
00061          for( unsigned short i=0; i != secTracks.size(); i++ ) {
00062               transientTracks.push_back( theTransientTrackBuilder->build( secTracks[i]) );
00063          }
00064          if( transientTracks.size() == 1 ) return  false;
00065          AdaptiveVertexFitter AVF;
00066          try {
00067             TransientVertex tv = AVF.vertex(transientTracks);
00068             the_vertex = reco::Vertex(tv);
00069          }
00070          catch(VertexException& exception){
00071             // AdaptivevertexFitter does not work
00072             LogDebug("NuclearInteractionMaker") << exception.what() << "\n";
00073             return false;
00074          }
00075          catch( cms::Exception& exception){
00076             // AdaptivevertexFitter does not work
00077             LogDebug("NuclearInteractionMaker") << exception.what() << "\n";
00078             return false;
00079          }
00080          if( the_vertex.isValid() ) {
00081               LogDebug("NuclearInteractionMaker") << "Try to build from AdaptiveVertexFitter with " << the_vertex.tracksSize() << " tracks";
00082               return true;
00083            }
00084          else return false;
00085 }
00086 
00087 
00088 bool NuclearVertexBuilder::FillVertexWithCrossingPoint(const reco::TrackRef& primTrack, const std::vector<reco::TrackRef>& secTracks) {
00089             FreeTrajectoryState primTraj = getTrajectory(primTrack);
00090 
00091             // get the secondary track with the max number of hits
00092             unsigned short maxHits = 0; int indice=-1;
00093             for( unsigned short i=0; i < secTracks.size(); i++) {
00094                    // Add references to daughters
00095                    unsigned short nhits = secTracks[i]->numberOfValidHits();
00096                    if( nhits > maxHits ) { maxHits = nhits; indice=i; }
00097             }
00098 
00099             // Closest points
00100             if(indice == -1) return false;
00101 
00102             ClosestApproachInRPhi* theApproach = closestApproach( primTrack, secTracks[indice]);
00103             GlobalPoint crossing = theApproach->crossingPoint();
00104             delete theApproach;
00105 
00106             // Create vertex (creation point)
00107             // TODO: add error
00108             the_vertex = reco::Vertex(reco::Vertex::Point(crossing.x(),
00109                                                           crossing.y(),
00110                                                           crossing.z()),
00111                                       reco::Vertex::Error(), 0.,0.,0);
00112 
00113             the_vertex.add(reco::TrackBaseRef( primTrack ), 1.0);
00114             for( unsigned short i=0; i < secTracks.size(); i++) {
00115                  if( i==indice ) the_vertex.add(reco::TrackBaseRef( secTracks[i] ), 1.0);
00116                  else the_vertex.add(reco::TrackBaseRef( secTracks[i] ), 0.0);
00117             }
00118             return true;
00119 }
00120 
00121 ClosestApproachInRPhi* NuclearVertexBuilder::closestApproach( const reco::TrackRef& primTrack, const reco::TrackRef& secTrack )  const{
00122             FreeTrajectoryState primTraj = getTrajectory(primTrack);
00123             ClosestApproachInRPhi *theApproach = new ClosestApproachInRPhi();
00124             FreeTrajectoryState secTraj = getTrajectory(secTrack);
00125             bool status = theApproach->calculate(primTraj,secTraj);
00126             if( status ) { return theApproach; }
00127             else { 
00128                    return NULL;
00129             }
00130 }
00131 
00132 bool NuclearVertexBuilder::isGoodSecondaryTrack( const reco::TrackRef& primTrack, const reco::TrackRef& secTrack ) const {
00133            ClosestApproachInRPhi* theApproach = closestApproach(primTrack, secTrack);
00134            bool result = false;
00135            if(theApproach)
00136              result = isGoodSecondaryTrack(secTrack, primTrack, theApproach->distance() , theApproach->crossingPoint());
00137            delete theApproach;
00138            return result;
00139 } 
00140 
00141 bool NuclearVertexBuilder::isGoodSecondaryTrack( const reco::TrackRef& secTrack, 
00142                                                  const reco::TrackRef& primTrack, 
00143                                                  const double& distOfClosestApp, 
00144                                                  const GlobalPoint& crossPoint ) const {
00145           float TRACKER_RADIUS=129;
00146           double pt2 = secTrack->pt();
00147           double Dpt2 = secTrack->ptError();
00148           double p1 = primTrack->p();
00149           double Dp1 = primTrack->qoverpError()*p1*p1;
00150           double p2 = secTrack->p();
00151           double Dp2 = secTrack->qoverpError()*p2*p2;
00152           std::cout << "1)" << distOfClosestApp << " < " << minDistFromPrim_ << " " << (distOfClosestApp < minDistFromPrim_)  << "\n";
00153           std::cout << "2)" << secTrack->normalizedChi2() << " < " << chi2Cut_ << " " << (secTrack->normalizedChi2() < chi2Cut_) << "\n";
00154           std::cout << "3)" << crossPoint.perp() << " < " << TRACKER_RADIUS << " " << (crossPoint.perp() < TRACKER_RADIUS) << "\n";
00155           std::cout << "4)" << (Dpt2/pt2) << " < " << DPtovPtCut_ << " " << ((Dpt2/pt2) < DPtovPtCut_)  << "\n";
00156           std::cout << "5)" << (p2-2*Dp2) << " < " << (p1+2*Dp1) << " " << ((p2-2*Dp2) < (p1+2*Dp1))<< "\n";
00157           if( distOfClosestApp < minDistFromPrim_ &&
00158               secTrack->normalizedChi2() < chi2Cut_ && 
00159               crossPoint.perp() < TRACKER_RADIUS && 
00160               (Dpt2/pt2) < DPtovPtCut_ &&
00161               (p2-2*Dp2) < (p1+2*Dp1)) return true;
00162           else return false;
00163 }
00164 
00165 
00166 bool NuclearVertexBuilder::isCompatible( const reco::TrackRef& secTrack ) const{
00167          
00168          reco::TrackRef primTrack = (*(the_vertex.tracks_begin())).castTo<reco::TrackRef>();
00169          ClosestApproachInRPhi *theApproach = closestApproach(primTrack, secTrack);
00170          bool result = false;
00171          if( theApproach ) {
00172            GlobalPoint crp = theApproach->crossingPoint();
00173            math::XYZPoint vtx = the_vertex.position();
00174            float dist = sqrt((crp.x()-vtx.x())*(crp.x()-vtx.x()) +
00175                         (crp.y()-vtx.y())*(crp.y()-vtx.y()) +
00176                         (crp.z()-vtx.z())*(crp.z()-vtx.z()));
00177 
00178            float distError = sqrt(the_vertex.xError()*the_vertex.xError() +
00179                                   the_vertex.yError()*the_vertex.yError() +
00180                                   the_vertex.zError()*the_vertex.zError());
00181  
00182            //std::cout << "Distance between Additional track and vertex =" << dist << " +/- " << distError << std::endl;
00183            // TODO : add condition on distance between last rechit of the primary and the first rec hit of the secondary
00184  
00185            result = (isGoodSecondaryTrack(secTrack, primTrack, theApproach->distance(), crp) 
00186                      && dist-distError<minDistFromVtx_);
00187          }
00188          delete theApproach;
00189          return result;
00190 }
00191 
00192 void NuclearVertexBuilder::addSecondaryTrack( const reco::TrackRef& secTrack ) {
00193         std::vector<reco::TrackRef> allSecondary;
00194         for( reco::Vertex::trackRef_iterator it=the_vertex.tracks_begin()+1; it != the_vertex.tracks_end(); it++) {
00195             allSecondary.push_back( (*it).castTo<reco::TrackRef>() );
00196         } 
00197         allSecondary.push_back( secTrack );
00198         build( (*the_vertex.tracks_begin()).castTo<reco::TrackRef>(), allSecondary );
00199 }
00200 
00201 void NuclearVertexBuilder::cleanTrackCollection( const reco::TrackRef& primTrack, 
00202                                                  std::vector<reco::TrackRef>& tC) const {
00203 
00204     // inspired from FinalTrackSelector (S. Wagner) modified by P. Janot
00205     LogDebug("NuclearInteractionMaker") << "cleanTrackCollection number of input tracks : " << tC.size();
00206    std::map<std::vector<reco::TrackRef>::const_iterator, std::vector<const TrackingRecHit*> > rh;
00207 
00208     // first remove bad quality tracks and create map
00209     std::vector<bool> selected(tC.size(), false);
00210     int i=0;
00211     for (std::vector<reco::TrackRef>::const_iterator track=tC.begin(); track!=tC.end(); track++){
00212        if( isGoodSecondaryTrack(primTrack, *track)) { 
00213             selected[i]=true;
00214             trackingRecHit_iterator itB = (*track)->recHitsBegin();
00215             trackingRecHit_iterator itE = (*track)->recHitsEnd();
00216             for (trackingRecHit_iterator it = itB;  it != itE; ++it) {
00217                const TrackingRecHit* hit = &(**it);
00218                rh[track].push_back(hit);
00219             }
00220         }
00221        i++;
00222     }
00223 
00224     // then remove duplicated tracks
00225     i=-1;
00226     for (std::vector<reco::TrackRef>::const_iterator track=tC.begin(); track!=tC.end(); track++){
00227       i++;
00228       int j=-1;
00229       for (std::vector<reco::TrackRef>::const_iterator track2=tC.begin(); track2!=tC.end(); track2++){
00230         j++;
00231         if ((!selected[j])||(!selected[i]))continue;
00232         if ((j<=i))continue;
00233         int noverlap=0;
00234         std::vector<const TrackingRecHit*>& iHits = rh[track];
00235         for ( unsigned ih=0; ih<iHits.size(); ++ih ) {
00236           const TrackingRecHit* it = iHits[ih];
00237           if (it->isValid()){
00238             std::vector<const TrackingRecHit*>& jHits = rh[track2];
00239             for ( unsigned ih2=0; ih2<jHits.size(); ++ih2 ) {
00240             const TrackingRecHit* jt = jHits[ih2];
00241               if (jt->isValid()){
00242                 const TrackingRecHit* kt = jt;
00243                 if ( it->sharesInput(kt,TrackingRecHit::some) )noverlap++;
00244                }
00245              }
00246           }
00247         }
00248         float fi=float(noverlap)/float((*track)->recHitsSize()); 
00249         float fj=float(noverlap)/float((*track2)->recHitsSize());
00250         if ((fi>shareFrac_)||(fj>shareFrac_)){
00251           if (fi<fj){
00252             selected[j]=false;
00253           }else{
00254             if (fi>fj){
00255               selected[i]=false;
00256             }else{
00257               if ((*track)->normalizedChi2() > (*track2)->normalizedChi2()){selected[i]=false;}else{selected[j]=false;}
00258             }//end fi > or = fj
00259           }//end fi < fj
00260         }//end got a duplicate
00261       }//end track2 loop
00262     }//end track loop
00263 
00264    std::vector< reco::TrackRef > newTrackColl;
00265    i=0;
00266    for (std::vector<reco::TrackRef>::const_iterator track=tC.begin(); track!=tC.end(); track++){
00267          if( selected[i] ) newTrackColl.push_back( *track );
00268          ++i;
00269    }
00270    tC = newTrackColl;
00271 }
00272 
00273 void NuclearVertexBuilder::checkEnergy( const reco::TrackRef& primTrack,
00274                                         std::vector<reco::TrackRef>& tC) const {
00275    float totalEnergy=0;
00276    for(size_t i=0; i< tC.size(); ++i) {
00277      totalEnergy += tC[i]->p();
00278    }
00279    if( totalEnergy > primTrack->p()+0.1*primTrack->p() ) {
00280            tC.pop_back();
00281            checkEnergy(primTrack,tC);
00282    }
00283 }