Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:26:09

0001 /** \file
0002  *
0003  * \author Stefano Lacaprara - INFN Legnaro <stefano.lacaprara@pd.infn.it>
0004  * \author Riccardo Bellan - INFN TO <riccardo.bellan@cern.ch>
0005  * \       A.Meneguzzo - Padova University  <anna.meneguzzo@pd.infn.it>
0006  * \       M.Pelliccioni - INFN TO <pellicci@cern.ch>
0007  * \       M.Meneghelli - INFN BO <marco.meneghelli@cern.ch>
0008  */
0009 
0010 /* This Class Header */
0011 #include "RecoLocalMuon/DTSegment/src/DTSegmentUpdator.h"
0012 
0013 /* Collaborating Class Header */
0014 
0015 //mene
0016 #include "DataFormats/DTRecHit/interface/DTChamberRecSegment2D.h"
0017 
0018 #include "DataFormats/DTRecHit/interface/DTRecSegment2D.h"
0019 #include "DataFormats/DTRecHit/interface/DTSLRecSegment2D.h"
0020 #include "DataFormats/DTRecHit/interface/DTChamberRecSegment2D.h"
0021 #include "DataFormats/DTRecHit/interface/DTRecSegment4D.h"
0022 #include "DataFormats/DTRecHit/interface/DTRecHit1D.h"
0023 #include "DataFormats/GeometryCommonDetAlgo/interface/ErrorFrameTransformer.h"
0024 
0025 #include "RecoLocalMuon/DTSegment/src/DTSegmentCand.h"
0026 #include "RecoLocalMuon/DTRecHit/interface/DTRecHitAlgoFactory.h"
0027 #include "RecoLocalMuon/DTSegment/src/DTLinearFit.h"
0028 
0029 #include "Geometry/Records/interface/MuonGeometryRecord.h"
0030 #include "Geometry/DTGeometry/interface/DTGeometry.h"
0031 #include "Geometry/DTGeometry/interface/DTLayer.h"
0032 
0033 #include "FWCore/Utilities/interface/Exception.h"
0034 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0035 #include "FWCore/Framework/interface/EventSetup.h"
0036 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0037 
0038 /* C++ Headers */
0039 #include <string>
0040 
0041 using namespace std;
0042 using namespace edm;
0043 
0044 /* ====================================================================== */
0045 
0046 /// Constructor
0047 DTSegmentUpdator::DTSegmentUpdator(const ParameterSet& config, edm::ConsumesCollector cc)
0048     : theFitter{std::make_unique<DTLinearFit>()},
0049       theAlgo{DTRecHitAlgoFactory::get()->create(
0050           config.getParameter<string>("recAlgo"), config.getParameter<ParameterSet>("recAlgoConfig"), cc)},
0051       theGeomToken(cc.esConsumes()),
0052       vdrift_4parfit(config.getParameter<bool>("performT0_vdriftSegCorrection")),
0053       T0_hit_resolution(config.getParameter<double>("hit_afterT0_resolution")),
0054       perform_delta_rejecting(config.getParameter<bool>("perform_delta_rejecting")),
0055       debug(config.getUntrackedParameter<bool>("debug", false)) {
0056   intime_cut = 20.;
0057   if (config.exists("intime_cut"))
0058     intime_cut = config.getParameter<double>("intime_cut");
0059 
0060   if (debug)
0061     cout << "[DTSegmentUpdator] Constructor called" << endl;
0062 }
0063 
0064 /// Destructor
0065 DTSegmentUpdator::~DTSegmentUpdator() = default;
0066 
0067 /* Operations */
0068 
0069 void DTSegmentUpdator::setES(const EventSetup& setup) {
0070   theGeom = setup.getHandle(theGeomToken);
0071   theAlgo->setES(setup);
0072 }
0073 
0074 void DTSegmentUpdator::update(DTRecSegment4D* seg, const bool calcT0, bool allow3par) const {
0075   if (debug)
0076     cout << "[DTSegmentUpdator] Starting to update the DTRecSegment4D" << endl;
0077 
0078   const bool hasPhi = seg->hasPhi();
0079   const bool hasZed = seg->hasZed();
0080 
0081   //reject the bad hits (due to delta rays)
0082   if (perform_delta_rejecting && hasPhi)
0083     rejectBadHits(seg->phiSegment());
0084 
0085   int step = (hasPhi && hasZed) ? 3 : 2;
0086   if (calcT0)
0087     step = 4;
0088 
0089   if (debug)
0090     cout << "Step of update is " << step << endl;
0091 
0092   GlobalPoint pos = theGeom->idToDet(seg->geographicalId())->toGlobal(seg->localPosition());
0093   GlobalVector dir = theGeom->idToDet(seg->geographicalId())->toGlobal(seg->localDirection());
0094 
0095   if (calcT0)
0096     calculateT0corr(seg);
0097 
0098   if (hasPhi)
0099     updateHits(seg->phiSegment(), pos, dir, step);
0100   if (hasZed)
0101     updateHits(seg->zSegment(), pos, dir, step);
0102 
0103   fit(seg, allow3par);
0104 }
0105 
0106 void DTSegmentUpdator::update(DTRecSegment2D* seg, bool allow3par) const {
0107   if (debug)
0108     cout << "[DTSegmentUpdator] Starting to update the DTRecSegment2D" << endl;
0109   GlobalPoint pos = (theGeom->idToDet(seg->geographicalId()))->toGlobal(seg->localPosition());
0110   GlobalVector dir = (theGeom->idToDet(seg->geographicalId()))->toGlobal(seg->localDirection());
0111 
0112   updateHits(seg, pos, dir);
0113   fit(seg, allow3par, false);
0114 }
0115 
0116 void DTSegmentUpdator::fit(DTRecSegment4D* seg, bool allow3par) const {
0117   if (debug)
0118     cout << "[DTSegmentUpdator] Fit DTRecSegment4D:" << endl;
0119   // after the update must refit the segments
0120 
0121   if (debug) {
0122     if (seg->hasPhi())
0123       cout << "    4D Segment contains a Phi segment. t0= " << seg->phiSegment()->t0()
0124            << "  chi2= " << seg->phiSegment()->chi2() << endl;
0125     if (seg->hasZed())
0126       cout << "    4D Segment contains a Zed segment. t0= " << seg->zSegment()->t0()
0127            << "  chi2= " << seg->zSegment()->chi2() << endl;
0128   }
0129 
0130   // If both phi and zed projections are present and the phi segment is in time (segment t0<intime_cut) the 3-par fit is blocked and
0131   // segments are fit with the 2-par fit. Setting intime_cut to -1 results in the 3-par fit being used always.
0132   if (seg->hasPhi()) {
0133     if (seg->hasZed()) {
0134       if (fabs(seg->phiSegment()->t0()) < intime_cut) {
0135         fit(seg->phiSegment(), allow3par, true);
0136         fit(seg->zSegment(), allow3par, true);
0137       } else {
0138         fit(seg->phiSegment(), allow3par, false);
0139         fit(seg->zSegment(), allow3par, false);
0140       }
0141     } else
0142       fit(seg->phiSegment(), allow3par, false);
0143   } else
0144     fit(seg->zSegment(), allow3par, false);
0145 
0146   const DTChamber* theChamber = theGeom->chamber(seg->chamberId());
0147 
0148   if (seg->hasPhi() && seg->hasZed()) {
0149     DTChamberRecSegment2D* segPhi = seg->phiSegment();
0150     DTSLRecSegment2D* segZed = seg->zSegment();
0151 
0152     // NB Phi seg is already in chamber ref
0153     LocalPoint posPhiInCh = segPhi->localPosition();
0154     LocalVector dirPhiInCh = segPhi->localDirection();
0155 
0156     // Zed seg is in SL one
0157     const DTSuperLayer* zSL = theChamber->superLayer(segZed->superLayerId());
0158     LocalPoint zPos(segZed->localPosition().x(), (zSL->toLocal(theChamber->toGlobal(segPhi->localPosition()))).y(), 0.);
0159 
0160     LocalPoint posZInCh = theChamber->toLocal(zSL->toGlobal(zPos));
0161 
0162     LocalVector dirZInCh = theChamber->toLocal(zSL->toGlobal(segZed->localDirection()));
0163 
0164     LocalPoint posZAt0 = posZInCh + dirZInCh * (-posZInCh.z()) / cos(dirZInCh.theta());
0165 
0166     // given the actual definition of chamber refFrame, (with z poiniting to IP),
0167     // the zed component of direction is negative.
0168     LocalVector dir = LocalVector(dirPhiInCh.x() / fabs(dirPhiInCh.z()), dirZInCh.y() / fabs(dirZInCh.z()), -1.);
0169 
0170     seg->setPosition(LocalPoint(posPhiInCh.x(), posZAt0.y(), 0.));
0171     seg->setDirection(dir.unit());
0172 
0173     AlgebraicSymMatrix mat(4);
0174 
0175     // set cov matrix
0176     mat[0][0] = segPhi->parametersError()[0][0];  //sigma (dx/dz)
0177     mat[0][2] = segPhi->parametersError()[0][1];  //cov(dx/dz,x)
0178     mat[2][2] = segPhi->parametersError()[1][1];  //sigma (x)
0179 
0180     seg->setCovMatrix(mat);
0181     seg->setCovMatrixForZed(posZInCh);
0182   } else if (seg->hasPhi()) {
0183     DTChamberRecSegment2D* segPhi = seg->phiSegment();
0184 
0185     seg->setPosition(segPhi->localPosition());
0186     seg->setDirection(segPhi->localDirection());
0187 
0188     AlgebraicSymMatrix mat(4);
0189     // set cov matrix
0190     mat[0][0] = segPhi->parametersError()[0][0];  //sigma (dx/dz)
0191     mat[0][2] = segPhi->parametersError()[0][1];  //cov(dx/dz,x)
0192     mat[2][2] = segPhi->parametersError()[1][1];  //sigma (x)
0193 
0194     seg->setCovMatrix(mat);
0195   } else if (seg->hasZed()) {
0196     DTSLRecSegment2D* segZed = seg->zSegment();
0197 
0198     // Zed seg is in SL one
0199     GlobalPoint glbPosZ = (theGeom->superLayer(segZed->superLayerId()))->toGlobal(segZed->localPosition());
0200     LocalPoint posZInCh = (theGeom->chamber(segZed->superLayerId().chamberId()))->toLocal(glbPosZ);
0201 
0202     GlobalVector glbDirZ = (theGeom->superLayer(segZed->superLayerId()))->toGlobal(segZed->localDirection());
0203     LocalVector dirZInCh = (theGeom->chamber(segZed->superLayerId().chamberId()))->toLocal(glbDirZ);
0204 
0205     LocalPoint posZAt0 = posZInCh + dirZInCh * (-posZInCh.z()) / cos(dirZInCh.theta());
0206 
0207     seg->setPosition(posZAt0);
0208     seg->setDirection(dirZInCh);
0209 
0210     AlgebraicSymMatrix mat(4);
0211     // set cov matrix
0212     seg->setCovMatrix(mat);
0213     seg->setCovMatrixForZed(posZInCh);
0214   }
0215 }
0216 
0217 bool DTSegmentUpdator::fit(DTSegmentCand* seg, bool allow3par, const bool fitdebug) const {
0218   //  if (debug && fitdebug) cout << "[DTSegmentUpdator] Fit DTRecSegment2D" << endl;
0219   //  if (!seg->good()) return false;
0220 
0221   //  DTSuperLayerId DTid = (DTSuperLayerId)seg->superLayer()->id();
0222   //  if (DTid.superlayer()==2)
0223   //    allow3par = 0;
0224 
0225   vector<float> x;
0226   vector<float> y;
0227   vector<float> sigy;
0228   vector<int> lfit;
0229   vector<double> dist;
0230 
0231   x.reserve(8);
0232   y.reserve(8);
0233   sigy.reserve(8);
0234   lfit.reserve(8);
0235   dist.reserve(8);
0236 
0237   for (DTSegmentCand::AssPointCont::const_iterator iter = seg->hits().begin(); iter != seg->hits().end(); ++iter) {
0238     LocalPoint pos = (*iter).first->localPosition((*iter).second);
0239     float xwire =
0240         (((*iter).first)->localPosition(DTEnums::Left).x() + ((*iter).first)->localPosition(DTEnums::Right).x()) / 2.;
0241     float distance = pos.x() - xwire;
0242 
0243     if ((*iter).second == DTEnums::Left)
0244       lfit.push_back(1);
0245     else
0246       lfit.push_back(-1);
0247 
0248     dist.push_back(distance);
0249     sigy.push_back(sqrt((*iter).first->localPositionError().xx()));
0250     x.push_back(pos.z());
0251     y.push_back(pos.x());
0252   }
0253 
0254   LocalPoint pos;
0255   LocalVector dir;
0256   AlgebraicSymMatrix covMat(2);
0257   float cminf = 0.;
0258   float vminf = 0.;
0259   double chi2 = 0.;
0260   double t0_corr = 0.;
0261 
0262   fit(x, y, lfit, dist, sigy, pos, dir, cminf, vminf, covMat, chi2, allow3par);
0263   if (cminf != 0)
0264     t0_corr = -cminf / 0.00543;  // convert drift distance to time
0265 
0266   if (debug && fitdebug)
0267     cout << "  DTcand chi2: " << chi2 << "/" << x.size() << "   t0: " << t0_corr << endl;
0268 
0269   seg->setPosition(pos);
0270   seg->setDirection(dir);
0271   seg->sett0(t0_corr);
0272   seg->setCovMatrix(covMat);
0273   seg->setChi2(chi2);
0274 
0275   // cout << "pos " << pos << endl;
0276   // cout << "dir " << dir << endl;
0277   // cout << "Mat " << covMat << endl;
0278 
0279   return true;
0280 }
0281 
0282 void DTSegmentUpdator::fit(DTRecSegment2D* seg, bool allow3par, bool block3par) const {
0283   if (debug)
0284     cout << "[DTSegmentUpdator] Fit DTRecSegment2D - 3par: " << allow3par << endl;
0285 
0286   vector<float> x;
0287   vector<float> y;
0288   vector<float> sigy;
0289   vector<int> lfit;
0290   vector<double> dist;
0291   x.reserve(8);
0292   y.reserve(8);
0293   sigy.reserve(8);
0294   lfit.reserve(8);
0295   dist.reserve(8);
0296 
0297   //  DTSuperLayerId DTid = (DTSuperLayerId)seg->geographicalId();
0298   //  if (DTid.superlayer()==2)
0299   //    allow3par = 0;
0300 
0301   vector<DTRecHit1D> hits = seg->specificRecHits();
0302   for (vector<DTRecHit1D>::const_iterator hit = hits.begin(); hit != hits.end(); ++hit) {
0303     // I have to get the hits position (the hit is in the layer rf) in SL frame...
0304     GlobalPoint glbPos = (theGeom->layer(hit->wireId().layerId()))->toGlobal(hit->localPosition());
0305     LocalPoint pos = (theGeom->idToDet(seg->geographicalId()))->toLocal(glbPos);
0306     x.push_back(pos.z());
0307     y.push_back(pos.x());
0308 
0309     const DTLayer* layer = theGeom->layer(hit->wireId().layerId());
0310     float xwire = layer->specificTopology().wirePosition(hit->wireId().wire());
0311     float distance = fabs(hit->localPosition().x() - xwire);
0312     dist.push_back(distance);
0313 
0314     int ilc = (hit->lrSide() == DTEnums::Left) ? 1 : -1;
0315     lfit.push_back(ilc);
0316 
0317     // Get local error in SL frame
0318     //RB: is it right in this way?
0319     ErrorFrameTransformer tran;
0320     GlobalError glbErr =
0321         tran.transform(hit->localPositionError(), (theGeom->layer(hit->wireId().layerId()))->surface());
0322     LocalError slErr = tran.transform(glbErr, (theGeom->idToDet(seg->geographicalId()))->surface());
0323     sigy.push_back(sqrt(slErr.xx()));
0324   }
0325 
0326   LocalPoint pos;
0327   LocalVector dir;
0328   AlgebraicSymMatrix covMat(2);
0329   double chi2 = 0.;
0330   float cminf = 0.;
0331   float vminf = 0.;
0332   double t0_corr = 0.;
0333 
0334   fit(x, y, lfit, dist, sigy, pos, dir, cminf, vminf, covMat, chi2, allow3par, block3par);
0335   if (cminf != 0)
0336     t0_corr = -cminf / 0.00543;  // convert drift distance to time
0337 
0338   if (debug)
0339     cout << "   DTSeg2d chi2: " << chi2 << endl;
0340   if (debug)
0341     cout << "   DTSeg2d Fit t0: " << t0_corr << endl;
0342   // cout << "pos " << segPosition << endl;
0343   // cout << "dir " << segDirection << endl;
0344   // cout << "Mat " << mat << endl;
0345 
0346   seg->setPosition(pos);
0347   seg->setDirection(dir);
0348   seg->setCovMatrix(covMat);
0349   seg->setChi2(chi2);
0350   seg->setT0(t0_corr);
0351 }
0352 
0353 void DTSegmentUpdator::fit(const vector<float>& x,
0354                            const vector<float>& y,
0355                            const vector<int>& lfit,
0356                            const vector<double>& dist,
0357                            const vector<float>& sigy,
0358                            LocalPoint& pos,
0359                            LocalVector& dir,
0360                            float& cminf,
0361                            float& vminf,
0362                            AlgebraicSymMatrix& covMatrix,
0363                            double& chi2,
0364                            const bool allow3par,
0365                            const bool block3par) const {
0366   float slope = 0.;
0367   float intercept = 0.;
0368   float covss = 0.;
0369   float covii = 0.;
0370   float covsi = 0.;
0371 
0372   cminf = 0;
0373   vminf = 0;
0374 
0375   int leftHits = 0, rightHits = 0;
0376   for (unsigned int i = 0; i < lfit.size(); i++)
0377     if (lfit[i] == 1)
0378       leftHits++;
0379     else
0380       rightHits++;
0381 
0382   theFitter->fit(x, y, x.size(), sigy, slope, intercept, chi2, covss, covii, covsi);
0383 
0384   // If we have at least one left and one right hit we can try the 3 parameter fit (if it is switched on)
0385   // FIXME: currently the covariance matrix from the 2-par fit is kept
0386   if (leftHits && rightHits && (leftHits + rightHits > 3) && allow3par) {
0387     theFitter->fitNpar(3, x, y, lfit, dist, sigy, slope, intercept, cminf, vminf, chi2, debug);
0388     double t0_corr = -cminf / 0.00543;
0389     if (fabs(t0_corr) < intime_cut && block3par) {
0390       theFitter->fit(x, y, x.size(), sigy, slope, intercept, chi2, covss, covii, covsi);
0391       cminf = 0;
0392     }
0393   }
0394 
0395   // cout << "slope " << slope << endl;
0396   // cout << "intercept " << intercept << endl;
0397 
0398   // intercept is the x() in chamber frame when the segment cross the chamber
0399   // plane (at z()=0), the y() is not measured, so let's put the center of the
0400   // chamber.
0401   pos = LocalPoint(intercept, 0., 0.);
0402 
0403   //  slope is dx()/dz(), while dy()/dz() is by definition 0, finally I want the
0404   //  segment to point outward, so opposite to local z
0405   dir = LocalVector(-slope, 0., -1.).unit();
0406 
0407   covMatrix = AlgebraicSymMatrix(2);
0408   covMatrix[0][0] = covss;  // this is var(dy/dz)
0409   covMatrix[1][1] = covii;  // this is var(y)
0410   covMatrix[1][0] = covsi;  // this is cov(dy/dz,y)
0411 }
0412 
0413 // The GlobalPoint and the GlobalVector can be either the glb position and the direction
0414 // of the 2D-segment itself or the glb position and direction of the 4D segment
0415 void DTSegmentUpdator::updateHits(DTRecSegment2D* seg, GlobalPoint& gpos, GlobalVector& gdir, const int step) const {
0416   // it is not necessary to have DTRecHit1D* to modify the obj in the container
0417   // but I have to be carefully, since I cannot make a copy before the iteration!
0418 
0419   vector<DTRecHit1D> toBeUpdatedRecHits = seg->specificRecHits();
0420   vector<DTRecHit1D> updatedRecHits;
0421 
0422   for (vector<DTRecHit1D>::iterator hit = toBeUpdatedRecHits.begin(); hit != toBeUpdatedRecHits.end(); ++hit) {
0423     const DTLayer* layer = theGeom->layer(hit->wireId().layerId());
0424 
0425     LocalPoint segPos = layer->toLocal(gpos);
0426     LocalVector segDir = layer->toLocal(gdir);
0427 
0428     // define impact angle needed by the step 2
0429     const float angle = atan(segDir.x() / -segDir.z());
0430 
0431     // define the local position (extr.) of the segment. Needed by the third step
0432     LocalPoint segPosAtLayer = segPos + segDir * (-segPos.z()) / cos(segDir.theta());
0433 
0434     DTRecHit1D newHit1D = (*hit);
0435     bool ok = true;
0436 
0437     if (step == 2) {
0438       ok = theAlgo->compute(layer, *hit, angle, newHit1D);
0439 
0440     } else if (step == 3) {
0441       LocalPoint hitPos(hit->localPosition().x(), +segPosAtLayer.y(), 0.);
0442       GlobalPoint glbpos = theGeom->layer(hit->wireId().layerId())->toGlobal(hitPos);
0443       newHit1D.setPosition(hitPos);
0444       ok = theAlgo->compute(layer, *hit, angle, glbpos, newHit1D);
0445 
0446     } else if (step == 4) {
0447       //const double vminf = seg->vDrift();   //  vdrift correction are recorded in the segment
0448       double vminf = 0.;
0449       if (vdrift_4parfit)
0450         vminf = seg->vDrift();  // use vdrift recorded in the segment only if vdrift_4parfit=True
0451 
0452       double cminf = 0.;
0453       if (seg->ist0Valid())
0454         cminf = -seg->t0() * 0.00543;
0455 
0456       //cout << "In updateHits: t0 = " << seg->t0() << endl;
0457       //cout << "In updateHits: vminf = " << vminf << endl;
0458       //cout << "In updateHits: cminf = " << cminf << endl;
0459 
0460       const float xwire = layer->specificTopology().wirePosition(hit->wireId().wire());
0461       const float distance = fabs(hit->localPosition().x() - xwire);
0462       const int ilc = (hit->lrSide() == DTEnums::Left) ? 1 : -1;
0463       const double dy_corr = (vminf * ilc * distance - cminf * ilc);
0464 
0465       LocalPoint point(hit->localPosition().x() + dy_corr, +segPosAtLayer.y(), 0.);
0466 
0467       //double final_hit_resol = T0_hit_resolution;
0468       //if(newHit1D.wireId().layerId().superlayerId().superLayer() != 2) final_hit_resol = final_hit_resol * 0.8;
0469       //LocalError error(final_hit_resol * final_hit_resol,0.,0.);
0470       LocalError error(T0_hit_resolution * T0_hit_resolution, 0., 0.);
0471       newHit1D.setPositionAndError(point, error);
0472 
0473       //FIXME: check that the hit is still inside the cell
0474       ok = true;
0475 
0476     } else
0477       throw cms::Exception("DTSegmentUpdator") << " updateHits called with wrong step " << endl;
0478 
0479     if (ok)
0480       updatedRecHits.push_back(newHit1D);
0481     else {
0482       LogError("DTSegmentUpdator") << "DTSegmentUpdator::updateHits failed update" << endl;
0483       throw cms::Exception("DTSegmentUpdator") << "updateHits failed update" << endl;
0484     }
0485   }
0486   seg->update(updatedRecHits);
0487 }
0488 
0489 void DTSegmentUpdator::rejectBadHits(DTChamberRecSegment2D* phiSeg) const {
0490   vector<float> x;
0491   vector<float> y;
0492 
0493   if (debug)
0494     cout << " Inside the segment updator, now loop on hits:   ( x == z_loc , y == x_loc) " << endl;
0495 
0496   vector<DTRecHit1D> hits = phiSeg->specificRecHits();
0497   const size_t N = hits.size();
0498   if (N < 3)
0499     return;
0500 
0501   for (vector<DTRecHit1D>::const_iterator hit = hits.begin(); hit != hits.end(); ++hit) {
0502     // I have to get the hits position (the hit is in the layer rf) in SL frame...
0503     GlobalPoint glbPos = (theGeom->layer(hit->wireId().layerId()))->toGlobal(hit->localPosition());
0504     LocalPoint pos = (theGeom->idToDet(phiSeg->geographicalId()))->toLocal(glbPos);
0505 
0506     x.push_back(pos.z());
0507     y.push_back(pos.x());
0508   }
0509 
0510   if (debug) {
0511     cout << " end of segment! " << endl;
0512     cout << " size = Number of Hits: " << x.size() << "  " << y.size() << endl;
0513   }
0514 
0515   // Perform the 2 par fit:
0516   float par[2] = {0., 0.};  // q , m
0517 
0518   //variables to perform the fit:
0519   float Sx = 0.;
0520   float Sy = 0.;
0521   float Sx2 = 0.;
0522   float Sxy = 0.;
0523 
0524   for (size_t i = 0; i < N; ++i) {
0525     Sx += x.at(i);
0526     Sy += y.at(i);
0527     Sx2 += x.at(i) * x.at(i);
0528     Sxy += x.at(i) * y.at(i);
0529   }
0530 
0531   const float delta = N * Sx2 - Sx * Sx;
0532   par[0] = (Sx2 * Sy - Sx * Sxy) / delta;
0533   par[1] = (N * Sxy - Sx * Sy) / delta;
0534 
0535   if (debug)
0536     cout << "fit 2 parameters done ----> par0: " << par[0] << "  par1: " << par[1] << endl;
0537 
0538   // Calc residuals:
0539   float residuals[N];
0540   float mean_residual = 0.;  //mean of the absolute values of residuals
0541   for (size_t i = 0; i < N; ++i) {
0542     residuals[i] = y.at(i) - par[1] * x.at(i) - par[0];
0543     mean_residual += std::abs(residuals[i]);
0544     if (debug) {
0545       cout << " i: " << i << " y_i " << y.at(i) << " x_i " << x.at(i) << " res_i " << residuals[i];
0546       if (i == N - 1)
0547         cout << endl;
0548     }
0549   }
0550 
0551   if (debug)
0552     cout << " Residuals computed! " << endl;
0553 
0554   mean_residual = mean_residual / (N - 2);
0555   if (debug)
0556     cout << " mean_residual: " << mean_residual << endl;
0557 
0558   int i = 0;
0559 
0560   // Perform bad hit rejecting -- update hits
0561   vector<DTRecHit1D> updatedRecHits;
0562   for (vector<DTRecHit1D>::const_iterator hit = hits.begin(); hit != hits.end(); ++hit) {
0563     float normResidual = mean_residual > 0 ? std::abs(residuals[i]) / mean_residual : 0;
0564     ++i;
0565     if (normResidual < 1.5) {
0566       const DTRecHit1D& newHit1D = (*hit);
0567       updatedRecHits.push_back(newHit1D);
0568       if (debug)
0569         cout << " accepted " << i << "th hit"
0570              << "  Irej: " << normResidual << endl;
0571     } else {
0572       if (debug)
0573         cout << " rejected " << i << "th hit"
0574              << "  Irej: " << normResidual << endl;
0575       continue;
0576     }
0577   }
0578 
0579   phiSeg->update(updatedRecHits);
0580 
0581   //final check!
0582   if (debug) {
0583     vector<float> x_upd;
0584     vector<float> y_upd;
0585 
0586     cout << " Check the update action: " << endl;
0587 
0588     vector<DTRecHit1D> hits_upd = phiSeg->specificRecHits();
0589     for (vector<DTRecHit1D>::const_iterator hit = hits_upd.begin(); hit != hits_upd.end(); ++hit) {
0590       // I have to get the hits position (the hit is in the layer rf) in SL frame...
0591       GlobalPoint glbPos = (theGeom->layer(hit->wireId().layerId()))->toGlobal(hit->localPosition());
0592       LocalPoint pos = (theGeom->idToDet(phiSeg->geographicalId()))->toLocal(glbPos);
0593 
0594       x_upd.push_back(pos.z());
0595       y_upd.push_back(pos.x());
0596 
0597       cout << " x_upd: " << pos.z() << "  y_upd: " << pos.x() << endl;
0598     }
0599 
0600     cout << " end of segment! " << endl;
0601     cout << " size = Number of Hits: " << x_upd.size() << "  " << y_upd.size() << endl;
0602 
0603   }  // end debug
0604 
0605   return;
0606 }  //end DTSegmentUpdator::rejectBadHits
0607 
0608 void DTSegmentUpdator::calculateT0corr(DTRecSegment4D* seg) const {
0609   if (seg->hasPhi())
0610     calculateT0corr(seg->phiSegment());
0611   if (seg->hasZed())
0612     calculateT0corr(seg->zSegment());
0613 }
0614 
0615 void DTSegmentUpdator::calculateT0corr(DTRecSegment2D* seg) const {
0616   // WARNING: since this method is called both with a 2D and a 2DPhi as argument
0617   // seg->geographicalId() can be a superLayerId or a chamberId
0618   if (debug)
0619     cout << "[DTSegmentUpdator] CalculateT0corr DTRecSegment4D" << endl;
0620 
0621   vector<double> d_drift;
0622   vector<float> x;
0623   vector<float> y;
0624   vector<int> lc;
0625 
0626   vector<DTRecHit1D> hits = seg->specificRecHits();
0627 
0628   DTWireId wireId;
0629   int nptfit = 0;
0630 
0631   for (vector<DTRecHit1D>::const_iterator hit = hits.begin(); hit != hits.end(); ++hit) {
0632     // I have to get the hits position (the hit is in the layer rf) in SL frame...
0633     GlobalPoint glbPos = (theGeom->layer(hit->wireId().layerId()))->toGlobal(hit->localPosition());
0634     LocalPoint pos = (theGeom->idToDet(seg->geographicalId()))->toLocal(glbPos);
0635 
0636     const DTLayer* layer = theGeom->layer(hit->wireId().layerId());
0637     float xwire = layer->specificTopology().wirePosition(hit->wireId().wire());
0638     float distance = fabs(hit->localPosition().x() - xwire);
0639 
0640     int ilc = (hit->lrSide() == DTEnums::Left) ? 1 : -1;
0641 
0642     nptfit++;
0643     x.push_back(pos.z());
0644     y.push_back(pos.x());
0645     lc.push_back(ilc);
0646     d_drift.push_back(distance);
0647 
0648     // cout << " d_drift "<<distance  <<" npt= " <<npt<<endl;
0649   }
0650 
0651   double chi2fit = 0.;
0652   float cminf = 0.;
0653   float vminf = 0.;
0654   float a, b;
0655 
0656   if (nptfit > 2) {
0657     //NB chi2fit is normalized
0658     theFitter->fit4Var(x, y, lc, d_drift, nptfit, a, b, cminf, vminf, chi2fit, vdrift_4parfit, debug);
0659 
0660     double t0cor = -999.;
0661     if (cminf > -998.)
0662       t0cor = -cminf / 0.00543;  // in ns
0663 
0664     //cout << "In calculateT0corr: t0 = " << t0cor << endl;
0665     //cout << "In calculateT0corr: vminf = " << vminf << endl;
0666     //cout << "In calculateT0corr: cminf = " << cminf << endl;
0667     //cout << "In calculateT0corr: chi2 = " << chi2fit << endl;
0668 
0669     seg->setT0(t0cor);      // time  and
0670     seg->setVdrift(vminf);  //  vdrift correction are recorded in the segment
0671   }
0672 }