CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_2_9/src/RecoTracker/CkfPattern/src/GroupedCkfTrajectoryBuilder.cc

Go to the documentation of this file.
00001 
00002 #include "RecoTracker/CkfPattern/interface/GroupedCkfTrajectoryBuilder.h"
00003 #include "TrajectorySegmentBuilder.h"
00004 
00005 
00006 #include "TrackingTools/DetLayers/interface/DetLayer.h"
00007 #include "TrackingTools/PatternTools/interface/TrajMeasLessEstim.h"
00008 
00009 #include "TrackingTools/KalmanUpdators/interface/KFUpdator.h"
00010 #include "TrackingTools/KalmanUpdators/interface/Chi2MeasurementEstimator.h"
00011 #include "TrackingTools/TrackFitters/interface/KFTrajectoryFitter.h"
00012 #include "RecoTracker/CkfPattern/interface/GroupedTrajCandLess.h"
00013 #include "TrackingTools/TrajectoryFiltering/interface/RegionalTrajectoryFilter.h"
00014 #include "TrackingTools/PatternTools/interface/TempTrajectory.h"
00015 #include "RecoTracker/MeasurementDet/interface/MeasurementTracker.h"
00016 #include "TrackingTools/MeasurementDet/interface/LayerMeasurements.h"
00017 #include "TrackingTools/Records/interface/TrackingComponentsRecord.h"
00018 #include "TrackingTools/DetLayers/interface/DetGroup.h"
00019 #include "RecoTracker/TkDetLayers/interface/GeometricSearchTracker.h"
00020 #include "TrackingTools/Records/interface/TransientRecHitRecord.h"
00021 #include "TrackingTools/TransientTrackingRecHit/interface/TransientTrackingRecHitBuilder.h"
00022 #include "TrackingTools/PatternTools/interface/TrajectoryMeasurement.h"
00023 
00024 #include "TrackingTools/PatternTools/interface/TrajectoryStateUpdator.h"
00025 #include "TrackingTools/KalmanUpdators/interface/KFUpdator.h"
00026 #include "TrackingTools/PatternTools/interface/Trajectory.h"
00027 #include "TrackingTools/PatternTools/interface/TrajMeasLessEstim.h"
00028 #include "TrackingTools/TrajectoryState/interface/BasicSingleTrajectoryState.h"
00029 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00030 #include "TrackingTools/PatternTools/interface/TransverseImpactPointExtrapolator.h"
00031 
00032 // only included for RecHit comparison operator:
00033 #include "TrackingTools/TrajectoryCleaning/interface/TrajectoryCleanerBySharedHits.h"
00034 
00035 // for looper reconstruction
00036 #include "TrackingTools/GeomPropagators/interface/HelixBarrelCylinderCrossing.h"
00037 #include "TrackingTools/GeomPropagators/interface/HelixBarrelPlaneCrossingByCircle.h"
00038 #include "TrackingTools/GeomPropagators/interface/HelixArbitraryPlaneCrossing.h"
00039 
00040 
00041 #include <algorithm> 
00042 
00043 using namespace std;
00044 
00045 //#define DBG2_GCTB
00046 
00047 //#define STANDARD_INTERMEDIARYCLEAN
00048 
00049 #ifdef STANDARD_INTERMEDIARYCLEAN
00050 #include "RecoTracker/CkfPattern/interface/IntermediateTrajectoryCleaner.h"
00051 #endif
00052 
00053 /* ====== B.M. to be ported layer ===========
00054 #ifdef DBG_GCTB
00055 #include "RecoTracker/CkfPattern/src/ShowCand.h"
00056 #endif
00057 // #define DBG2_GCTB
00058 #ifdef DBG2_GCTB
00059 #include "RecoTracker/CkfPattern/src/SimIdPrinter.h"
00060 #include "Tracker/TkDebugTools/interface/LayerFinderByDet.h"
00061 #include "Tracker/TkLayout/interface/TkLayerName.h"
00062 #endif
00063 =================================== */
00064 
00065 
00066 GroupedCkfTrajectoryBuilder::
00067 GroupedCkfTrajectoryBuilder(const edm::ParameterSet&              conf,
00068                             const TrajectoryStateUpdator*         updator,
00069                             const Propagator*                     propagatorAlong,
00070                             const Propagator*                     propagatorOpposite,
00071                             const Chi2MeasurementEstimatorBase*   estimator,
00072                             const TransientTrackingRecHitBuilder* recHitBuilder,
00073                             const MeasurementTracker*             measurementTracker,
00074                             const TrajectoryFilter*               filter,
00075                             const TrajectoryFilter*               inOutFilter):
00076 
00077 
00078   BaseCkfTrajectoryBuilder(conf,
00079                            updator, propagatorAlong,propagatorOpposite,
00080                            estimator, recHitBuilder, measurementTracker, filter, inOutFilter)
00081 {
00082   // fill data members from parameters (eventually data members could be dropped)
00083   //
00084   theMaxCand                  = conf.getParameter<int>("maxCand");
00085 
00086   theLostHitPenalty           = conf.getParameter<double>("lostHitPenalty");
00087   theFoundHitBonus            = conf.getParameter<double>("foundHitBonus");
00088   theIntermediateCleaning     = conf.getParameter<bool>("intermediateCleaning");
00089   theAlwaysUseInvalid         = conf.getParameter<bool>("alwaysUseInvalidHits");
00090   theLockHits                 = conf.getParameter<bool>("lockHits");
00091   theBestHitOnly              = conf.getParameter<bool>("bestHitOnly");
00092   theMinNrOf2dHitsForRebuild  = 2;
00093   theRequireSeedHitsInRebuild = conf.getParameter<bool>("requireSeedHitsInRebuild");
00094   theMinNrOfHitsForRebuild    = max(0,conf.getParameter<int>("minNrOfHitsForRebuild"));
00095   maxPtForLooperReconstruction     = conf.existsAs<double>("maxPtForLooperReconstruction") ? 
00096     conf.getParameter<double>("maxPtForLooperReconstruction") : 0;
00097 
00098   /* ======= B.M. to be ported layer ===========
00099   bool setOK = thePropagator->setMaxDirectionChange(1.6);
00100   if (!setOK) 
00101     cout  << "GroupedCkfTrajectoryBuilder WARNING: "
00102           << "propagator does not support setMaxDirectionChange" 
00103           << endl;
00104   //   addStopCondition(theMinPtStopCondition);
00105 
00106   theConfigurableCondition = createAlgo<TrajectoryFilter>(componentConfig("StopCondition"));
00107   ===================================== */
00108 
00109 }
00110 
00111 /*
00112   void GroupedCkfTrajectoryBuilder::setEvent(const edm::Event& event) const
00113   {
00114   theMeasurementTracker->update(event);
00115 }
00116 */
00117 
00118 GroupedCkfTrajectoryBuilder::TrajectoryContainer 
00119 GroupedCkfTrajectoryBuilder::trajectories (const TrajectorySeed& seed) const 
00120 {
00121   TrajectoryContainer ret; 
00122   ret.reserve(10);
00123   buildTrajectories(seed, ret, 0);
00124   return ret; 
00125 }
00126 
00127 GroupedCkfTrajectoryBuilder::TrajectoryContainer 
00128 GroupedCkfTrajectoryBuilder::trajectories (const TrajectorySeed& seed, 
00129                                            const TrackingRegion& region) const
00130 {
00131   TrajectoryContainer ret; 
00132   ret.reserve(10);
00133   RegionalTrajectoryFilter regionalCondition(region);
00134   buildTrajectories(seed, ret, &regionalCondition);
00135   return ret; 
00136 }
00137 
00138 void 
00139 GroupedCkfTrajectoryBuilder::trajectories (const TrajectorySeed& seed, GroupedCkfTrajectoryBuilder::TrajectoryContainer &ret) const 
00140 {
00141   buildTrajectories(seed,ret,0);
00142 }
00143 
00144 void
00145 GroupedCkfTrajectoryBuilder::trajectories (const TrajectorySeed& seed, 
00146                                             GroupedCkfTrajectoryBuilder::TrajectoryContainer &ret,
00147                                             const TrackingRegion& region) const
00148 {
00149   RegionalTrajectoryFilter regionalCondition(region);
00150   buildTrajectories(seed,ret,&regionalCondition);
00151 }
00152 
00153 void  
00154 GroupedCkfTrajectoryBuilder::rebuildSeedingRegion(const TrajectorySeed& seed,
00155                                                   TrajectoryContainer& result) const {    
00156   TempTrajectory startingTraj = createStartingTrajectory( seed);
00157   TempTrajectoryContainer work;
00158 
00159   TrajectoryContainer final;
00160 
00161   work.reserve(result.size());
00162   for (TrajectoryContainer::iterator traj=result.begin();
00163        traj!=result.end(); ++traj) {
00164     if(traj->isValid()) work.push_back(TempTrajectory(*traj));
00165   }
00166 
00167   rebuildSeedingRegion(startingTraj,work);
00168   final.reserve(work.size());
00169 
00170   for (TempTrajectoryContainer::iterator traj=work.begin();
00171        traj!=work.end(); ++traj) {
00172     final.push_back(traj->toTrajectory());
00173   }
00174   
00175   result.swap(final);
00176   
00177 }
00178 
00179 void
00180 GroupedCkfTrajectoryBuilder::buildTrajectories (const TrajectorySeed& seed,
00181                                                 GroupedCkfTrajectoryBuilder::TrajectoryContainer &result,
00182                                                 const TrajectoryFilter* regionalCondition) const
00183 {
00184   //
00185   // Build trajectory outwards from seed
00186   //
00187 
00188   analyseSeed( seed);
00189 
00190   TempTrajectory startingTraj = createStartingTrajectory( seed);
00191 
00192   work_.clear();
00193   const bool inOut = true;
00194   groupedLimitedCandidates( startingTraj, regionalCondition, theForwardPropagator, inOut, work_);
00195   if ( work_.empty() )  return ;
00196 
00197 
00198 
00199   /*  rebuilding is de-coupled from standard building
00200   //
00201   // try to additional hits in the seeding region
00202   //
00203   if ( theMinNrOfHitsForRebuild>0 ) {
00204     // reverse direction
00205     //thePropagator->setPropagationDirection(oppositeDirection(seed.direction()));
00206     // rebuild part of the trajectory
00207     rebuildSeedingRegion(startingTraj,work);
00208   }
00209 
00210   */
00211 
00212   result.reserve(work_.size());
00213   for (TempTrajectoryContainer::const_iterator it = work_.begin(), ed = work_.end(); it != ed; ++it) {
00214       result.push_back( it->toTrajectory() );
00215   }
00216 
00217   work_.clear(); 
00218   if (work_.capacity() > work_MaxSize_) {  TempTrajectoryContainer().swap(work_); work_.reserve(work_MaxSize_/2); }
00219 
00220   analyseResult(result);
00221 
00222   LogDebug("CkfPattern")<< "GroupedCkfTrajectoryBuilder: returning result of size " << result.size();
00223 
00224 }
00225 
00226 
00227 void 
00228 GroupedCkfTrajectoryBuilder::groupedLimitedCandidates (TempTrajectory& startingTraj, 
00229                                                        const TrajectoryFilter* regionalCondition,
00230                                                        const Propagator* propagator, 
00231                                                        bool inOut,
00232                                                        TempTrajectoryContainer& result) const
00233 {
00234   unsigned int nIter=1;
00235   TempTrajectoryContainer candidates;
00236   TempTrajectoryContainer newCand;
00237   candidates.push_back( startingTraj);
00238 
00239   while ( !candidates.empty()) {
00240 
00241     newCand.clear();
00242     for (TempTrajectoryContainer::iterator traj=candidates.begin();
00243          traj!=candidates.end(); traj++) {
00244       if ( !advanceOneLayer(*traj, regionalCondition, propagator, inOut, newCand, result) ) {
00245         LogDebug("CkfPattern")<< "GCTB: terminating after advanceOneLayer==false";
00246         continue;
00247       }
00248 
00249       LogDebug("CkfPattern")<<"newCand(1): after advanced one layer:\n"<<PrintoutHelper::dumpCandidates(newCand);
00250 
00251       if ((int)newCand.size() > theMaxCand) {
00252         //ShowCand()(newCand);
00253 
00254         sort( newCand.begin(), newCand.end(), GroupedTrajCandLess(theLostHitPenalty,theFoundHitBonus));
00255         newCand.erase( newCand.begin()+theMaxCand, newCand.end());
00256       }
00257       LogDebug("CkfPattern")<<"newCand(2): after removing extra candidates.\n"<<PrintoutHelper::dumpCandidates(newCand);
00258     }
00259 
00260     LogDebug("CkfPattern") << "newCand.size() at end = " << newCand.size();
00261 /*
00262     if (theIntermediateCleaning) {
00263       candidates.clear();
00264       candidates = groupedIntermediaryClean(newCand);
00265     } else {
00266       candidates.swap(newCand);
00267     }
00268 */
00269     if (theIntermediateCleaning) {
00270 #ifdef STANDARD_INTERMEDIARYCLEAN
00271         IntermediateTrajectoryCleaner::clean(newCand);  
00272 #else 
00273         groupedIntermediaryClean(newCand);
00274 #endif  
00275 
00276     }   
00277     candidates.swap(newCand);
00278 
00279     LogDebug("CkfPattern") <<"candidates(3): "<<result.size()<<" candidates after "<<nIter++<<" groupedCKF iteration: \n"
00280                            <<PrintoutHelper::dumpCandidates(result)
00281                            <<"\n "<<candidates.size()<<" running candidates are: \n"
00282                            <<PrintoutHelper::dumpCandidates(candidates);
00283   }
00284 }
00285 
00286 std::string whatIsTheNextStep(TempTrajectory& traj , std::pair<TrajectoryStateOnSurface,std::vector<const DetLayer*> >& stateAndLayers){
00287   std::stringstream buffer;
00288   vector<const DetLayer*> & nl = stateAndLayers.second;
00289 #include "TrackingTools/DetLayers/interface/BarrelDetLayer.h"
00290 #include "TrackingTools/DetLayers/interface/ForwardDetLayer.h"
00291   //B.M. TkLayerName layerName;
00292   //B.M. buffer << "Started from " << layerName(traj.lastLayer()) 
00293   const BarrelDetLayer* sbdl = dynamic_cast<const BarrelDetLayer*>(traj.lastLayer());
00294   const ForwardDetLayer* sfdl = dynamic_cast<const ForwardDetLayer*>(traj.lastLayer());
00295   if (sbdl) {
00296     buffer << "Started from " << traj.lastLayer() << " r=" << sbdl->specificSurface().radius() 
00297            << " phi=" << sbdl->specificSurface().phi() << endl;
00298   } else if (sfdl) {
00299     buffer << "Started from " << traj.lastLayer() << " z " << sfdl->specificSurface().position().z()
00300            << " phi " << sfdl->specificSurface().phi() << endl;
00301   }
00302   buffer << "Trying to go to";
00303   for ( vector<const DetLayer*>::iterator il=nl.begin();
00304         il!=nl.end(); il++){ 
00305     //B.M. buffer << " " << layerName(*il)  << " " << *il << endl;
00306     const BarrelDetLayer* bdl = dynamic_cast<const BarrelDetLayer*>(*il);
00307     const ForwardDetLayer* fdl = dynamic_cast<const ForwardDetLayer*>(*il);
00308     
00309     if (bdl) buffer << " r " << bdl->specificSurface().radius() << endl;
00310     if (fdl) buffer << " z " << fdl->specificSurface().position().z() << endl;
00311     //buffer << " " << *il << endl;   
00312   }
00313   return buffer.str();
00314 }
00315 
00316 std::string whatIsTheStateToUse(TrajectoryStateOnSurface &initial, TrajectoryStateOnSurface & stateToUse, const DetLayer * l){
00317   std::stringstream buffer;
00318   buffer << "GCTB: starting from " 
00319          << " r / phi / z = " << stateToUse.globalPosition().perp()
00320          << " / " << stateToUse.globalPosition().phi()
00321          << " / " << stateToUse.globalPosition().z() 
00322          << " , pt / phi / pz /charge = " 
00323          << stateToUse.globalMomentum().perp() << " / "  
00324          << stateToUse.globalMomentum().phi() << " / " 
00325          << stateToUse.globalMomentum().z() << " / " 
00326          << stateToUse.charge()
00327          << " for layer at "<< l << endl;
00328   buffer << "     errors:";
00329   for ( int i=0; i<5; i++ )  buffer << " " << sqrt(stateToUse.curvilinearError().matrix()(i,i));
00330   buffer << endl;
00331   
00332   //buffer << "GCTB: starting from r / phi / z = " << initial.globalPosition().perp()
00333   //<< " / " << initial.globalPosition().phi()
00334   //<< " / " << initial.globalPosition().z() << " , pt / pz = " 
00335   //<< initial.globalMomentum().perp() << " / " 
00336   //<< initial.globalMomentum().z() << " for layer at "
00337   //<< l << endl;
00338   //buffer << "     errors:";
00339   //for ( int i=0; i<5; i++ )  buffer << " " << sqrt(initial.curvilinearError().matrix()(i,i));
00340   //buffer << endl;
00341   return buffer.str();
00342 }
00343 
00344 
00345 bool 
00346 GroupedCkfTrajectoryBuilder::advanceOneLayer (TempTrajectory& traj, 
00347                                               const TrajectoryFilter* regionalCondition, 
00348                                               const Propagator* propagator,
00349                                               bool inOut,
00350                                               TempTrajectoryContainer& newCand, 
00351                                               TempTrajectoryContainer& result) const
00352 {
00353   std::pair<TSOS,std::vector<const DetLayer*> > stateAndLayers = findStateAndLayers(traj);
00354   if(maxPtForLooperReconstruction>0 && inOut){
00355     if(traj.lastLayer()->location()==0 && 
00356        stateAndLayers.first.globalMomentum().perp()<maxPtForLooperReconstruction)
00357       stateAndLayers.second.push_back(traj.lastLayer());
00358   }
00359 
00360   vector<const DetLayer*>::iterator layerBegin = stateAndLayers.second.begin();
00361   vector<const DetLayer*>::iterator layerEnd   = stateAndLayers.second.end();
00362 
00363   //   if (nl.empty()) {
00364   //     addToResult(traj,result,inOut);
00365   //     return false;
00366   //   }
00367   
00368   LogDebug("CkfPattern")<<whatIsTheNextStep(traj, stateAndLayers);
00369   
00370   bool foundSegments(false);
00371   bool foundNewCandidates(false);
00372   for ( vector<const DetLayer*>::iterator il=layerBegin; 
00373         il!=layerEnd; il++) {
00374 
00375     TSOS stateToUse = stateAndLayers.first;
00376 
00377     double dPhiCacheForLoopersReconstruction(0);
00378     if ((*il)==traj.lastLayer()){
00379       if(maxPtForLooperReconstruction>0){
00380         // ------ For loopers reconstruction
00381         //cout<<" self propagating in advanceOneLayer (for loopers) \n";
00382         const BarrelDetLayer* sbdl = dynamic_cast<const BarrelDetLayer*>(traj.lastLayer());
00383         if(sbdl){
00384           HelixBarrelCylinderCrossing cylinderCrossing(stateToUse.globalPosition(),
00385                                                        stateToUse.globalMomentum(),
00386                                                        stateToUse.transverseCurvature(),
00387                                                        propagator->propagationDirection(),
00388                                                        sbdl->specificSurface());
00389           if(!cylinderCrossing.hasSolution()) continue;
00390           GlobalPoint starting = stateToUse.globalPosition();
00391           GlobalPoint target1 = cylinderCrossing.position1();
00392           GlobalPoint target2 = cylinderCrossing.position2();
00393           
00394           GlobalPoint farther = fabs(starting.phi()-target1.phi()) > fabs(starting.phi()-target2.phi()) ?
00395             target1 : target2;
00396         
00397           const Bounds& bounds( sbdl->specificSurface().bounds());
00398           float length = bounds.length() / 2.f;
00399         
00400           /*
00401             cout << "starting: " << starting << endl;
00402             cout << "target1: " << target1 << endl;
00403             cout << "target2: " << target2 << endl;
00404             cout << "dphi: " << (target1.phi()-target2.phi()) << endl;
00405             cout << "length: " << length << endl;
00406           */
00407         
00408           /*
00409           float deltaZ = bounds.thickness()/2.f/fabs(tan(stateToUse.globalDirection().theta()) ) ;
00410           if(stateToUse.hasError())
00411             deltaZ += 3*sqrt(stateToUse.cartesianError().position().czz());
00412           if( fabs(farther.z()) > length + deltaZ ) continue;
00413           */
00414           if(fabs(farther.z())*0.95>length) continue;
00415 
00416           Geom::Phi<double> tmpDphi = target1.phi()-target2.phi();
00417 
00418           // -- FIXME: this cut should be configurable and it has to be tuned
00419           //if(tmpDphi.degrees() )>170)continue;
00420           //if(fabs(tmpDphi)>2.966) continue;
00421           if(fabs(tmpDphi)>1.5) continue;
00422           GlobalPoint target((target1.x()+target2.x())/2,
00423                              (target1.y()+target2.y())/2,
00424                              (target1.z()+target2.z())/2);
00425           
00426           //cout << "target: " << target << endl;
00427           
00428 
00429           
00430           TransverseImpactPointExtrapolator extrapolator;
00431           stateToUse = extrapolator.extrapolate(stateToUse, target, *propagator);
00432           if (!stateToUse.isValid()) continue; //SK: consider trying the original? probably not
00433 
00434           //dPhiCacheForLoopersReconstruction = fabs(target1.phi()-target2.phi())*2.;
00435           dPhiCacheForLoopersReconstruction = fabs(tmpDphi);
00436         }else{
00437           continue;
00438         }
00439       }else{
00440         // ------ For cosmics reconstruction
00441         LogDebug("CkfPattern")<<" self propagating in advanceOneLayer.\n from: \n"<<stateToUse;
00442         //self navigation case
00443         // go to a middle point first
00444         TransverseImpactPointExtrapolator middle;
00445         GlobalPoint center(0,0,0);
00446         stateToUse = middle.extrapolate(stateToUse, center, *theForwardPropagator);
00447         
00448         if (!stateToUse.isValid()) continue;
00449         LogDebug("CkfPattern")<<"to: "<<stateToUse;
00450       }
00451     }
00452     
00453     unsigned int maxCandidates = theMaxCand > 21 ? theMaxCand*2 : 42; //limit the number of returned segments
00454     TrajectorySegmentBuilder layerBuilder(theMeasurementTracker,
00455                                           theLayerMeasurements,
00456                                           **il,*propagator,
00457                                           *theUpdator,*theEstimator,
00458                                           theLockHits,theBestHitOnly, maxCandidates);
00459 
00460     LogDebug("CkfPattern")<<whatIsTheStateToUse(stateAndLayers.first,stateToUse,*il);
00461     
00462     TempTrajectoryContainer segments=
00463       layerBuilder.segments(stateToUse);
00464 
00465     LogDebug("CkfPattern")<< "GCTB: number of segments = " << segments.size();
00466 
00467     if ( !segments.empty() )  foundSegments = true;
00468 
00469     for ( TempTrajectoryContainer::const_iterator is=segments.begin();
00470           is!=segments.end(); is++ ) {
00471       //
00472       // assume "invalid hit only" segment is last in list
00473       //
00474       const TempTrajectory::DataContainer & measurements = is->measurements();
00475       if ( !theAlwaysUseInvalid && is!=segments.begin() && measurements.size()==1 && 
00476            (measurements.front().recHit()->getType() == TrackingRecHit::missing) )  break;
00477       //
00478       // create new candidate
00479       //
00480       TempTrajectory newTraj(traj);
00481       traj.setDPhiCacheForLoopersReconstruction(dPhiCacheForLoopersReconstruction);
00482       
00483       //----  avoid to add the same hits more than once in the trajectory ----
00484       bool toBeRejected(false);
00485       for(const TempTrajectory::DataContainer::const_iterator revIt = measurements.rbegin(); 
00486           revIt!=measurements.rend(); --revIt){
00487         int tmpCounter(0);
00488         for(const TempTrajectory::DataContainer::const_iterator newTrajMeasIt = newTraj.measurements().rbegin(); 
00489             newTrajMeasIt != newTraj.measurements().rend(); --newTrajMeasIt){
00490           if(tmpCounter==2) break;
00491           if(revIt->recHit()->geographicalId()==newTrajMeasIt->recHit()->geographicalId()){
00492             toBeRejected=true;
00493             break;
00494           }
00495           tmpCounter++;
00496         }
00497       }
00498 
00499       if(!toBeRejected){
00500         //newTraj.push(*is);
00501         //std::cout << "DEBUG: newTraj after push found,lost: " 
00502         //        << newTraj.foundHits() << " , " 
00503         //        << newTraj.lostHits() << " , "
00504         //        << newTraj.measurements().size() << std::endl;
00505       }else{    
00506         /*cout << "WARNING: neglect candidate because it contains the same hit twice \n";
00507         cout << "-- discarded track's pt,eta,#found: " 
00508              << newTraj.lastMeasurement().updatedState().globalMomentum().perp() << " , "
00509              << newTraj.lastMeasurement().updatedState().globalMomentum().eta() << " , "
00510              << newTraj.foundHits() << "\n";
00511         */
00512         continue; //Are we sure about this????
00513       }
00514       // ------------------------
00515 
00516 
00517       newTraj.push(*is);
00518       //GIO// for ( vector<TM>::const_iterator im=measurements.begin();
00519       //GIO//        im!=measurements.end(); im++ )  newTraj.push(*im);
00520       //if ( toBeContinued(newTraj,regionalCondition) ) { TOBE FIXED
00521       if ( toBeContinued(newTraj, inOut) ) {
00522         // Have added one more hit to track candidate
00523         
00524         LogDebug("CkfPattern")<<"GCTB: adding updated trajectory to candidates: inOut="<<inOut<<" hits="<<newTraj.foundHits();
00525 
00526         newCand.push_back(newTraj);
00527         foundNewCandidates = true;
00528       }
00529       else {
00530         // Have finished building this track. Check if it passes cuts.
00531 
00532         LogDebug("CkfPattern")<< "GCTB: adding completed trajectory to results if passes cuts: inOut="<<inOut<<" hits="<<newTraj.foundHits();
00533 
00534         addToResult(newTraj, result, inOut);
00535       }
00536     }
00537   }
00538 
00539   if ( !foundSegments ){
00540     LogDebug("CkfPattern")<< "GCTB: adding input trajectory to result";
00541     addToResult(traj, result, inOut);
00542   }
00543   return foundNewCandidates;
00544 }
00545 
00546 //TempTrajectoryContainer
00547 void
00548 GroupedCkfTrajectoryBuilder::groupedIntermediaryClean (TempTrajectoryContainer& theTrajectories) const 
00549 {
00550   //if (theTrajectories.empty()) return TrajectoryContainer();
00551   //TrajectoryContainer result;
00552   if (theTrajectories.empty()) return;  
00553   //RecHitEqualByChannels recHitEqualByChannels(false, false);
00554   int firstLayerSize, secondLayerSize;
00555   vector<const DetLayer*> firstLayers, secondLayers;
00556 
00557   for (TempTrajectoryContainer::iterator firstTraj=theTrajectories.begin();
00558        firstTraj!=(theTrajectories.end()-1); firstTraj++) {
00559 
00560     if ( (!firstTraj->isValid()) ||
00561          (!firstTraj->lastMeasurement().recHit()->isValid()) ) continue;
00562     const TempTrajectory::DataContainer & firstMeasurements = firstTraj->measurements();
00563     layers(firstMeasurements, firstLayers);
00564     firstLayerSize = firstLayers.size();
00565     if ( firstLayerSize<4 )  continue;
00566 
00567     for (TempTrajectoryContainer::iterator secondTraj=(firstTraj+1);
00568        secondTraj!=theTrajectories.end(); secondTraj++) {
00569 
00570       if ( (!secondTraj->isValid()) ||
00571            (!secondTraj->lastMeasurement().recHit()->isValid()) ) continue;
00572       const TempTrajectory::DataContainer & secondMeasurements = secondTraj->measurements();
00573       layers(secondMeasurements, secondLayers);
00574       secondLayerSize = secondLayers.size();
00575       //
00576       // only candidates using the same last 3 layers are compared
00577       //
00578       if ( firstLayerSize!=secondLayerSize )  continue;
00579       if ( firstLayers[0]!=secondLayers[0] ||
00580            firstLayers[1]!=secondLayers[1] ||
00581            firstLayers[2]!=secondLayers[2] )  continue;
00582 
00583       TempTrajectory::DataContainer::const_iterator im1 = firstMeasurements.rbegin();
00584       TempTrajectory::DataContainer::const_iterator im2 = secondMeasurements.rbegin();
00585       //
00586       // check for identical hits in the last layer
00587       //
00588       bool unequal(false);
00589       const DetLayer* layerPtr = firstLayers[0];
00590       while ( im1!=firstMeasurements.rend()&&im2!=secondMeasurements.rend() ) {
00591         if ( im1->layer()!=layerPtr || im2->layer()!=layerPtr )  break;
00592         if ( !(im1->recHit()->isValid()) || !(im2->recHit()->isValid()) ||
00594              !im1->recHit()->hit()->sharesInput(im2->recHit()->hit(), TrackingRecHit::some) ) {
00595           unequal = true;
00596           break;
00597         }
00598         --im1;
00599         --im2;
00600       }
00601       if ( im1==firstMeasurements.rend() || im2==secondMeasurements.rend() ||
00602            im1->layer()==layerPtr || im2->layer()==layerPtr || unequal )  continue;
00603       //
00604       // check for invalid hits in the layer -2
00605       // compare only candidates with invalid / valid combination
00606       //
00607       layerPtr = firstLayers[1];
00608       bool firstValid(true);
00609       while ( im1!=firstMeasurements.rend()&&im1->layer()==layerPtr ) {
00610         if ( !im1->recHit()->isValid() )  firstValid = false;
00611         --im1;
00612       }
00613       bool secondValid(true);
00614       while ( im2!=secondMeasurements.rend()&&im2->layer()==layerPtr ) {
00615         if ( !im2->recHit()->isValid() )  secondValid = false;
00616         --im2;
00617       }
00618       if ( !tkxor(firstValid,secondValid) )  continue;
00619       //
00620       // ask for identical hits in layer -3
00621       //
00622       unequal = false;
00623       layerPtr = firstLayers[2];
00624       while ( im1!=firstMeasurements.rend()&&im2!=secondMeasurements.rend() ) {
00625         if ( im1->layer()!=layerPtr || im2->layer()!=layerPtr )  break;
00626         if ( !(im1->recHit()->isValid()) || !(im2->recHit()->isValid()) ||
00628              !im1->recHit()->hit()->sharesInput(im2->recHit()->hit(), TrackingRecHit::some) ) {
00629           unequal = true;
00630           break;
00631         }
00632         --im1;
00633         --im2;
00634       }
00635       if ( im1==firstMeasurements.rend() || im2==secondMeasurements.rend() ||
00636            im1->layer()==layerPtr || im2->layer()==layerPtr || unequal )  continue;
00637 
00638       if ( !firstValid ) {
00639         firstTraj->invalidate();
00640         break;
00641       }
00642       else {
00643         secondTraj->invalidate();
00644         break;
00645       }
00646     }
00647   }
00648 /*
00649   for (TempTrajectoryContainer::const_iterator it = theTrajectories.begin();
00650        it != theTrajectories.end(); it++) {
00651     if(it->isValid()) result.push_back( *it);
00652   }
00653 
00654   return result;
00655 */
00656   theTrajectories.erase(std::remove_if( theTrajectories.begin(),theTrajectories.end(),
00657                                         std::not1(std::mem_fun_ref(&TempTrajectory::isValid))),
00658  //                                     boost::bind(&TempTrajectory::isValid,_1)), 
00659                         theTrajectories.end());
00660 }
00661 
00662 void
00663 GroupedCkfTrajectoryBuilder::layers (const TempTrajectory::DataContainer& measurements,
00664                                      vector<const DetLayer*> &result) const 
00665 {
00666   result.clear();
00667 
00668   if ( measurements.empty() )  return ;
00669 
00670   result.push_back(measurements.back().layer());
00671   TempTrajectory::DataContainer::const_iterator ifirst = measurements.rbegin();
00672   --ifirst;      
00673   for ( TempTrajectory::DataContainer::const_iterator im=ifirst;
00674         im!=measurements.rend(); --im ) {
00675     if ( im->layer()!=result.back() )  result.push_back(im->layer());
00676   }
00677 
00678   for (vector<const DetLayer*>::const_iterator iter = result.begin(); iter != result.end(); iter++){
00679     if (!*iter) edm::LogWarning("CkfPattern")<< "Warning: null det layer!! ";
00680   }
00681 }
00682 
00683 void
00684 GroupedCkfTrajectoryBuilder::rebuildSeedingRegion(TempTrajectory& startingTraj,
00685                                                   TempTrajectoryContainer& result) const
00686 {
00687   //
00688   // Rebuilding of trajectories. Candidates are taken from result,
00689   // which will be replaced with the solutions after rebuild
00690   // (assume vector::swap is more efficient than building new container)
00691   //
00692   LogDebug("CkfPattern")<< "Starting to rebuild " << result.size() << " tracks";
00693   //
00694   // Fitter (need to create it here since the propagation direction
00695   // might change between different starting trajectories)
00696   //
00697   KFTrajectoryFitter fitter(&(*theBackwardPropagator),&updator(),&estimator());
00698   //
00699   TempTrajectoryContainer reFitted;
00700   TrajectorySeed::range rseedHits = startingTraj.seed().recHits();
00701   std::vector<const TrackingRecHit*> seedHits;
00702   //seedHits.insert(seedHits.end(), rseedHits.first, rseedHits.second);
00703   //for (TrajectorySeed::recHitContainer::const_iterator iter = rseedHits.first; iter != rseedHits.second; iter++){
00704   //    seedHits.push_back(&*iter);
00705   //}
00706 
00707   //unsigned int nSeed(seedHits.size());
00708   unsigned int nSeed(rseedHits.second-rseedHits.first);
00709   //seedHits.reserve(nSeed);
00710   TempTrajectoryContainer rebuiltTrajectories;
00711   for ( TempTrajectoryContainer::iterator it=result.begin();
00712         it!=result.end(); it++ ) {
00713     //
00714     // skip candidates which are not exceeding the seed size 
00715     // (e.g. because no Tracker layers outside seeding region) 
00716     //
00717 
00718     if ( it->measurements().size()<=startingTraj.measurements().size() ) {
00719       rebuiltTrajectories.push_back(*it);
00720       LogDebug("CkfPattern")<< "RebuildSeedingRegion skipped as in-out trajectory does not exceed seed size.";
00721       continue;
00722     }
00723     //
00724     // Refit - keep existing trajectory in case fit is not possible
00725     // or fails
00726     //
00727     backwardFit(*it,nSeed,fitter,reFitted,seedHits);
00728     if ( reFitted.size()!=1 ) {
00729       rebuiltTrajectories.push_back(*it);
00730       LogDebug("CkfPattern")<< "RebuildSeedingRegion skipped as backward fit failed";
00731       //                            << "after reFitted.size() " << reFitted.size();
00732       continue;
00733     }
00734     //LogDebug("CkfPattern")<<"after reFitted.size() " << reFitted.size();
00735     //
00736     // Rebuild seeding part. In case it fails: keep initial trajectory
00737     // (better to drop it??)
00738     //
00739     int nRebuilt =
00740       rebuildSeedingRegion (seedHits,reFitted.front(),rebuiltTrajectories);
00741 
00742     if ( nRebuilt==0 ) it->invalidate();  // won't use original in-out track
00743 
00744     if ( nRebuilt<=0 ) rebuiltTrajectories.push_back(*it);
00745 
00746   }
00747   //
00748   // Replace input trajectories with new ones
00749   //
00750   result.swap(rebuiltTrajectories);
00751   result.erase(std::remove_if( result.begin(),result.end(),
00752                                std::not1(std::mem_fun_ref(&TempTrajectory::isValid))),
00753                result.end());
00754 }
00755 
00756 int
00757 GroupedCkfTrajectoryBuilder::rebuildSeedingRegion(const std::vector<const TrackingRecHit*>& seedHits, 
00758                                                   TempTrajectory& candidate,
00759                                                   TempTrajectoryContainer& result) const 
00760 {
00761   //
00762   // Starting from track found by in-out tracking phase, extrapolate it inwards through
00763   // the seeding region if possible in towards smaller Tracker radii, searching for additional
00764   // hits.
00765   // The resulting trajectories are returned in result,
00766   // the count is the return value.
00767   //
00768   TempTrajectoryContainer rebuiltTrajectories;
00769 #ifdef DBG2_GCTB
00770 /*  const LayerFinderByDet layerFinder;
00771   if ( !seedHits.empty() && seedHits.front().isValid() ) {
00772     DetLayer* seedLayer = layerFinder(seedHits.front().det());
00773     cout << "Seed hit at " << seedHits.front().globalPosition()
00774          << " " << seedLayer << endl;
00775     cout << "Started from " 
00776          << candidate.lastMeasurement().updatedState().globalPosition().perp() << " "
00777          << candidate.lastMeasurement().updatedState().globalPosition().z() << endl;
00778     pair<bool,TrajectoryStateOnSurface> layerComp(false,TrajectoryStateOnSurface());
00779     if ( seedLayer ) layerComp =
00780       seedLayer->compatible(candidate.lastMeasurement().updatedState(),
00781                               propagator(),estimator());
00782     pair<bool,TrajectoryStateOnSurface> detComp =
00783       seedHits.front().det().compatible(candidate.lastMeasurement().updatedState(),
00784                                         propagator(),estimator());
00785     cout << "  layer compatibility = " << layerComp.first;
00786     cout << "  det compatibility = " << detComp.first;
00787     if ( detComp.first ) {
00788       cout << "  estimate = " 
00789            << estimator().estimate(detComp.second,seedHits.front()).second ;
00790     }
00791     cout << endl;
00792   }*/
00793   cout << "Before backward building: #measurements = " 
00794        << candidate.measurements().size() ; //<< endl;;
00795 #endif
00796   //
00797   // Use standard building with standard cuts. Maybe better to use different
00798   // cuts from "forward" building (e.g. no check on nr. of invalid hits)?
00799   //
00800   const bool inOut = false;
00801   groupedLimitedCandidates(candidate, (const TrajectoryFilter*)0, theBackwardPropagator, inOut, rebuiltTrajectories);
00802 
00803   LogDebug("CkfPattern")<<" After backward building: "<<PrintoutHelper::dumpCandidates(rebuiltTrajectories);
00804 
00805   //
00806   // Check & count resulting candidates
00807   //
00808   int nrOfTrajectories(0);
00809   bool orig_ok = false;
00810   //const RecHitEqualByChannels recHitEqual(false,false);
00811   //vector<TM> oldMeasurements(candidate.measurements());
00812   for ( TempTrajectoryContainer::iterator it=rebuiltTrajectories.begin();
00813         it!=rebuiltTrajectories.end(); it++ ) {
00814 
00815     TempTrajectory::DataContainer newMeasurements(it->measurements());
00816     //
00817     // Verify presence of seeding hits?
00818     //
00819     if ( theRequireSeedHitsInRebuild ) {
00820       orig_ok = true;
00821       // no hits found (and possibly some invalid hits discarded): drop track
00822       if ( newMeasurements.size()<=candidate.measurements().size() ){  
00823         LogDebug("CkfPattern") << "newMeasurements.size()<=candidate.measurements().size()";
00824         continue;
00825       } 
00826       // verify presence of hits
00827       //GIO//if ( !verifyHits(newMeasurements.begin()+candidate.measurements().size(),
00828       //GIO//                  newMeasurements.end(),seedHits) ){
00829       if ( !verifyHits(newMeasurements.rbegin(), 
00830                        newMeasurements.size() - candidate.measurements().size(),
00831                        seedHits) ){
00832         LogDebug("CkfPattern")<< "seed hits not found in rebuild";
00833         continue; 
00834       }
00835     }
00836     //
00837     // construct final trajectory in the right order
00838     //
00839     TempTrajectory reversedTrajectory(it->seed(),it->seed().direction());
00840     for (TempTrajectory::DataContainer::const_iterator im=newMeasurements.rbegin(), ed = newMeasurements.rend();
00841           im != ed; --im ) {
00842       reversedTrajectory.push(*im);
00843     }
00844     // save & count result
00845     result.push_back(reversedTrajectory);
00846     nrOfTrajectories++;
00847 
00848     LogDebug("CkgPattern")<<"New traj direction = " << reversedTrajectory.direction()<<"\n"
00849                           <<PrintoutHelper::dumpMeasurements(reversedTrajectory.measurements());
00850   }
00851   // If nrOfTrajectories = 0 and orig_ok = true, this means that a track was actually found on the
00852   // out-in step (meeting those requirements) but did not have the seed hits in it.
00853   // In this case when we return we will go ahead and use the original in-out track.
00854 
00855   // If nrOfTrajectories = 0 and orig_ok = false, this means that the out-in step failed to
00856   // find any track.  Two cases are a technical failure in fitting the original seed hits or
00857   // because the track did not meet the out-in criteria (which may be stronger than the out-in
00858   // criteria).  In this case we will NOT allow the original in-out track to be used.
00859 
00860   if ( (nrOfTrajectories == 0) && orig_ok ) {
00861     nrOfTrajectories = -1;
00862   }
00863   return nrOfTrajectories;
00864 }
00865 
00866 void
00867 GroupedCkfTrajectoryBuilder::backwardFit (TempTrajectory& candidate, unsigned int nSeed,
00868                                                     const TrajectoryFitter& fitter,
00869                                                     TempTrajectoryContainer& fittedTracks,
00870                                                     std::vector<const TrackingRecHit*>& remainingHits) const
00871 {
00872   //
00873   // clear array of non-fitted hits
00874   //
00875   remainingHits.clear();
00876   fittedTracks.clear();
00877   //
00878   // skip candidates which are not exceeding the seed size
00879   // (e.g. Because no Tracker layers exist outside seeding region)
00880   //
00881   if ( candidate.measurements().size()<=nSeed ) {
00882     fittedTracks.clear();
00883     return;
00884   }
00885 
00886   LogDebug("CkfPattern")<<"nSeed " << nSeed << endl
00887                         << "Old traj direction = " << candidate.direction() << endl
00888                         <<PrintoutHelper::dumpMeasurements(candidate.measurements());
00889 
00890   //
00891   // backward fit trajectory.
00892   // (Will try to fit only hits outside the seeding region. However,
00893   // if there are not enough of these, it will also use the seeding hits).
00894   //
00895   TempTrajectory::DataContainer oldMeasurements(candidate.measurements());
00896 //   int nOld(oldMeasurements.size());
00897 //   const unsigned int nHitAllMin(5);
00898 //   const unsigned int nHit2dMin(2);
00899   unsigned int nHit(0);    // number of valid hits after seeding region
00900   //unsigned int nHit2d(0);  // number of valid hits after seeding region with 2D info
00901   // use all hits except the first n (from seed), but require minimum
00902   // specified in configuration.
00903   //  Swapped over next two lines.
00904   unsigned int nHitMin = max(candidate.foundHits()-nSeed,theMinNrOfHitsForRebuild);
00905   //  unsigned int nHitMin = oldMeasurements.size()-nSeed;
00906   // we want to rebuild only if the number of VALID measurements excluding the seed measurements is higher than the cut
00907   if (nHitMin<theMinNrOfHitsForRebuild){
00908         fittedTracks.clear();
00909         return;
00910   }
00911 
00912   LogDebug("CkfPattern")/* << "nHitMin " << nHitMin*/ <<"Sizes: " << oldMeasurements.size() << " / ";
00913   //
00914   // create input trajectory for backward fit
00915   //
00916   Trajectory fwdTraj(candidate.seed(),oppositeDirection(candidate.direction()));
00917   //const TrajectorySeed seed = TrajectorySeed(PTrajectoryStateOnDet(), TrajectorySeed::recHitContainer(), oppositeDirection(candidate.direction()));
00918   //Trajectory fwdTraj(seed, oppositeDirection(candidate.direction()));
00919   std::vector<const DetLayer*> bwdDetLayer; 
00920   for ( TempTrajectory::DataContainer::const_iterator im=oldMeasurements.rbegin();
00921         im!=oldMeasurements.rend(); --im) {
00922     const TrackingRecHit* hit = im->recHit()->hit();
00923     //
00924     // add hits until required number is reached
00925     //
00926     if ( nHit<nHitMin ){//|| nHit2d<theMinNrOf2dHitsForRebuild ) {
00927       fwdTraj.push(*im);
00928       bwdDetLayer.push_back(im->layer());
00929       //
00930       // count valid / 2D hits
00931       //
00932       if ( hit->isValid() ) {
00933         nHit++;
00934         //if ( hit.isMatched() ||
00935         //     hit.det().detUnits().front()->type().module()==pixel )
00936         //nHit2d++;
00937       }
00938     }
00939     //if (nHit==nHitMin) lastBwdDetLayer=im->layer();   
00940     //
00941     // keep remaining (valid) hits for verification
00942     //
00943     else if ( hit->isValid() ) {
00944       //std::cout << "Adding a remaining hit" << std::endl;
00945       remainingHits.push_back(hit);
00946     }
00947   }
00948   //
00949   // Fit only if required number of valid hits can be used
00950   //
00951   if ( nHit<nHitMin ){  //|| nHit2d<theMinNrOf2dHitsForRebuild ) {
00952     fittedTracks.clear();
00953     return;
00954   }
00955   //
00956   // Do the backward fit (important: start from scaled, not random cov. matrix!)
00957   //
00958   TrajectoryStateOnSurface firstTsos(fwdTraj.firstMeasurement().updatedState());
00959   //cout << "firstTsos "<< firstTsos << endl;
00960   firstTsos.rescaleError(10.);
00961   //TrajectoryContainer bwdFitted(fitter.fit(fwdTraj.seed(),fwdTraj.recHits(),firstTsos));
00962   TrajectoryContainer bwdFitted(fitter.fit(
00963                 TrajectorySeed(PTrajectoryStateOnDet(), TrajectorySeed::recHitContainer(), oppositeDirection(candidate.direction())),
00964                 fwdTraj.recHits(),firstTsos));
00965   if (bwdFitted.size()){
00966     LogDebug("CkfPattern")<<"Obtained " << bwdFitted.size() << " bwdFitted trajectories with measurement size " << bwdFitted.front().measurements().size();
00967         TempTrajectory fitted(fwdTraj.seed(), fwdTraj.direction());
00968         vector<TM> tmsbf = bwdFitted.front().measurements();
00969         int iDetLayer=0;
00970         //this is ugly but the TM in the fitted track do not contain the DetLayer.
00971         //So we have to cache the detLayer pointers and replug them in.
00972         //For the backward building it would be enaugh to cache the last DetLayer, 
00973         //but for the intermediary cleaning we need all
00974         for ( vector<TM>::const_iterator im=tmsbf.begin();im!=tmsbf.end(); im++ ) {
00975                 fitted.push(TM( (*im).forwardPredictedState(),
00976                                 (*im).backwardPredictedState(),
00977                                 (*im).updatedState(),
00978                                 (*im).recHit(),
00979                                 (*im).estimate(),
00980                                 bwdDetLayer[iDetLayer]));
00981 
00982                 LogDebug("CkfPattern")<<PrintoutHelper::dumpMeasurement(*im);
00983                 iDetLayer++;
00984         }
00985 /*
00986         TM lastMeas = bwdFitted.front().lastMeasurement();
00987         fitted.pop();
00988         fitted.push(TM(lastMeas.forwardPredictedState(), 
00989                                lastMeas.backwardPredictedState(), 
00990                                lastMeas.updatedState(),
00991                                lastMeas.recHit(),
00992                                lastMeas.estimate(),
00993                                lastBwdDetLayer));*/
00994         fittedTracks.push_back(fitted);
00995   }
00996   //
00997   // save result
00998   //
00999   //fittedTracks.swap(bwdFitted);
01000   //cout << "Obtained " << fittedTracks.size() << " fittedTracks trajectories with measurement size " << fittedTracks.front().measurements().size() << endl;
01001 }
01002 
01003 bool
01004 GroupedCkfTrajectoryBuilder::verifyHits (TempTrajectory::DataContainer::const_iterator rbegin,
01005                                          size_t maxDepth,
01006                                          const std::vector<const TrackingRecHit*>& hits) const
01007 {
01008   //
01009   // verify presence of the seeding hits
01010   //
01011   LogDebug("CkfPattern")<<"Checking for " << hits.size() << " hits in "
01012                         << maxDepth << " measurements" << endl;
01013 
01014   TempTrajectory::DataContainer::const_iterator rend = rbegin; 
01015   while (maxDepth > 0) { --maxDepth; --rend; }
01016   for ( vector<const TrackingRecHit*>::const_iterator ir=hits.begin();
01017         ir!=hits.end(); ir++ ) {
01018     // assume that all seeding hits are valid!
01019     bool foundHit(false);
01020     for ( TempTrajectory::DataContainer::const_iterator im=rbegin; im!=rend; --im ) {
01021       if ( im->recHit()->isValid() && (*ir)->sharesInput(im->recHit()->hit(), TrackingRecHit::some) ) {
01022         foundHit = true;
01023         break;
01024       }
01025     }
01026     if ( !foundHit )  return false;
01027   }
01028   return true;
01029 }
01030 
01031 
01032 
01033