CMS 3D CMS Logo

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