CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/src/RecoMuon/MuonIdentification/src/DTTimingExtractor.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    MuonIdentification
00004 // Class:      DTTimingExtractor
00005 // 
00011 //
00012 // Original Author:  Traczyk Piotr
00013 //         Created:  Thu Oct 11 15:01:28 CEST 2007
00014 // $Id: DTTimingExtractor.cc,v 1.10 2010/12/15 11:07:40 ptraczyk Exp $
00015 //
00016 //
00017 
00018 #include "RecoMuon/MuonIdentification/interface/DTTimingExtractor.h"
00019 
00020 
00021 // user include files
00022 #include "FWCore/Framework/interface/Frameworkfwd.h"
00023 #include "FWCore/Framework/interface/EDProducer.h"
00024 
00025 #include "FWCore/Framework/interface/Event.h"
00026 #include "FWCore/Framework/interface/MakerMacros.h"
00027 
00028 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00029 
00030 #include "RecoMuon/TrackingTools/interface/MuonServiceProxy.h"
00031 
00032 #include "Geometry/Records/interface/MuonGeometryRecord.h"
00033 #include "DataFormats/MuonDetId/interface/MuonSubdetId.h"
00034 #include "Geometry/DTGeometry/interface/DTGeometry.h"
00035 #include "Geometry/DTGeometry/interface/DTLayer.h"
00036 #include "Geometry/DTGeometry/interface/DTChamber.h"
00037 #include "Geometry/DTGeometry/interface/DTSuperLayer.h"
00038 #include "DataFormats/DTRecHit/interface/DTSLRecSegment2D.h"
00039 #include "DataFormats/DTRecHit/interface/DTRecSegment2D.h"
00040 
00041 #include "Geometry/Records/interface/GlobalTrackingGeometryRecord.h"
00042 #include "Geometry/CommonDetUnit/interface/GlobalTrackingGeometry.h"
00043 #include "TrackingTools/Records/interface/TrackingComponentsRecord.h"
00044 
00045 #include "DataFormats/MuonReco/interface/Muon.h"
00046 #include "DataFormats/MuonReco/interface/MuonFwd.h"
00047 #include "DataFormats/DTRecHit/interface/DTRecSegment2D.h"
00048 #include "DataFormats/DTRecHit/interface/DTRecSegment4DCollection.h"
00049 #include "DataFormats/DTRecHit/interface/DTRecSegment2DCollection.h"
00050 #include "DataFormats/TrackingRecHit/interface/TrackingRecHitFwd.h"
00051 #include "RecoMuon/TransientTrackingRecHit/interface/MuonTransientTrackingRecHit.h"
00052 
00053 #include "DataFormats/TrackReco/interface/Track.h"
00054 #include "DataFormats/TrackReco/interface/TrackFwd.h"
00055 #include "DataFormats/TrackReco/interface/TrackExtra.h"
00056 #include "DataFormats/TrackReco/interface/TrackExtraFwd.h"
00057 
00058 
00059 // system include files
00060 #include <memory>
00061 #include <vector>
00062 #include <string>
00063 #include <iostream>
00064 
00065 namespace edm {
00066   class ParameterSet;
00067   class EventSetup;
00068   class InputTag;
00069 }
00070 
00071 class MuonServiceProxy;
00072 
00073 //
00074 // constructors and destructor
00075 //
00076 DTTimingExtractor::DTTimingExtractor(const edm::ParameterSet& iConfig)
00077   :
00078   DTSegmentTags_(iConfig.getParameter<edm::InputTag>("DTsegments")),
00079   theHitsMin_(iConfig.getParameter<int>("HitsMin")),
00080   thePruneCut_(iConfig.getParameter<double>("PruneCut")),
00081   theTimeOffset_(iConfig.getParameter<double>("DTTimeOffset")),
00082   useSegmentT0_(iConfig.getParameter<bool>("UseSegmentT0")),
00083   doWireCorr_(iConfig.getParameter<bool>("DoWireCorr")),
00084   requireBothProjections_(iConfig.getParameter<bool>("RequireBothProjections")),
00085   debug(iConfig.getParameter<bool>("debug"))
00086 {
00087   edm::ParameterSet serviceParameters = iConfig.getParameter<edm::ParameterSet>("ServiceParameters");
00088   theService = new MuonServiceProxy(serviceParameters);
00089   
00090   edm::ParameterSet matchParameters = iConfig.getParameter<edm::ParameterSet>("MatchParameters");
00091 
00092   theMatcher = new MuonSegmentMatcher(matchParameters, theService);
00093 }
00094 
00095 
00096 DTTimingExtractor::~DTTimingExtractor()
00097 {
00098   if (theService) delete theService;
00099   if (theMatcher) delete theMatcher;
00100 }
00101 
00102 
00103 //
00104 // member functions
00105 //
00106 
00107 // ------------ method called to produce the data  ------------
00108 void
00109 DTTimingExtractor::fillTiming(TimeMeasurementSequence &tmSequence, reco::TrackRef muonTrack, const edm::Event& iEvent, const edm::EventSetup& iSetup)
00110 {
00111 
00112 //  using reco::TrackCollection;
00113 
00114   if (debug) 
00115     std::cout << " *** Muon Timimng Extractor ***" << std::endl;
00116 
00117   theService->update(iSetup);
00118 
00119   const GlobalTrackingGeometry *theTrackingGeometry = &*theService->trackingGeometry();
00120 
00121   // get the DT geometry
00122   edm::ESHandle<DTGeometry> theDTGeom;
00123   iSetup.get<MuonGeometryRecord>().get(theDTGeom);
00124   
00125   edm::ESHandle<Propagator> propagator;
00126   iSetup.get<TrackingComponentsRecord>().get("SteppingHelixPropagatorAny", propagator);
00127   const Propagator *propag = propagator.product();
00128 
00129   double invbeta=0;
00130   double invbetaerr=0;
00131   int totalWeight=0;
00132   std::vector<TimeMeasurement> tms;
00133 
00134   math::XYZPoint  pos=muonTrack->innerPosition();
00135   math::XYZVector mom=muonTrack->innerMomentum();
00136   GlobalPoint  posp(pos.x(), pos.y(), pos.z());
00137   GlobalVector momv(mom.x(), mom.y(), mom.z());
00138   FreeTrajectoryState muonFTS(posp, momv, (TrackCharge)muonTrack->charge(), theService->magneticField().product());
00139 
00140   // get the DT segments that were used to construct the muon
00141   std::vector<const DTRecSegment4D*> range = theMatcher->matchDT(*muonTrack,iEvent);
00142 
00143   // create a collection on TimeMeasurements for the track        
00144   for (std::vector<const DTRecSegment4D*>::iterator rechit = range.begin(); rechit!=range.end();++rechit) {
00145 
00146     // Create the ChamberId
00147     DetId id = (*rechit)->geographicalId();
00148     DTChamberId chamberId(id.rawId());
00149     int station = chamberId.station();
00150 
00151     // use only segments with both phi and theta projections present (optional)
00152     bool bothProjections = ( ((*rechit)->hasPhi()) && ((*rechit)->hasZed()) );
00153     if (requireBothProjections_ && !bothProjections) continue;
00154 
00155     // loop over (theta, phi) segments
00156     for (int phi=0; phi<2; phi++) {
00157 
00158       const DTRecSegment2D* segm;
00159       if (phi) segm = dynamic_cast<const DTRecSegment2D*>((*rechit)->phiSegment()); 
00160         else segm = dynamic_cast<const DTRecSegment2D*>((*rechit)->zSegment());
00161 
00162       if(segm == 0) continue;
00163       if (!segm->specificRecHits().size()) continue;
00164 
00165       const GeomDet* geomDet = theTrackingGeometry->idToDet(segm->geographicalId());
00166       const std::vector<DTRecHit1D> hits1d = segm->specificRecHits();
00167 
00168       // store all the hits from the segment
00169       for (std::vector<DTRecHit1D>::const_iterator hiti=hits1d.begin(); hiti!=hits1d.end(); hiti++) {
00170 
00171         const GeomDet* dtcell = theTrackingGeometry->idToDet(hiti->geographicalId());
00172         TimeMeasurement thisHit;
00173 
00174         std::pair< TrajectoryStateOnSurface, double> tsos;
00175         tsos=propag->propagateWithPath(muonFTS,dtcell->surface());
00176 
00177         double dist;            
00178         if (tsos.first.isValid()) dist = tsos.second+posp.mag(); 
00179           else dist = dtcell->toGlobal(hiti->localPosition()).mag();
00180 
00181         thisHit.driftCell = hiti->geographicalId();
00182         if (hiti->lrSide()==DTEnums::Left) thisHit.isLeft=true; else thisHit.isLeft=false;
00183         thisHit.isPhi = phi;
00184         thisHit.posInLayer = geomDet->toLocal(dtcell->toGlobal(hiti->localPosition())).x();
00185         thisHit.distIP = dist;
00186         thisHit.station = station;
00187         if (useSegmentT0_ && segm->ist0Valid()) thisHit.timeCorr=segm->t0();
00188         else thisHit.timeCorr=0.;
00189         thisHit.timeCorr += theTimeOffset_;
00190 
00191           
00192         // signal propagation along the wire correction for unmached theta or phi segment hits
00193         if (doWireCorr_ && !bothProjections && tsos.first.isValid()) {
00194           const DTLayer* layer = theDTGeom->layer(hiti->wireId());
00195           float propgL = layer->toLocal( tsos.first.globalPosition() ).y();
00196           float wirePropCorr = propgL/24.4*0.00543; // signal propagation speed along the wire
00197           if (thisHit.isLeft) wirePropCorr=-wirePropCorr;
00198           thisHit.posInLayer += wirePropCorr;
00199         } 
00200           
00201         tms.push_back(thisHit);
00202       }
00203     } // phi = (0,1)            
00204   } // rechit
00205       
00206   bool modified = false;
00207   std::vector <double> dstnc, dsegm, dtraj, hitWeight, left;
00208     
00209   // Now loop over the measurements, calculate 1/beta and cut away outliers
00210   do {    
00211 
00212     modified = false;
00213     dstnc.clear();
00214     dsegm.clear();
00215     dtraj.clear();
00216     hitWeight.clear();
00217     left.clear();
00218       
00219     std::vector <int> hit_idx;
00220     totalWeight=0;
00221       
00222     // Rebuild segments
00223     for (int sta=1;sta<5;sta++)
00224       for (int phi=0;phi<2;phi++) {
00225           std::vector <TimeMeasurement> seg;
00226           std::vector <int> seg_idx;
00227         int tmpos=0;
00228         for (std::vector<TimeMeasurement>::iterator tm=tms.begin(); tm!=tms.end(); ++tm) {
00229           if ((tm->station==sta) && (tm->isPhi==phi)) {
00230             seg.push_back(*tm);
00231             seg_idx.push_back(tmpos);
00232           }
00233           tmpos++;  
00234         }
00235           
00236         unsigned int segsize = seg.size();
00237           
00238         if (segsize<theHitsMin_) continue;
00239 
00240         double a=0, b=0;
00241     std::vector <double> hitxl,hitxr,hityl,hityr;
00242 
00243         for (std::vector<TimeMeasurement>::iterator tm=seg.begin(); tm!=seg.end(); ++tm) {
00244  
00245           DetId id = tm->driftCell;
00246           const GeomDet* dtcell = theTrackingGeometry->idToDet(id);
00247           DTChamberId chamberId(id.rawId());
00248           const GeomDet* dtcham = theTrackingGeometry->idToDet(chamberId);
00249 
00250           double celly=dtcham->toLocal(dtcell->position()).z();
00251             
00252           if (tm->isLeft) {
00253             hitxl.push_back(celly);
00254             hityl.push_back(tm->posInLayer);
00255           } else {
00256             hitxr.push_back(celly);
00257             hityr.push_back(tm->posInLayer);
00258           }    
00259         }
00260 
00261         if (!fitT0(a,b,hitxl,hityl,hitxr,hityr)) {
00262           if (debug)
00263             std::cout << "     t0 = zero, Left hits: " << hitxl.size() << " Right hits: " << hitxr.size() << std::endl;
00264           continue;
00265         }
00266           
00267         // a segment must have at least one left and one right hit
00268         if ((!hitxl.size()) || (!hityl.size())) continue;
00269 
00270         int segidx=0;
00271         for (std::vector<TimeMeasurement>::const_iterator tm=seg.begin(); tm!=seg.end(); ++tm) {
00272 
00273           DetId id = tm->driftCell;
00274           const GeomDet* dtcell = theTrackingGeometry->idToDet(id);
00275           DTChamberId chamberId(id.rawId());
00276           const GeomDet* dtcham = theTrackingGeometry->idToDet(chamberId);
00277 
00278           double layerZ  = dtcham->toLocal(dtcell->position()).z();
00279           double segmLocalPos = b+layerZ*a;
00280           double hitLocalPos = tm->posInLayer;
00281           int hitSide = -tm->isLeft*2+1;
00282           double t0_segm = (-(hitSide*segmLocalPos)+(hitSide*hitLocalPos))/0.00543+tm->timeCorr;
00283             
00284           dstnc.push_back(tm->distIP);
00285           dsegm.push_back(t0_segm);
00286           left.push_back(hitSide);
00287           hitWeight.push_back(((double)seg.size()-2.)/(double)seg.size());
00288           hit_idx.push_back(seg_idx.at(segidx));
00289           segidx++;
00290         }
00291           
00292         totalWeight+=seg.size()-2;
00293       }
00294 
00295     if (totalWeight==0) break;        
00296 
00297     // calculate the value and error of 1/beta from the complete set of 1D hits
00298     if (debug)
00299       std::cout << " Points for global fit: " << dstnc.size() << std::endl;
00300 
00301     // inverse beta - weighted average of the contributions from individual hits
00302     invbeta=0;
00303     for (unsigned int i=0;i<dstnc.size();i++) 
00304       invbeta+=(1.+dsegm.at(i)/dstnc.at(i)*30.)*hitWeight.at(i)/totalWeight;
00305 
00306     double chimax=0.;
00307     std::vector<TimeMeasurement>::iterator tmmax;
00308     
00309     // the dispersion of inverse beta
00310     double diff;
00311     for (unsigned int i=0;i<dstnc.size();i++) {
00312       diff=(1.+dsegm.at(i)/dstnc.at(i)*30.)-invbeta;
00313       diff=diff*diff*hitWeight.at(i);
00314       invbetaerr+=diff;
00315       if (diff/totalWeight>chimax) { 
00316         tmmax=tms.begin()+hit_idx.at(i);
00317         chimax=diff;
00318       }
00319     }
00320     
00321     invbetaerr=sqrt(invbetaerr/totalWeight); 
00322  
00323     // cut away the outliers
00324     if (chimax>thePruneCut_) {
00325       tms.erase(tmmax);
00326       modified=true;
00327     }    
00328 
00329     if (debug)
00330       std::cout << " Measured 1/beta: " << invbeta << " +/- " << invbetaerr << std::endl;
00331 
00332   } while (modified);
00333 
00334   for (unsigned int i=0;i<dstnc.size();i++) {
00335     tmSequence.dstnc.push_back(dstnc.at(i));
00336     tmSequence.local_t0.push_back(dsegm.at(i));
00337     tmSequence.weight.push_back(hitWeight.at(i));
00338   }
00339 
00340   tmSequence.totalWeight=totalWeight;
00341 
00342 }
00343 
00344 double
00345 DTTimingExtractor::fitT0(double &a, double &b, std::vector<double> xl, std::vector<double> yl, std::vector<double> xr, std::vector<double> yr ) {
00346 
00347   double sx=0,sy=0,sxy=0,sxx=0,ssx=0,ssy=0,s=0,ss=0;
00348 
00349   for (unsigned int i=0; i<xl.size(); i++) {
00350     sx+=xl[i];
00351     sy+=yl[i];
00352     sxy+=xl[i]*yl[i];
00353     sxx+=xl[i]*xl[i];
00354     s++;
00355     ssx+=xl[i];
00356     ssy+=yl[i];
00357     ss++;
00358   } 
00359 
00360   for (unsigned int i=0; i<xr.size(); i++) {
00361     sx+=xr[i];
00362     sy+=yr[i];
00363     sxy+=xr[i]*yr[i];
00364     sxx+=xr[i]*xr[i];
00365     s++;
00366     ssx-=xr[i];
00367     ssy-=yr[i];
00368     ss--;
00369   } 
00370 
00371   double delta = ss*ss*sxx+s*sx*sx+s*ssx*ssx-s*s*sxx-2*ss*sx*ssx;
00372   
00373   double t0_corr=0.;
00374 
00375   if (delta) {
00376     a=(ssy*s*ssx+sxy*ss*ss+sy*sx*s-sy*ss*ssx-ssy*sx*ss-sxy*s*s)/delta;
00377     b=(ssx*sy*ssx+sxx*ssy*ss+sx*sxy*s-sxx*sy*s-ssx*sxy*ss-sx*ssy*ssx)/delta;
00378     t0_corr=(ssx*s*sxy+sxx*ss*sy+sx*sx*ssy-sxx*s*ssy-sx*ss*sxy-ssx*sx*sy)/delta;
00379   }
00380 
00381   // convert drift distance to time
00382   t0_corr/=-0.00543;
00383 
00384   return t0_corr;
00385 }
00386 
00387 
00388 //define this as a plug-in
00389 //DEFINE_FWK_MODULE(DTTimingExtractor);