CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_1/src/RecoMuon/MuonSeedGenerator/src/MuonSeedCreator.cc

Go to the documentation of this file.
00001 
00009 #include "RecoMuon/MuonSeedGenerator/src/MuonSeedCreator.h"
00010 
00011 #include "RecoMuon/TransientTrackingRecHit/interface/MuonTransientTrackingRecHit.h"
00012 
00013 #include "RecoMuon/TrackingTools/interface/MuonPatternRecoDumper.h"
00014 
00015 #include "MagneticField/Engine/interface/MagneticField.h"
00016 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00017 
00018 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00019 #include "TrackingTools/DetLayers/interface/DetLayer.h"
00020 
00021 #include "DataFormats/TrajectoryState/interface/PTrajectoryStateOnDet.h"
00022 #include "DataFormats/Common/interface/OwnVector.h"
00023 #include "DataFormats/MuonDetId/interface/DTChamberId.h"
00024 #include "DataFormats/MuonDetId/interface/CSCDetId.h"
00025 #include "DataFormats/MuonDetId/interface/RPCDetId.h"
00026 
00027 #include "FWCore/Framework/interface/EventSetup.h"
00028 #include "FWCore/Framework/interface/ESHandle.h"
00029 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00030 
00031 #include "gsl/gsl_statistics.h"
00032 
00033 
00034 /*
00035  * Constructor
00036  */
00037 MuonSeedCreator::MuonSeedCreator(const edm::ParameterSet& pset){
00038   
00039   theMinMomentum  = pset.getParameter<double>("minimumSeedPt");  
00040   theMaxMomentum  = pset.getParameter<double>("maximumSeedPt");  
00041   defaultMomentum = pset.getParameter<double>("defaultSeedPt");
00042   debug           = pset.getParameter<bool>("DebugMuonSeed");
00043   sysError        = pset.getParameter<double>("SeedPtSystematics");
00044   // load seed PT parameters 
00045   DT12 = pset.getParameter<std::vector<double> >("DT_12");
00046   DT13 = pset.getParameter<std::vector<double> >("DT_13");
00047   DT14 = pset.getParameter<std::vector<double> >("DT_14");
00048   DT23 = pset.getParameter<std::vector<double> >("DT_23");
00049   DT24 = pset.getParameter<std::vector<double> >("DT_24");
00050   DT34 = pset.getParameter<std::vector<double> >("DT_34");
00051 
00052   CSC01 = pset.getParameter<std::vector<double> >("CSC_01");
00053   CSC12 = pset.getParameter<std::vector<double> >("CSC_12");
00054   CSC02 = pset.getParameter<std::vector<double> >("CSC_02");
00055   CSC13 = pset.getParameter<std::vector<double> >("CSC_13");
00056   CSC03 = pset.getParameter<std::vector<double> >("CSC_03");
00057   CSC14 = pset.getParameter<std::vector<double> >("CSC_14");
00058   CSC23 = pset.getParameter<std::vector<double> >("CSC_23");
00059   CSC24 = pset.getParameter<std::vector<double> >("CSC_24");
00060   CSC34 = pset.getParameter<std::vector<double> >("CSC_34");
00061 
00062   OL1213 = pset.getParameter<std::vector<double> >("OL_1213");
00063   OL1222 = pset.getParameter<std::vector<double> >("OL_1222");
00064   OL1232 = pset.getParameter<std::vector<double> >("OL_1232");
00065   OL1213 = pset.getParameter<std::vector<double> >("OL_1213");
00066   OL2222 = pset.getParameter<std::vector<double> >("OL_1222");
00067 
00068   SME11 =  pset.getParameter<std::vector<double> >("SME_11");
00069   SME12 =  pset.getParameter<std::vector<double> >("SME_12");
00070   SME13 =  pset.getParameter<std::vector<double> >("SME_13");
00071   SME21 =  pset.getParameter<std::vector<double> >("SME_21");
00072   SME22 =  pset.getParameter<std::vector<double> >("SME_22");
00073   SME31 =  pset.getParameter<std::vector<double> >("SME_31");
00074   SME32 =  pset.getParameter<std::vector<double> >("SME_32");
00075   SME41 =  pset.getParameter<std::vector<double> >("SME_41");
00076 
00077   SMB10 =  pset.getParameter<std::vector<double> >("SMB_10");
00078   SMB11 =  pset.getParameter<std::vector<double> >("SMB_11");
00079   SMB12 =  pset.getParameter<std::vector<double> >("SMB_12");
00080   SMB20 =  pset.getParameter<std::vector<double> >("SMB_20");
00081   SMB21 =  pset.getParameter<std::vector<double> >("SMB_21");
00082   SMB22 =  pset.getParameter<std::vector<double> >("SMB_22");
00083   SMB30 =  pset.getParameter<std::vector<double> >("SMB_30");
00084   SMB31 =  pset.getParameter<std::vector<double> >("SMB_31");
00085   SMB32 =  pset.getParameter<std::vector<double> >("SMB_32");
00086 
00087   // Load dphi scale parameters
00088   CSC01_1 = pset.getParameter<std::vector<double> >("CSC_01_1_scale");
00089   CSC12_1 = pset.getParameter<std::vector<double> >("CSC_12_1_scale");
00090   CSC12_2 = pset.getParameter<std::vector<double> >("CSC_12_2_scale");
00091   CSC12_3 = pset.getParameter<std::vector<double> >("CSC_12_3_scale");
00092   CSC13_2 = pset.getParameter<std::vector<double> >("CSC_13_2_scale");
00093   CSC13_3 = pset.getParameter<std::vector<double> >("CSC_13_3_scale");
00094   CSC14_3 = pset.getParameter<std::vector<double> >("CSC_14_3_scale");
00095   CSC23_1 = pset.getParameter<std::vector<double> >("CSC_23_1_scale");
00096   CSC23_2 = pset.getParameter<std::vector<double> >("CSC_23_2_scale");
00097   CSC24_1 = pset.getParameter<std::vector<double> >("CSC_24_1_scale");
00098   CSC34_1 = pset.getParameter<std::vector<double> >("CSC_34_1_scale");
00099 
00100   DT12_1 = pset.getParameter<std::vector<double> >("DT_12_1_scale");
00101   DT12_2 = pset.getParameter<std::vector<double> >("DT_12_2_scale");
00102   DT13_1 = pset.getParameter<std::vector<double> >("DT_13_1_scale");
00103   DT13_2 = pset.getParameter<std::vector<double> >("DT_13_2_scale");
00104   DT14_1 = pset.getParameter<std::vector<double> >("DT_14_1_scale");
00105   DT14_2 = pset.getParameter<std::vector<double> >("DT_14_2_scale");
00106   DT23_1 = pset.getParameter<std::vector<double> >("DT_23_1_scale");
00107   DT23_2 = pset.getParameter<std::vector<double> >("DT_23_2_scale");
00108   DT24_1 = pset.getParameter<std::vector<double> >("DT_24_1_scale");
00109   DT24_2 = pset.getParameter<std::vector<double> >("DT_24_2_scale");
00110   DT34_1 = pset.getParameter<std::vector<double> >("DT_34_1_scale");
00111   DT34_2 = pset.getParameter<std::vector<double> >("DT_34_2_scale");
00112 
00113   OL_1213 = pset.getParameter<std::vector<double> >("OL_1213_0_scale");
00114   OL_1222 = pset.getParameter<std::vector<double> >("OL_1222_0_scale");
00115   OL_1232 = pset.getParameter<std::vector<double> >("OL_1232_0_scale");
00116   OL_2213 = pset.getParameter<std::vector<double> >("OL_2213_0_scale");
00117   OL_2222 = pset.getParameter<std::vector<double> >("OL_2222_0_scale");
00118 
00119   SMB_10S = pset.getParameter<std::vector<double> >("SMB_10_0_scale");
00120   SMB_11S = pset.getParameter<std::vector<double> >("SMB_11_0_scale");
00121   SMB_12S = pset.getParameter<std::vector<double> >("SMB_12_0_scale");
00122   SMB_20S = pset.getParameter<std::vector<double> >("SMB_20_0_scale");
00123   SMB_21S = pset.getParameter<std::vector<double> >("SMB_21_0_scale");
00124   SMB_22S = pset.getParameter<std::vector<double> >("SMB_22_0_scale");
00125   SMB_30S = pset.getParameter<std::vector<double> >("SMB_30_0_scale");
00126   SMB_31S = pset.getParameter<std::vector<double> >("SMB_31_0_scale");
00127   SMB_32S = pset.getParameter<std::vector<double> >("SMB_32_0_scale");
00128 
00129   SME_11S = pset.getParameter<std::vector<double> >("SME_11_0_scale");
00130   SME_12S = pset.getParameter<std::vector<double> >("SME_12_0_scale");
00131   SME_13S = pset.getParameter<std::vector<double> >("SME_13_0_scale");
00132   SME_21S = pset.getParameter<std::vector<double> >("SME_21_0_scale");
00133   SME_22S = pset.getParameter<std::vector<double> >("SME_22_0_scale");
00134 
00135 }
00136 
00137 
00138 /*
00139  * Destructor
00140  */
00141 MuonSeedCreator::~MuonSeedCreator(){
00142   
00143 }
00144 
00145 
00146 /*
00147  * createSeed
00148  *
00149  * Note type = 1 --> CSC
00150  *           = 2 --> Overlap
00151  *           = 3 --> DT
00152  */
00153 TrajectorySeed MuonSeedCreator::createSeed(int type, SegmentContainer seg, std::vector<int> layers, int NShowers, int NShowerSegments ) {
00154 
00155   // The index of the station closest to the IP
00156   int last = 0;
00157 
00158   double ptmean = theMinMomentum;
00159   double sptmean = theMinMomentum;
00160 
00161   AlgebraicVector t(4);
00162   AlgebraicSymMatrix mat(5,0) ;
00163   LocalPoint segPos;
00164 
00165   // Compute the pt according to station types used;
00166   if (type == 1 ) estimatePtCSC(seg, layers, ptmean, sptmean);
00167   if (type == 2 ) estimatePtOverlap(seg, layers, ptmean, sptmean);
00168   if (type == 3 ) estimatePtDT(seg, layers, ptmean, sptmean);
00169   if (type == 4 ) estimatePtSingle(seg, layers, ptmean, sptmean);
00170   // type 5 are the seeding for ME1/4
00171   if (type == 5 ) estimatePtCSC(seg, layers, ptmean, sptmean);
00172 
00173   // for certain clear showering case, set-up the minimum value 
00174   if ( NShowers > 0 ) estimatePtShowering( NShowers, NShowerSegments, ptmean, sptmean ); 
00175   //if ( NShowers > 0 ) std::cout<<" Showering happened "<<NShowers<<" times w/ "<< NShowerSegments<<std::endl; ; 
00176 
00177 
00178   // Minimal pt
00179   double charge = 1.0;
00180   if (ptmean < 0.) charge = -1.0; 
00181   if ( (charge * ptmean) < theMinMomentum ) {
00182     ptmean  = theMinMomentum * charge;
00183     sptmean = theMinMomentum ;
00184   }
00185   else if ( (charge * ptmean) > theMaxMomentum ) {
00186     ptmean  = theMaxMomentum * charge;
00187     sptmean = theMaxMomentum * 0.25 ;
00188   }
00189 
00190   LocalTrajectoryParameters param;
00191 
00192   double p_err =0.0;
00193   // determine the seed layer
00194   int    best_seg= 0;
00195   double chi2_dof = 9999.0;
00196   unsigned int ini_seg = 0;
00197   // avoid generating seed from  1st layer(ME1/1)
00198   if ( type == 5 )  ini_seg = 1;
00199   for (size_t i = ini_seg ; i < seg.size(); i++) {
00200       double dof = static_cast<double>(seg[i]->degreesOfFreedom());
00201       if ( chi2_dof  < ( seg[i]->chi2()/dof ) ) continue;
00202       chi2_dof = seg[i]->chi2() / dof ;
00203       best_seg = static_cast<int>(i);
00204   }  
00205   
00206 
00207   if ( type==1 || type==5 || type== 4) {
00208      // Fill the LocalTrajectoryParameters
00210      last = best_seg;
00211      // last = 0;
00212      GlobalVector mom = seg[last]->globalPosition()-GlobalPoint();
00213      segPos = seg[last]->localPosition();
00215   
00216      GlobalVector polar(GlobalVector::Spherical(mom.theta(),seg[last]->globalDirection().phi(),1.));
00217 
00219      polar *= fabs(ptmean)/polar.perp();
00221      LocalVector segDirFromPos = seg[last]->det()->toLocal(polar);
00222      int chargeI = static_cast<int>(charge);
00223      LocalTrajectoryParameters param1(segPos, segDirFromPos, chargeI);
00224      param = param1;
00225      p_err =  (sptmean*sptmean)/(polar.mag()*polar.mag()*ptmean*ptmean) ;
00226      mat = seg[last]->parametersError().similarityT( seg[last]->projectionMatrix() );  
00227      mat[0][0]= p_err;
00228      if ( type == 5 ) { 
00229         mat[0][0] = mat[0][0]/fabs( tan(mom.theta()) ); 
00230         mat[1][1] = mat[1][1]/fabs( tan(mom.theta()) ); 
00231         mat[3][3] = 2.25*mat[3][3];
00232         mat[4][4] = 2.25*mat[4][4];
00233      }
00234      if ( type == 4 ) { 
00235         mat[0][0] = mat[0][0]/fabs( tan(mom.theta()) ); 
00236         mat[1][1] = mat[1][1]/fabs( tan(mom.theta()) ); 
00237         mat[2][2] = 2.25*mat[2][2];
00238         mat[3][3] = 2.25*mat[3][3];
00239         mat[4][4] = 2.25*mat[4][4];
00240      }
00241      double dh = fabs( seg[last]->globalPosition().eta() ) - 1.6 ; 
00242      if ( fabs(dh) < 0.1 && type == 1 ) {
00243         mat[1][1] = 4.*mat[1][1];
00244         mat[2][2] = 4.*mat[2][2];
00245         mat[3][3] = 9.*mat[3][3];
00246         mat[4][4] = 9.*mat[4][4];
00247      }
00248 
00249      //if ( !highPt && type != 1 ) mat[1][1]= 2.25*mat[1][1];
00250      //if (  highPt && type != 1 ) mat[3][3]= 2.25*mat[1][1];
00251      //mat[2][2]= 3.*mat[2][2];
00252      //mat[3][3]= 2.*mat[3][3];
00253      //mat[4][4]= 2.*mat[4][4];
00254   }
00255   else {
00256      // Fill the LocalTrajectoryParameters
00258      last = 0;
00259      segPos = seg[last]->localPosition();
00260      GlobalVector mom = seg[last]->globalPosition()-GlobalPoint();
00262      GlobalVector polar(GlobalVector::Spherical(mom.theta(),seg[last]->globalDirection().phi(),1.));
00263      //GlobalVector polar(GlobalVector::Spherical(seg[last]->globalDirection().theta(),seg[last]->globalDirection().phi(),1.));
00264 
00266      //double ptRatio = 1.0 - (2.808/(fabs(ptmean) -1)) + (4.546/( (fabs(ptmean)-1)*(fabs(ptmean)-1)) );
00267      //ptmean = ptmean*ptRatio ;
00268       
00270      polar *= fabs(ptmean)/polar.perp();
00272      LocalVector segDirFromPos = seg[last]->det()->toLocal(polar);
00273      int chargeI = static_cast<int>(charge);
00274      LocalTrajectoryParameters param1(segPos, segDirFromPos, chargeI);
00275      param = param1;
00276      p_err =  (sptmean*sptmean)/(polar.mag()*polar.mag()*ptmean*ptmean) ;
00277      mat = seg[last]->parametersError().similarityT( seg[last]->projectionMatrix() );  
00278      //mat[0][0]= 1.44 * p_err;
00279      mat[0][0]= p_err;
00280   }
00281 
00282   if ( debug ) {
00283     GlobalPoint gp = seg[last]->globalPosition();
00284     float Geta = gp.eta();
00285 
00286     std::cout << "Type "      << type   << " Nsegments " << layers.size() << " ";
00287     std::cout << "pt "        << ptmean << " errpt    " << sptmean 
00288               << " eta "      << Geta   << " charge "   << charge 
00289               << std::endl;
00290   }
00291 
00292   // this perform H.T() * parErr * H, which is the projection of the 
00293   // the measurement error (rechit rf) to the state error (TSOS rf)
00294   // Legend:
00295   // H => is the 4x5 projection matrix
00296   // parError the 4x4 parameter error matrix of the RecHit
00297 
00298   
00299   LocalTrajectoryError error(asSMatrix<5>(mat));
00300   
00301   // Create the TrajectoryStateOnSurface
00302   TrajectoryStateOnSurface tsos(param, error, seg[last]->det()->surface(),&*BField);
00303   
00304   // Take the DetLayer on which relies the segment
00305   DetId id = seg[last]->geographicalId();
00306 
00307   // Transform it in a TrajectoryStateOnSurface
00308   
00309   
00310   PTrajectoryStateOnDet seedTSOS = trajectoryStateTransform::persistentState( tsos, id.rawId());
00311 
00312   edm::OwnVector<TrackingRecHit> container;
00313   for (unsigned l=0; l<seg.size(); l++) {
00314       container.push_back( seg[l]->hit()->clone() ); 
00315       //container.push_back(seg[l]->hit()); 
00316   }
00317 
00318   TrajectorySeed theSeed(seedTSOS,container,alongMomentum);
00319   return theSeed;
00320 }
00321 
00322 
00323 /*
00324  * estimatePtCSC
00325  *
00326  * Look at delta phi to determine pt as:
00327  * pt = (c_1 * eta + c_2) / dphi
00328  *
00329  * Note that only segment pairs with one segment in the ME1 layers give sensitive results
00330  *
00331  */
00332 void MuonSeedCreator::estimatePtCSC(SegmentContainer seg, std::vector<int> layers, double& thePt, double& theSpt ) {
00333 
00334   unsigned size = seg.size();
00335   if (size < 2) return;
00336   
00337   // reverse the segment and layer container first for pure CSC case
00338   //if ( layers[0] > layers[ layers.size()-1 ] ) {
00339   //   reverse( layers.begin(), layers.end() );
00340   //   reverse( seg.begin(), seg.end() );
00341   //}
00342 
00343   std::vector<double> ptEstimate;
00344   std::vector<double> sptEstimate;
00345 
00346   thePt  = defaultMomentum;
00347   theSpt = defaultMomentum;
00348 
00349   double pt = 0.;
00350   double spt = 0.;   
00351   GlobalPoint  segPos[2];
00352 
00353   int layer0 = layers[0];
00354   segPos[0] = seg[0]->globalPosition();
00355   float eta = fabs( segPos[0].eta() );
00356   //float corr = fabs( tan(segPos[0].theta()) );
00357   // use pt from vertex information
00358   /*
00359   if ( layer0 == 0 ) {
00360      SegmentContainer seg0;
00361      seg0.push_back(seg[0]);
00362      std::vector<int> lyr0(1,0);
00363      estimatePtSingle( seg0, lyr0, thePt, theSpt);
00364      ptEstimate.push_back( thePt );
00365      sptEstimate.push_back( theSpt );
00366   }
00367   */
00368 
00369   //std::cout<<" estimate CSC "<<std::endl;
00370 
00371   unsigned idx1 = size;
00372   if (size > 1) {
00373     while ( idx1 > 1 ) {
00374       idx1--;
00375       int layer1 = layers[idx1];
00376       if (layer0 == layer1) continue;
00377       segPos[1] = seg[idx1]->globalPosition();      
00378 
00379       double dphi = segPos[0].phi() - segPos[1].phi();
00380       //double temp_dphi = dphi/corr;
00381       double temp_dphi = dphi;
00382        
00383       double sign = 1.0;  
00384       if (temp_dphi < 0.) {
00385         temp_dphi = -1.0*temp_dphi;
00386         sign = -1.0;
00387       }
00388 
00389       // Ensure that delta phi is not too small to prevent pt from blowing up
00390       if (temp_dphi < 0.0001 ) { 
00391          temp_dphi = 0.0001 ;
00392          pt = theMaxMomentum ;
00393          spt = theMaxMomentum*0.25 ; 
00394          ptEstimate.push_back( pt*sign );
00395          sptEstimate.push_back( spt );
00396       }
00397       // ME1 is inner-most
00398       if ( layer0 == 0 && temp_dphi >= 0.0001 ) {
00399  
00400         // ME1/2 is outer-most
00401         if ( layer1 ==  1 ) {
00402           //temp_dphi = scaledPhi(temp_dphi, CSC01_1[3] );
00403           pt  = getPt( CSC01, eta , temp_dphi )[0];
00404           spt = getPt( CSC01, eta , temp_dphi )[1];
00405         }  
00406         // ME2 is outer-most
00407         else if ( layer1 == 2  ) {
00408           //temp_dphi = scaledPhi(temp_dphi, CSC12_3[3] );
00409           pt  = getPt( CSC02, eta , temp_dphi )[0];
00410           spt = getPt( CSC02, eta , temp_dphi )[1];
00411         }
00412         // ME3 is outer-most
00413         else if ( layer1 == 3 ) {
00414           //temp_dphi = scaledPhi(temp_dphi, CSC13_3[3] );
00415           pt  = getPt( CSC03, eta , temp_dphi )[0];
00416           spt = getPt( CSC03, eta , temp_dphi )[1];
00417         }
00418         // ME4 is outer-most
00419         else {
00420           //temp_dphi = scaledPhi(temp_dphi, CSC14_3[3]);
00421           pt  = getPt( CSC14, eta , temp_dphi )[0];
00422           spt = getPt( CSC14, eta , temp_dphi )[1];
00423         }
00424         ptEstimate.push_back( pt*sign );
00425         sptEstimate.push_back( spt );
00426       }
00427 
00428       // ME1/2,ME1/3 is inner-most
00429       if ( layer0 == 1 ) {
00430         // ME2 is outer-most
00431         if ( layer1 == 2 ) {
00432 
00433           //if ( eta <= 1.2 )  {   temp_dphi = scaledPhi(temp_dphi, CSC12_1[3]); }
00434           //if ( eta >  1.2 )  {   temp_dphi = scaledPhi(temp_dphi, CSC12_2[3]); }
00435           pt  = getPt( CSC12, eta , temp_dphi )[0];
00436           spt = getPt( CSC12, eta , temp_dphi )[1];
00437         }
00438         // ME3 is outer-most
00439         else if ( layer1 == 3 ) {
00440           temp_dphi = scaledPhi(temp_dphi, CSC13_2[3]);
00441           pt  = getPt( CSC13, eta , temp_dphi )[0];
00442           spt = getPt( CSC13, eta , temp_dphi )[1];
00443         }
00444         // ME4 is outer-most
00445         else {
00446           temp_dphi = scaledPhi(temp_dphi, CSC14_3[3]);
00447           pt  = getPt( CSC14, eta , temp_dphi )[0];
00448           spt = getPt( CSC14, eta , temp_dphi )[1];
00449         }
00450         ptEstimate.push_back( pt*sign );
00451         sptEstimate.push_back( spt );
00452       }
00453 
00454       // ME2 is inner-most
00455       if ( layer0 == 2 && temp_dphi > 0.0001 ) {
00456 
00457         // ME4 is outer-most
00458         bool ME4av =false;
00459         if ( layer1 == 4 )  {
00460           temp_dphi = scaledPhi(temp_dphi, CSC24_1[3]);
00461           pt  = getPt( CSC24, eta , temp_dphi )[0];
00462           spt = getPt( CSC24, eta , temp_dphi )[1];
00463           ME4av = true;
00464         }
00465         // ME3 is outer-most
00466         else {
00467           // if ME2-4 is availabe , discard ME2-3 
00468           if ( !ME4av ) {
00469             if ( eta <= 1.7 )  {   temp_dphi = scaledPhi(temp_dphi, CSC23_1[3]); }
00470             if ( eta >  1.7 )  {   temp_dphi = scaledPhi(temp_dphi, CSC23_2[3]); }
00471             pt  = getPt( CSC23, eta , temp_dphi )[0];
00472             spt = getPt( CSC23, eta , temp_dphi )[1];
00473           }
00474         }
00475         ptEstimate.push_back( pt*sign );   
00476         sptEstimate.push_back( spt );
00477       }
00478 
00479       // ME3 is inner-most
00480       if ( layer0 == 3 && temp_dphi > 0.0001 ) {
00481 
00482         temp_dphi = scaledPhi(temp_dphi, CSC34_1[3]);
00483         pt  = getPt( CSC34, eta , temp_dphi )[0];
00484         spt = getPt( CSC34, eta , temp_dphi )[1];
00485         ptEstimate.push_back( pt*sign );   
00486         sptEstimate.push_back( spt );
00487       }
00488 
00489     } 
00490   }
00491 
00492   // Compute weighted average if have more than one estimator
00493   if ( ptEstimate.size() > 0 ) weightedPt( ptEstimate, sptEstimate, thePt, theSpt);
00494 
00495 }
00496 
00497 
00498 /*
00499  * estimatePtDT
00500  *
00501  * Look at delta phi between segments to determine pt as:
00502  * pt = (c_1 * eta + c_2) / dphi
00503  */
00504 void MuonSeedCreator::estimatePtDT(SegmentContainer seg, std::vector<int> layers, double& thePt, double& theSpt) {
00505 
00506   unsigned size = seg.size();
00507   if (size < 2) return;
00508   
00509   std::vector<double> ptEstimate;
00510   std::vector<double> sptEstimate;
00511 
00512   thePt  = defaultMomentum;
00513   theSpt = defaultMomentum;
00514 
00515   double pt = 0.;
00516   double spt = 0.;   
00517   GlobalPoint segPos[2];
00518 
00519   int layer0 = layers[0];
00520   segPos[0] = seg[0]->globalPosition();
00521   float eta = fabs(segPos[0].eta());
00522 
00523   //std::cout<<" estimate DT "<<std::endl;
00524   // inner-most layer
00525   //for ( unsigned idx0 = 0; idx0 < size-1; ++idx0 ) {
00526   //  layer0 = layers[idx0];
00527   //  segPos[0]  = seg[idx0]->globalPosition();
00528     // outer-most layer
00529     // for ( unsigned idx1 = idx0+1; idx1 < size; ++idx1 ) {
00530     for ( unsigned idx1 = 1; idx1 <size ;  ++idx1 ) {
00531 
00532       int layer1 = layers[idx1];
00533       segPos[1] = seg[idx1]->globalPosition();      
00534  
00535       //eta = fabs(segPos[1].eta());  
00536       //if (layer1 == -4) eta = fabs(segPos[0].eta());
00537 
00538       double dphi = segPos[0].phi() - segPos[1].phi();
00539       double temp_dphi = dphi;
00540 
00541       // Ensure that delta phi is not too small to prevent pt from blowing up
00542       
00543       double sign = 1.0;  
00544       if (temp_dphi < 0.) {
00545         temp_dphi = -temp_dphi;
00546         sign = -1.0;
00547       }
00548       
00549       if (temp_dphi < 0.0001 ) { 
00550          temp_dphi = 0.0001 ;
00551          pt = theMaxMomentum ;
00552          spt = theMaxMomentum*0.25 ; 
00553          ptEstimate.push_back( pt*sign );
00554          sptEstimate.push_back( spt );
00555       }
00556 
00557       // MB1 is inner-most
00558       bool MB23av = false;
00559       if (layer0 == -1 && temp_dphi > 0.0001 ) {
00560         // MB2 is outer-most
00561         if (layer1 == -2) {
00562 
00563           if ( eta <= 0.7 )  {   temp_dphi = scaledPhi(temp_dphi, DT12_1[3]); }
00564           if ( eta >  0.7 )  {   temp_dphi = scaledPhi(temp_dphi, DT12_2[3]); }
00565           pt  = getPt( DT12, eta , temp_dphi )[0];
00566           spt = getPt( DT12, eta , temp_dphi )[1];
00567           MB23av = true;
00568         }
00569         // MB3 is outer-most
00570         else if (layer1 == -3) {
00571 
00572           if ( eta <= 0.6 )  {   temp_dphi = scaledPhi(temp_dphi, DT13_1[3]); }
00573           if ( eta >  0.6 )  {   temp_dphi = scaledPhi(temp_dphi, DT13_2[3]); }
00574           pt  = getPt( DT13, eta , temp_dphi )[0];
00575           spt = getPt( DT13, eta , temp_dphi )[1];
00576           MB23av = true;
00577         }
00578         // MB4 is outer-most
00579         else {
00580           if ( !MB23av ) {
00581              if ( eta <= 0.52 )  {   temp_dphi = scaledPhi(temp_dphi, DT14_1[3]); }
00582              if ( eta >  0.52 )  {   temp_dphi = scaledPhi(temp_dphi, DT14_2[3]); }
00583              pt  = getPt( DT14, eta , temp_dphi )[0];
00584              spt = getPt( DT14, eta , temp_dphi )[1];
00585           }
00586         }
00587         ptEstimate.push_back( pt*sign );
00588         sptEstimate.push_back( spt );
00589       }
00590 
00591       // MB2 is inner-most
00592       if (layer0 == -2 && temp_dphi > 0.0001 ) {
00593         // MB3 is outer-most
00594         if ( layer1 == -3) {
00595 
00596           if ( eta <= 0.6 )  {   temp_dphi = scaledPhi(temp_dphi, DT23_1[3]); }
00597           if ( eta >  0.6 )  {   temp_dphi = scaledPhi(temp_dphi, DT23_2[3]); }
00598           pt  = getPt( DT23, eta , temp_dphi )[0];
00599           spt = getPt( DT23, eta , temp_dphi )[1];
00600         }
00601         // MB4 is outer-most
00602         else {
00603 
00604           if ( eta <= 0.52 )  {   temp_dphi = scaledPhi(temp_dphi, DT24_1[3]); }
00605           if ( eta >  0.52 )  {   temp_dphi = scaledPhi(temp_dphi, DT24_2[3]); }
00606           pt  = getPt( DT24, eta , temp_dphi )[0];
00607           spt = getPt( DT24, eta , temp_dphi )[1];
00608         }
00609         ptEstimate.push_back( pt*sign );
00610         sptEstimate.push_back( spt );
00611       }
00612 
00613       // MB3 is inner-most    -> only marginally useful to pick up the charge
00614       if (layer0 == -3 && temp_dphi > 0.0001 ) {
00615         // MB4 is outer-most
00616 
00617         if ( eta <= 0.51 )  {   temp_dphi = scaledPhi(temp_dphi, DT34_1[3]); }
00618         if ( eta >  0.51 )  {   temp_dphi = scaledPhi(temp_dphi, DT34_2[3]); }
00619         pt  = getPt( DT34, eta , temp_dphi )[0];
00620         spt = getPt( DT34, eta , temp_dphi )[1];
00621         ptEstimate.push_back( pt*sign );   
00622         sptEstimate.push_back( spt );
00623       }
00624     }   
00625   //}
00626   
00627   
00628   // Compute weighted average if have more than one estimator
00629   if (ptEstimate.size() > 0 ) weightedPt( ptEstimate, sptEstimate, thePt, theSpt);
00630 
00631 }
00632 
00633 
00634 /*
00635  * estimatePtOverlap
00636  *
00637  */
00638 void MuonSeedCreator::estimatePtOverlap(SegmentContainer seg, std::vector<int> layers, double& thePt, double& theSpt) {
00639 
00640   int size = layers.size();
00641 
00642   thePt  = defaultMomentum;
00643   theSpt = defaultMomentum;
00644 
00645   SegmentContainer segCSC;
00646   std::vector<int> layersCSC;
00647   SegmentContainer segDT;
00648   std::vector<int> layersDT;
00649 
00650   // DT layers are numbered as -4 to -1, whereas CSC layers go from 0 to 4:
00651   for ( unsigned j = 0; j < layers.size(); ++j ) {
00652     if ( layers[j] > -1 ) {
00653       segCSC.push_back(seg[j]);
00654       layersCSC.push_back(layers[j]);
00655     } 
00656     else {
00657       segDT.push_back(seg[j]);
00658       layersDT.push_back(layers[j]);
00659     } 
00660   }
00661 
00662   std::vector<double> ptEstimate;
00663   std::vector<double> sptEstimate;
00664 
00665   GlobalPoint segPos[2];
00666   int layer0 = layers[0];
00667   segPos[0] = seg[0]->globalPosition();
00668   float eta = fabs(segPos[0].eta());
00669   //std::cout<<" estimate OL "<<std::endl;
00670     
00671   if ( segDT.size() > 0 && segCSC.size() > 0 ) {
00672     int layer1 = layers[size-1];
00673     segPos[1] = seg[size-1]->globalPosition();
00674   
00675     double dphi = segPos[0].phi() - segPos[1].phi();
00676     double temp_dphi = dphi;
00677 
00678     // Ensure that delta phi is not too small to prevent pt from blowing up
00679     
00680     double sign = 1.0;
00681     if (temp_dphi < 0.) {      
00682       temp_dphi = -temp_dphi;
00683       sign = -1.0;  
00684     } 
00685      
00686     if (temp_dphi < 0.0001 ) { 
00687          temp_dphi = 0.0001 ;
00688          thePt = theMaxMomentum ;
00689          theSpt = theMaxMomentum*0.25 ; 
00690          ptEstimate.push_back( thePt*sign );
00691          sptEstimate.push_back( theSpt );
00692     }
00693   
00694     // MB1 is inner-most
00695     if ( layer0 == -1 && temp_dphi > 0.0001 ) {
00696       // ME1/3 is outer-most
00697       if ( layer1 == 1 ) {
00698         temp_dphi = scaledPhi(temp_dphi, OL_1213[3]);
00699         thePt  = getPt( OL1213, eta , temp_dphi )[0];
00700         theSpt = getPt( OL1213, eta , temp_dphi )[1];
00701       }
00702       // ME2 is outer-most
00703       else if ( layer1 == 2) {
00704         temp_dphi = scaledPhi(temp_dphi, OL_1222[3]);
00705         thePt  = getPt( OL1222, eta , temp_dphi )[0];
00706         theSpt = getPt( OL1222, eta , temp_dphi )[1];
00707       }
00708       // ME3 is outer-most
00709       else {
00710         temp_dphi = scaledPhi(temp_dphi, OL_1232[3]);
00711         thePt  = getPt( OL1232, eta , temp_dphi )[0];
00712         theSpt = getPt( OL1232, eta , temp_dphi )[1];
00713       }
00714       ptEstimate.push_back(thePt*sign);
00715       sptEstimate.push_back(theSpt);
00716     } 
00717     // MB2 is inner-most
00718     if ( layer0 == -2 && temp_dphi > 0.0001 ) {
00719       // ME1/3 is outer-most
00720       if ( layer1 == 1 ) {
00721         temp_dphi = scaledPhi(temp_dphi, OL_2213[3]);
00722         thePt  = getPt( OL2213, eta , temp_dphi )[0];
00723         theSpt = getPt( OL2213, eta , temp_dphi )[1];
00724         ptEstimate.push_back(thePt*sign);
00725         sptEstimate.push_back(theSpt);
00726       }
00727       // ME2 is outer-most
00728       if ( layer1 == 2) {
00729         temp_dphi = scaledPhi(temp_dphi, OL_2222[3]);
00730         thePt  = getPt( OL2222, eta , temp_dphi )[0];
00731         theSpt = getPt( OL2222, eta , temp_dphi )[1];
00732       }
00733     }
00734   } 
00735 
00736   if ( segDT.size() > 1 ) {
00737     estimatePtDT(segDT, layersDT, thePt, theSpt);
00738     ptEstimate.push_back(thePt);
00739     sptEstimate.push_back(theSpt);
00740   } 
00741 
00742   /*
00743   // not useful ....and pt estimation is bad
00744   if ( segCSC.size() > 1 ) {
00745     // don't estimate pt without ME1 information
00746     bool CSCLayer1=false;
00747     for (unsigned i=0; i< layersCSC.size(); i++) {
00748         if ( layersCSC[i]==0 || layersCSC[i]==1 ) CSCLayer1 = true;
00749     }
00750     if (CSCLayer1) {
00751        estimatePtCSC(segCSC, layersCSC, thePt, theSpt);
00752        ptEstimate.push_back(thePt);
00753        sptEstimate.push_back(theSpt);
00754     }
00755   }
00756   */
00757 
00758   // Compute weighted average if have more than one estimator
00759   if (ptEstimate.size() > 0 ) weightedPt( ptEstimate, sptEstimate, thePt, theSpt);
00760 
00761 }
00762 /*
00763  *
00764  *   estimate Pt for single segment events
00765  *
00766  */
00767 void MuonSeedCreator::estimatePtSingle(SegmentContainer seg, std::vector<int> layers, double& thePt, double& theSpt) {
00768 
00769   thePt  = defaultMomentum;
00770   theSpt = defaultMomentum;
00771 
00772   GlobalPoint segPos = seg[0]->globalPosition();
00773   double eta = segPos.eta();
00774   GlobalVector gv = seg[0]->globalDirection();
00775 
00776   // Psi is angle between the segment origin and segment direction
00777   // Use dot product between two vectors to get Psi in global x-y plane
00778   double cosDpsi  = (gv.x()*segPos.x() + gv.y()*segPos.y());
00779   cosDpsi /= sqrt(segPos.x()*segPos.x() + segPos.y()*segPos.y());
00780   cosDpsi /= sqrt(gv.x()*gv.x() + gv.y()*gv.y());
00781 
00782   double axb = ( segPos.x()*gv.y() ) - ( segPos.y()*gv.x() ) ;
00783   double sign = (axb < 0.) ? 1.0 : -1.0;
00784 
00785   double dpsi = fabs(acos(cosDpsi)) ;
00786   if ( dpsi > 1.570796 ) {
00787       dpsi = 3.141592 - dpsi;
00788       sign = -1.*sign ;
00789   }
00790   if (fabs(dpsi) < 0.00005) {
00791      dpsi = 0.00005;
00792   }
00793 
00794   // the 1st layer
00795   if ( layers[0] == -1 ) {
00796      // MB10
00797      if ( fabs(eta) < 0.3 ) {
00798         dpsi = scaledPhi(dpsi, SMB_10S[3] );
00799         thePt  = getPt( SMB10, eta , dpsi )[0];
00800         theSpt = getPt( SMB10, eta , dpsi )[1];
00801      }
00802      // MB11
00803      if ( fabs(eta) >= 0.3 && fabs(eta) < 0.82 ) {
00804         dpsi = scaledPhi(dpsi, SMB_11S[3] );
00805         thePt  = getPt( SMB11, eta , dpsi )[0];
00806         theSpt = getPt( SMB11, eta , dpsi )[1];
00807      }
00808      // MB12
00809      if ( fabs(eta) >= 0.82 && fabs(eta) < 1.2 ) {
00810         dpsi = scaledPhi(dpsi, SMB_12S[3] );
00811         thePt  = getPt( SMB12, eta , dpsi )[0];
00812         theSpt = getPt( SMB12, eta , dpsi )[1];
00813      }
00814   }
00815   if ( layers[0] == 1 ) {
00816      // ME13
00817      if ( fabs(eta) > 0.92 && fabs(eta) < 1.16 ) {
00818         dpsi = scaledPhi(dpsi, SME_13S[3] );
00819         thePt  = getPt( SME13, eta , dpsi )[0];
00820         theSpt = getPt( SME13, eta , dpsi )[1];
00821      }
00822      // ME12
00823      if ( fabs(eta) >= 1.16 && fabs(eta) <= 1.6 ) {
00824         dpsi = scaledPhi(dpsi, SME_12S[3] );
00825         thePt  = getPt( SME12, eta , dpsi )[0];
00826         theSpt = getPt( SME12, eta , dpsi )[1];
00827      }
00828   }
00829   if ( layers[0] == 0  ) {
00830      // ME11
00831      if ( fabs(eta) > 1.6 ) {
00832         dpsi = scaledPhi(dpsi, SMB_11S[3] );
00833         thePt  = getPt( SME11, eta , dpsi )[0];
00834         theSpt = getPt( SME11, eta , dpsi )[1];
00835      }
00836   }
00837   // the 2nd layer
00838   if ( layers[0] == -2 ) {
00839      // MB20
00840      if ( fabs(eta) < 0.25 ) {
00841         dpsi = scaledPhi(dpsi, SMB_20S[3] );
00842         thePt  = getPt( SMB20, eta , dpsi )[0];
00843         theSpt = getPt( SMB20, eta , dpsi )[1];
00844      }
00845      // MB21
00846      if ( fabs(eta) >= 0.25 && fabs(eta) < 0.72 ) {
00847         dpsi = scaledPhi(dpsi, SMB_21S[3] );
00848         thePt  = getPt( SMB21, eta , dpsi )[0];
00849         theSpt = getPt( SMB21, eta , dpsi )[1];
00850      }
00851      // MB22
00852      if ( fabs(eta) >= 0.72 && fabs(eta) < 1.04 ) {
00853         dpsi = scaledPhi(dpsi, SMB_22S[3] );
00854         thePt  = getPt( SMB22, eta , dpsi )[0];
00855         theSpt = getPt( SMB22, eta , dpsi )[1];
00856      }
00857   }
00858   if ( layers[0] == 2 ) {
00859      // ME22
00860      if ( fabs(eta) > 0.95 && fabs(eta) <= 1.6 ) {
00861         dpsi = scaledPhi(dpsi, SME_22S[3] );
00862         thePt  = getPt( SME22, eta , dpsi )[0];
00863         theSpt = getPt( SME22, eta , dpsi )[1];
00864      }
00865      // ME21
00866      if ( fabs(eta) > 1.6 && fabs(eta) < 2.45 ) {
00867         dpsi = scaledPhi(dpsi, SME_21S[3] );
00868         thePt  = getPt( SME21, eta , dpsi )[0];
00869         theSpt = getPt( SME21, eta , dpsi )[1];
00870      }
00871   }
00872 
00873   // the 3rd layer
00874   if ( layers[0] == -3 ) {
00875      // MB30
00876      if ( fabs(eta) <= 0.22 ) {
00877         dpsi = scaledPhi(dpsi, SMB_30S[3] );
00878         thePt  = getPt( SMB30, eta , dpsi )[0];
00879         theSpt = getPt( SMB30, eta , dpsi )[1];
00880      }
00881      // MB31
00882      if ( fabs(eta) > 0.22 && fabs(eta) <= 0.6 ) {
00883         dpsi = scaledPhi(dpsi, SMB_31S[3] );
00884         thePt  = getPt( SMB31, eta , dpsi )[0];
00885         theSpt = getPt( SMB31, eta , dpsi )[1];
00886      }
00887      // MB32
00888      if ( fabs(eta) > 0.6 && fabs(eta) < 0.95 ) {
00889         dpsi = scaledPhi(dpsi, SMB_32S[3] );
00890         thePt  = getPt( SMB32, eta , dpsi )[0];
00891         theSpt = getPt( SMB32, eta , dpsi )[1];
00892      }
00893   }
00894   thePt = fabs(thePt)*sign;
00895   theSpt = fabs(theSpt);
00896 
00897   return;
00898 }
00899 
00900 // setup the minimum value for obvious showering cases  
00901 void MuonSeedCreator::estimatePtShowering(int& NShowers, int& NShowerSegments,  double& thePt, double& theSpt) {
00902 
00903   if ( NShowers > 2 && thePt < 300. ) {
00904      thePt  = 800. ;
00905      theSpt = 200. ; 
00906   } 
00907   if ( NShowers == 2 && NShowerSegments >  11 && thePt < 150. ) {
00908      thePt = 280. ;
00909      theSpt = 70. ; 
00910   }
00911   if ( NShowers == 2 && NShowerSegments <= 11 && thePt < 50.  ) {
00912      thePt =  80.;
00913      theSpt = 40. ;
00914   }
00915   if ( NShowers == 1 && NShowerSegments <= 5 && thePt < 10. ) {
00916      thePt = 16. ;
00917      theSpt = 8. ; 
00918   }
00919 
00920 }
00921 
00922 /*
00923  * weightedPt
00924  *
00925  * Look at delta phi between segments to determine pt as:
00926  * pt = (c_1 * eta + c_2) / dphi
00927  */
00928 void MuonSeedCreator::weightedPt(std::vector<double> ptEstimate, std::vector<double> sptEstimate, double& thePt, double& theSpt) {
00929 
00930  
00931   int size = ptEstimate.size();
00932 
00933   // If only one element, by-pass computation below
00934   if (size < 2) {
00935     thePt = ptEstimate[0];
00936     theSpt = sptEstimate[0];
00937     return;
00938   }
00939 
00940   double charge = 0.;
00941   // If have more than one pt estimator, first look if any estimator is biased
00942   // by comparing the charge of each estimator
00943 
00944   for ( unsigned j = 0; j < ptEstimate.size(); j++ ) {
00945     //std::cout<<" weighting pt: "<< ptEstimate[j] <<std::endl; 
00946     if ( ptEstimate[j] < 0. ) {
00947       // To prevent from blowing up, add 0.1 
00948       charge -= 1. * (ptEstimate[j]*ptEstimate[j]) / (sptEstimate[j]*sptEstimate[j] );  // weight by relative error on pt
00949     } else {
00950       charge += 1. * (ptEstimate[j]*ptEstimate[j]) / (sptEstimate[j]*sptEstimate[j] );  // weight by relative error on pt
00951     }
00952   }
00953  
00954   // No need to normalize as we want to know only sign ( + or - )
00955   if (charge < 0.) {
00956     charge = -1.;
00957   } else {
00958     charge = 1.;
00959   }
00960 
00961   //int n = 0;
00962   double weightPtSum  = 0.;
00963   double sigmaSqr_sum = 0.;
00964           
00965   // Now, we want to compute average Pt using estimators with "correct" charge
00966   // This is to remove biases
00967   for ( unsigned j = 0; j < ptEstimate.size(); ++j ) {
00968     //if ( (minpt_ratio < 0.5) && (fabs(ptEstimate[j]) < 5.0) ) continue;
00969     //if ( ptEstimate[j] * charge > 0. ) {
00970       //n++;
00971       sigmaSqr_sum += 1.0 / (sptEstimate[j]*sptEstimate[j]);
00972       weightPtSum  += fabs(ptEstimate[j])/(sptEstimate[j]*sptEstimate[j]);
00973     //}
00974   }
00975   /*  
00976   if (n < 1) {
00977     thePt  = defaultMomentum*charge;
00978     theSpt = defaultMomentum; 
00979     return;
00980   } 
00981   */
00982   // Compute weighted mean and error
00983 
00984   thePt  = (charge*weightPtSum) / sigmaSqr_sum;
00985   theSpt = sqrt( 1.0 / sigmaSqr_sum ) ;
00986 
00987   //std::cout<<" final weighting : "<< thePt <<" ~ "<< fabs( theSpt/thePt ) <<std::endl;
00988 
00989   return;
00990 }
00991 
00992 std::vector<double> MuonSeedCreator::getPt(std::vector<double> vPara, double eta, double dPhi ) {
00993 
00994        double h  = fabs(eta);
00995        double estPt  = ( vPara[0] + vPara[1]*h + vPara[2]*h*h ) / dPhi;
00996        double estSPt = ( vPara[3] + vPara[4]*h + vPara[5]*h*h ) * estPt;
00997        std::vector<double> paraPt ;
00998        paraPt.push_back( estPt );
00999        paraPt.push_back( estSPt ) ;
01000 
01001        //std::cout<<"      pt:"<<estPt<<" +/-"<< estSPt<<"   h:"<<eta<<"  df:"<<dPhi<<std::endl;
01002        return paraPt ;
01003 }
01004 
01005 double MuonSeedCreator::scaledPhi( double dphi, double t1) {
01006 
01007   if (dphi != 0. ) {
01008 
01009     double oPhi = 1./dphi ;
01010     dphi = dphi /( 1. + t1/( oPhi + 10. ) ) ;
01011     return dphi ;
01012 
01013   } else {
01014     return dphi ;
01015   } 
01016 
01017 }
01018