CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/RecoLocalMuon/DTSegment/src/DTSegmentUpdator.cc

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