CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_0/src/RecoLocalMuon/CSCSegment/src/CSCSegAlgoHitPruning.cc

Go to the documentation of this file.
00001 
00012 #include "RecoLocalMuon/CSCSegment/src/CSCSegAlgoHitPruning.h"
00013 
00014 #include "Geometry/CSCGeometry/interface/CSCLayer.h"
00015 #include <DataFormats/CSCRecHit/interface/CSCRecHit2D.h>
00016 #include <DataFormats/CSCRecHit/interface/CSCSegment.h>
00017 #include <Geometry/CSCGeometry/interface/CSCChamber.h>
00018 #include "CommonTools/Statistics/interface/ChiSquaredProbability.h"
00019 
00020 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00021 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00022 
00023 #include <algorithm>
00024 #include <cmath>
00025 #include <iostream>
00026 #include <string>
00027 
00028 
00029 /* Constructor
00030  *
00031  */
00032 CSCSegAlgoHitPruning::CSCSegAlgoHitPruning(const edm::ParameterSet& ps) {
00033   BrutePruning           = ps.getParameter<bool>("BrutePruning");
00034 
00035 }
00036 
00037 
00038 /* Destructor:
00039  *
00040  */
00041 CSCSegAlgoHitPruning::~CSCSegAlgoHitPruning(){
00042 
00043 }
00044 
00045 
00046 /* pruneBadHits
00047  *
00048  */
00049 std::vector<CSCSegment> CSCSegAlgoHitPruning::pruneBadHits(const CSCChamber* aChamber, std::vector<CSCSegment> segments) {
00050 
00051   theChamber = aChamber;
00052 
00053   std::vector<CSCSegment>          segments_temp;
00054   std::vector<ChamberHitContainer> rechits_clusters; 
00055   
00056   const float chi2ndfProbMin = 1.0e-4;
00057   bool use_brute_force = BrutePruning;
00058 
00059   int hit_nr = 0;
00060   int hit_nr_worst = -1;
00061   //int hit_nr_2ndworst = -1;
00062   
00063   for (std::vector<CSCSegment>::iterator it=segments.begin(); it != segments.end(); it++) {
00064     
00065     if ( !use_brute_force ) {// find worst hit
00066       
00067       float chisq    = (*it).chi2();
00068       int nhits      = (*it).nRecHits();
00069       LocalPoint localPos = (*it).localPosition();
00070       LocalVector segDir = (*it).localDirection();
00071       const CSCChamber* cscchamber = theChamber;
00072       float globZ       ;
00073           
00074       GlobalPoint globalPosition = cscchamber->toGlobal(localPos);
00075       globZ = globalPosition.z();
00076       
00077       
00078       if ( ChiSquaredProbability((double)chisq,(double)(2*nhits-4)) < chi2ndfProbMin  ) {
00079 
00080         // find (rough) "residuals" (NOT excluding the hit from the fit - speed!) of hits on segment
00081         std::vector<CSCRecHit2D> theseRecHits = (*it).specificRecHits();
00082         std::vector<CSCRecHit2D>::const_iterator iRH_worst;
00083         //float xdist_local       = -99999.;
00084 
00085         float xdist_local_worst_sig = -99999.;
00086         float xdist_local_2ndworst_sig = -99999.;
00087         float xdist_local_sig       = -99999.;
00088 
00089         hit_nr = 0;
00090         hit_nr_worst = -1;
00091         //hit_nr_2ndworst = -1;
00092 
00093         for ( std::vector<CSCRecHit2D>::const_iterator iRH = theseRecHits.begin(); iRH != theseRecHits.end(); iRH++ ) {
00094           //mark "worst" hit:
00095           
00096           //float z_at_target ;
00097           //float radius      ;
00098           float loc_x_at_target ;
00099           //float loc_y_at_target ;
00100           //float loc_z_at_target ;
00101 
00102           //z_at_target  = 0.;
00103           loc_x_at_target  = 0.;
00104           //loc_y_at_target  = 0.;
00105           //loc_z_at_target  = 0.;
00106           //radius       = 0.;
00107           
00108           // set the z target in CMS global coordinates:
00109           const CSCLayer* csclayerRH = theChamber->layer((*iRH).cscDetId().layer());
00110           LocalPoint localPositionRH = (*iRH).localPosition();
00111           GlobalPoint globalPositionRH = csclayerRH->toGlobal(localPositionRH); 
00112           
00113           LocalError rerrlocal = (*iRH).localPositionError();  
00114           float xxerr = rerrlocal.xx();
00115           
00116           float target_z     = globalPositionRH.z();  // target z position in cm (z pos of the hit)
00117           
00118           loc_x_at_target = localPos.x() + (segDir.x()*( target_z - globZ ));
00119           //loc_y_at_target = localPos.y() + (segDir.y()*( target_z - globZ ));
00120           //loc_z_at_target = target_z;
00121 
00122           // have to transform the segments coordinates back to the local frame... how?!!!!!!!!!!!!
00123           
00124           //xdist_local  = fabs(localPositionRH.x() - loc_x_at_target);
00125           xdist_local_sig  = fabs((localPositionRH.x() -loc_x_at_target)/(xxerr));
00126           
00127           if( xdist_local_sig > xdist_local_worst_sig ) {
00128             xdist_local_2ndworst_sig = xdist_local_worst_sig;
00129             xdist_local_worst_sig    = xdist_local_sig;
00130             iRH_worst            = iRH;
00131             //hit_nr_2ndworst = hit_nr_worst;
00132             hit_nr_worst = hit_nr;
00133           }
00134           else if(xdist_local_sig > xdist_local_2ndworst_sig) {
00135             xdist_local_2ndworst_sig = xdist_local_sig;
00136             //hit_nr_2ndworst = hit_nr;
00137           }
00138           ++hit_nr;
00139         }
00140 
00141         // reset worst hit number if certain criteria apply.
00142         // Criteria: 2nd worst hit must be at least a factor of
00143         // 1.5 better than the worst in terms of sigma:
00144         if ( xdist_local_worst_sig / xdist_local_2ndworst_sig < 1.5 ) {
00145           hit_nr_worst    = -1;
00146           //hit_nr_2ndworst = -1;
00147         }
00148       }
00149     }
00150 
00151     // if worst hit was found, refit without worst hit and select if considerably better than original fit.
00152     // Can also use brute force: refit all n-1 hit segments and choose one over the n hit if considerably "better"
00153    
00154       std::vector< CSCRecHit2D > buffer;
00155       std::vector< std::vector< CSCRecHit2D > > reduced_segments;
00156       std::vector< CSCRecHit2D > theseRecHits = (*it).specificRecHits();
00157       float best_red_seg_prob = 0.0;
00158       // usefor chi2 1 diff   float best_red_seg_prob = 99999.;
00159       buffer.clear();
00160       if( ChiSquaredProbability((double)(*it).chi2(),(double)((2*(*it).nRecHits())-4)) < chi2ndfProbMin  ) {
00161         
00162         buffer = theseRecHits;
00163 
00164         // Dirty switch: here one can select to refit all possible subsets or just the one without the 
00165         // tagged worst hit:
00166         if( use_brute_force ) { // Brute force method: loop over all possible segments:
00167           for(size_t bi = 0; bi < buffer.size(); bi++) {
00168             reduced_segments.push_back(buffer);
00169             reduced_segments[bi].erase(reduced_segments[bi].begin()+(bi),reduced_segments[bi].begin()+(bi+1));
00170           }
00171         }
00172         else { // More elegant but still biased: erase only worst hit
00173           // Comment: There is not a very strong correlation of the worst hit with the one that one should remove... 
00174           if( hit_nr_worst >= 0 && hit_nr_worst <= int(buffer.size())  ) {
00175             // fill segment in buffer, delete worst hit
00176             buffer.erase(buffer.begin()+(hit_nr_worst),buffer.begin()+(hit_nr_worst+1));
00177             reduced_segments.push_back(buffer);
00178           }
00179           else {
00180             // only fill segment in array, do not delete anything
00181             reduced_segments.push_back(buffer);
00182           }
00183         }
00184       }
00185       
00186       // Loop over the subsegments and fit (only one segment if "use_brute_force" is false):
00187       for (size_t iSegment=0; iSegment<reduced_segments.size(); iSegment++ ) {
00188         // loop over hits on given segment and push pointers to hits into protosegment
00189         protoSegment.clear();
00190         for (size_t m = 0; m<reduced_segments[iSegment].size(); ++m ) {
00191           protoSegment.push_back(&reduced_segments[iSegment][m]);
00192         }
00193         fitSlopes(); 
00194         fillChiSquared();
00195         fillLocalDirection();
00196         // calculate error matrix
00197         AlgebraicSymMatrix protoErrors = calculateError();   
00198         // but reorder components to match what's required by TrackingRecHit interface 
00199         // i.e. slopes first, then positions 
00200         flipErrors( protoErrors ); 
00201         //
00202         CSCSegment temp(protoSegment, protoIntercept, protoDirection, protoErrors, protoChi2);
00203 
00204         // replace n hit segment with n-1 hit segment, if segment probability is 1e3 better:
00205         if( ( ChiSquaredProbability((double)(*it).chi2(),(double)((2*(*it).nRecHits())-4)) 
00206               < 
00207               (1.e-3)*(ChiSquaredProbability((double)temp.chi2(),(double)(2*temp.nRecHits()-4))) )
00208             && 
00209             ( (ChiSquaredProbability((double)temp.chi2(),(double)(2*temp.nRecHits()-4))) 
00210               > best_red_seg_prob 
00211               )
00212             &&
00213             ( (ChiSquaredProbability((double)temp.chi2(),(double)(2*temp.nRecHits()-4))) > 1e-10 )
00214             ) {
00215           best_red_seg_prob = ChiSquaredProbability((double)temp.chi2(),(double)(2*temp.nRecHits()-4));
00216           // exchange current n hit segment (*it) with better n-1 hit segment:
00217           (*it) = temp;
00218         }
00219       }
00220   }
00221   
00222   return segments;
00223   
00224 }
00225 
00226 
00227 /* Method fitSlopes
00228  *
00229  * Perform a Least Square Fit on a segment as per SK algo
00230  *
00231  */
00232 void CSCSegAlgoHitPruning::fitSlopes() {
00233   CLHEP::HepMatrix M(4,4,0);
00234   CLHEP::HepVector B(4,0);
00235   ChamberHitContainer::const_iterator ih = protoSegment.begin();
00236   for (ih = protoSegment.begin(); ih != protoSegment.end(); ++ih) {
00237     const CSCRecHit2D& hit = (**ih);
00238     const CSCLayer* layer  = theChamber->layer(hit.cscDetId().layer());
00239     GlobalPoint gp         = layer->toGlobal(hit.localPosition());
00240     LocalPoint  lp         = theChamber->toLocal(gp); 
00241     // ptc: Local position of hit w.r.t. chamber
00242     double u = lp.x();
00243     double v = lp.y();
00244     double z = lp.z();
00245     // ptc: Covariance matrix of local errors 
00246     CLHEP::HepMatrix IC(2,2);
00247     IC(1,1) = hit.localPositionError().xx();
00248     IC(1,2) = hit.localPositionError().xy();
00249     IC(2,2) = hit.localPositionError().yy();
00250     IC(2,1) = IC(1,2); // since Cov is symmetric
00251     // ptc: Invert covariance matrix (and trap if it fails!)
00252     int ierr = 0;
00253     IC.invert(ierr); // inverts in place
00254     if (ierr != 0) {
00255       LogDebug("CSC") << "CSCSegment::fitSlopes: failed to invert covariance matrix=\n" << IC << "\n";      
00256 //       std::cout<< "CSCSegment::fitSlopes: failed to invert covariance matrix=\n" << IC << "\n"<<std::endl;
00257     }
00258     
00259     M(1,1) += IC(1,1);
00260     M(1,2) += IC(1,2);
00261     M(1,3) += IC(1,1) * z;
00262     M(1,4) += IC(1,2) * z;
00263     B(1)   += u * IC(1,1) + v * IC(1,2);
00264     
00265     M(2,1) += IC(2,1);
00266     M(2,2) += IC(2,2);
00267     M(2,3) += IC(2,1) * z;
00268     M(2,4) += IC(2,2) * z;
00269     B(2)   += u * IC(2,1) + v * IC(2,2);
00270     
00271     M(3,1) += IC(1,1) * z;
00272     M(3,2) += IC(1,2) * z;
00273     M(3,3) += IC(1,1) * z * z;
00274     M(3,4) += IC(1,2) * z * z;
00275     B(3)   += ( u * IC(1,1) + v * IC(1,2) ) * z;
00276     
00277     M(4,1) += IC(2,1) * z;
00278     M(4,2) += IC(2,2) * z;
00279     M(4,3) += IC(2,1) * z * z;
00280     M(4,4) += IC(2,2) * z * z;
00281     B(4)   += ( u * IC(2,1) + v * IC(2,2) ) * z;
00282   }
00283   CLHEP::HepVector p = solve(M, B);
00284   
00285   // Update member variables 
00286   // Note that origin has local z = 0
00287   protoIntercept = LocalPoint(p(1), p(2), 0.);
00288   protoSlope_u = p(3);
00289   protoSlope_v = p(4);
00290 }
00291 
00292 
00293 /* Method fillChiSquared
00294  *
00295  * Determine Chi^2 for the proto wire segment
00296  *
00297  */
00298 void CSCSegAlgoHitPruning::fillChiSquared() {
00299   
00300   double chsq = 0.;
00301   
00302   ChamberHitContainer::const_iterator ih;
00303   for (ih = protoSegment.begin(); ih != protoSegment.end(); ++ih) {
00304     
00305     const CSCRecHit2D& hit = (**ih);
00306     const CSCLayer* layer  = theChamber->layer(hit.cscDetId().layer());
00307     GlobalPoint gp         = layer->toGlobal(hit.localPosition());
00308     LocalPoint lp          = theChamber->toLocal(gp);
00309     
00310     double u = lp.x();
00311     double v = lp.y();
00312     double z = lp.z();
00313     
00314     double du = protoIntercept.x() + protoSlope_u * z - u;
00315     double dv = protoIntercept.y() + protoSlope_v * z - v;
00316     
00317     CLHEP::HepMatrix IC(2,2);
00318     IC(1,1) = hit.localPositionError().xx();
00319     IC(1,2) = hit.localPositionError().xy();
00320     IC(2,2) = hit.localPositionError().yy();
00321     IC(2,1) = IC(1,2);
00322     
00323     // Invert covariance matrix
00324     int ierr = 0;
00325     IC.invert(ierr);
00326     if (ierr != 0) {
00327       LogDebug("CSC") << "CSCSegment::fillChiSquared: failed to invert covariance matrix=\n" << IC << "\n";
00328 //       std::cout << "CSCSegment::fillChiSquared: failed to invert covariance matrix=\n" << IC << "\n";
00329       
00330     }
00331     
00332     chsq += du*du*IC(1,1) + 2.*du*dv*IC(1,2) + dv*dv*IC(2,2);
00333   }
00334 
00335   protoChi2 = chsq;
00336 }
00337 
00338 
00339 /* fillLocalDirection
00340  *
00341  */
00342 void CSCSegAlgoHitPruning::fillLocalDirection() {
00343   // Always enforce direction of segment to point from IP outwards
00344   // (Incorrect for particles not coming from IP, of course.)
00345   
00346   double dxdz = protoSlope_u;
00347   double dydz = protoSlope_v;
00348   double dz   = 1./sqrt(1. + dxdz*dxdz + dydz*dydz);
00349   double dx   = dz*dxdz;
00350   double dy   = dz*dydz;
00351   LocalVector localDir(dx,dy,dz);
00352   
00353   // localDir may need sign flip to ensure it points outward from IP
00354   // ptc: Examine its direction and origin in global z: to point outward
00355   // the localDir should always have same sign as global z...
00356   
00357   double globalZpos    = ( theChamber->toGlobal( protoIntercept ) ).z();
00358   double globalZdir    = ( theChamber->toGlobal( localDir ) ).z();
00359   double directionSign = globalZpos * globalZdir;
00360   protoDirection       = (directionSign * localDir).unit();
00361 }
00362 
00363 
00364 /* weightMatrix
00365  *   
00366  */
00367 AlgebraicSymMatrix CSCSegAlgoHitPruning::weightMatrix() const {
00368   
00369   std::vector<const CSCRecHit2D*>::const_iterator it;
00370   int nhits = protoSegment.size();
00371   AlgebraicSymMatrix matrix(2*nhits, 0);
00372   int row = 0;
00373   
00374   for (it = protoSegment.begin(); it != protoSegment.end(); ++it) {
00375     
00376     const CSCRecHit2D& hit = (**it);
00377     ++row;
00378     matrix(row, row)   = hit.localPositionError().xx();
00379     matrix(row, row+1) = hit.localPositionError().xy();
00380     ++row;
00381     matrix(row, row-1) = hit.localPositionError().xy();
00382     matrix(row, row)   = hit.localPositionError().yy();
00383   }
00384   int ierr;
00385   matrix.invert(ierr);
00386   return matrix;
00387 }
00388 
00389 
00390 /* derivativeMatrix
00391  *
00392  */
00393 CLHEP::HepMatrix CSCSegAlgoHitPruning::derivativeMatrix() const {
00394   
00395   ChamberHitContainer::const_iterator it;
00396   int nhits = protoSegment.size();
00397   CLHEP::HepMatrix matrix(2*nhits, 4);
00398   int row = 0;
00399   
00400   for(it = protoSegment.begin(); it != protoSegment.end(); ++it) {
00401     
00402     const CSCRecHit2D& hit = (**it);
00403     const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
00404     GlobalPoint gp = layer->toGlobal(hit.localPosition());      
00405     LocalPoint lp = theChamber->toLocal(gp); 
00406     float z = lp.z();
00407     ++row;
00408     matrix(row, 1) = 1.;
00409     matrix(row, 3) = z;
00410     ++row;
00411     matrix(row, 2) = 1.;
00412     matrix(row, 4) = z;
00413   }
00414   return matrix;
00415 }
00416 
00417 
00418 /* calculateError
00419  *
00420  */
00421 AlgebraicSymMatrix CSCSegAlgoHitPruning::calculateError() const {
00422   
00423   AlgebraicSymMatrix weights = weightMatrix();
00424   AlgebraicMatrix A = derivativeMatrix();
00425   
00426   // (AT W A)^-1
00427   // from https://www.phys.ufl.edu/~avery/fitting.html, part I
00428   int ierr;
00429   AlgebraicSymMatrix result = weights.similarityT(A);
00430   result.invert(ierr);
00431   
00432   // blithely assuming the inverting never fails...
00433   return result;
00434 }
00435 
00436 
00437 void CSCSegAlgoHitPruning::flipErrors( AlgebraicSymMatrix& a ) const { 
00438     
00439   // The CSCSegment needs the error matrix re-arranged 
00440     
00441   AlgebraicSymMatrix hold( a ); 
00442     
00443   // errors on slopes into upper left 
00444   a(1,1) = hold(3,3); 
00445   a(1,2) = hold(3,4); 
00446   a(2,1) = hold(4,3); 
00447   a(2,2) = hold(4,4); 
00448     
00449   // errors on positions into lower right 
00450   a(3,3) = hold(1,1); 
00451   a(3,4) = hold(1,2); 
00452   a(4,3) = hold(2,1); 
00453   a(4,4) = hold(2,2); 
00454     
00455   // off-diagonal elements remain unchanged 
00456     
00457 } 
00458