CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/src/RecoMuon/MuonSeedGenerator/src/SETPatternRecognition.cc

Go to the documentation of this file.
00001 
00005 #include "RecoMuon/MuonSeedGenerator/src/SETPatternRecognition.h"
00006 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00007 #include "FWCore/Framework/interface/Event.h"
00008 #include "RecoMuon/TrackingTools/interface/MuonPatternRecoDumper.h"
00009 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00010 #include "TrackingTools/DetLayers/interface/DetLayer.h"
00011 #include "Geometry/CommonDetUnit/interface/GeomDet.h"
00012 #include "DataFormats/DTRecHit/interface/DTRecSegment4D.h"
00013 #include "DataFormats/DTRecHit/interface/DTRecSegment4DCollection.h"            
00014 #include "DataFormats/CSCRecHit/interface/CSCSegmentCollection.h"             
00015 #include "DataFormats/RPCRecHit/interface/RPCRecHitCollection.h"                
00016 #include "TMath.h"
00017 
00018 
00019 using namespace edm;
00020 using namespace std;
00021 
00022 SETPatternRecognition::SETPatternRecognition(const ParameterSet& parameterSet)
00023 : MuonSeedVPatternRecognition(parameterSet.getParameter<ParameterSet>("SETTrajBuilderParameters").getParameter<ParameterSet>("FilterParameters"))
00024 {
00025   const string metname = "Muon|RecoMuon|SETPatternRecognition";  
00026   // Parameter set for the Builder
00027   ParameterSet trajectoryBuilderParameters = parameterSet.getParameter<ParameterSet>("SETTrajBuilderParameters");
00028   // The inward-outward fitter (starts from seed state)
00029   ParameterSet filterPSet = trajectoryBuilderParameters.getParameter<ParameterSet>("FilterParameters");
00030   maxActiveChambers = filterPSet.getParameter<int>("maxActiveChambers"); 
00031   useRPCs = filterPSet.getParameter<bool>("EnableRPCMeasurement");
00032   DTRecSegmentLabel  = filterPSet.getParameter<edm::InputTag>("DTRecSegmentLabel");
00033   CSCRecSegmentLabel  = filterPSet.getParameter<edm::InputTag>("CSCRecSegmentLabel");
00034   RPCRecSegmentLabel  = filterPSet.getParameter<edm::InputTag>("RPCRecSegmentLabel");
00035 
00036   outsideChamberErrorScale = filterPSet.getParameter<double>("OutsideChamberErrorScale");
00037   minLocalSegmentAngle = filterPSet.getParameter<double>("MinLocalSegmentAngle");
00038   //----
00039 
00040 } 
00041 
00042 //---- it is a "cluster recognition" actually; the pattern recognition is in SETFilter 
00043 void SETPatternRecognition::produce(const edm::Event& event, const edm::EventSetup& eventSetup,
00044                          std::vector<MuonRecHitContainer> & segments_clusters)
00045 {
00046   const string metname = "Muon|RecoMuon|SETMuonSeedSeed";  
00047 
00048   //---- Build collection of all segments
00049   MuonRecHitContainer muonRecHits;
00050   MuonRecHitContainer muonRecHits_DT2D_hasPhi;
00051   MuonRecHitContainer muonRecHits_DT2D_hasZed;
00052   MuonRecHitContainer muonRecHits_RPC;
00053 
00054   // ********************************************;
00055   // Get the DT-Segment collection from the Event
00056   // ********************************************;
00057 
00058   edm::Handle<DTRecSegment4DCollection> dtRecHits;
00059   event.getByLabel(DTRecSegmentLabel, dtRecHits);
00060   std::vector<DTChamberId> chambers_DT;
00061   std::vector<DTChamberId>::const_iterator chIt_DT;
00062   for (DTRecSegment4DCollection::const_iterator rechit = dtRecHits->begin(); rechit!=dtRecHits->end();++rechit) {
00063     bool insert = true;
00064     for(chIt_DT=chambers_DT.begin(); chIt_DT != chambers_DT.end(); ++chIt_DT){
00065       if (((*rechit).chamberId().wheel() == (*chIt_DT).wheel()) &&
00066           ((*rechit).chamberId().station() == (*chIt_DT).station()) &&
00067           ((*rechit).chamberId().sector() == (*chIt_DT).sector())){
00068         insert = false;
00069       }
00070     }
00071     if (insert){
00072       chambers_DT.push_back((*rechit).chamberId());
00073     }
00074     if(segmentCleaning((*rechit).geographicalId(), 
00075                        rechit->localPosition(), rechit->localPositionError(),
00076                        rechit->localDirection(), rechit->localDirectionError(),
00077                        rechit->chi2(), rechit->degreesOfFreedom())){
00078       continue;
00079     }
00080     if( (rechit->hasZed() && rechit->hasPhi()) ) {
00081     muonRecHits.push_back(MuonTransientTrackingRecHit::specificBuild(theService->trackingGeometry()->idToDet((*rechit).geographicalId()),&*rechit));
00082     }
00083     else if(rechit->hasZed()) {
00084     muonRecHits_DT2D_hasZed.push_back(MuonTransientTrackingRecHit::specificBuild(theService->trackingGeometry()->idToDet((*rechit).geographicalId()),&*rechit));
00085     }
00086     else if(rechit->hasPhi()) { // safeguard
00087     muonRecHits_DT2D_hasPhi.push_back(MuonTransientTrackingRecHit::specificBuild(theService->trackingGeometry()->idToDet((*rechit).geographicalId()),&*rechit));
00088     }
00089     else {
00090       //std::cout<<"Warning in "<<metname<<": DT segment which claims to have neither phi nor Z."<<std::endl;
00091     }
00092   }
00093   //std::cout<<"DT done"<<std::endl;
00094 
00095   // ********************************************;
00096   // Get the CSC-Segment collection from the event
00097   // ********************************************;
00098 
00099   edm::Handle<CSCSegmentCollection> cscSegments;
00100   event.getByLabel(CSCRecSegmentLabel, cscSegments);
00101   std::vector<CSCDetId> chambers_CSC;
00102   std::vector<CSCDetId>::const_iterator chIt_CSC;
00103   for(CSCSegmentCollection::const_iterator rechit=cscSegments->begin(); rechit != cscSegments->end(); ++rechit) {
00104     bool insert = true;
00105     for(chIt_CSC=chambers_CSC.begin(); chIt_CSC != chambers_CSC.end(); ++chIt_CSC){
00106       if (((*rechit).cscDetId().chamber() == (*chIt_CSC).chamber()) &&
00107           ((*rechit).cscDetId().station() == (*chIt_CSC).station()) &&
00108           ((*rechit).cscDetId().ring() == (*chIt_CSC).ring()) &&
00109           ((*rechit).cscDetId().endcap() == (*chIt_CSC).endcap())){
00110         insert = false;
00111       }
00112     }
00113     if (insert){
00114       chambers_CSC.push_back((*rechit).cscDetId().chamberId());
00115     }
00116     if(segmentCleaning((*rechit).geographicalId(), 
00117                        rechit->localPosition(), rechit->localPositionError(),
00118                        rechit->localDirection(), rechit->localDirectionError(),
00119                        rechit->chi2(), rechit->degreesOfFreedom())){
00120       continue;
00121     }
00122     muonRecHits.push_back(MuonTransientTrackingRecHit::specificBuild(theService->trackingGeometry()->idToDet((*rechit).geographicalId()),&*rechit));
00123   }
00124   //std::cout<<"CSC done"<<std::endl;
00125 
00126   // ********************************************;
00127   // Get the RPC-Hit collection from the event
00128   // ********************************************;
00129 
00130   edm::Handle<RPCRecHitCollection> rpcRecHits;
00131   event.getByLabel(RPCRecSegmentLabel, rpcRecHits);
00132   if(useRPCs){
00133     for(RPCRecHitCollection::const_iterator rechit=rpcRecHits->begin(); rechit != rpcRecHits->end(); ++rechit) {
00134       // RPCs are special
00135       const LocalVector  localDirection(0.,0.,1.);
00136       const LocalError localDirectionError (0.,0.,0.); 
00137       const double chi2 = 1.;
00138       const int ndf = 1;
00139       if(segmentCleaning((*rechit).geographicalId(), 
00140                          rechit->localPosition(), rechit->localPositionError(),
00141                          localDirection, localDirectionError,
00142                          chi2, ndf)){
00143         continue;
00144       }
00145       muonRecHits_RPC.push_back(MuonTransientTrackingRecHit::specificBuild(theService->trackingGeometry()->idToDet((*rechit).geographicalId()),&*rechit));
00146     }
00147   }
00148   //std::cout<<"RPC done"<<std::endl;
00149   //
00150   if(int(chambers_DT.size() + chambers_CSC.size()) > maxActiveChambers){
00151     // std::cout <<" Too many active chambers : nDT = "<<chambers_DT.size()<<
00152     // " nCSC = "<<chambers_CSC.size()<<"  Skip them all."<<std::endl;
00153     edm::LogWarning("tooManyActiveChambers")<<" Too many active chambers : nDT = "<<chambers_DT.size()
00154                      <<" nCSC = "<<chambers_CSC.size()<<"  Skip them all.";
00155     muonRecHits.clear();                                
00156     muonRecHits_DT2D_hasPhi.clear();    
00157     muonRecHits_DT2D_hasZed.clear();
00158     muonRecHits_RPC.clear();
00159   }
00160   //---- Find "pre-clusters" from all segments; these contain potential muon candidates
00161 
00162   //---- From all the hits (i.e. segments; sometimes "rechits" is also used with the same meaning;
00163   //---- this convention has meaning in the global reconstruction though could be misleading 
00164   //---- from a local reconstruction point of view; "local rechits" are used in the backward fit only) 
00165   //---- make clusters of hits; a trajectory could contain hits from one cluster only   
00166 
00167   // the clustering procedure is very similar to the one used in the segment reconstruction 
00168 
00169   bool useDT2D_hasPhi = true;
00170   bool useDT2D_hasZed = true;
00171   double dXclusBoxMax         = 0.60; // phi - can be as large as 15 - 20 degrees for 6 GeV muons
00172   double dYclusBoxMax = 0.;
00173 
00174   // this is the main selection criteria; the value of 0.02 rad seems wide enough to 
00175   // contain any hit from a passing muon and still narrow enough to remove good part of
00176   // possible "junk" hits
00177   // (Comment: it may be better to allow maximum difference between any two hits in a trajectory
00178   // to be 0.02 or 0.04 or ...; currently the requirement below is imposed on two consecutive hits)  
00179 
00180   dYclusBoxMax              = 0.02; // theta // hardoded - remove it!
00181   
00182   // X and Y are distance variables - we use eta and phi here
00183 
00184   float dXclus = 0.0;
00185   float dXclus_box = 0.0;
00186   float dYclus_box = 0.0;
00187 
00188   MuonRecHitContainer temp;
00189 
00190   std::vector< MuonRecHitContainer > seeds;
00191 
00192   std::vector<float> running_meanX;
00193   std::vector<float> running_meanY;
00194 
00195   std::vector<float> seed_minX;
00196   std::vector<float> seed_maxX;
00197   std::vector<float> seed_minY;
00198   std::vector<float> seed_maxY;
00199 
00200   // split rechits into subvectors and return vector of vectors:
00201   // Loop over rechits 
00202   // Create one seed per hit
00203   for (MuonRecHitContainer::const_iterator it = muonRecHits.begin(); it != muonRecHits.end(); ++it ) {
00204 
00205     // try to avoid using 2D DT segments. We will add them later to the 
00206     // clusters they are most likely to belong to. Might need to add them 
00207     // to more than just one cluster, if we find them to be consistent with 
00208     // more than one. This would lead to an implicit sharing of hits between 
00209     // SA muon candidates. 
00210 
00211     temp.clear();
00212 
00213     temp.push_back((*it));
00214 
00215     seeds.push_back(temp);
00216 
00217     // First added hit in seed defines the mean to which the next hit is compared
00218     // for this seed.
00219 
00220     running_meanX.push_back( (*it)->globalPosition().phi() );
00221     running_meanY.push_back( (*it)->globalPosition().theta() );
00222 
00223     // set min/max X and Y for box containing the hits in the precluster:
00224     seed_minX.push_back( (*it)->globalPosition().phi() );
00225     seed_maxX.push_back( (*it)->globalPosition().phi() );
00226     seed_minY.push_back( (*it)->globalPosition().theta() );
00227     seed_maxY.push_back( (*it)->globalPosition().theta() );
00228   }
00229 
00230   // merge clusters that are too close
00231   // measure distance between final "running mean"
00232   for(unsigned int NNN = 0; NNN < seeds.size(); ++NNN) {
00233 
00234     for(unsigned int MMM = NNN+1; MMM < seeds.size(); ++MMM) {
00235       if(running_meanX[MMM] == 999999. || running_meanX[NNN] == 999999. ) {
00236         //        LogDebug("CSC") << "CSCSegmentST::clusterHits: Warning: Skipping used seeds, this should happen - inform developers!\n";
00237         //std::cout<<"We should never see this line now!!!"<<std::endl;
00238         continue; //skip seeds that have been used 
00239       }
00240 
00241       // Some complications for using phi as a clustering variable due to wrap-around (-pi = pi)
00242       // Define temporary mean, min, and max variables for the cluster which could be merged (NNN)
00243       double temp_meanX = running_meanX[NNN];
00244       double temp_minX = seed_minX[NNN];
00245       double temp_maxX = seed_maxX[NNN];
00246 
00247       // check if the difference between the two phi values is greater than pi
00248       // if so, need to shift temporary values by 2*pi to make a valid comparison
00249       dXclus = running_meanX[NNN] - running_meanX[MMM];
00250       if (dXclus > TMath::Pi()) {
00251         temp_meanX = temp_meanX - 2.*TMath::Pi();
00252         temp_minX = temp_minX - 2.*TMath::Pi();
00253         temp_maxX = temp_maxX - 2.*TMath::Pi();
00254       }
00255       if (dXclus < -TMath::Pi()) {
00256         temp_meanX = temp_meanX + 2.*TMath::Pi();
00257         temp_minX = temp_minX + 2.*TMath::Pi();
00258         temp_maxX = temp_maxX + 2.*TMath::Pi();
00259       }
00260 
00261       //       // calculate cut criteria for simple running mean distance cut:
00262       //       // not sure that these values are really used anywhere
00263 
00264       // calculate minmal distance between precluster boxes containing the hits:
00265       // use the temp variables from above for phi of the NNN cluster 
00266       if ( temp_meanX > running_meanX[MMM] )         dXclus_box = temp_minX - seed_maxX[MMM];
00267       else                                           dXclus_box = seed_minX[MMM] - temp_maxX;
00268       if ( running_meanY[NNN] > running_meanY[MMM] ) dYclus_box = seed_minY[NNN] - seed_maxY[MMM];
00269       else                                           dYclus_box = seed_minY[MMM] - seed_maxY[NNN];
00270 
00271 
00272       if( dXclus_box < dXclusBoxMax && dYclus_box < dYclusBoxMax ) {
00273         // merge clusters!
00274         // merge by adding seed NNN to seed MMM and erasing seed NNN
00275 
00276         // calculate running mean for the merged seed:
00277         // use the temp variables from above for phi of the NNN cluster 
00278         running_meanX[MMM] = (temp_meanX*seeds[NNN].size() + running_meanX[MMM]*seeds[MMM].size()) / (seeds[NNN].size()+seeds[MMM].size());
00279         running_meanY[MMM] = (running_meanY[NNN]*seeds[NNN].size() + running_meanY[MMM]*seeds[MMM].size()) / (seeds[NNN].size()+seeds[MMM].size());
00280 
00281         // update min/max X and Y for box containing the hits in the merged cluster:
00282         // use the temp variables from above for phi of the NNN cluster 
00283         if ( temp_minX <= seed_minX[MMM] ) seed_minX[MMM] = temp_minX;
00284         if ( temp_maxX >  seed_maxX[MMM] ) seed_maxX[MMM] = temp_maxX;
00285         if ( seed_minY[NNN] <= seed_minY[MMM] ) seed_minY[MMM] = seed_minY[NNN];
00286         if ( seed_maxY[NNN] >  seed_maxY[MMM] ) seed_maxY[MMM] = seed_maxY[NNN];
00287 
00288         // now check to see if the running mean has moved outside of the allowed -pi to pi region
00289         // if so, then adjust shift all values up or down by 2 * pi
00290         if (running_meanX[MMM] > TMath::Pi()) {
00291           running_meanX[MMM] = running_meanX[MMM] - 2.*TMath::Pi();
00292           seed_minX[MMM] = seed_minX[MMM] - 2.*TMath::Pi();
00293           seed_maxX[MMM] = seed_maxX[MMM] - 2.*TMath::Pi();
00294         }
00295         if (running_meanX[MMM] < -TMath::Pi()) {
00296           running_meanX[MMM] = running_meanX[MMM] + 2.*TMath::Pi();
00297           seed_minX[MMM] = seed_minX[MMM] + 2.*TMath::Pi();
00298           seed_maxX[MMM] = seed_maxX[MMM] + 2.*TMath::Pi();
00299         }
00300 
00301         // add seed NNN to MMM (lower to larger number)
00302         seeds[MMM].insert(seeds[MMM].end(),seeds[NNN].begin(),seeds[NNN].end());
00303 
00304         // mark seed NNN as used (at the moment just set running mean to 999999.)
00305         running_meanX[NNN] = 999999.;
00306         running_meanY[NNN] = 999999.;
00307         // we have merged a seed (NNN) to the highter seed (MMM) - need to contimue to 
00308         // next seed (NNN+1)
00309         break;
00310       }
00311 
00312     }
00313   }
00314   bool tooCloseClusters = false;
00315   if(seeds.size()>1){
00316     std::vector <double> seedTheta(seeds.size());
00317     for(unsigned int iSeed = 0;iSeed<seeds.size();++iSeed){
00318       seedTheta[iSeed] = seeds[iSeed][0]->globalPosition().theta(); 
00319       if(iSeed){
00320         double dTheta = fabs(seedTheta[iSeed] - seedTheta[iSeed-1]);
00321         if (dTheta < 0.5){ //? should be something more clever
00322           tooCloseClusters = true;
00323           break;
00324         }
00325       }
00326     }
00327     
00328   }
00329 
00330   // have formed clusters from all hits except for 2D DT segments. Now add the 2D segments to the 
00331   // compatible clusters. For this we compare the mean cluster postition with the 
00332   // 2D segment position. We should use the valid coordinate only and use the bad coordinate 
00333   // as a cross check.
00334   for(unsigned int NNN = 0; NNN < seeds.size(); ++NNN) {
00335     if(running_meanX[NNN] == 999999.) continue; //skip seeds that have been marked as used up in merging
00336 
00337     // We have a valid cluster - loop over all 2D segments.
00338     if(useDT2D_hasZed) {
00339       for (MuonRecHitContainer::const_iterator it2 = muonRecHits_DT2D_hasZed.begin(); it2 != muonRecHits_DT2D_hasZed.end(); ++it2 ) {
00340         // check that global theta of 2-D segment lies within cluster box plus or minus allowed slop
00341         if (((*it2)->globalPosition().theta() < seed_maxY[NNN] + dYclusBoxMax) && ((*it2)->globalPosition().theta() > seed_minY[NNN] - dYclusBoxMax)) {
00342           // check that global phi of 2-D segment (assumed to be center of chamber since no phi hit info)
00343           // matches with cluster box plus or minus allowed slop given that the true phi value could be 
00344           // anywhere within a given chamber (+/- 5 degrees ~ 0.09 radians from center) 
00345           if(
00346              !( 
00347                (
00348                 ((*it2)->globalPosition().phi() + 0.09) < (seed_minX[NNN] - dXclusBoxMax) 
00349                 && 
00350                 ((*it2)->globalPosition().phi() - 0.09) < (seed_minX[NNN] - dXclusBoxMax)
00351                 )
00352                ||
00353                (
00354                 ((*it2)->globalPosition().phi() + 0.09) > (seed_maxX[NNN] + dXclusBoxMax) 
00355                 && 
00356                 ((*it2)->globalPosition().phi() - 0.09) > (seed_maxX[NNN] + dXclusBoxMax)
00357                 )
00358                )
00359              ) { // we have checked that the 2Dsegment is within tight theta boundaries and loose phi boundaries of the current cluster -> add it
00360             seeds[NNN].push_back((*it2));
00361             
00362           }
00363         }                 
00364       }
00365       
00366     }
00367     
00368     // put DT hasphi loop here
00369     if (useDT2D_hasPhi) {
00370       
00371       for (MuonRecHitContainer::const_iterator it2 = muonRecHits_DT2D_hasPhi.begin(); it2 != muonRecHits_DT2D_hasPhi.end(); ++it2 ) {
00372         if (((*it2)->globalPosition().phi() < seed_maxX[NNN] + dXclusBoxMax) && ((*it2)->globalPosition().phi() > seed_minX[NNN] - dXclusBoxMax)) {
00373           if(
00374              !( 
00375                (
00376                 ((*it2)->globalPosition().theta() + 0.3) < (seed_minY[NNN] - dYclusBoxMax) 
00377                 && 
00378                 ((*it2)->globalPosition().theta() - 0.3) < (seed_minY[NNN] - dYclusBoxMax)
00379                 )
00380                ||
00381                (
00382                 ((*it2)->globalPosition().theta() + 0.3) > (seed_maxY[NNN] + dYclusBoxMax) 
00383                 && 
00384                 ((*it2)->globalPosition().theta() - 0.3) > (seed_maxY[NNN] + dYclusBoxMax)
00385                 )
00386                )
00387              ) { // we have checked that the 2Dsegment is within tight phi boundaries and loose theta boundaries of the current cluster -> add it
00388             seeds[NNN].push_back((*it2)); // warning - neeed eta/theta switch here
00389             
00390           }
00391         }
00392       }
00393     } // DT2D_hastPhi loop
00394     
00395     // put RPC loop here
00396     int secondCh = 0;
00397     DetId detId_prev;
00398     if(seeds[NNN].size()>1){// actually we should check how many chambers with measurements are present
00399       for(unsigned int iRH = 0 ;iRH<seeds[NNN].size() ;++iRH){
00400         if( iRH && detId_prev != seeds[NNN][iRH]->hit()->geographicalId()){
00401           ++secondCh;
00402           break;
00403         }
00404         detId_prev = seeds[NNN][iRH]->hit()->geographicalId();
00405       }
00406     }
00407 
00408     if (useRPCs && !secondCh && !tooCloseClusters) {
00409       for (MuonRecHitContainer::const_iterator it2 = muonRecHits_RPC.begin(); it2 != muonRecHits_RPC.end(); ++it2 ) {
00410         if (((*it2)->globalPosition().phi() < seed_maxX[NNN] + dXclusBoxMax) && ((*it2)->globalPosition().phi() > seed_minX[NNN] - dXclusBoxMax)) {
00411           if(
00412              !( 
00413                (
00414                 ((*it2)->globalPosition().theta() + 0.3) < (seed_minY[NNN] - dYclusBoxMax) 
00415                 && 
00416                 ((*it2)->globalPosition().theta() - 0.3) < (seed_minY[NNN] - dYclusBoxMax)
00417                 )
00418                ||
00419                (
00420                 ((*it2)->globalPosition().theta() + 0.3) > (seed_maxY[NNN] + dYclusBoxMax) 
00421                 && 
00422                 ((*it2)->globalPosition().theta() - 0.3) > (seed_maxY[NNN] + dYclusBoxMax)
00423                 )
00424                )
00425              ) { // we have checked that the 2Dsegment is within tight phi boundaries and loose theta boundaries of the current cluster -> add it
00426             seeds[NNN].push_back((*it2)); // warning - neeed eta/theta switch here
00427             
00428           }
00429         }
00430       }
00431     } // RPC loop
00432   }
00433   
00434   // hand over the final seeds to the output
00435   // would be more elegant if we could do the above step with 
00436   // erasing the merged ones, rather than the 
00437   for(unsigned int NNN = 0; NNN < seeds.size(); ++NNN) {
00438     if(running_meanX[NNN] == 999999.) continue; //skip seeds that have been marked as used up in merging
00439     //std::cout<<"Next Cluster..."<<std::endl;
00440     segments_clusters.push_back(seeds[NNN]);
00441   }
00442 }
00443 
00444 
00445 bool SETPatternRecognition::segmentCleaning(const DetId & detId, 
00446                                             const LocalPoint& localPosition, const LocalError& localError,
00447                                             const LocalVector& localDirection, const LocalError& localDirectionError,
00448                                             const double& chi2, const int& ndf){
00449   // drop segments which are "bad"
00450   bool dropTheSegment = true;
00451   const GeomDet* geomDet = theService->trackingGeometry()->idToDet( detId );
00452   // only segments whithin the boundaries of the chamber
00453   bool insideCh = geomDet->surface().bounds().inside(localPosition, localError,outsideChamberErrorScale);
00454 
00455   // Don't use segments (nearly) parallel to the chamberi;
00456   // the direction vector is normalized (R=1)  
00457   bool parallelSegment = fabs(localDirection.z())>minLocalSegmentAngle? false: true;
00458 
00459   if(insideCh && !parallelSegment){
00460     dropTheSegment = false;
00461   }
00462   // use chi2 too? (DT, CSCs, RPCs; 2D, 4D;...)
00463 
00464 
00465   return dropTheSegment;
00466 }