CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_9_patch3/src/RecoMuon/CosmicMuonProducer/src/GlobalCosmicMuonTrajectoryBuilder.cc

Go to the documentation of this file.
00001 
00010 #include "RecoMuon/CosmicMuonProducer/interface/GlobalCosmicMuonTrajectoryBuilder.h"
00011 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00012 #include "FWCore/Framework/interface/Event.h"
00013 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00014 
00015 #include "TrackingTools/PatternTools/interface/TrajectoryMeasurement.h"
00016 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00017 
00018 #include "DataFormats/TrackReco/interface/Track.h"
00019 #include "DataFormats/TrackReco/interface/TrackFwd.h"
00020 #include "DataFormats/TrackReco/interface/TrackExtraFwd.h"
00021 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00022 #include "TrackingTools/Records/interface/TransientRecHitRecord.h"
00023 #include "TrackingTools/TransientTrackingRecHit/interface/TransientTrackingRecHitBuilder.h"
00024 #include "TrackingTools/GeomPropagators/interface/StateOnTrackerBound.h"
00025 #include "DataFormats/Math/interface/deltaPhi.h"
00026 
00027 using namespace std;
00028 using namespace edm;
00029 
00030 //
00031 // constructor
00032 //
00033 GlobalCosmicMuonTrajectoryBuilder::GlobalCosmicMuonTrajectoryBuilder(const edm::ParameterSet& par,
00034                                                                      const MuonServiceProxy* service) : theService(service) {
00035   ParameterSet smootherPSet = par.getParameter<ParameterSet>("SmootherParameters");
00036   theSmoother = new CosmicMuonSmoother(smootherPSet,theService);
00037 
00038   ParameterSet trackMatcherPSet = par.getParameter<ParameterSet>("GlobalMuonTrackMatcher");
00039   theTrackMatcher = new GlobalMuonTrackMatcher(trackMatcherPSet,theService);
00040 
00041   theTkTrackLabel = par.getParameter<InputTag>("TkTrackCollectionLabel");
00042   theTrackerRecHitBuilderName = par.getParameter<string>("TrackerRecHitBuilder");
00043   theMuonRecHitBuilderName = par.getParameter<string>("MuonRecHitBuilder");
00044   thePropagatorName = par.getParameter<string>("Propagator");
00045   category_ = "Muon|RecoMuon|CosmicMuon|GlobalCosmicMuonTrajectoryBuilder";
00046 
00047 }
00048 
00049 //
00050 // destructor
00051 //
00052 
00053 GlobalCosmicMuonTrajectoryBuilder::~GlobalCosmicMuonTrajectoryBuilder() {
00054 
00055   if (theSmoother) delete theSmoother;
00056   if (theTrackMatcher) delete theTrackMatcher;
00057 }
00058 
00059 //
00060 // set Event
00061 //
00062 void GlobalCosmicMuonTrajectoryBuilder::setEvent(const edm::Event& event) {
00063   event.getByLabel(theTkTrackLabel,theTrackerTracks);
00064 
00065 //  edm::Handle<std::vector<Trajectory> > handleTrackerTrajs;
00066 //  if ( event.getByLabel(theTkTrackLabel,handleTrackerTrajs) && handleTrackerTrajs.isValid() ) {
00067 //      tkTrajsAvailable = true;
00068 //      allTrackerTrajs = &*handleTrackerTrajs;   
00069 //      LogInfo("GlobalCosmicMuonTrajectoryBuilder") 
00070 //      << "Tk Trajectories Found! " << endl;
00071 //  } else {
00072 //      LogInfo("GlobalCosmicMuonTrajectoryBuilder") 
00073 //      << "No Tk Trajectories Found! " << endl;
00074 //      tkTrajsAvailable = false;
00075 //  }
00076 
00077    theService->eventSetup().get<TransientRecHitRecord>().get(theTrackerRecHitBuilderName,theTrackerRecHitBuilder);
00078     theService->eventSetup().get<TransientRecHitRecord>().get(theMuonRecHitBuilderName,theMuonRecHitBuilder);
00079 
00080 }
00081 
00082 //
00083 // reconstruct trajectories
00084 //
00085 MuonCandidate::CandidateContainer GlobalCosmicMuonTrajectoryBuilder::trajectories(const TrackCand& muCand) {
00086   MuonCandidate::CandidateContainer result;
00087 
00088   if (!theTrackerTracks.isValid()) {
00089     LogTrace(category_)<< "Tracker Track collection is invalid!!!";
00090     return result;
00091   }
00092 
00093   LogTrace(category_) <<"Found "<<theTrackerTracks->size()<<" tracker Tracks";
00094   if (theTrackerTracks->empty()) return result;
00095 
00096   vector<TrackCand> matched = match(muCand, theTrackerTracks);
00097 
00098   LogTrace(category_) <<"TrackMatcher found " << matched.size() << "tracker tracks matched";
00099   
00100   if ( matched.empty()) return result;
00101   reco::TrackRef tkTrack = matched.front().second;
00102   
00103   if ( tkTrack.isNull() ) return result;
00104   reco::TrackRef muTrack = muCand.second;
00105 
00106   ConstRecHitContainer muRecHits;
00107 
00108   if (muCand.first == 0 || !muCand.first->isValid()) { 
00109      muRecHits = getTransientRecHits(*muTrack);
00110   } else {
00111      muRecHits = muCand.first->recHits();
00112   }
00113 
00114   LogTrace(category_)<<"mu RecHits: "<<muRecHits.size();
00115 
00116   ConstRecHitContainer tkRecHits = getTransientRecHits(*tkTrack);
00117 
00118 //  if ( !tkTrajsAvailable ) {
00119 //     tkRecHits = getTransientRecHits(*tkTrack);
00120 //  } else {
00121 //     tkRecHits = allTrackerTrajs->front().recHits();
00122 //  }
00123 
00124   ConstRecHitContainer hits; //= tkRecHits;
00125   LogTrace(category_)<<"tk RecHits: "<<tkRecHits.size();
00126 
00127 //  hits.insert(hits.end(), muRecHits.begin(), muRecHits.end());
00128 //  stable_sort(hits.begin(), hits.end(), DecreasingGlobalY());
00129 
00130   sortHits(hits, muRecHits, tkRecHits);
00131 
00132 //  LogTrace(category_)<< "Used RecHits after sort: "<<hits.size()<<endl;;
00133 //  LogTrace(category_) <<utilities()->print(hits)<<endl;
00134 //  LogTrace(category_) << "== End of Used RecHits == "<<endl;
00135 
00136   
00137 
00138   TrajectoryStateOnSurface muonState1 = trajectoryStateTransform::innerStateOnSurface(*muTrack, *theService->trackingGeometry(), &*theService->magneticField());
00139   TrajectoryStateOnSurface tkState1 = trajectoryStateTransform::innerStateOnSurface(*tkTrack, *theService->trackingGeometry(), &*theService->magneticField());
00140 
00141   TrajectoryStateOnSurface muonState2 = trajectoryStateTransform::outerStateOnSurface(*muTrack, *theService->trackingGeometry(), &*theService->magneticField());
00142   TrajectoryStateOnSurface tkState2 = trajectoryStateTransform::outerStateOnSurface(*tkTrack, *theService->trackingGeometry(), &*theService->magneticField());
00143 
00144   TrajectoryStateOnSurface firstState1 =
00145    ( muonState1.globalPosition().y() > tkState1.globalPosition().y() )? muonState1 : tkState1;
00146   TrajectoryStateOnSurface firstState2 =
00147    ( muonState2.globalPosition().y() > tkState2.globalPosition().y() )? muonState2 : tkState2;
00148 
00149   TrajectoryStateOnSurface firstState =
00150    ( firstState1.globalPosition().y() > firstState2.globalPosition().y() )? firstState1 : firstState2;
00151 
00152     GlobalPoint front, back;
00153     if(hits.size()>0){
00154       front=hits.front()->globalPosition();
00155       back=hits.back()->globalPosition();
00156       if ( (front.perp()<130 && fabs(front.z())<300)|| (back.perp() <130 && fabs(back.z())<300)){
00157         if (hits.front()->globalPosition().perp()>hits.back()->globalPosition().perp()) reverse(hits.begin(), hits.end());
00158         tkState1 = trajectoryStateTransform::innerStateOnSurface(*tkTrack, *theService->trackingGeometry(), &*theService->magneticField());
00159         tkState2 = trajectoryStateTransform::outerStateOnSurface(*tkTrack, *theService->trackingGeometry(), &*theService->magneticField());
00160         firstState =( tkState1.globalPosition().perp() < tkState2.globalPosition().perp() )? tkState1 : tkState2;
00161       }
00162     }
00163     if (!firstState.isValid())       return result;
00164   LogTrace(category_) <<"firstTSOS pos: "<<firstState.globalPosition()<<"mom: "<<firstState.globalMomentum();
00165 
00166   // begin refitting
00167 
00168   TrajectorySeed seed;
00169   vector<Trajectory> refitted = theSmoother->trajectories(seed,hits,firstState);
00170 
00171   if ( refitted.empty() ) {
00172     LogTrace(category_)<<"smoothing trajectories fail";
00173     refitted = theSmoother->fit(seed,hits,firstState); //FIXME
00174   }
00175 
00176   if (refitted.empty()) {
00177      LogTrace(category_)<<"refit fail";
00178      return result;
00179   }
00180 
00181   Trajectory* myTraj = new Trajectory(refitted.front());
00182 
00183   const std::vector<TrajectoryMeasurement>& mytms = myTraj->measurements(); 
00184   LogTrace(category_)<<"measurements in final trajectory "<<mytms.size();
00185   LogTrace(category_) <<"Orignally there are "<<tkTrack->found()<<" tk rhs and "<<muTrack->found()<<" mu rhs.";
00186 
00187   if ( mytms.size() <= tkTrack->found() ) {
00188      LogTrace(category_)<<"insufficient measurements. skip... ";
00189      return result;
00190   }
00191 
00192   MuonCandidate* myCand = new MuonCandidate(myTraj,muTrack,tkTrack);
00193   result.push_back(myCand);
00194   LogTrace(category_)<<"final global cosmic muon: ";
00195   for (std::vector<TrajectoryMeasurement>::const_iterator itm = mytms.begin();
00196        itm != mytms.end(); ++itm ) {
00197        LogTrace(category_)<<"updated pos "<<itm->updatedState().globalPosition()
00198                        <<"mom "<<itm->updatedState().globalMomentum();
00199    }
00200   return result;
00201 }
00202 
00203 void GlobalCosmicMuonTrajectoryBuilder::sortHits(ConstRecHitContainer& hits, ConstRecHitContainer& muonHits, ConstRecHitContainer& tkHits) {
00204 
00205    if ( tkHits.empty() ) {
00206       LogTrace(category_) << "No valid tracker hits";
00207       return;
00208    }
00209    if ( muonHits.empty() ) {
00210       LogTrace(category_) << "No valid muon hits";
00211       return;
00212    }
00213 
00214    ConstRecHitContainer::const_iterator frontTkHit = tkHits.begin();
00215    ConstRecHitContainer::const_iterator backTkHit  = tkHits.end() - 1;
00216    while ( !(*frontTkHit)->isValid() && frontTkHit != backTkHit) {frontTkHit++;}
00217    while ( !(*backTkHit)->isValid() && backTkHit != frontTkHit)  {backTkHit--;}
00218 
00219    ConstRecHitContainer::const_iterator frontMuHit = muonHits.begin();
00220    ConstRecHitContainer::const_iterator backMuHit  = muonHits.end() - 1;
00221    while ( !(*frontMuHit)->isValid() && frontMuHit != backMuHit) {frontMuHit++;}
00222    while ( !(*backMuHit)->isValid() && backMuHit != frontMuHit)  {backMuHit--;}
00223 
00224    if ( frontTkHit == backTkHit ) {
00225       LogTrace(category_) << "No valid tracker hits";
00226       return;
00227    }
00228    if ( frontMuHit == backMuHit ) {
00229       LogTrace(category_) << "No valid muon hits";
00230       return;
00231    }
00232 
00233   GlobalPoint frontTkPos = (*frontTkHit)->globalPosition();
00234   GlobalPoint backTkPos = (*backTkHit)->globalPosition();
00235 
00236   GlobalPoint frontMuPos = (*frontMuHit)->globalPosition();
00237   GlobalPoint backMuPos = (*backMuHit)->globalPosition();
00238 
00239   //sort hits going from higher to lower positions
00240   if ( frontTkPos.y() < backTkPos.y() )  {//check if tk hits order same direction
00241     reverse(tkHits.begin(), tkHits.end());
00242   }
00243 
00244   if ( frontMuPos.y() < backMuPos.y() )  {
00245     reverse(muonHits.begin(), muonHits.end());
00246   }
00247 
00248 //  LogTrace(category_)<< "tkHits after sort: "<<tkHits.size()<<endl;;
00249 //  LogTrace(category_) <<utilities()->print(tkHits)<<endl;
00250 //  LogTrace(category_) << "== End of tkHits == "<<endl;
00251 
00252 //  LogTrace(category_)<< "muonHits after sort: "<<muonHits.size()<<endl;;
00253 //  LogTrace(category_) <<utilities()->print(muonHits)<<endl;
00254 //  LogTrace(category_)<< "== End of muonHits == "<<endl;
00255 
00256   //separate muon hits into 2 different hemisphere
00257   ConstRecHitContainer::iterator middlepoint = muonHits.begin();
00258   bool insertInMiddle = false;
00259 
00260   for (ConstRecHitContainer::iterator ihit = muonHits.begin(); 
00261        ihit != muonHits.end() - 1; ihit++ ) {
00262     GlobalPoint ipos = (*ihit)->globalPosition();
00263     GlobalPoint nextpos = (*(ihit+1))->globalPosition();
00264     if ( (ipos-nextpos).mag() < 100.0 ) continue;
00265 
00266     GlobalPoint middle((ipos.x()+nextpos.x())/2, (ipos.y()+nextpos.y())/2, (ipos.z()+nextpos.z())/2);
00267     LogTrace(category_)<<"ipos "<<ipos<<"nextpos"<<nextpos<<" middle "<<middle<<endl;
00268     if ( (middle.perp() < ipos.perp()) && (middle.perp() < nextpos.perp() ) ) {
00269       LogTrace(category_)<<"found middlepoint"<<endl;
00270       middlepoint = ihit;
00271       insertInMiddle = true;
00272       break;
00273     }
00274   }
00275 
00276   //insert track hits in correct order
00277   if ( insertInMiddle ) { //if tk hits should be sandwich
00278     GlobalPoint jointpointpos = (*middlepoint)->globalPosition();
00279     LogTrace(category_)<<"jointpoint "<<jointpointpos<<endl;
00280     if ((frontTkPos - jointpointpos).mag() > (backTkPos - jointpointpos).mag() ) {//check if tk hits order same direction
00281       reverse(tkHits.begin(), tkHits.end());
00282     }
00283     muonHits.insert(middlepoint+1, tkHits.begin(), tkHits.end());
00284     hits = muonHits; 
00285   } else { // append at one end
00286     if ( frontTkPos.y() < frontMuPos.y() ) { //insert at the end
00287       LogTrace(category_)<<"insert at the end "<<frontTkPos << frontMuPos <<endl;
00288 
00289       hits = muonHits; 
00290       hits.insert(hits.end(), tkHits.begin(), tkHits.end());
00291     } else { //insert at the beginning
00292       LogTrace(category_)<<"insert at the beginning "<<frontTkPos << frontMuPos <<endl;
00293       hits = tkHits;
00294       hits.insert(hits.end(), muonHits.begin(), muonHits.end());
00295     }
00296   }
00297 }
00298 
00299 
00300 TransientTrackingRecHit::ConstRecHitContainer
00301 GlobalCosmicMuonTrajectoryBuilder::getTransientRecHits(const reco::Track& track) const {
00302 
00303   TransientTrackingRecHit::ConstRecHitContainer result;
00304 
00305   
00306 
00307   TrajectoryStateOnSurface currTsos = trajectoryStateTransform::innerStateOnSurface(track, *theService->trackingGeometry(), &*theService->magneticField());
00308   for (trackingRecHit_iterator hit = track.recHitsBegin(); hit != track.recHitsEnd(); ++hit) {
00309     if((*hit)->isValid()) {
00310       DetId recoid = (*hit)->geographicalId();
00311       if ( recoid.det() == DetId::Tracker ) {
00312         TransientTrackingRecHit::RecHitPointer ttrhit = theTrackerRecHitBuilder->build(&**hit);
00313         TrajectoryStateOnSurface predTsos =  theService->propagator(thePropagatorName)->propagate(currTsos, theService->trackingGeometry()->idToDet(recoid)->surface());
00314         LogTrace(category_)<<"predtsos "<<predTsos.isValid();
00315         if ( predTsos.isValid() ) {
00316           currTsos = predTsos;
00317           TransientTrackingRecHit::RecHitPointer preciseHit = ttrhit->clone(currTsos);
00318           result.push_back(preciseHit);
00319        }
00320       } else if ( recoid.det() == DetId::Muon ) {
00321         result.push_back(theMuonRecHitBuilder->build(&**hit));
00322       }
00323     }
00324   }
00325   return result;
00326 }
00327 
00328 std::vector<GlobalCosmicMuonTrajectoryBuilder::TrackCand> GlobalCosmicMuonTrajectoryBuilder::match(const TrackCand& mu, const edm::Handle<reco::TrackCollection>& tktracks) {
00329    
00330    std::vector<TrackCand> result;
00331 
00332    
00333    TrajectoryStateOnSurface innerTsos =trajectoryStateTransform::innerStateOnSurface(*(mu.second), *theService->trackingGeometry(), &*theService->magneticField());
00334    TrajectoryStateOnSurface outerTsos = trajectoryStateTransform::outerStateOnSurface(*(mu.second), *theService->trackingGeometry(), &*theService->magneticField());
00335    //build tracker TrackCands and pick the best match if size greater than 2
00336    vector<TrackCand> tkTrackCands;
00337    for(reco::TrackCollection::size_type i=0; i<theTrackerTracks->size(); ++i){
00338      reco::TrackRef tkTrack(theTrackerTracks,i);
00339      TrackCand tkCand = TrackCand((Trajectory*)(0),tkTrack);
00340      tkTrackCands.push_back(tkCand);
00341      LogTrace(category_) << "chisq is " << theTrackMatcher->match(mu,tkCand,0,0);
00342      LogTrace(category_) << "d is " << theTrackMatcher->match(mu,tkCand,1,0);
00343      LogTrace(category_) << "r_pos is " << theTrackMatcher->match(mu,tkCand,2,0);
00344    }
00345 
00346    // now if only 1 tracker tracks, return it
00347    if (tkTrackCands.size() <= 1 ) {
00348       return tkTrackCands;
00349    }
00350  
00351    // if there're many tracker tracks
00352 
00353    // if muon is only on one side
00354    GlobalPoint innerPos = innerTsos.globalPosition();
00355    GlobalPoint outerPos = outerTsos.globalPosition();
00356 
00357    if ( ( innerPos.basicVector().dot( innerTsos.globalMomentum().basicVector() ) *
00358        outerPos.basicVector().dot(outerTsos.globalMomentum().basicVector() ) > 0 ) ) {
00359 
00360       GlobalPoint geoInnerPos = (innerPos.mag() < outerPos.mag()) ? innerPos : outerPos;
00361      LogTrace(category_) <<"geoInnerPos Mu "<<geoInnerPos<<endl;
00362 
00363      // if there're tracker tracks totally on the other half
00364      // and there're tracker tracks on the same half
00365      // remove the tracks on the other half
00366      for(vector<TrackCand>::const_iterator itkCand = tkTrackCands.begin(); itkCand != tkTrackCands.end(); ++itkCand) {
00367 
00368         reco::TrackRef tkTrack = itkCand->second;
00369 
00370         GlobalPoint tkInnerPos(tkTrack->innerPosition().x(), tkTrack->innerPosition().y(), tkTrack->innerPosition().z());
00371         GlobalPoint tkOuterPos(tkTrack->outerPosition().x(), tkTrack->outerPosition().y(), tkTrack->outerPosition().z());
00372         LogTrace(category_) <<"tkTrack "<<tkInnerPos<<" "<<tkOuterPos<<endl;
00373 
00374         float closetDistance11 =  (geoInnerPos - tkInnerPos).mag() ; 
00375         float closetDistance12 =  (geoInnerPos - tkOuterPos).mag() ;
00376         float closetDistance1 = (closetDistance11 < closetDistance12) ? closetDistance11 : closetDistance12;
00377         LogTrace(category_) <<"closetDistance1 "<<closetDistance1<<endl;
00378 
00379         if (true || !isTraversing(*tkTrack) ) {
00380             bool keep = true;
00381             for(vector<TrackCand>::const_iterator itkCand2 = tkTrackCands.begin(); itkCand2 != tkTrackCands.end(); ++itkCand2) {
00382                 if (itkCand2 == itkCand ) continue;
00383                 reco::TrackRef tkTrack2 = itkCand2->second;
00384 
00385                 GlobalPoint tkInnerPos2(tkTrack2->innerPosition().x(), tkTrack2->innerPosition().y(), tkTrack2->innerPosition().z());
00386                 GlobalPoint tkOuterPos2(tkTrack2->outerPosition().x(), tkTrack2->outerPosition().y(), tkTrack2->outerPosition().z());
00387                 LogTrace(category_) <<"tkTrack2 "<< tkInnerPos2 <<" "<<tkOuterPos2 <<endl;
00388 
00389                 float farthestDistance21 =  (geoInnerPos - tkInnerPos2).mag() ;
00390                 float farthestDistance22 =  (geoInnerPos - tkOuterPos2).mag() ;
00391                 float farthestDistance2 = (farthestDistance21 > farthestDistance22) ? farthestDistance21 : farthestDistance22;
00392                 LogTrace(category_) <<"farthestDistance2 "<<farthestDistance2<<endl;
00393 
00394                 if (closetDistance1 > farthestDistance2 - 1e-3) {
00395                      keep = false;
00396                      break;
00397                 } 
00398             }
00399             if (keep) result.push_back(*itkCand);
00400             else LogTrace(category_) <<"The Track is on different hemisphere"<<endl;
00401         } else {
00402           result.push_back(*itkCand);
00403         } 
00404      }
00405      if ( result.empty() ) { 
00406         //if all tk tracks on the other side, still keep them
00407         result = tkTrackCands;
00408      }
00409    } else { // muon is traversing
00410        result = tkTrackCands;
00411    }
00412 
00413   // match muCand to tkTrackCands
00414   vector<TrackCand> matched_trackerTracks = theTrackMatcher->match(mu, result);
00415 
00416   LogTrace(category_) <<"TrackMatcher found " << matched_trackerTracks.size() << "tracker tracks matched";
00417   
00418   //now pick the best matched one
00419   if(  matched_trackerTracks.size() < 2 ) {
00420     return matched_trackerTracks;
00421   } else {
00422     // in case of more than 1 tkTrack,
00423     // select the best-one based on distance (matchOption==1)
00424     // at innermost Mu hit surface. (surfaceOption == 0)
00425     result.clear();
00426     TrackCand bestMatch;
00427 
00428     double quality = 1e6;
00429     double max_quality = 1e6;
00430     for( vector<TrackCand>::const_iterator iter = matched_trackerTracks.begin(); iter != matched_trackerTracks.end(); iter++) {
00431       quality = theTrackMatcher->match(mu,*iter, 1, 0);
00432       LogTrace(category_) <<" quality of tracker track is " << quality;
00433       if( quality < max_quality ) {
00434         max_quality=quality;
00435         bestMatch = (*iter);
00436       }
00437     }
00438     LogTrace(category_) <<" Picked tracker track with quality " << max_quality;
00439     result.push_back(bestMatch);
00440     return result;
00441   }  
00442 }
00443 
00444 
00445 bool GlobalCosmicMuonTrajectoryBuilder::isTraversing(const reco::Track& track) const {
00446 
00447   trackingRecHit_iterator firstValid;
00448   for (trackingRecHit_iterator hit = track.recHitsBegin(); hit != track.recHitsEnd(); ++hit) {
00449     if((*hit)->isValid()) {
00450        firstValid = hit;
00451        break;
00452     }
00453   }
00454 
00455   trackingRecHit_iterator lastValid;
00456   for (trackingRecHit_iterator hit = track.recHitsEnd() - 1; hit != track.recHitsBegin() - 1; --hit) {
00457     if((*hit)->isValid()) {
00458        lastValid = hit;
00459        break;
00460     }
00461   }
00462 
00463   GlobalPoint posFirst = theService->trackingGeometry()->idToDet((*firstValid)->geographicalId())->position();
00464 
00465   GlobalPoint posLast  = theService->trackingGeometry()->idToDet((*lastValid)->geographicalId() )->position();
00466 
00467   GlobalPoint middle((posFirst.x()+posLast.x())/2, (posFirst.y()+posLast.y())/2, (posFirst.z()+posLast.z())/2);
00468 
00469   if ( (middle.mag() < posFirst.mag()) && (middle.mag() < posLast.mag() ) ) {
00470      return true;
00471   }
00472   return false;
00473 
00474 }