CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_1/src/RecoTracker/CkfPattern/src/TrajectorySegmentBuilder.cc

Go to the documentation of this file.
00001 
00002 #include "TrajectorySegmentBuilder.h"
00003 
00004 #include "RecoTracker/CkfPattern/src/RecHitIsInvalid.h"
00005 #include "TrackingTools/PatternTools/interface/TempTrajectory.h"
00006 
00007 #include "DataFormats/TrajectorySeed/interface/TrajectorySeed.h"
00008 #include "TrackingTools/KalmanUpdators/interface/KFUpdator.h"
00009 #include "TrackingTools/PatternTools/interface/MeasurementEstimator.h"
00010 #include "TrackingTools/PatternTools/interface/Trajectory.h"
00011 #include "TrackingTools/PatternTools/interface/TrajectoryMeasurement.h"
00012 #include "TrackingTools/MeasurementDet/interface/TrajectoryMeasurementGroup.h"
00013 #include "TrackingTools/DetLayers/interface/DetGroup.h"
00014 #include "TrackingTools/DetLayers/interface/DetLayer.h"
00015 #include "RecoTracker/CkfPattern/src/TrajectoryLessByFoundHits.h"
00016 #include "TrackingTools/PatternTools/interface/TrajectoryStateUpdator.h"
00017 #include "TrackingTools/DetLayers/interface/GeomDetCompatibilityChecker.h"
00018 #include "TrackingTools/MeasurementDet/interface/MeasurementDet.h"
00019 
00020 #include <algorithm> 
00021 
00022 // #define DBG_TSB
00023 
00024 namespace {
00025 #ifdef STAT_TSB
00026   struct StatCount {
00027     long long totGroup;
00028     long long totSeg;
00029     long long totLockHits;
00030     void zero() {
00031       totGroup=totSeg=totLockHits=0;
00032     }
00033     void incr(long long g, long long s, long long l) {
00034       totGroup+=g;
00035       totSeg+=s;
00036       totLockHits+=l;
00037      }
00038     void print() const {
00039       std::cout << "TrajectorySegmentBuilder stat\nGroup/Seg/Lock "
00040                 << totGroup<<'/'<<totSeg<<'/'<<totLockHits
00041                 << std::endl;
00042     }
00043     StatCount() { zero();}
00044     ~StatCount() { print();}
00045   };
00046 
00047 #else
00048   struct StatCount {
00049     void incr(long long, long long, long long){}
00050   };
00051 #endif
00052 
00053   StatCount statCount;
00054 
00055 }
00056 
00057 
00058 using namespace std;
00059 
00060 TrajectorySegmentBuilder::TempTrajectoryContainer
00061 TrajectorySegmentBuilder::segments (const TSOS startingState)
00062 {
00063   //
00064   // create empty trajectory
00065   //
00066   theLockedHits.clear();
00067   TempTrajectory startingTrajectory(theFullPropagator.propagationDirection());
00068   //
00069   // get measurement groups
00070   //
00071   vector<TMG> measGroups = 
00072     theLayerMeasurements->groupedMeasurements(theLayer,startingState,theFullPropagator,theEstimator);
00073     //B.M. theLayer.groupedMeasurements(startingState,theFullPropagator,theEstimator);
00074 
00075 #ifdef DBG_TSB
00076   cout << "TSB: number of measurement groups = " << measGroups.size() << endl;
00077   //  theDbgFlg = measGroups.size()>1;
00078   theDbgFlg = true;
00079 #else
00080   theDbgFlg = false;
00081 #endif
00082 
00083 
00084 #ifdef DBG_TSB
00085   if ( theDbgFlg ) {
00086     int ntot(1);
00087     for (vector<TMG>::const_iterator ig=measGroups.begin();
00088          ig!=measGroups.end(); ++ig) {
00089       int ngrp(0);
00090       const vector<TM>& measurements = ig->measurements();
00091       for ( vector<TM>::const_iterator im=measurements.begin();
00092             im!=measurements.end(); ++im ) {
00093         if ( im->recHit()->isValid() )  ngrp++;
00094       }
00095       cout << " " << ngrp;
00096       if ( ngrp>0 )  ntot *= ngrp;
00097     }  
00098     cout << endl;
00099     cout << "TrajectorySegmentBuilder::partialTrajectories:: det ids & hit types / group" << endl;
00100     for (vector<TMG>::const_iterator ig=measGroups.begin();
00101          ig!=measGroups.end(); ++ig) {
00102       const vector<TM>& measurements = ig->measurements();
00103       for ( vector<TM>::const_iterator im=measurements.begin();
00104             im!=measurements.end(); ++im ) {
00105         if ( im!=measurements.begin() )  cout << " / ";
00106         if ( im->recHit()->det() )
00107           cout << im->recHit()->det()->geographicalId().rawId() << " "
00108                << im->recHit()->getType();
00109         else
00110           cout << "no det";
00111       }
00112       cout << endl;
00113     }  
00114   
00115 
00116 //   if ( measGroups.size()>4 ) {
00117     cout << typeid(theLayer).name() << endl;
00118     cout << startingState.localError().matrix() << endl;
00119 //     for (vector<TMG>::const_iterator ig=measGroups.begin();
00120 //       ig!=measGroups.end(); ig++) {
00121 //       cout << "Nr. of measurements = " << ig->measurements().size() << endl;
00122 //       const DetGroup& dg = ig->detGroup();
00123 //       for ( DetGroup::const_iterator id=dg.begin();
00124 //          id!=dg.end(); id++ ) {
00125 //      GlobalPoint p(id->det()->position());
00126 //      GlobalVector v(id->det()->toGlobal(LocalVector(0.,0.,1.)));
00127 //      cout << p.perp() << " " << p.phi() << " " << p.z() << " ; "
00128 //           << v.phi() << " " << v.z() << endl;
00129 //       }
00130 //     }
00131 //   }
00132   }
00133 #endif
00134 
00135   TempTrajectoryContainer candidates = 
00136     addGroup(startingTrajectory,measGroups.begin(),measGroups.end());
00137 
00138   if (theDbgFlg) cout << "TSB: back with " << candidates.size() << " candidates" << endl;
00139   // clean
00140   //
00141   //
00142   // add invalid hit - try to get first detector hit by the extrapolation
00143   //
00144 
00145   updateWithInvalidHit(startingTrajectory,measGroups,candidates);
00146 
00147   if (theDbgFlg) cout << "TSB: " << candidates.size() << " candidates after invalid hit" << endl;
00148 
00149   statCount.incr(measGroups.size(), candidates.size(), theLockedHits.size());
00150 
00151 
00152   theLockedHits.clear();
00153 
00154   return candidates;
00155 }
00156 
00157 void TrajectorySegmentBuilder::updateTrajectory (TempTrajectory& traj,
00158                                                  const TM& tm) const
00159 {
00160   TSOS predictedState = tm.predictedState();
00161   ConstRecHitPointer hit = tm.recHit();
00162  
00163   if ( hit->isValid()) {
00164     traj.push( TM( predictedState, theUpdator.update( predictedState, *hit),
00165                    hit, tm.estimate(), tm.layer()));
00166 
00167 //     TrajectoryMeasurement tm(traj.lastMeasurement());
00168 //     if ( tm.updatedState().isValid() ) {
00169 //       if ( !hit.det().surface().bounds().inside(tm.updatedState().localPosition(),
00170 //                                              tm.updatedState().localError().positionError(),3.) ) {
00171 //      cout << "Incompatibility after update for det at " << hit.det().position() << ":" << endl;
00172 //      cout << tm.predictedState().localPosition() << " " 
00173 //           << tm.predictedState().localError().positionError() << endl;
00174 //      cout << hit.localPosition() << " " << hit.localPositionError() << endl;
00175 //      cout << tm.updatedState().localPosition() << " "
00176 //           << tm.updatedState().localError().positionError() << endl;
00177 //       }
00178 //     }
00179   }
00180   else {
00181     traj.push( TM( predictedState, hit,0, tm.layer()));
00182   }
00183 }
00184 
00185 
00186 TrajectorySegmentBuilder::TempTrajectoryContainer
00187 TrajectorySegmentBuilder::addGroup (TempTrajectory& traj,
00188                                     vector<TMG>::const_iterator begin,
00189                                     vector<TMG>::const_iterator end)
00190 {
00191   vector<TempTrajectory> ret;
00192   if ( begin==end ) {
00193     //std::cout << "TrajectorySegmentBuilder::addGroup" << " traj.empty()=" << traj.empty() << "EMPTY" << std::endl;
00194     if (theDbgFlg) cout << "TSB::addGroup : no groups left" << endl;
00195     if ( !traj.empty() )
00196       ret.push_back(traj);
00197     return ret;
00198   }
00199   
00200   if (theDbgFlg) cout << "TSB::addGroup : traj.size() = " << traj.measurements().size()
00201                       << " first group at " << &(*begin)
00202                    //        << " nr. of candidates = " << candidates.size() 
00203                       << endl;
00204 
00205 
00206   TempTrajectoryContainer updatedTrajectories; updatedTrajectories.reserve(2);
00207   if ( traj.measurements().empty() ) {
00208     vector<TM> firstMeasurements = unlockedMeasurements(begin->measurements());
00209     if ( theBestHitOnly )
00210       updateCandidatesWithBestHit(traj,firstMeasurements,updatedTrajectories);
00211     else
00212       updateCandidates(traj,begin->measurements(),updatedTrajectories);
00213     if (theDbgFlg) cout << "TSB::addGroup : updating with first group - "
00214                         << updatedTrajectories.size() << " trajectories" << endl;
00215   }
00216   else {
00217     if ( theBestHitOnly )
00218       updateCandidatesWithBestHit(traj,redoMeasurements(traj,begin->detGroup()),
00219                                   updatedTrajectories);
00220     else
00221       updateCandidates(traj,redoMeasurements(traj,begin->detGroup()),
00222                        updatedTrajectories);
00223     if (theDbgFlg) cout << "TSB::addGroup : updating"
00224                         << updatedTrajectories.size() << " trajectories" << endl;
00225   }
00226 
00227   if (begin+1 != end) {
00228       ret.reserve(4); // a good upper bound
00229       for ( TempTrajectoryContainer::iterator it=updatedTrajectories.begin();
00230             it!=updatedTrajectories.end(); ++it ) {
00231         if (theDbgFlg) cout << "TSB::addGroup : trying to extend candidate at "
00232                             << &(*it) << " size " << it->measurements().size() << endl;
00233         vector<TempTrajectory> finalTrajectories = addGroup(*it,begin+1,end);
00234         if (theDbgFlg) cout << "TSB::addGroup : " << finalTrajectories.size()
00235                             << " finalised candidates before cleaning" << endl;
00236         //B.M. to be ported later
00237         cleanCandidates(finalTrajectories);
00238 
00239         if (theDbgFlg) cout << "TSB::addGroup : got " << finalTrajectories.size()
00240                             << " finalised candidates" << endl;
00241         ret.insert(ret.end(),finalTrajectories.begin(),
00242                       finalTrajectories.end());
00243       }
00244   } else {
00245       ret.reserve(updatedTrajectories.size());
00246       for (TempTrajectoryContainer::iterator it=updatedTrajectories.begin(); 
00247               it!=updatedTrajectories.end(); ++it ) { 
00248         if (!it->empty()) ret.push_back(*it);
00249       }
00250   }
00251 
00252   //std::cout << "TrajectorySegmentBuilder::addGroup" << 
00253   //             " traj.empty()=" << traj.empty() << 
00254   //             " end-begin=" << (end-begin)  <<
00255   //             " #updated=" << updatedTrajectories.size() << 
00256   //             " #result=" << ret.size() << std::endl;
00257   return ret;
00258 }
00259 
00260 void
00261 TrajectorySegmentBuilder::updateCandidates (TempTrajectory& traj,
00262                                             const vector<TM>& measurements,
00263                                             TempTrajectoryContainer& candidates)
00264 {
00265   //
00266   // generate updated candidates with all valid hits
00267   //
00268   for ( vector<TM>::const_iterator im=measurements.begin();
00269         im!=measurements.end(); ++im ) {
00270     if ( im->recHit()->isValid() ) {
00271       candidates.push_back(traj);
00272       updateTrajectory(candidates.back(),*im);
00273       if ( theLockHits )  lockMeasurement(*im);
00274     }
00275   }
00276   //
00277   // keep old trajectory
00278   //
00279   candidates.push_back(traj);
00280 }
00281 
00282 void
00283 TrajectorySegmentBuilder::updateCandidatesWithBestHit (TempTrajectory& traj,
00284                                                        const vector<TM>& measurements,
00285                                                        TempTrajectoryContainer& candidates)
00286 {
00287   vector<TM>::const_iterator ibest = measurements.begin();
00288   // get first
00289   while(ibest!=measurements.end() && !ibest->recHit()->isValid()) ++ibest;
00290   if ( ibest!=measurements.end() ) {
00291     // find real best;
00292     for ( vector<TM>::const_iterator im=ibest+1;
00293           im!=measurements.end(); ++im ) {
00294       if ( im->recHit()->isValid() &&
00295            im->estimate()<ibest->estimate()
00296            )
00297         ibest = im;
00298     } 
00299 
00300 
00301     if ( theLockHits )  lockMeasurement(*ibest);
00302     candidates.push_back(traj);
00303     updateTrajectory(candidates.back(),*ibest);
00304 
00305     if ( theDbgFlg )
00306       cout << "TSB: found best measurement at " 
00307            << ibest->recHit()->globalPosition().perp() << " "
00308            << ibest->recHit()->globalPosition().phi() << " "
00309            << ibest->recHit()->globalPosition().z() << endl;
00310     
00311   }
00312 
00313   //
00314   // keep old trajectorTempy
00315   //
00316   candidates.push_back(traj);
00317 }
00318 
00319 vector<TrajectoryMeasurement>
00320 TrajectorySegmentBuilder::redoMeasurements (const TempTrajectory& traj,
00321                                             const DetGroup& detGroup) const
00322 {
00323   vector<TM> result;
00324   //
00325   // loop over all dets
00326   //
00327   if (theDbgFlg) cout << "TSB::redoMeasurements : nr. of measurements / group =";
00328 
00329   for (DetGroup::const_iterator idet=detGroup.begin(); 
00330        idet!=detGroup.end(); ++idet) {
00331     //
00332     // ======== ask for measurements ==============       
00333     //B.M vector<TM> tmp = idet->det()->measurements(traj.lastMeasurement().updatedState(),
00334     //                                         theGeomPropagator,theEstimator);
00335     
00336     pair<bool, TrajectoryStateOnSurface> compat = 
00337       GeomDetCompatibilityChecker().isCompatible(idet->det(),
00338                                                  traj.lastMeasurement().updatedState(),
00339                                                  theGeomPropagator,theEstimator);
00340     
00341     if (theDbgFlg && !compat.first) cout << " 0";
00342 
00343     if(!compat.first) continue;
00344     const MeasurementDet* mdet = theMeasurementTracker->idToDet(idet->det()->geographicalId());
00345     vector<TM> tmp
00346       = mdet->fastMeasurements( compat.second, idet->trajectoryState(), theGeomPropagator, theEstimator);
00347     
00348 
00349     //perhaps could be enough just:
00350     //vector<TM> tmp = mdet->fastMeasurements( idet->trajectoryState(),
00351     //                                       traj.lastMeasurement().updatedState(),
00352     //                                       theGeomPropagator, theEstimator);
00353     // ==================================================
00354 
00355     //
00356     // only collect valid RecHits
00357     //
00358     if (theDbgFlg) cout << " " << tmp.size();
00359 
00360     for(vector<TM>::iterator tmpIt=tmp.begin(); tmpIt!=tmp.end(); ++tmpIt){
00361       if ( tmpIt->recHit()->isValid() ) {
00362         tmpIt->setLayer(&theLayer); // set layer in TM, because the Det cannot do it
00363         result.push_back(*tmpIt);
00364       }
00365     }
00366   }
00367   if (theDbgFlg) cout << endl;
00368 
00369   return result;
00370 }
00371 
00372 void 
00373 TrajectorySegmentBuilder::updateWithInvalidHit (TempTrajectory& traj,
00374                                                 const vector<TMG>& groups,
00375                                                 TempTrajectoryContainer& candidates) const
00376 {
00377   //
00378   // first try to find an inactive hit with dets crossed by the prediction,
00379   //   then take any inactive hit
00380   //
00381   // loop over groups
00382   for ( int iteration=0; iteration<2; iteration++ ) {
00383     for ( vector<TMG>::const_iterator ig=groups.begin(); ig!=groups.end(); ++ig) {
00384       // loop over measurements
00385       const vector<TM>& measurements = ig->measurements();
00386       for ( vector<TM>::const_reverse_iterator im=measurements.rbegin();
00387             im!=measurements.rend(); ++im ) {
00388         ConstRecHitPointer hit = im->recHit();
00389         if ( hit->getType()==TrackingRecHit::valid ||
00390              hit->getType()==TrackingRecHit::missing )  continue;
00391         //
00392         // check, if the extrapolation traverses the Det or
00393         // if 2nd iteration
00394         //
00395         if ( hit->det() ) {
00396           TSOS predState(im->predictedState());
00397           if ( iteration>0 || 
00398                (predState.isValid() &&
00399                 hit->det()->surface().bounds().inside(predState.localPosition())) ) {
00400             // add the hit
00401             /*TempTrajectory newTraj(traj);
00402             updateTrajectory(newTraj,*im);
00403             candidates.push_back(newTraj);  // FIXME: avoid useless copy */
00404             candidates.push_back(traj); 
00405             updateTrajectory(candidates.back(), *im);
00406             if ( theDbgFlg ) cout << "TrajectorySegmentBuilder::updateWithInvalidHit "
00407                                   << "added inactive hit" << endl;
00408             return;
00409           }
00410         }
00411       }
00412     }
00413   }
00414   //
00415   // No suitable inactive hit: add a missing one
00416   //
00417   bool found(false);
00418   for ( int iteration=0; iteration<2; iteration++ ) {
00419     //
00420     // loop over groups
00421     //
00422     for ( vector<TMG>::const_iterator ig=groups.begin();
00423           ig!=groups.end(); ++ig) {
00424       const vector<TM>& measurements = ig->measurements();
00425       for ( vector<TM>::const_reverse_iterator im=measurements.rbegin();
00426             im!=measurements.rend(); ++im ) {
00427         //
00428         // only use invalid hits
00429         //
00430         ConstRecHitPointer hit = im->recHit();
00431         if ( hit->isValid() )  continue;
00432 
00433         //
00434         // check, if the extrapolation traverses the Det
00435         //
00436         TSOS predState(im->predictedState());
00437         if(hit->det()){ 
00438           if ( iteration>0 || (predState.isValid() &&
00439                                hit->det()->surface().bounds().inside(predState.localPosition())) ) {
00440             // add invalid hit
00441             /*TempTrajectory newTraj(traj);
00442             updateTrajectory(newTraj,*im);
00443             candidates.push_back(newTraj);  // FIXME: avoid useless copy */
00444             candidates.push_back(traj); 
00445             updateTrajectory(candidates.back(), *im);
00446             found = true;
00447             break;
00448           }
00449 
00450         }else{
00451           if ( iteration>0 || (predState.isValid() &&
00452                                im->layer()->surface().bounds().inside(predState.localPosition())) ){
00453             // add invalid hit
00454             /*TempTrajectory newTraj(traj);
00455             updateTrajectory(newTraj,*im);
00456             candidates.push_back(newTraj);  // FIXME: avoid useless copy */
00457             candidates.push_back(traj); 
00458             updateTrajectory(candidates.back(), *im);
00459             found = true;
00460             break;          
00461           }
00462         }
00463       }
00464       if ( found )  break;
00465     }
00466     if ( theDbgFlg && !found ) cout << "TrajectorySegmentBuilder::updateWithInvalidHit: "
00467                                     << " did not find invalid hit on 1st iteration" << endl;
00468     if ( found )  break;
00469   }
00470   if ( !found ) {
00471     if (theDbgFlg) cout << "TrajectorySegmentBuilder::updateWithInvalidHit: "
00472                         << " did not find invalid hit" << endl;
00473   }
00474 }
00475 
00476 vector<TrajectoryMeasurement>
00477 TrajectorySegmentBuilder::unlockedMeasurements (const vector<TM>& measurements) const
00478 {
00479 //   if ( !theLockHits )  return measurements;
00480 
00481   //========== B.M. to be ported later ===============
00482   vector<TM> result;
00483   result.reserve(measurements.size());
00484 
00485   //RecHitEqualByChannels recHitEqual(false,true);
00486 
00487   for ( vector<TM>::const_iterator im=measurements.begin();
00488         im!=measurements.end(); ++im ) {
00489     ConstRecHitPointer testHit = im->recHit();
00490     if ( !testHit->isValid() )  continue;
00491     bool found(false);
00492     if ( theLockHits ) {
00493       for ( ConstRecHitContainer::const_iterator ih=theLockedHits.begin();
00494             ih!=theLockedHits.end(); ++ih ) {
00495         if ( (*ih)->hit()->sharesInput(testHit->hit(), TrackingRecHit::all) ) {
00496           found = true;
00497           break;
00498         }
00499       }
00500     }
00501     if ( !found )  result.push_back(*im);
00502   }
00503   return result;
00504   //================================= 
00505   //return measurements; // temporary solution before RecHitEqualByChannels is ported
00506 }
00507 
00508 void
00509 TrajectorySegmentBuilder::lockMeasurement (const TM& measurement)
00510 {
00511   theLockedHits.push_back(measurement.recHit());
00512 }
00513 
00514 
00515 
00516 // ================= B.M. to be ported later ===============================
00517 void
00518 TrajectorySegmentBuilder::cleanCandidates (vector<TempTrajectory>& candidates) const
00519 {
00520   //
00521   // remove candidates which are subsets of others
00522   // assumptions: no invalid hits and no duplicates
00523   //
00524   if ( candidates.size()<=1 )  return;
00525   //RecHitEqualByChannels recHitEqual(false,true);
00526   //
00527   vector<TempTrajectory> sortedCandidates(candidates);
00528   sort(sortedCandidates.begin(),sortedCandidates.end(),TrajectoryLessByFoundHits());
00529 //   cout << "SortedCandidates.foundHits";
00530 //   for ( vector<Trajectory>::iterator i1=sortedCandidates.begin();
00531 //      i1!=sortedCandidates.end(); i1++ ) 
00532 //     cout << " " << i1->foundHits();
00533 //   cout << endl;
00534   //
00535   for ( vector<TempTrajectory>::iterator i1=sortedCandidates.begin();
00536         i1!=sortedCandidates.end()-1; ++i1 ) {
00537     // get measurements of candidate to be checked
00538     const TempTrajectory::DataContainer & measurements1 = i1->measurements();
00539     for ( vector<TempTrajectory>::iterator i2=i1+1;
00540           i2!=sortedCandidates.end(); ++i2 ) {
00541       // no duplicates: two candidates of same size are different
00542       if ( i2->foundHits()==i1->foundHits() )  continue;
00543       // get measurements of "reference"
00544       const TempTrajectory::DataContainer & measurements2 = i2->measurements();
00545       //
00546       // use the fact that TMs are ordered:
00547       // start search in trajectory#1 from last hit match found
00548       //
00549       bool allFound(true);
00550       TempTrajectory::DataContainer::const_iterator from2 = measurements2.rbegin(), im2end = measurements2.rend();
00551       for ( TempTrajectory::DataContainer::const_iterator im1=measurements1.rbegin(),im1end = measurements1.rend();
00552             im1!=im1end; --im1 ) {
00553         // redundant protection - segments should not contain invalid RecHits
00554         if ( !im1->recHit()->isValid() )  continue;
00555         bool found(false);
00556         for ( TempTrajectory::DataContainer::const_iterator im2=from2;
00557               im2!=im2end; --im2 ) {
00558           // redundant protection - segments should not contain invalid RecHits
00559           if ( !im2->recHit()->isValid() )  continue;
00560           if ( im1->recHit()->hit()->sharesInput(im2->recHit()->hit(), TrackingRecHit::all) ) {
00561             found = true;
00562             from2 = im2; --from2;
00563             break;
00564           }
00565         }
00566         if ( !found ) {
00567           allFound = false;
00568           break;
00569         }
00570       }
00571       if ( allFound )  i1->invalidate();
00572     }
00573   }
00574 /*
00575   candidates.clear();
00576   for ( vector<Trajectory>::const_iterator i=sortedCandidates.begin();
00577         i!=sortedCandidates.end(); i++ ) {
00578     if ( i->isValid() )  candidates.push_back(*i);
00579   }
00580 */
00581   candidates.erase(std::remove_if( candidates.begin(),candidates.end(),
00582                                    std::not1(std::mem_fun_ref(&TempTrajectory::isValid))),
00583  //                                boost::bind(&TempTrajectory::isValid,_1)), 
00584                                    candidates.end()); 
00585 #ifdef DBG_TSB
00586   cout << "TSB: cleanCandidates: reduced from " << sortedCandidates.size()
00587        << " to " << candidates.size() << " candidates" << endl;
00588 #endif
00589   return;
00590 }
00591 
00592 //==================================================