CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/RecoLocalMuon/DTSegment/src/DTSegmentUpdator.cc

Go to the documentation of this file.
00001 
00012 /* This Class Header */
00013 #include "RecoLocalMuon/DTSegment/src/DTSegmentUpdator.h"
00014 
00015 /* Collaborating Class Header */
00016 
00017 //mene
00018 #include "DataFormats/DTRecHit/interface/DTChamberRecSegment2D.h"
00019 
00020 #include "DataFormats/DTRecHit/interface/DTRecSegment2D.h"
00021 #include "DataFormats/DTRecHit/interface/DTSLRecSegment2D.h"
00022 #include "DataFormats/DTRecHit/interface/DTChamberRecSegment2D.h"
00023 #include "DataFormats/DTRecHit/interface/DTRecSegment4D.h"
00024 #include "DataFormats/DTRecHit/interface/DTRecHit1D.h"
00025 #include "DataFormats/GeometryCommonDetAlgo/interface/ErrorFrameTransformer.h"
00026 
00027 #include "RecoLocalMuon/DTSegment/src/DTSegmentCand.h"
00028 #include "RecoLocalMuon/DTRecHit/interface/DTRecHitAlgoFactory.h"
00029 #include "RecoLocalMuon/DTSegment/src/DTLinearFit.h"
00030 
00031 #include "Geometry/Records/interface/MuonGeometryRecord.h"
00032 #include "Geometry/DTGeometry/interface/DTGeometry.h"
00033 #include "Geometry/DTGeometry/interface/DTLayer.h"
00034 
00035 #include "FWCore/Utilities/interface/Exception.h"
00036 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00037 #include "FWCore/Framework/interface/EventSetup.h"
00038 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00039 
00040 /* C++ Headers */
00041 #include <string>
00042 
00043 using namespace std;
00044 using namespace edm;
00045 
00046 /* ====================================================================== */
00047 
00049 DTSegmentUpdator::DTSegmentUpdator(const ParameterSet& config) :
00050   theFitter(new DTLinearFit()) ,
00051   vdrift_4parfit(config.getParameter<bool>("performT0_vdriftSegCorrection")),
00052   T0_hit_resolution(config.getParameter<double>("hit_afterT0_resolution")),
00053   perform_delta_rejecting(config.getParameter<bool>("perform_delta_rejecting")),
00054   debug(config.getUntrackedParameter<bool>("debug",false)) 
00055 {  
00056   string theAlgoName = config.getParameter<string>("recAlgo");
00057   theAlgo = DTRecHitAlgoFactory::get()->create(theAlgoName, 
00058                                                config.getParameter<ParameterSet>("recAlgoConfig"));
00059 
00060   if(debug)
00061     cout << "[DTSegmentUpdator] Constructor called" << endl;
00062 }
00063 
00065 DTSegmentUpdator::~DTSegmentUpdator() {
00066   delete theFitter;
00067 }
00068 
00069 /* Operations */ 
00070 
00071 void DTSegmentUpdator::setES(const EventSetup& setup){
00072   setup.get<MuonGeometryRecord>().get(theGeom);
00073   theAlgo->setES(setup);
00074 }
00075 
00076 void DTSegmentUpdator::update(DTRecSegment4D* seg, const bool calcT0) const {
00077 
00078   if(debug) cout << "[DTSegmentUpdator] Starting to update the segment" << endl;
00079 
00080   const bool hasPhi = seg->hasPhi();
00081   const bool hasZed = seg->hasZed();
00082 
00083   //reject the bad hits (due to delta rays)
00084   if(perform_delta_rejecting && hasPhi) rejectBadHits(seg->phiSegment());
00085 
00086   int step = (hasPhi && hasZed) ? 3 : 2;
00087   if(calcT0) step = 4;
00088 
00089   if(debug) cout << "Step of update is " << step << endl;
00090 
00091   GlobalPoint  pos = theGeom->idToDet(seg->geographicalId())->toGlobal(seg->localPosition());
00092   GlobalVector dir = theGeom->idToDet(seg->geographicalId())->toGlobal(seg->localDirection());
00093 
00094   if(calcT0) calculateT0corr(seg);
00095 
00096   if(hasPhi) updateHits(seg->phiSegment(),pos,dir,step);
00097   if(hasZed) updateHits(seg->zSegment()  ,pos,dir,step);
00098 
00099   fit(seg);
00100 }
00101 
00102 void DTSegmentUpdator::update(DTRecSegment2D* seg) const {
00103   GlobalPoint pos = (theGeom->idToDet(seg->geographicalId()))->toGlobal(seg->localPosition());
00104   GlobalVector dir = (theGeom->idToDet(seg->geographicalId()))->toGlobal(seg->localDirection());
00105 
00106   updateHits(seg,pos,dir);
00107   fit(seg);
00108 }
00109 
00110 void DTSegmentUpdator::fit(DTRecSegment4D* seg)  const {
00111   // after the update must refit the segments
00112   if(seg->hasPhi()) fit(seg->phiSegment());
00113   if(seg->hasZed()) fit(seg->zSegment());
00114 
00115   const DTChamber* theChamber = theGeom->chamber(seg->chamberId());
00116 
00117   if(seg->hasPhi() && seg->hasZed() ) {
00118 
00119     DTChamberRecSegment2D *segPhi=seg->phiSegment();
00120     DTSLRecSegment2D *segZed=seg->zSegment();
00121 
00122     // NB Phi seg is already in chamber ref
00123     LocalPoint posPhiInCh = segPhi->localPosition();
00124     LocalVector dirPhiInCh= segPhi->localDirection();
00125 
00126     // Zed seg is in SL one
00127     const DTSuperLayer* zSL = theChamber->superLayer(segZed->superLayerId());
00128     LocalPoint zPos(segZed->localPosition().x(), 
00129                     (zSL->toLocal(theChamber->toGlobal(segPhi->localPosition()))).y(),
00130                     0.);
00131 
00132     LocalPoint posZInCh = theChamber->toLocal(zSL->toGlobal(zPos));
00133 
00134     LocalVector dirZInCh = theChamber->toLocal(zSL->toGlobal(segZed->localDirection()));
00135 
00136     LocalPoint posZAt0 = posZInCh + dirZInCh*(-posZInCh.z())/cos(dirZInCh.theta());
00137 
00138     // given the actual definition of chamber refFrame, (with z poiniting to IP),
00139     // the zed component of direction is negative.
00140     LocalVector dir=LocalVector(dirPhiInCh.x()/fabs(dirPhiInCh.z()),dirZInCh.y()/fabs(dirZInCh.z()),-1.);
00141 
00142     seg->setPosition(LocalPoint(posPhiInCh.x(),posZAt0.y(),0.));
00143     seg->setDirection(dir.unit());
00144 
00145     AlgebraicSymMatrix mat(4);
00146 
00147     // set cov matrix
00148     mat[0][0] = segPhi->parametersError()[0][0]; //sigma (dx/dz)
00149     mat[0][2] = segPhi->parametersError()[0][1]; //cov(dx/dz,x)
00150     mat[2][2] = segPhi->parametersError()[1][1]; //sigma (x)
00151 
00152     seg->setCovMatrix(mat);
00153     seg->setCovMatrixForZed(posZInCh);
00154 
00155   }
00156 
00157   else if (seg->hasPhi()) {
00158     DTChamberRecSegment2D *segPhi=seg->phiSegment();
00159 
00160     seg->setPosition(segPhi->localPosition());
00161     seg->setDirection(segPhi->localDirection());
00162 
00163     AlgebraicSymMatrix mat(4);
00164     // set cov matrix
00165     mat[0][0] = segPhi->parametersError()[0][0]; //sigma (dx/dz)
00166     mat[0][2] = segPhi->parametersError()[0][1]; //cov(dx/dz,x)
00167     mat[2][2] = segPhi->parametersError()[1][1]; //sigma (x)
00168 
00169     seg->setCovMatrix(mat);
00170   }
00171 
00172   else if (seg->hasZed()) {
00173     DTSLRecSegment2D *segZed = seg->zSegment();
00174 
00175     // Zed seg is in SL one
00176     GlobalPoint glbPosZ = ( theGeom->superLayer(segZed->superLayerId()) )->toGlobal(segZed->localPosition());
00177     LocalPoint posZInCh = ( theGeom->chamber(segZed->superLayerId().chamberId()) )->toLocal(glbPosZ);
00178 
00179     GlobalVector glbDirZ = (theGeom->superLayer(segZed->superLayerId()) )->toGlobal(segZed->localDirection());
00180     LocalVector dirZInCh = (theGeom->chamber(segZed->superLayerId().chamberId()) )->toLocal(glbDirZ);
00181 
00182     LocalPoint posZAt0 = posZInCh+
00183       dirZInCh*(-posZInCh.z())/cos(dirZInCh.theta());
00184 
00185     seg->setPosition(posZAt0);
00186     seg->setDirection(dirZInCh);
00187 
00188     AlgebraicSymMatrix mat(4);
00189     // set cov matrix
00190     seg->setCovMatrix(mat);
00191     seg->setCovMatrixForZed(posZInCh);
00192   }
00193 }
00194 
00195 bool DTSegmentUpdator::fit(DTSegmentCand* seg) const {
00196   if (!seg->good()) return false;
00197 
00198   vector<float> x;
00199   vector<float> y;
00200   vector<float> sigy;
00201 
00202   DTSegmentCand::AssPointCont hits=seg->hits();
00203   for (DTSegmentCand::AssPointCont::const_iterator iter=hits.begin();
00204        iter!=hits.end(); ++iter) {
00205     LocalPoint pos = (*iter).first->localPosition((*iter).second);
00206     x.push_back(pos.z()); 
00207     y.push_back(pos.x());
00208     sigy.push_back(sqrt((*iter).first->localPositionError().xx()));
00209   }
00210 
00211   LocalPoint pos;
00212   LocalVector dir;
00213   AlgebraicSymMatrix covMat(2);
00214 
00215   double chi2 = 0.;
00216   fit(x,y,sigy,pos,dir,covMat,chi2);
00217 
00218   seg->setPosition(pos);
00219   seg->setDirection(dir);
00220 
00221   //cout << "pos " << segPosition<< endl;
00222   //cout << "dir " << segDirection<< endl;
00223 
00224   seg->setCovMatrix(covMat);
00225   // cout << "Mat " << covMat << endl;
00226 
00227   seg->setChi2(chi2);
00228   return true;
00229 }
00230 
00231 void DTSegmentUpdator::fit(DTRecSegment2D* seg) const {
00232   // WARNING: since this method is called both with a 2D and a 2DPhi as argument
00233   // seg->geographicalId() can be a superLayerId or a chamberId 
00234 
00235   vector<float> x;
00236   vector<float> y;
00237   vector<float> sigy;
00238 
00239   vector<DTRecHit1D> hits=seg->specificRecHits();
00240   for (vector<DTRecHit1D>::const_iterator hit=hits.begin();
00241        hit!=hits.end(); ++hit) {
00242 
00243     // I have to get the hits position (the hit is in the layer rf) in SL frame...
00244     GlobalPoint glbPos = ( theGeom->layer( hit->wireId().layerId() ) )->toGlobal(hit->localPosition());
00245     LocalPoint pos = ( theGeom->idToDet(seg->geographicalId()) )->toLocal(glbPos);
00246 
00247     x.push_back(pos.z()); 
00248     y.push_back(pos.x());
00249 
00250     // Get local error in SL frame
00251     //RB: is it right in this way? 
00252     ErrorFrameTransformer tran;
00253     GlobalError glbErr =
00254       tran.transform( hit->localPositionError(),(theGeom->layer( hit->wireId().layerId() ))->surface());
00255     LocalError slErr =
00256       tran.transform( glbErr, (theGeom->idToDet(seg->geographicalId()))->surface());
00257 
00258     sigy.push_back(sqrt(slErr.xx()));
00259   }
00260 
00261   LocalPoint pos;
00262   LocalVector dir;
00263   AlgebraicSymMatrix covMat(2);
00264   double chi2 = 0.;
00265 
00266   fit(x,y,sigy,pos,dir,covMat,chi2);
00267 
00268   seg->setPosition(pos);
00269   seg->setDirection(dir);
00270 
00271   //cout << "pos " << segPosition << endl;
00272   //cout << "dir " << segDirection << endl;
00273 
00274   seg->setCovMatrix(covMat);
00275   // cout << "Mat " << mat << endl;
00276 
00277   seg->setChi2(chi2);
00278 }
00279 
00280 void DTSegmentUpdator::fit(const vector<float>& x,
00281                            const vector<float>& y, 
00282                            const vector<float>& sigy,
00283                            LocalPoint& pos,
00284                            LocalVector& dir,
00285                            AlgebraicSymMatrix& covMatrix,
00286                            double& chi2)  const {
00287 
00288   float slope     = 0.;
00289   float intercept = 0.;
00290   float covss     = 0.;
00291   float covii     = 0.;
00292   float covsi     = 0.;
00293 
00294   // do the fit
00295   theFitter->fit(x,y,x.size(),sigy,slope,intercept,covss,covii,covsi);
00296   // cout << "slope " << slope << endl;
00297   // cout << "intercept " << intercept << endl;
00298 
00299   // intercept is the x() in chamber frame when the segment cross the chamber
00300   // plane (at z()=0), the y() is not measured, so let's put the center of the
00301   // chamber.
00302   pos = LocalPoint(intercept,0.,0.);
00303 
00304   //  slope is dx()/dz(), while dy()/dz() is by definition 0, finally I want the
00305   //  segment to point outward, so opposite to local z
00306   dir = LocalVector(-slope,0.,-1.).unit();
00307 
00308   covMatrix = AlgebraicSymMatrix(2);
00309   covMatrix[0][0] = covss; // this is var(dy/dz)
00310   covMatrix[1][1] = covii; // this is var(y)
00311   covMatrix[1][0] = covsi; // this is cov(dy/dz,y)
00312 
00313   /* Calculate chi2. */
00314   chi2 = 0.;
00315   for(unsigned int i=0; i<x.size() ; ++i) {
00316     double resid= y[i] - (intercept + slope*x[i]);
00317     chi2 += (resid/sigy[i])*(resid/sigy[i]);
00318   }
00319 }
00320 
00321 // The GlobalPoint and the GlobalVector can be either the glb position and the direction
00322 // of the 2D-segment itself or the glb position and direction of the 4D segment
00323 void DTSegmentUpdator::updateHits(DTRecSegment2D* seg, GlobalPoint &gpos,
00324                                   GlobalVector &gdir, const int step) const{
00325 
00326   // it is not necessary to have DTRecHit1D* to modify the obj in the container
00327   // but I have to be carefully, since I cannot make a copy before the iteration!
00328 
00329   vector<DTRecHit1D> toBeUpdatedRecHits = seg->specificRecHits();
00330   vector<DTRecHit1D> updatedRecHits;
00331 
00332   for (vector<DTRecHit1D>::iterator hit= toBeUpdatedRecHits.begin(); 
00333        hit!=toBeUpdatedRecHits.end(); ++hit) {
00334 
00335     const DTLayer* layer = theGeom->layer( hit->wireId().layerId() );
00336 
00337     LocalPoint segPos=layer->toLocal(gpos);
00338     LocalVector segDir=layer->toLocal(gdir);
00339 
00340     // define impact angle needed by the step 2
00341     const float angle = atan(segDir.x()/-segDir.z());
00342 
00343     // define the local position (extr.) of the segment. Needed by the third step 
00344     LocalPoint segPosAtLayer=segPos+segDir*(-segPos.z())/cos(segDir.theta());
00345 
00346     DTRecHit1D newHit1D = (*hit);
00347 
00348     bool ok = true;
00349 
00350     if (step == 2) {
00351       ok = theAlgo->compute(layer,*hit,angle,newHit1D);
00352 
00353     } else if (step == 3) {
00354 
00355       LocalPoint hitPos(hit->localPosition().x(),+segPosAtLayer.y(),0.);
00356 
00357       GlobalPoint glbpos= theGeom->layer( hit->wireId().layerId() )->toGlobal(hitPos);
00358 
00359       newHit1D.setPosition(hitPos);
00360 
00361       ok = theAlgo->compute(layer,*hit,angle,glbpos,newHit1D);
00362 
00363     } else if (step == 4) {
00364 
00365       //const double vminf = seg->vDrift();   //  vdrift correction are recorded in the segment    
00366       double vminf =0.;
00367       if(vdrift_4parfit) vminf = seg->vDrift();   // use vdrift recorded in the segment only if vdrift_4parfit=True
00368 
00369       double cminf = 0.;
00370       if(seg->ist0Valid()) cminf = - seg->t0()*0.00543;
00371 
00372       //cout << "In updateHits: t0 = " << seg->t0() << endl;
00373       //cout << "In updateHits: vminf = " << vminf << endl;
00374       //cout << "In updateHits: cminf = " << cminf << endl;
00375 
00376       const float xwire = layer->specificTopology().wirePosition(hit->wireId().wire());
00377       const float distance = fabs(hit->localPosition().x() - xwire);
00378 
00379       const int ilc = ( hit->lrSide() == DTEnums::Left ) ? 1 : -1;
00380 
00381       const double dy_corr = (vminf*ilc*distance-cminf*ilc ); 
00382 
00383       LocalPoint point(hit->localPosition().x() + dy_corr, +segPosAtLayer.y(), 0.);
00384 
00385       //double final_hit_resol = T0_hit_resolution;
00386       //if(newHit1D.wireId().layerId().superlayerId().superLayer() != 2) final_hit_resol = final_hit_resol * 0.8;
00387       //LocalError error(final_hit_resol * final_hit_resol,0.,0.);
00388 
00389       LocalError error(T0_hit_resolution*T0_hit_resolution,0.,0.);
00390 
00391       newHit1D.setPositionAndError(point, error);
00392 
00393       //FIXME: check that the hit is still inside the cell
00394       ok = true;
00395 
00396     } else throw cms::Exception("DTSegmentUpdator")<<" updateHits called with wrong step " << endl;
00397 
00398     if (ok) updatedRecHits.push_back(newHit1D);
00399     else {
00400       LogError("DTSegmentUpdator")<<"DTSegmentUpdator::updateHits failed update" << endl;
00401       throw cms::Exception("DTSegmentUpdator")<<"updateHits failed update"<<endl;
00402     }
00403 
00404   }
00405   seg->update(updatedRecHits);
00406 }
00407 
00408 void DTSegmentUpdator::rejectBadHits(DTChamberRecSegment2D* phiSeg) const {
00409 
00410   vector<float> x;
00411   vector<float> y;
00412   
00413   if(debug) cout << " Inside the segment updator, now loop on hits:   ( x == z_loc , y == x_loc) " << endl;
00414  
00415   vector<DTRecHit1D> hits = phiSeg->specificRecHits();
00416   for (vector<DTRecHit1D>::const_iterator hit=hits.begin();
00417        hit!=hits.end(); ++hit) {
00418 
00419     // I have to get the hits position (the hit is in the layer rf) in SL frame...
00420     GlobalPoint glbPos = ( theGeom->layer( hit->wireId().layerId() ) )->toGlobal(hit->localPosition());
00421     LocalPoint pos = ( theGeom->idToDet(phiSeg->geographicalId()) )->toLocal(glbPos);
00422 
00423     x.push_back(pos.z()); 
00424     y.push_back(pos.x());
00425   }
00426 
00427   if(debug){
00428     cout << " end of segment! " << endl;
00429     cout << " size = Number of Hits: " << x.size() << "  " << y.size() << endl;
00430   }
00431   
00432   // Perform the 2 par fit:
00433   float par[2]={0.,0.}; // q , m
00434 
00435   //variables to perform the fit:
00436   float Sx = 0.;
00437   float Sy = 0.;
00438   float Sx2 = 0.;
00439   float Sy2 = 0.;
00440   float Sxy = 0.;
00441 
00442   size_t N =  x.size();
00443         
00444   for(size_t i = 0; i < N;++i){
00445     Sx += x.at(i);
00446     Sy += y.at(i);
00447     Sx2 += x.at(i)*x.at(i);
00448     Sy2 += y.at(i)*y.at(i);
00449     Sxy += x.at(i)*y.at(i);
00450                 
00451   }
00452         
00453   const float delta = N*Sx2 - Sx*Sx;
00454   par[0] = ( Sx2*Sy - Sx*Sxy )/delta;
00455   par[1] = ( N*Sxy - Sx*Sy )/delta;
00456 
00457   if(debug) cout << "fit 2 parameters done ----> par0: "<< par[0] << "  par1: "<< par[1] << endl;
00458 
00459   // Calc residuals:
00460   float residuals[N];
00461         
00462   for(size_t i = 0; i < N;++i)
00463     residuals[i] = 0;
00464         
00465   for(size_t i = 0; i < N;++i){
00466     residuals[i] = y.at(i) - par[1]*x.at(i) - par[0];
00467     if(debug){ 
00468       cout<<" i: "<<i<<" y_i "<<y.at(i)<<" x_i "<<x.at(i)<<" res_i "<<residuals[i]; 
00469       if (i==N-1) cout<<endl;
00470     }
00471   }
00472         
00473   if(debug) cout << " Residuals computed! "<<  endl;
00474                 
00475                 
00476   // Perform bad hit rejecting -- update hits
00477   vector<DTRecHit1D> updatedRecHits;
00478         
00479   float mean_residual = 0.; //mean of the absolute values of residuals
00480         
00481   for (size_t i = 0; i < N; ++i)
00482     mean_residual += fabs(residuals[i]);
00483         
00484   mean_residual = mean_residual/(N - 2);        
00485         
00486   if(debug) cout << " mean_residual: "<< mean_residual << endl;
00487         
00488   int i = 0;
00489         
00490   for (vector<DTRecHit1D>::const_iterator hit=hits.begin();
00491        hit!=hits.end(); ++hit) {
00492                 
00493     DTRecHit1D newHit1D = (*hit);
00494 
00495     float normResidual = mean_residual > 0 ? fabs(residuals[i])/mean_residual : 0;
00496     if(normResidual < 1.5){
00497                                         
00498       updatedRecHits.push_back(newHit1D);
00499       if(debug) cout << " accepted "<< i+1 << "th hit" <<"  Irej: " << normResidual << endl;
00500       ++i;
00501     }
00502     else {
00503       if(debug) cout << " rejected "<< i+1 << "th hit" <<"  Irej: " << normResidual << endl;
00504       ++i;
00505       continue;
00506     }
00507   }
00508         
00509   phiSeg->update(updatedRecHits);       
00510   
00511   //final check!
00512   if(debug){ 
00513   
00514     vector<float> x_upd;
00515     vector<float> y_upd;
00516  
00517     cout << " Check the update action: " << endl;
00518  
00519     vector<DTRecHit1D> hits_upd = phiSeg->specificRecHits();
00520     for (vector<DTRecHit1D>::const_iterator hit=hits_upd.begin();
00521          hit!=hits_upd.end(); ++hit) {
00522 
00523       // I have to get the hits position (the hit is in the layer rf) in SL frame...
00524       GlobalPoint glbPos = ( theGeom->layer( hit->wireId().layerId() ) )->toGlobal(hit->localPosition());
00525       LocalPoint pos = ( theGeom->idToDet(phiSeg->geographicalId()) )->toLocal(glbPos);
00526 
00527       x_upd.push_back(pos.z()); 
00528       y_upd.push_back(pos.x());
00529 
00530       cout << " x_upd: "<< pos.z() << "  y_upd: "<< pos.x() << endl;
00531 
00532 
00533     }
00534   
00535     cout << " end of segment! " << endl;
00536     cout << " size = Number of Hits: " << x_upd.size() << "  " << y_upd.size() << endl;
00537     
00538   }// end debug
00539   
00540   return;
00541 } //end DTSegmentUpdator::rejectBadHits
00542 
00543 void DTSegmentUpdator::calculateT0corr(DTRecSegment4D* seg) const {
00544   if(seg->hasPhi()) calculateT0corr(seg->phiSegment());
00545   if(seg->hasZed()) calculateT0corr(seg->zSegment());
00546 }
00547 
00548 void DTSegmentUpdator::calculateT0corr(DTRecSegment2D* seg) const {
00549   // WARNING: since this method is called both with a 2D and a 2DPhi as argument
00550   // seg->geographicalId() can be a superLayerId or a chamberId 
00551 
00552   vector<double> d_drift;
00553   vector<float> x;
00554   vector<float> y;
00555   vector<int> lc;
00556 
00557   vector<DTRecHit1D> hits=seg->specificRecHits();
00558 
00559   DTWireId wireId;
00560   int nptfit = 0;
00561 
00562   for (vector<DTRecHit1D>::const_iterator hit=hits.begin();
00563        hit!=hits.end(); ++hit) {
00564 
00565     // I have to get the hits position (the hit is in the layer rf) in SL frame...
00566     GlobalPoint glbPos = ( theGeom->layer( hit->wireId().layerId() ) )->toGlobal(hit->localPosition());
00567     LocalPoint pos = ( theGeom->idToDet(seg->geographicalId()) )->toLocal(glbPos);
00568 
00569     const DTLayer* layer = theGeom->layer( hit->wireId().layerId() );
00570     float xwire = layer->specificTopology().wirePosition(hit->wireId().wire());
00571     float distance = fabs(hit->localPosition().x() - xwire);
00572 
00573     int ilc = ( hit->lrSide() == DTEnums::Left ) ? 1 : -1;
00574 
00575     nptfit++;
00576     x.push_back(pos.z()); 
00577     y.push_back(pos.x());
00578     lc.push_back(ilc);
00579     d_drift.push_back(distance);
00580 
00581     // cout << " d_drift "<<distance  <<" npt= " <<npt<<endl;
00582   }
00583 
00584   double chi2fit = 0.;
00585   float cminf    = 0.;
00586   double vminf   = 0.;
00587 
00588   if ( nptfit > 2 ) {
00589     //NB chi2fit is normalized
00590     Fit4Var(x,y,lc,d_drift,nptfit,cminf,vminf,chi2fit);
00591 
00592     double t0cor = -999.;
00593     if(cminf > -998.) t0cor = - cminf/0.00543 ; // in ns
00594 
00595     //cout << "In calculateT0corr: t0 = " << t0cor << endl;
00596     //cout << "In calculateT0corr: vminf = " << vminf << endl;
00597     //cout << "In calculateT0corr: cminf = " << cminf << endl;
00598     //cout << "In calculateT0corr: chi2 = " << chi2fit << endl;
00599 
00600     seg->setT0(t0cor);          // time  and
00601     seg->setVdrift(vminf);   //  vdrift correction are recorded in the segment    
00602   }
00603 }
00604 
00605 
00606 void DTSegmentUpdator::Fit4Var(const vector<float>& xfit,
00607                                const vector<float>& yfit,
00608                                const vector<int>& lfit,
00609                                const vector<double>& tfit,
00610                                const int nptfit,
00611                                float& cminf,
00612                                double& vminf,
00613                                double& chi2fit) const { 
00614 
00615   const double sigma = 0.0295;// errors can be inserted .just load them/that is the usual TB resolution value for DT chambers 
00616   double aminf = 0.;
00617   double bminf = 0.;
00618   int nppar = 0;
00619   double sx = 0.;
00620   double  sx2 = 0.;
00621   double sy = 0.;
00622   double sxy = 0.;
00623   double sl = 0.;
00624   double sl2 = 0.;
00625   double sly = 0.;
00626   double slx = 0.;
00627   double st = 0.;
00628   double st2 = 0.;
00629   double slt = 0.;
00630   double sltx = 0.;
00631   double slty = 0.;
00632   double chi2fitN2 = -1. ;
00633   double chi2fit3 = -1.;
00634   double chi2fitN3 = -1. ;
00635   double chi2fitN4 = -1.;
00636   float bminf3 = bminf;
00637   float aminf3 = aminf;
00638   float cminf3 = cminf;
00639   int nppar2 = 0;
00640   int nppar3 = 0;
00641   int nppar4 = 0;
00642 
00643   cminf = -999.;
00644   vminf = 0.;
00645 
00646   for (int j=0; j<nptfit; j++){
00647     sx  = sx + xfit[j];       
00648     sy  = sy + yfit[j];
00649     sx2 = sx2 + xfit[j]*xfit[j];
00650     sxy = sxy + xfit[j]*yfit[j];
00651     sl  = sl + lfit[j];       
00652     sl2 = sl2 + lfit[j]*lfit[j];
00653     sly = sly + lfit[j]*yfit[j];
00654     slx = slx + lfit[j]*xfit[j];
00655     st = st + tfit[j];
00656     st2 = st2 + tfit[j] * tfit[j];
00657     slt = slt + lfit[j] * tfit[j];
00658     sltx = sltx + lfit[j] * tfit[j]*xfit[j];
00659     slty = slty + lfit[j] * tfit[j]*yfit[j];
00660 
00661   } //end loop
00662 
00663   const double delta = nptfit*sx2 - sx*sx;
00664 
00665   double a = 0.;
00666   double b = 0.;               
00667 
00668   if (delta!=0){   //
00669     a = (sx2*sy - sx*sxy)/delta;
00670     b = (nptfit*sxy - sx*sy)/delta;
00671 
00672     //  cout << " NPAR=2 : slope = "<<b<< "    intercept = "<<a <<endl;
00673     for (int j=0; j<nptfit; j++){
00674       const double ypred = a + b*xfit[j];
00675       const double dy = (yfit[j] - ypred)/sigma;
00676       chi2fit = chi2fit + dy*dy;
00677     } //end loop chi2
00678   }
00679 
00680   bminf = b;
00681   aminf = a;
00682 
00683   nppar = 2; 
00684   nppar2 = nppar; 
00685 
00686   chi2fitN2 = chi2fit/(nptfit-2);
00687 
00688   // cout << "dt0 = 0chi2fit = " << chi2fit << "  slope = "<<b<<endl;
00689 
00690   if (nptfit >= 3) {
00691 
00692     const double d1 = sy;
00693     const double d2 = sxy;
00694     const double d3 = sly;
00695     const double c1 = sl;
00696     const double c2 = slx;
00697     const double c3 = sl2;
00698     const double b1 = sx;
00699     const double b2 = sx2;
00700     const double b3 = slx;
00701     const double a1 = nptfit;
00702     const double a2 = sx;
00703     const double a3 = sl;
00704 
00705     //these parameters are not used in the 4-variables fit
00706     const double b4 = b2*a1-b1*a2;
00707     const double c4 = c2*a1-c1*a2;
00708     const double d4 = d2*a1-d1*a2;
00709     const double b5 = a1*b3-a3*b1;
00710     const double c5 = a1*c3-a3*c1;
00711     const double d5 = a1*d3-d1*a3;
00712     const double a6 = slt;
00713     const double b6 = sltx;
00714     const double c6 = st;
00715     const double v6 = st2;      
00716     const double d6 = slty;
00717 
00718     if (((c5*b4-c4*b5)*b4*a1)!=0) {
00719       nppar = 3;
00720       chi2fit = 0.;
00721       cminf = (d5*b4-d4*b5)/(c5*b4-c4*b5);
00722       bminf = d4/b4 -cminf *c4/b4;
00723       aminf = (d1/a1 -cminf*c1/a1 -bminf*b1/a1);
00724 
00725       for (int j=0; j<nptfit; j++){
00726         const double ypred = aminf + bminf*xfit[j];
00727         const double dy = (yfit[j]-cminf*lfit[j] - ypred)/sigma;
00728         chi2fit = chi2fit + dy*dy;
00729 
00730       } //end loop chi2
00731       chi2fit3 = chi2fit;
00732       if (nptfit>3)
00733         chi2fitN3 = chi2fit /(nptfit-3);
00734 
00735     }
00736     else {
00737       cminf = -999.;
00738       bminf = b;
00739       aminf = a;
00740       chi2fit3 = chi2fit;
00741       chi2fitN3 = chi2fit /(nptfit-2);
00742     }
00743 
00744     bminf3 = bminf;
00745     aminf3 = aminf;
00746     cminf3 = cminf;
00747     nppar3 = nppar;
00748 
00749     if (debug) {
00750       cout << "dt0= 0 : slope 2 = " << b << " pos in  = " << a << " chi2fitN2 = " << chi2fitN2
00751            << " nppar = " << nppar2 << " nptfit = " << nptfit << endl;
00752       cout << "dt0 = 0 : slope 3 = " << bminf << " pos out = " << aminf << " chi2fitN3 = "
00753            << chi2fitN3 << " nppar = " << nppar3 << " T0_ev ns = " << cminf/0.00543 << endl;
00754     } 
00755 
00756     //***********************************
00757     //     cout << " vdrift_4parfit "<< vdrift_4parfit<<endl;
00758     if( nptfit>=5) { 
00759       const double det = (a1*a1*(b2*v6 - b6*b6) - a1*(a2*a2*v6 - 2*a2*a6*b6 + a6*a6*b2 + b2*c6*c6 + b3*(b3*v6 - 2*b6*c6))
00760                           + a2*a2*c6*c6 + 2*a2*(a3*(b3*v6 - b6*c6) - a6*b3*c6) + a3*a3*(b6*b6 - b2*v6)
00761                           + a6*(2*a3*(b2*c6 - b3*b6) + a6*b3*b3)); 
00762 
00763       // the dv/vdrift correction may be computed  under vdrift_4parfit request;
00764       if (det != 0) { 
00765         nppar = 4;
00766         chi2fit = 0.;
00767         // computation of   a, b, c e v
00768         aminf = (a1*(a2*(b6*d6 - v6*d2) + a6*(b6*d2 - b2*d6) + d1*(b2*v6 - b6*b6)) - a2*(b3*(c6*d6 - v6*d3)
00769                  + c6*(b6*d3 - c6*d2)) + a3*(b2*(c6*d6 - v6*d3) + b3*(v6*d2 - b6*d6) + b6*(b6*d3 - c6*d2))
00770                  + a6*(b2*c6*d3 + b3*(b3*d6 - b6*d3 - c6*d2)) - d1*(b2*c6*c6 + b3*(b3*v6 - 2*b6*c6)))/det;
00771         bminf = - (a1*a1*(b6*d6 - v6*d2) - a1*(a2*(a6*d6 - v6*d1) - a6*a6*d2 + a6*b6*d1 + b3*(c6*d6 - v6*d3)
00772                  + c6*(b6*d3 - c6*d2)) + a2*(a3*(c6*d6 - v6*d3) + c6*(a6*d3 - c6*d1)) + a3*a3*(v6*d2 - b6*d6)
00773                  + a3*(a6*(b3*d6 + b6*d3 - 2*c6*d2) - d1*(b3*v6 - b6*c6)) - a6*b3*(a6*d3 - c6*d1))/det;
00774         cminf = -(a1*(b2*(c6*d6 - v6*d3) + b3*(v6*d2 - b6*d6) + b6*(b6*d3 - c6*d2)) + a2*a2*(v6*d3 - c6*d6)
00775                  + a2*(a3*(b6*d6 - v6*d2) + a6*(b3*d6 - 2*b6*d3 + c6*d2) - d1*(b3*v6 - b6*c6))
00776                  + a3*(d1*(b2*v6 - b6*b6) - a6*(b2*d6 - b6*d2)) + a6*(a6*(b2*d3 - b3*d2) - d1*(b2*c6 - b3*b6)))/det;
00777         vminf = - (a1*a1*(b2*d6 - b6*d2) - a1*(a2*a2*d6 - a2*(a6*d2 + b6*d1) + a6*b2*d1 + b2*c6*d3
00778                  + b3*(b3*d6 - b6*d3 - c6*d2)) + a2*a2*c6*d3 + a2*(a3*(2*b3*d6 - b6*d3 - c6*d2) - b3*(a6*d3 + c6*d1))
00779                  + a3*a3*(b6*d2 - b2*d6) + a3*(a6*(b2*d3 - b3*d2) + d1*(b2*c6 - b3*b6)) + a6*b3*b3*d1)/det;
00780 
00781         //  chi 2
00782         for (int j=0; j<nptfit; j++) {
00783           const double ypred = aminf + bminf*xfit[j];
00784           const double dy = (yfit[j]+vminf*lfit[j]*tfit[j]-cminf*lfit[j] -ypred)/sigma; 
00785           chi2fit = chi2fit + dy*dy;
00786 
00787         } //end loop chi2
00788         if (nptfit<=nppar){ 
00789           chi2fitN4=-1;
00790           //            cout << "nptfit " << nptfit << " nppar " << nppar << endl;
00791         }
00792         else{
00793           chi2fitN4= chi2fit / (nptfit-nppar); 
00794         }
00795       }
00796       else {
00797         vminf = 0.;
00798 
00799         if (nptfit <= nppar) chi2fitN4=-1;
00800         else chi2fitN4  = chi2fit / (nptfit-nppar); 
00801       }
00802 
00803       if (fabs(vminf) >= 0.29) {
00804         // for safety and for code construction..dont accept correction on dv/vdrift greater then 0.09
00805         vminf = 0.;
00806         cminf = cminf3;
00807         aminf = aminf3;
00808         bminf = bminf3;
00809         nppar = 3;
00810         chi2fit = chi2fit3;
00811       }
00812 
00813     }  //end if vdrift
00814 
00815      if(!vdrift_4parfit){         //if not required explicitly leave the t0 and track step as at step 3
00816                                   // just update vdrift value vmin for storing in the segments for monitoring
00817        cminf = cminf3;
00818        aminf = aminf3;
00819        bminf = bminf3;
00820        nppar = 3;
00821        chi2fit = chi2fit3;
00822      }
00823 
00824     nppar4 = nppar;
00825 
00826   }  //end nptfit >=3
00827 
00828   if (debug) {
00829     cout << "   dt0= 0 : slope 4  = " << bminf << " pos out = " << aminf <<" chi2fitN4 = " << chi2fitN4
00830          << "  nppar= " << nppar4 << " T0_ev ns= " << cminf/0.00543 <<" delta v = " << vminf <<endl;
00831     cout << nptfit << " nptfit " << " end  chi2fit = " << chi2fit/ (nptfit-nppar ) << " T0_ev ns= " << cminf/0.00543 << " delta v = " << vminf <<endl;
00832   }
00833 
00834   if ( fabs(vminf) >= 0.09 && debug ) {  //checks only vdrift less then 10 % accepted
00835     cout << "vminf gt 0.09 det=  " << endl;
00836     cout << "dt0= 0 : slope 4 = "<< bminf << " pos out = " << aminf << " chi2fitN4 = " << chi2fitN4
00837          << " T0_ev ns = " << cminf/0.00543 << " delta v = "<< vminf << endl;
00838     cout << "dt0 = 0 : slope 2 = "<< b << " pos in = " << a <<" chi2fitN2 = " << chi2fitN2
00839          << " nppar = " << nppar-1 << " nptfit = " << nptfit <<endl;
00840     cout << "dt0 = 0 : slope 3 = " << bminf << " pos out = " << aminf << " chi2fitN3 = "
00841          << chi2fitN3 << " T0_ev ns = " << cminf/0.00543 << endl;
00842     cout << nptfit   <<" nptfit "<< "   end  chi2fit = " << chi2fit << "T0_ev ns= " << cminf/0.00543 << "delta v = "<< vminf <<endl;        
00843   }
00844 
00845   if (nptfit != nppar) chi2fit = chi2fit / (nptfit-nppar);
00846 }