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
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
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
00072 LogDebug("NuclearInteractionMaker") << exception.what() << "\n";
00073 return false;
00074 }
00075 catch( cms::Exception& exception){
00076
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
00092 unsigned short maxHits = 0; int indice=-1;
00093 for( unsigned short i=0; i < secTracks.size(); i++) {
00094
00095 unsigned short nhits = secTracks[i]->numberOfValidHits();
00096 if( nhits > maxHits ) { maxHits = nhits; indice=i; }
00097 }
00098
00099
00100 if(indice == -1) return false;
00101
00102 ClosestApproachInRPhi* theApproach = closestApproach( primTrack, secTracks[indice]);
00103 GlobalPoint crossing = theApproach->crossingPoint();
00104 delete theApproach;
00105
00106
00107
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
00183
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
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
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
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 }
00259 }
00260 }
00261 }
00262 }
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 }