CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/RecoLocalMuon/DTRecHit/plugins/DTParametrizedDriftAlgo.cc

Go to the documentation of this file.
00001 /*
00002  *  See header file for a description of this class.
00003  *
00004  *  $Date: 2009/04/30 09:30:07 $
00005  *  $Revision: 1.3 $
00006  *  \author G. Cerminara - INFN Torino
00007  */
00008 
00009 #include "RecoLocalMuon/DTRecHit/plugins/DTParametrizedDriftAlgo.h"
00010 #include "CalibMuon/DTDigiSync/interface/DTTTrigBaseSync.h"
00011 #include "RecoLocalMuon/DTRecHit/plugins/DTTime2DriftParametrization.h"
00012 
00013 #include "DataFormats/MuonDetId/interface/DTWireId.h"
00014 #include "Geometry/DTGeometry/interface/DTLayer.h"
00015 
00016 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00017 #include "MagneticField/Engine/interface/MagneticField.h"
00018 
00019 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00020 #include "FWCore/Framework/interface/ESHandle.h"
00021 #include "FWCore/Framework/interface/EventSetup.h"
00022 
00023 #include <iostream>
00024 #include <iomanip>
00025 
00026 using namespace std;
00027 using namespace edm;
00028 
00029 
00030 DTParametrizedDriftAlgo::DTParametrizedDriftAlgo(const ParameterSet& config) :
00031   DTRecHitBaseAlgo(config) {
00032     interpolate = config.getParameter<bool>("interpolate");
00033 
00034     minTime = config.getParameter<double>("minTime"); // FIXME: Default was -3 ns
00035 
00036     maxTime = config.getParameter<double>("maxTime"); // FIXME: Default was 415 ns
00037 
00038     // Set verbose output
00039     debug = config.getUntrackedParameter<bool>("debug","false");
00040     
00041   }
00042 
00043 
00044 
00045 DTParametrizedDriftAlgo::~DTParametrizedDriftAlgo(){}
00046 
00047 
00048 
00049 void DTParametrizedDriftAlgo::setES(const EventSetup& setup) {
00050   theSync->setES(setup);
00051   // Access the magnetic field
00052   ESHandle<MagneticField> magneticField;
00053   setup.get<IdealMagneticFieldRecord>().get(magneticField);
00054   magField = &*magneticField;
00055 }
00056 
00057 
00058 
00059 // First Step
00060 bool DTParametrizedDriftAlgo::compute(const DTLayer* layer,
00061                                       const DTDigi& digi,
00062                                       LocalPoint& leftPoint,
00063                                       LocalPoint& rightPoint,
00064                                       LocalError& error) const {
00065   // Get the layerId
00066   DTLayerId layerId = layer->id();//FIXME: pass it instead of get it from layer
00067   const DTWireId wireId(layerId, digi.wire());
00068   
00069   // Get Wire position
00070   if(!layer->specificTopology().isWireValid(wireId.wire())) return false;
00071   LocalPoint locWirePos(layer->specificTopology().wirePosition(wireId.wire()), 0, 0);
00072   const GlobalPoint globWirePos = layer->toGlobal(locWirePos);
00073   
00074   // impact angle on DT chamber
00075   // compute the impact angle using the centre of the wire,
00076   // only for RZ superlayer (eta). In the other cases theta is very close to 0.
00077   float angle=0.0;    
00078 
00079   if (layerId.superlayer() == 2 ) {
00080     //GlobalPoint lPos=layer->position();
00081     GlobalVector lDir=(GlobalPoint()-globWirePos).unit();
00082     LocalVector lDirLoc=layer->toLocal(lDir);
00083 
00084     angle = atan(lDirLoc.x()/-lDirLoc.z());
00085   } 
00086   
00087   return compute(layer, wireId, digi.time(), angle, globWirePos,
00088                  leftPoint, rightPoint, error, 1);
00089 }
00090 
00091 
00092 
00093 // Second step
00094 bool DTParametrizedDriftAlgo::compute(const DTLayer* layer,
00095                                       const DTRecHit1D& recHit1D,
00096                                       const float& angle,
00097                                       DTRecHit1D& newHit1D) const {
00098   const DTWireId wireId = recHit1D.wireId();
00099   
00100   // Get Wire position
00101   if(!layer->specificTopology().isWireValid(wireId.wire())) return false;
00102   LocalPoint locWirePos(layer->specificTopology().wirePosition(wireId.wire()), 0, 0);
00103   const GlobalPoint globWirePos = layer->toGlobal(locWirePos);
00104 
00105   return compute(layer, wireId, recHit1D.digiTime(), angle, globWirePos,
00106                  newHit1D, 2);
00107 }
00108 
00109 
00110 
00111 // Third step
00112 bool DTParametrizedDriftAlgo::compute(const DTLayer* layer,
00113                                       const DTRecHit1D& recHit1D,
00114                                       const float& angle,
00115                                       const GlobalPoint& globPos, 
00116                                       DTRecHit1D& newHit1D) const {
00117   return compute(layer, recHit1D.wireId(), recHit1D.digiTime(), angle,
00118                  globPos, newHit1D, 3);
00119 }
00120 
00121 
00122 
00123 // Do the actual work.
00124 bool DTParametrizedDriftAlgo::compute(const DTLayer* layer,
00125                                       const DTWireId& wireId,
00126                                       const float digiTime,
00127                                       const float& angle,
00128                                       const GlobalPoint& globPos, 
00129                                       LocalPoint& leftPoint,
00130                                       LocalPoint& rightPoint,
00131                                       LocalError& error,
00132                                       int step) const {
00133   // Subtract Offset according to DTTTrigBaseSync concrete instance
00134   // chosen with the 'tZeroMode' parameter
00135   float driftTime = digiTime - theSync->offset(layer, wireId, globPos);
00136 
00137   // check for out-of-time only at step 1
00138   if (step==1 && (driftTime < minTime || driftTime > maxTime)) {
00139     if (debug)
00140       cout << "*** Drift time out of window for in-time hits "
00141            << driftTime << endl;
00142 
00143     if(step == 1) { //FIXME: protection against failure at 2nd and 3rd steps, must be checked!!!
00144       // Hits are interpreted as coming from out-of-time pile-up and recHit
00145       // is ignored.
00146       return false;
00147     }
00148   }
00149   
00150   // Small negative times interpreted as hits close to the wire.
00151   if (driftTime<0.) driftTime=0;
00152 
00153   //----------------------------------------------------------------------
00154   // Magnetic Field in layer frame
00155   const LocalVector BLoc =
00156     layer->toLocal(magField->inTesla(globPos));
00157 
00158   float By = BLoc.y();
00159   float Bz = BLoc.z();  
00160 
00161   //--------------------------------------------------------------------
00162   // Calculate the drift distance and the resolution from the parametrization
00163   
00164   DTTime2DriftParametrization::drift_distance DX;
00165   static DTTime2DriftParametrization par;
00166 
00167   bool parStatus =
00168     par.computeDriftDistance_mean(driftTime, angle, By, Bz, interpolate, &DX);
00169 
00170   if (!parStatus) {
00171     if (debug)
00172       cout << "[DTParametrizedDriftAlgo]*** WARNING: call to parametrization failed" << endl;
00173     return false;
00174   }
00175 
00176   float sigma_l = DX.x_width_m;
00177   float sigma_r = DX.x_width_p;
00178   float drift = DX.x_drift;
00179 
00180 
00181   float reso = 0;
00182 
00183   bool variableSigma = false;
00184   // By defualt the errors are obtained from a fit of the residuals in the various
00185   // stations/SL.
00186   // The error returned by DTTime2DriftParametrization can not be used easily
00187   // to determine the hit error due to the way the parametrization of the error
00188   // is done (please contcat the authors for details).
00189   // Anyhow changing variableSigma==true, an attempt is done to set a variable error
00190   // according to the sigma calculated by DTTime2DriftParametrization.
00191   // Additionally, contributions from uncertaionties in TOF and signal propagation
00192   // corrections are added.
00193   // Uncertainty in the determination of incident angle and hit position
00194   // (ie B value) are NOT accounted.
00195   // This is not the default since it does not give good results...
00196 
00197   int wheel = abs(wireId.wheel());
00198   if (variableSigma) {
00199     float sTDelays=0;
00200     if (step==1) {               // 1. step
00201       reso = (sigma_l+sigma_r)/2.; // FIXME: theta/B are not yet known...
00202       if (wireId.superlayer()==2) {    // RZ
00203         sTDelays = 2.92;
00204       } else {                   // RPhi
00205         if (wheel==0) {
00206           sTDelays = 2.74;
00207         } else if (wheel==1) {
00208           sTDelays = 1.83;
00209         } else if (wheel==2){
00210           sTDelays = 1.25;
00211         }
00212       } 
00213     } else if (step==2) {        // 2. step
00214       reso = (sigma_l+sigma_r)/2.; // FIXME: B is not yet known...
00215       if (wireId.superlayer()==2) {    // RZ
00216         sTDelays = 0.096;
00217       } else {                   // RPhi
00218         if (wheel==0) {
00219           sTDelays = 0.022;
00220         } else if (wheel==1) {
00221           sTDelays = 0.079;
00222         } else if (wheel==2){
00223           sTDelays = 0.124;
00224         }
00225       }      
00226     } else if (step==3) {        // 3. step
00227       reso = (sigma_l+sigma_r)/2.;
00228       if (wireId.superlayer()==2) {    // RZ
00229         sTDelays = 0.096;
00230       } else {                   // RPhi
00231         if (wheel==0) {
00232           sTDelays = 0.022;
00233         } else if (wheel==1) {
00234           sTDelays = 0.079;
00235         } else if (wheel==2){
00236           sTDelays = 0.124;
00237         }
00238       }
00239     }
00240     float sXDelays = sTDelays*DX.v_drift/10.; 
00241     reso = sqrt(reso*reso + sXDelays*sXDelays);
00242   } else { // Use a fixed sigma, from fit of residuals.
00243     if (step==1) {     // 1. step
00244       if (wireId.superlayer()==2) {     
00245         if (wheel==0) {
00246           reso = 0.0250;
00247         } else if (wheel==1) {
00248           reso = 0.0271;
00249         } else if (wheel==2){
00250           reso = 0.0308;
00251         }
00252       } else {
00253         reso = 0.0237;
00254       }
00255     } else if (step==2) {                  // 2. step //FIXME
00256       if (wireId.superlayer()==2) {
00257         if (wheel==0) {
00258           reso = 0.0250;
00259         } else if (wheel==1) {
00260           reso = 0.0271;
00261         } else if (wheel==2){
00262           reso = 0.0305;
00263         }
00264       } else {
00265         reso = 0.0231;
00266       }
00267     } else if (step==3) {                  // 3. step
00268       if (wireId.superlayer()==2) {
00269         if (wheel==0) {
00270           reso = 0.0196;
00271         } else if (wheel==1) {
00272           reso = 0.0210;
00273         } else if (wheel==2){
00274           reso = 0.0228;
00275         }
00276       } else {
00277         reso = 0.0207;
00278       }
00279     }
00280   }
00281   //--------------------------------------------------------------------
00282 
00283   error = LocalError(reso*reso,0.,0.);
00284 
00285   // Get Wire position
00286   if(!layer->specificTopology().isWireValid(wireId.wire())) return false;
00287   LocalPoint locWirePos(layer->specificTopology().wirePosition(wireId.wire()), 0, 0);
00288 
00289   //Build the two possible points and the error on the position
00290   leftPoint  = LocalPoint(locWirePos.x()-drift,
00291                           locWirePos.y(),
00292                           locWirePos.z());
00293   rightPoint = LocalPoint(locWirePos.x()+drift,
00294                           locWirePos.y(),
00295                           locWirePos.z());
00296 
00297   if (debug) {
00298     int prevW = cout.width();
00299     cout << setiosflags(ios::showpoint | ios::fixed) << setw(3)
00300          << "[DTParametrizedDriftAlgo]: step " << step << endl
00301          << "  Global Position  " << globPos << endl
00302          << "  Local Position   " << layer->toLocal(globPos) << endl
00303       //          << "  y along Wire     " << wireCoord << endl
00304          << "  Digi time        " << digiTime << endl
00305       //          << "  dpropDelay       " << propDelay << endl
00306       //          << "  deltaTOF         " << deltaTOF << endl
00307          << " >Drif time        " << driftTime << endl
00308          << " >Angle            " << angle * 180./M_PI << endl
00309          << " <Drift distance   " << drift << endl
00310          << " <sigma_l          " << sigma_l << endl
00311          << " <sigma_r          " << sigma_r << endl
00312          << "  reso             " << reso << endl
00313          << "  leftPoint        " << leftPoint << endl
00314          << "  rightPoint       " << rightPoint << endl
00315          << "  error            " << error
00316          <<  resetiosflags(ios::showpoint | ios::fixed)  << setw(prevW) << endl 
00317          << endl;  
00318   }
00319 
00320   return true;
00321 }
00322 
00323 
00324 // Interface to the method which does the actual work suited for 2nd and 3rd steps 
00325 bool DTParametrizedDriftAlgo::compute(const DTLayer* layer,
00326                                       const DTWireId& wireId,
00327                                       const float digiTime,
00328                                       const float& angle,
00329                                       const GlobalPoint& globPos, 
00330                                       DTRecHit1D& newHit1D,
00331                                       int step) const {
00332   LocalPoint leftPoint;
00333   LocalPoint rightPoint;
00334   LocalError error;
00335     
00336   if(compute(layer, wireId, digiTime, angle, globPos, leftPoint, rightPoint, error, step)) {
00337     // Set the position and the error of the rechit which is being updated
00338     switch(newHit1D.lrSide()) {
00339         
00340     case DTEnums::Left:
00341         {
00342           // Keep the original y position of newHit1D: for step==3, it's the
00343           // position along the wire. Needed for rotation alignment
00344           LocalPoint leftPoint3D(leftPoint.x(), newHit1D.localPosition().y(), leftPoint.z());
00345           newHit1D.setPositionAndError(leftPoint3D, error);
00346           break;
00347         }
00348         
00349     case DTEnums::Right:
00350         {
00351           // as above: 3d position
00352           LocalPoint rightPoint3D(rightPoint.x(), newHit1D.localPosition().y(), rightPoint.z());
00353           newHit1D.setPositionAndError(rightPoint3D, error);
00354           break;
00355         }
00356         
00357     default:
00358       throw cms::Exception("InvalidDTCellSide") << "[DTParametrizedDriftAlgo] Compute at Step "
00359                                                 << step << ", Hit side "
00360                                                 << newHit1D.lrSide()
00361                                                 << " is invalid!" << endl;
00362       return false;
00363     }
00364       
00365     return true;
00366   }else {
00367     return false;
00368   }
00369 }
00370 
00371 
00372 bool DTParametrizedDriftAlgo::interpolate;
00373 
00374 
00375 float DTParametrizedDriftAlgo::minTime;
00376 
00377   
00378 float DTParametrizedDriftAlgo::maxTime;
00379 
00380   
00381 bool DTParametrizedDriftAlgo::debug;