CMS 3D CMS Logo

CSCSegAlgoDF.cc

Go to the documentation of this file.
00001 
00007 #include "CSCSegAlgoDF.h"
00008 
00009 #include "Geometry/CSCGeometry/interface/CSCLayer.h"
00010 // For clhep Matrix::solve
00011 #include "DataFormats/CLHEP/interface/AlgebraicObjects.h"
00012 
00013 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00014 
00015 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00017 
00018 #include "CommonTools/Statistics/interface/ChiSquaredProbability.h"
00019 
00020 #include "CSCSegAlgoPreClustering.h"
00021 #include "CSCSegAlgoShowering.h"
00022 
00023 #include <algorithm>
00024 #include <cmath>
00025 #include <iostream>
00026 #include <string>
00027 
00028 
00029 /* Constructor
00030  *
00031  */
00032 CSCSegAlgoDF::CSCSegAlgoDF(const edm::ParameterSet& ps) : CSCSegmentAlgorithm(ps), myName("CSCSegAlgoDF") {
00033         
00034   debug                  = ps.getUntrackedParameter<bool>("CSCSegmentDebug");
00035   minLayersApart         = ps.getParameter<int>("minLayersApart");
00036   minHitsPerSegment      = ps.getParameter<int>("minHitsPerSegment");
00037   dRPhiFineMax           = ps.getParameter<double>("dRPhiFineMax");
00038   dPhiFineMax            = ps.getParameter<double>("dPhiFineMax");
00039   tanThetaMax            = ps.getParameter<double>("tanThetaMax");
00040   tanPhiMax              = ps.getParameter<double>("tanPhiMax");        
00041   chi2Max                = ps.getParameter<double>("chi2Max");  
00042   preClustering          = ps.getUntrackedParameter<bool>("preClustering");
00043   minHitsForPreClustering= ps.getParameter<int>("minHitsForPreClustering");
00044   nHitsPerClusterIsShower= ps.getParameter<int>("nHitsPerClusterIsShower");
00045   Pruning                = ps.getUntrackedParameter<bool>("Pruning");
00046   maxRatioResidual       = ps.getParameter<double>("maxRatioResidualPrune");
00047 
00048   preCluster_            = new CSCSegAlgoPreClustering( ps );
00049   showering_             = new CSCSegAlgoShowering( ps );
00050 }
00051 
00052 
00053 /* Destructor
00054  *
00055  */
00056 CSCSegAlgoDF::~CSCSegAlgoDF() {
00057   delete preCluster_;
00058   delete showering_;
00059 }
00060 
00061 
00062 /* run
00063  *
00064  */
00065 std::vector<CSCSegment> CSCSegAlgoDF::run(const CSCChamber* aChamber, ChamberHitContainer rechits) {
00066 
00067   // Store chamber info in temp memory
00068   theChamber = aChamber; 
00069 
00070   int nHits = rechits.size();
00071 
00072   // Segments prior to pruning
00073   std::vector<CSCSegment> segments_temp;  
00074 
00075   if ( preClustering && nHits > minHitsForPreClustering ) {
00076     // This is where the segment origin is in the chamber on avg.
00077     std::vector<CSCSegment> testSegments;
00078     std::vector<ChamberHitContainer> clusteredHits = preCluster_->clusterHits(theChamber, rechits);
00079     // loop over the found clusters:
00080     for (std::vector<ChamberHitContainer>::iterator subrechits = clusteredHits.begin(); subrechits != clusteredHits.end(); ++subrechits ) {
00081       // build the subset of segments:
00082       std::vector<CSCSegment> segs = buildSegments( (*subrechits) );
00083       // add the found subset of segments to the collection of all segments in this chamber:
00084       segments_temp.insert( segments_temp.end(), segs.begin(), segs.end() );
00085     }
00086   } else {
00087     std::vector<CSCSegment> segs = buildSegments( rechits );
00088     // add the found subset of segments to the collection of all segments in this chamber:
00089     segments_temp.insert( segments_temp.end(), segs.begin(), segs.end() ); 
00090   }
00091 
00092   return segments_temp; 
00093 }
00094 
00095 
00096 /* This builds segments by first creating proto-segments from at least 3 hits.
00097  * We intend to try all possible pairs of hits to start segment building. 'All possible' 
00098  * means each hit lies on different layers in the chamber.  Once a hit has been assigned 
00099  * to a segment, we don't consider it again, THAT IS, FOR THE FIRST PASS ONLY !
00100  * In fact, this is one of the possible flaw with the SK algorithms as it sometimes manages
00101  * to build segments with the wrong starting points.  In the DF algorithm, the endpoints
00102  * are tested as the best starting points in a 2nd loop.
00103  *
00104  * Also, only a certain muonsPerChamberMax maximum number of segments can be produced in the chamber
00105  */
00106 std::vector<CSCSegment> CSCSegAlgoDF::buildSegments(ChamberHitContainer rechits) {
00107 
00108   // Clear buffer for segment vector
00109   std::vector<CSCSegment> segmentInChamber;
00110   segmentInChamber.clear();
00111 
00112   unsigned nHitInChamber = rechits.size();
00113   if ( nHitInChamber < 3 ) return segmentInChamber;
00114 
00115   LayerIndex layerIndex( nHitInChamber );
00116 
00117   unsigned nLayers = 0;
00118   int old_layer = -1;   
00119   for ( unsigned int i = 0; i < nHitInChamber; i++ ) {    
00120     int this_layer = rechits[i]->cscDetId().layer();
00121     layerIndex[i] = this_layer;
00122     if ( this_layer != old_layer ) {
00123       old_layer = this_layer;
00124       nLayers++;   
00125     }
00126   }
00127   
00128   if ( nLayers < 3 ) return segmentInChamber;
00129 
00130   double z1 = theChamber->layer(1)->position().z();
00131   double z6 = theChamber->layer(6)->position().z();
00132   
00133   if ( z1 > 0. ) {
00134     if ( z1 > z6 ) { 
00135       reverse( layerIndex.begin(), layerIndex.end() );
00136       reverse( rechits.begin(),    rechits.end() );
00137     }    
00138   }
00139   else if ( z1 < 0. ) {
00140     if ( z1 < z6 ) {
00141       reverse( layerIndex.begin(), layerIndex.end() );
00142       reverse( rechits.begin(),    rechits.end() );
00143     }    
00144   }
00145 
00146   // Showering muon
00147   if ( preClustering && int(nHitInChamber) > nHitsPerClusterIsShower && nLayers > 2 ) {
00148     CSCSegment segShower = showering_->showerSeg(theChamber, rechits);
00149 
00150     // Make sure have at least 3 hits...
00151     if ( segShower.nRecHits() < 3 ) return segmentInChamber;
00152 
00153     segmentInChamber.push_back(segShower);
00154 
00155     return segmentInChamber;
00156   }
00157 
00158 
00159   // Initialize flags that a given hit has been allocated to a segment
00160   BoolContainer used_ini(rechits.size(), false);
00161   usedHits = used_ini;
00162   
00163   ChamberHitContainerCIt ib = rechits.begin();
00164   ChamberHitContainerCIt ie = rechits.end();
00165     
00166   // Now Loop over hits within the chamber to find 1st seed for segment building
00167   for ( ChamberHitContainerCIt i1 = ib; i1 < ie; ++i1 ) {
00168     if ( usedHits[i1-ib] ) continue;
00169 
00170     const CSCRecHit2D* h1 = *i1;
00171     int layer1 = layerIndex[i1-ib];
00172     const CSCLayer* l1 = theChamber->layer(layer1);
00173     GlobalPoint gp1 = l1->toGlobal(h1->localPosition());
00174     LocalPoint lp1 = theChamber->toLocal(gp1);  
00175            
00176     // Loop over hits backward to find 2nd seed for segment building
00177     for ( ChamberHitContainerCIt i2 = ie-1; i2 > ib; --i2 ) {   
00178 
00179       if ( usedHits[i2-ib] ) continue;   // Hit has been used already
00180 
00181       int layer2 = layerIndex[i2-ib];
00182       if ( (layer2 - layer1) < minLayersApart ) continue;
00183 
00184       const CSCRecHit2D* h2 = *i2;
00185       const CSCLayer* l2 = theChamber->layer(layer2);
00186       GlobalPoint gp2 = l2->toGlobal(h2->localPosition());
00187       LocalPoint lp2 = theChamber->toLocal(gp2);  
00188 
00189       // Clear proto segment so it can be (re)-filled 
00190       protoSegment.clear();
00191 
00192       // localPosition is position of hit wrt layer (so local z = 0)
00193       protoIntercept = h1->localPosition();
00194 
00195       // We want hit wrt chamber (and local z will be != 0)
00196       float dz = gp2.z()-gp1.z();
00197       protoSlope_u = (lp2.x() - lp1.x())/dz ;
00198       protoSlope_v = (lp2.y() - lp1.y())/dz ;    
00199 
00200       // Test if entrance angle is roughly pointing towards IP
00201       if (fabs(protoSlope_v) > tanThetaMax) continue;
00202       if (fabs(protoSlope_u) > tanPhiMax ) continue;
00203      
00204       protoSegment.push_back(h1);
00205       protoSegment.push_back(h2);
00206         
00207       // Try adding hits to proto segment
00208       tryAddingHitsToSegment(rechits, i1, i2, layerIndex); 
00209         
00210       // Check no. of hits on segment to see if segment is large enough
00211       bool segok = true;
00212       unsigned iadd = 0;
00213 
00214       if (protoSegment.size() < minHitsPerSegment+iadd) segok = false;
00215   
00216       if ( Pruning && segok ) pruneFromResidual();
00217 
00218       // Check if segment satisfies chi2 requirement
00219       if (protoChi2 > chi2Max) segok = false;
00220 
00221       if ( segok ) {
00222 
00223         // Fill segment properties
00224        
00225         // Local direction
00226         double dz   = 1./sqrt(1. + protoSlope_u*protoSlope_u + protoSlope_v*protoSlope_v);
00227         double dx   = dz * protoSlope_u;
00228         double dy   = dz * protoSlope_v;
00229         LocalVector localDir(dx,dy,dz);
00230       
00231         // localDir may need sign flip to ensure it points outward from IP  
00232         double globalZpos    = ( theChamber->toGlobal( protoIntercept ) ).z();
00233         double globalZdir    = ( theChamber->toGlobal( localDir ) ).z();
00234         double directionSign = globalZpos * globalZdir;
00235         protoDirection       = (directionSign * localDir).unit();
00236 
00237         // Error matrix
00238         AlgebraicSymMatrix protoErrors = calculateError();     
00239         CSCSegment temp(protoSegment, protoIntercept, protoDirection, protoErrors, protoChi2); 
00240 
00241         segmentInChamber.push_back(temp); 
00242 
00243         if (nHitInChamber-protoSegment.size() < 3) return segmentInChamber; 
00244         if (segmentInChamber.size() > 4) return segmentInChamber;
00245 
00246         // Flag used hits
00247         flagHitsAsUsed(rechits);
00248       } 
00249     } 
00250   }
00251   return segmentInChamber;
00252 }
00253 
00254 
00255 /* Method tryAddingHitsToSegment
00256  *
00257  * Look at left over hits and try to add them to proto segment by looking how far they
00258  * are from the segment in terms of the hit error matrix (so how many sigmas away).
00259  *
00260  */
00261 void CSCSegAlgoDF::tryAddingHitsToSegment( const ChamberHitContainer& rechits, 
00262                                            const ChamberHitContainerCIt i1, 
00263                                            const ChamberHitContainerCIt i2,
00264                                            LayerIndex layerIndex ) {
00265   
00266 /* Iterate over the layers with hits in the chamber
00267  * Skip the layers containing the segment endpoints on first pass, but then
00268  * try hits on layer containing the segment starting points on 2nd pass
00269  * if segment has >2 hits.  Once a hit is added to a layer, don't replace it 
00270  * until 2nd iteration
00271  */  
00272   
00273   ChamberHitContainerCIt ib = rechits.begin();
00274   ChamberHitContainerCIt ie = rechits.end();
00275   closeHits.clear();
00276 
00277   for ( ChamberHitContainerCIt i = ib; i != ie; ++i ) {
00278 
00279     if (i == i1 || i == i2 ) continue;
00280     if ( usedHits[i-ib] ) continue;   // Don't use hits already part of a segment.
00281 
00282     const CSCRecHit2D* h = *i;
00283     int layer = layerIndex[i-ib];
00284     int layer1 = layerIndex[i1-ib];
00285     int layer2 = layerIndex[i2-ib];
00286 
00287     // Low multiplicity case
00288     if (rechits.size() < 9) {
00289       if ( isHitNearSegment( h ) ) {
00290         if ( !hasHitOnLayer(layer) ) {
00291           addHit(h, layer);
00292         } else {
00293           closeHits.push_back(h);
00294         }
00295       }
00296 
00297     // High multiplicity case
00298     } else { 
00299       if ( isHitNearSegment( h ) ) {
00300         if ( !hasHitOnLayer(layer) ) {
00301           addHit(h, layer);
00302           updateParameters();
00303         // Don't change the starting points at this stage !!!
00304         } else {
00305           closeHits.push_back(h);
00306           if (layer != layer1 && layer != layer2 ) compareProtoSegment(h, layer);
00307         }
00308       }
00309     }
00310   }
00311  
00312   if ( int(protoSegment.size()) < 3) return;
00313 
00314   updateParameters();
00315 
00316   // 2nd pass to remove biases 
00317   // This time, also consider changing the endpoints
00318   for ( ChamberHitContainerCIt i = closeHits.begin() ; i != closeHits.end(); ++i ) {      
00319     const CSCRecHit2D* h = *i;      
00320     int layer = (*i)->cscDetId().layer();     
00321     compareProtoSegment(h, layer); 
00322   } 
00323 
00324 }
00325 
00326 
00327 /* isHitNearSegment
00328  *
00329  * Compare rechit with expected position from proto_segment
00330  */
00331 bool CSCSegAlgoDF::isHitNearSegment( const CSCRecHit2D* hit) const {
00332 
00333   const CSCLayer* layer = theChamber->layer(hit->cscDetId().layer());
00334 
00335   // hit phi position in global coordinates
00336   GlobalPoint Hgp = layer->toGlobal(hit->localPosition());
00337   double Hphi = Hgp.phi();                                
00338   if (Hphi < 0.) Hphi += 2.*M_PI;
00339   LocalPoint Hlp = theChamber->toLocal(Hgp);
00340   double z = Hlp.z();  
00341 
00342   double LocalX = protoIntercept.x() + protoSlope_u * z;
00343   double LocalY = protoIntercept.y() + protoSlope_v * z;
00344   LocalPoint Slp(LocalX, LocalY, z);
00345   GlobalPoint Sgp = theChamber->toGlobal(Slp); 
00346   double Sphi = Sgp.phi();
00347   if (Sphi < 0.) Sphi += 2.*M_PI;
00348   double R = sqrt(Sgp.x()*Sgp.x() + Sgp.y()*Sgp.y());
00349   
00350   double deltaPhi = Sphi - Hphi;
00351   if (deltaPhi >  2.*M_PI) deltaPhi -= 2.*M_PI;
00352   if (deltaPhi < -2.*M_PI) deltaPhi += 2.*M_PI;
00353   if (deltaPhi < 0.) deltaPhi = -deltaPhi; 
00354 
00355   double RdeltaPhi = R * deltaPhi;
00356 
00357   if (RdeltaPhi < dRPhiFineMax && deltaPhi < dPhiFineMax ) return true;
00358 
00359   return false;
00360 }
00361 
00362 
00363 /* Method addHit
00364  *
00365  * Test if can add hit to proto segment. If so, try to add it.
00366  *
00367  */
00368 bool CSCSegAlgoDF::addHit(const CSCRecHit2D* aHit, int layer) {
00369   
00370   // Return true if hit was added successfully and then parameters are updated.
00371   // Return false if there is already a hit on the same layer, or insert failed.
00372   
00373   bool ok = true;
00374   
00375   // Test that we are not trying to add the same hit again
00376   for ( ChamberHitContainer::const_iterator it = protoSegment.begin(); it != protoSegment.end(); it++ ) 
00377     if ( aHit == (*it)  ) return false;
00378   
00379   protoSegment.push_back(aHit);
00380 
00381   return ok;
00382 }    
00383 
00384 
00385 /* Method updateParameters
00386  *      
00387  * Perform a simple Least Square Fit on proto segment to determine slope and intercept
00388  *
00389  */   
00390 void CSCSegAlgoDF::updateParameters() {
00391 
00392   // Compute slope from Least Square Fit    
00393   HepMatrix M(4,4,0);
00394   HepVector B(4,0);
00395 
00396   ChamberHitContainer::const_iterator ih;
00397   
00398   for (ih = protoSegment.begin(); ih != protoSegment.end(); ++ih) {
00399     
00400     const CSCRecHit2D& hit = (**ih);
00401     const CSCLayer* layer  = theChamber->layer(hit.cscDetId().layer());
00402     GlobalPoint gp         = layer->toGlobal(hit.localPosition());
00403     LocalPoint  lp         = theChamber->toLocal(gp); 
00404     
00405     double u = lp.x();
00406     double v = lp.y();
00407     double z = lp.z();
00408     
00409     // ptc: Covariance matrix of local errors 
00410     HepMatrix IC(2,2);
00411     IC(1,1) = hit.localPositionError().xx();
00412     IC(1,2) = hit.localPositionError().xy();
00413     IC(2,2) = hit.localPositionError().yy();
00414     IC(2,1) = IC(1,2); // since Cov is symmetric
00415     
00416     // ptc: Invert covariance matrix (and trap if it fails!)
00417     int ierr = 0;
00418     IC.invert(ierr); // inverts in place
00419     if (ierr != 0) {
00420       LogDebug("CSC") << "CSCSegment::fitSlopes: failed to invert covariance matrix=\n" << IC << "\n";      
00421     }
00422     
00423     M(1,1) += IC(1,1);
00424     M(1,2) += IC(1,2);
00425     M(1,3) += IC(1,1) * z;
00426     M(1,4) += IC(1,2) * z;
00427     B(1)   += u * IC(1,1) + v * IC(1,2);
00428     
00429     M(2,1) += IC(2,1);
00430     M(2,2) += IC(2,2);
00431     M(2,3) += IC(2,1) * z;
00432     M(2,4) += IC(2,2) * z;
00433     B(2)   += u * IC(2,1) + v * IC(2,2);
00434     
00435     M(3,1) += IC(1,1) * z;
00436     M(3,2) += IC(1,2) * z;
00437     M(3,3) += IC(1,1) * z * z;
00438     M(3,4) += IC(1,2) * z * z;
00439     B(3)   += ( u * IC(1,1) + v * IC(1,2) ) * z;
00440     
00441     M(4,1) += IC(2,1) * z;
00442     M(4,2) += IC(2,2) * z;
00443     M(4,3) += IC(2,1) * z * z;
00444     M(4,4) += IC(2,2) * z * z;
00445     B(4)   += ( u * IC(2,1) + v * IC(2,2) ) * z;
00446   }
00447   
00448   HepVector p = solve(M, B);
00449   
00450   // Update member variables 
00451   // Note that origin has local z = 0
00452 
00453   protoIntercept = LocalPoint(p(1), p(2), 0.);
00454   protoSlope_u = p(3);
00455   protoSlope_v = p(4);
00456 
00457 
00458   // Determine Chi^2 for the proto wire segment
00459   
00460   double chsq = 0.;
00461   
00462   for (ih = protoSegment.begin(); ih != protoSegment.end(); ++ih) {
00463     
00464     const CSCRecHit2D& hit = (**ih);
00465     const CSCLayer* layer  = theChamber->layer(hit.cscDetId().layer());
00466     GlobalPoint gp         = layer->toGlobal(hit.localPosition());
00467     LocalPoint lp          = theChamber->toLocal(gp);
00468     
00469     double u = lp.x();
00470     double v = lp.y();
00471     double z = lp.z();
00472     
00473     double du = protoIntercept.x() + protoSlope_u * z - u;
00474     double dv = protoIntercept.y() + protoSlope_v * z - v;
00475     
00476     HepMatrix IC(2,2);
00477     IC(1,1) = hit.localPositionError().xx();
00478     IC(1,2) = hit.localPositionError().xy();
00479     IC(2,2) = hit.localPositionError().yy();
00480     IC(2,1) = IC(1,2);
00481     
00482     // Invert covariance matrix
00483     int ierr = 0;
00484     IC.invert(ierr);
00485     if (ierr != 0) {
00486       LogDebug("CSC") << "CSCSegment::fillChiSquared: failed to invert covariance matrix=\n" << IC << "\n";      
00487     }
00488     chsq += du*du*IC(1,1) + 2.*du*dv*IC(1,2) + dv*dv*IC(2,2);
00489   }
00490   protoChi2 = chsq;
00491 }
00492 
00493 
00494 /* hasHitOnLayer
00495  *
00496  * Just make sure hit to be added to layer comes from different layer than those in proto segment   
00497  */
00498 bool CSCSegAlgoDF::hasHitOnLayer(int layer) const {
00499   
00500   // Is there already a hit on this layer?
00501   for ( ChamberHitContainerCIt it = protoSegment.begin(); it != protoSegment.end(); it++ )
00502     if ( (*it)->cscDetId().layer() == layer ) return true;
00503   
00504   return false;
00505 }
00506 
00507 
00508 /* Method compareProtoSegment
00509  *      
00510  * For hit coming from the same layer of an existing hit within the proto segment
00511  * test if achieve better chi^2 by using this hit than the other
00512  *
00513  */ 
00514 void CSCSegAlgoDF::compareProtoSegment(const CSCRecHit2D* h, int layer) {
00515   
00516   // Store old segment first
00517   double old_protoChi2                  = protoChi2;
00518   LocalPoint old_protoIntercept         = protoIntercept;
00519   float old_protoSlope_u                = protoSlope_u;
00520   float old_protoSlope_v                = protoSlope_v;
00521   LocalVector old_protoDirection        = protoDirection;
00522   ChamberHitContainer old_protoSegment  = protoSegment;
00523  
00524 
00525   // Try adding the hit to existing segment, and remove old one existing in same layer
00526   ChamberHitContainer::iterator it;
00527   for ( it = protoSegment.begin(); it != protoSegment.end(); ) {
00528     if ( (*it)->cscDetId().layer() == layer ) {
00529       it = protoSegment.erase(it);
00530     } else {
00531       ++it;
00532     }
00533   }
00534   bool ok = addHit(h, layer);
00535 
00536   if (ok) updateParameters();
00537   
00538   if ( (protoChi2 > old_protoChi2) || ( !ok ) ) {
00539     protoChi2       = old_protoChi2;
00540     protoIntercept  = old_protoIntercept;
00541     protoSlope_u    = old_protoSlope_u;
00542     protoSlope_v    = old_protoSlope_v;
00543     protoDirection  = old_protoDirection;
00544     protoSegment    = old_protoSegment;
00545   }
00546 }
00547 
00548 
00549 /* Method flagHitsAsUsed
00550  *
00551  * Flag hits which have entered segment building so we don't reuse them.
00552  * Also flag does which were very close to segment to reduce combinatorics
00553  */
00554 void CSCSegAlgoDF::flagHitsAsUsed(const ChamberHitContainer& rechitsInChamber) {
00555   
00556   // Flag hits on segment as used
00557   ChamberHitContainerCIt ib = rechitsInChamber.begin();
00558   ChamberHitContainerCIt hi, iu;
00559   
00560   for ( hi = protoSegment.begin(); hi != protoSegment.end(); ++hi ) {
00561     for ( iu = ib; iu != rechitsInChamber.end(); ++iu ) {
00562       if (*hi == *iu) usedHits[iu-ib] = true;
00563     }
00564   }
00565   // Don't reject hits marked as "nearby" for now.
00566   // So this is bypassed at all times for now !!!
00567   // Perhaps add back to speed up algorithm some more
00568   if (closeHits.size() > 0) return;  
00569   for ( hi = closeHits.begin(); hi != closeHits.end(); ++hi ) {
00570     for ( iu = ib; iu != rechitsInChamber.end(); ++iu ) {
00571       if (*hi == *iu) usedHits[iu-ib] = true;
00572     }
00573   }
00574 
00575 }
00576 
00577 
00578 /* calculateError
00579  *
00580  */
00581 AlgebraicSymMatrix CSCSegAlgoDF::calculateError() const {
00582 
00583   // Blightly assume the following never fails
00584  
00585   std::vector<const CSCRecHit2D*>::const_iterator it;
00586   int nhits = protoSegment.size();
00587   int ierr; 
00588 
00589   AlgebraicSymMatrix weights(2*nhits, 0);
00590   AlgebraicMatrix A(2*nhits, 4);
00591 
00592   int row = 0;  
00593   for (it = protoSegment.begin(); it != protoSegment.end(); ++it) {
00594     const CSCRecHit2D& hit = (**it);
00595     const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
00596     GlobalPoint gp = layer->toGlobal(hit.localPosition());      
00597     LocalPoint lp = theChamber->toLocal(gp); 
00598     float z = lp.z();
00599     ++row;
00600     weights(row, row)   = hit.localPositionError().xx();
00601     weights(row, row+1) = hit.localPositionError().xy();
00602     A(row, 1) = 1.;
00603     A(row, 3) = z;
00604     ++row;
00605     weights(row, row-1) = hit.localPositionError().xy();
00606     weights(row, row)   = hit.localPositionError().yy();
00607     A(row, 2) = 1.;
00608     A(row, 4) = z;
00609   }
00610   weights.invert(ierr);
00611 
00612   AlgebraicSymMatrix a = weights.similarityT(A);
00613   a.invert(ierr);
00614     
00615   // but reorder components to match what's required by TrackingRecHit interface 
00616   // i.e. slopes first, then positions 
00617     
00618   AlgebraicSymMatrix hold( a ); 
00619     
00620   // errors on slopes into upper left 
00621   a(1,1) = hold(3,3); 
00622   a(1,2) = hold(3,4); 
00623   a(2,1) = hold(4,3); 
00624   a(2,2) = hold(4,4); 
00625     
00626   // errors on positions into lower right 
00627   a(3,3) = hold(1,1); 
00628   a(3,4) = hold(1,2); 
00629   a(4,3) = hold(2,1); 
00630   a(4,4) = hold(2,2); 
00631     
00632   // off-diagonal elements remain unchanged 
00633   return a;    
00634 } 
00635 
00636 
00637 
00638 // Try to clean up segments by quickly looking at residuals
00639 void CSCSegAlgoDF::pruneFromResidual(){
00640 
00641   // Only prune if have at least 5 hits 
00642   if ( protoSegment.size() < 5 ) return ;
00643 
00644 
00645   // Now Study residuals
00646       
00647   float maxResidual = 0.;
00648   float sumResidual = 0.;
00649   int nHits = 0;
00650   int badIndex = -1;
00651   int j = 0;
00652 
00653 
00654   ChamberHitContainer::const_iterator ih;
00655 
00656   for ( ih = protoSegment.begin(); ih != protoSegment.end(); ++ih ) {
00657     const CSCRecHit2D& hit = (**ih);
00658     const CSCLayer* layer  = theChamber->layer(hit.cscDetId().layer());
00659     GlobalPoint gp         = layer->toGlobal(hit.localPosition());
00660     LocalPoint lp          = theChamber->toLocal(gp);
00661 
00662     double u = lp.x();
00663     double v = lp.y();
00664     double z = lp.z();
00665 
00666     double du = protoIntercept.x() + protoSlope_u * z - u;
00667     double dv = protoIntercept.y() + protoSlope_v * z - v;
00668 
00669     float residual = sqrt(du*du + dv*dv);
00670 
00671     sumResidual += residual;
00672     nHits++;
00673     if ( residual > maxResidual ) {
00674       maxResidual = residual;
00675       badIndex = j;
00676     }
00677     j++;
00678   }
00679 
00680   float corrAvgResidual = (sumResidual - maxResidual)/(nHits -1);
00681 
00682   // Keep all hits 
00683   if ( maxResidual/corrAvgResidual < maxRatioResidual ) return;
00684 
00685 
00686   // Drop worse hit and recompute segment properties + fill
00687 
00688   ChamberHitContainer newProtoSegment;
00689 
00690   j = 0;
00691   for ( ih = protoSegment.begin(); ih != protoSegment.end(); ++ih ) {
00692     if ( j != badIndex ) newProtoSegment.push_back(*ih);
00693     j++;
00694   }
00695   
00696   protoSegment.clear();
00697 
00698   for ( ih = newProtoSegment.begin(); ih != newProtoSegment.end(); ++ih ) {
00699     protoSegment.push_back(*ih);
00700   }
00701 
00702   // Update segment parameters
00703   updateParameters();
00704 
00705 }
00706 
00707 
00708 /*
00709  * Order the hits such that 2nd one is closest in x,y to first seed hit in global coordinates
00710  */
00711 void CSCSegAlgoDF::orderSecondSeed( GlobalPoint gp1,
00712                                            const ChamberHitContainerCIt i1, 
00713                                            const ChamberHitContainerCIt i2, 
00714                                            const ChamberHitContainer& rechits, 
00715                                            LayerIndex layerIndex ) {
00716 
00717   secondSeedHits.clear();
00718 
00719   ChamberHitContainerCIt ib = rechits.begin();
00720   ChamberHitContainerCIt ie = rechits.end();
00721 
00722   int layer1 = layerIndex[i1-ib];
00723   int layer2 = layerIndex[i2-ib];
00724 
00725 
00726   // Now fill vector of rechits closest to center of mass:
00727   // secondSeedHitsIdx.clear() = 0;
00728 
00729   // Loop over all hits and find hit closest to 1st seed.
00730   for ( ChamberHitContainerCIt i2 = ie-1; i2 > i1; --i2 ) {     
00731 
00732 
00733   }
00734 
00735         
00736 }

Generated on Tue Jun 9 17:43:50 2009 for CMSSW by  doxygen 1.5.4