CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/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(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   TrajectoryStateTransform tsTransform;
00309   
00310   //PTrajectoryStateOnDet *seedTSOS = tsTransform.persistentState( tsos, id.rawId());
00311   std::auto_ptr<PTrajectoryStateOnDet> seedTSOS(tsTransform.persistentState( tsos, id.rawId()));  
00312 
00313   edm::OwnVector<TrackingRecHit> container;
00314   for (unsigned l=0; l<seg.size(); l++) {
00315       container.push_back( seg[l]->hit()->clone() ); 
00316       //container.push_back(seg[l]->hit()); 
00317   }
00318 
00319   TrajectorySeed theSeed(*seedTSOS,container,alongMomentum);
00320   return theSeed;
00321 }
00322 
00323 
00324 /*
00325  * estimatePtCSC
00326  *
00327  * Look at delta phi to determine pt as:
00328  * pt = (c_1 * eta + c_2) / dphi
00329  *
00330  * Note that only segment pairs with one segment in the ME1 layers give sensitive results
00331  *
00332  */
00333 void MuonSeedCreator::estimatePtCSC(SegmentContainer seg, std::vector<int> layers, double& thePt, double& theSpt ) {
00334 
00335   unsigned size = seg.size();
00336   if (size < 2) return;
00337   
00338   // reverse the segment and layer container first for pure CSC case
00339   //if ( layers[0] > layers[ layers.size()-1 ] ) {
00340   //   reverse( layers.begin(), layers.end() );
00341   //   reverse( seg.begin(), seg.end() );
00342   //}
00343 
00344   std::vector<double> ptEstimate;
00345   std::vector<double> sptEstimate;
00346 
00347   thePt  = defaultMomentum;
00348   theSpt = defaultMomentum;
00349 
00350   double pt = 0.;
00351   double spt = 0.;   
00352   GlobalPoint  segPos[2];
00353 
00354   int layer0 = layers[0];
00355   segPos[0] = seg[0]->globalPosition();
00356   float eta = fabs( segPos[0].eta() );
00357   //float corr = fabs( tan(segPos[0].theta()) );
00358   // use pt from vertex information
00359   /*
00360   if ( layer0 == 0 ) {
00361      SegmentContainer seg0;
00362      seg0.push_back(seg[0]);
00363      std::vector<int> lyr0(1,0);
00364      estimatePtSingle( seg0, lyr0, thePt, theSpt);
00365      ptEstimate.push_back( thePt );
00366      sptEstimate.push_back( theSpt );
00367   }
00368   */
00369 
00370   //std::cout<<" estimate CSC "<<std::endl;
00371 
00372   unsigned idx1 = size;
00373   if (size > 1) {
00374     while ( idx1 > 1 ) {
00375       idx1--;
00376       int layer1 = layers[idx1];
00377       if (layer0 == layer1) continue;
00378       segPos[1] = seg[idx1]->globalPosition();      
00379 
00380       double dphi = segPos[0].phi() - segPos[1].phi();
00381       //double temp_dphi = dphi/corr;
00382       double temp_dphi = dphi;
00383        
00384       double sign = 1.0;  
00385       if (temp_dphi < 0.) {
00386         temp_dphi = -1.0*temp_dphi;
00387         sign = -1.0;
00388       }
00389 
00390       // Ensure that delta phi is not too small to prevent pt from blowing up
00391       if (temp_dphi < 0.0001 ) { 
00392          temp_dphi = 0.0001 ;
00393          pt = theMaxMomentum ;
00394          spt = theMaxMomentum*0.25 ; 
00395          ptEstimate.push_back( pt*sign );
00396          sptEstimate.push_back( spt );
00397       }
00398       // ME1 is inner-most
00399       if ( layer0 == 0 && temp_dphi >= 0.0001 ) {
00400  
00401         // ME1/2 is outer-most
00402         if ( layer1 ==  1 ) {
00403           //temp_dphi = scaledPhi(temp_dphi, CSC01_1[3] );
00404           pt  = getPt( CSC01, eta , temp_dphi )[0];
00405           spt = getPt( CSC01, eta , temp_dphi )[1];
00406         }  
00407         // ME2 is outer-most
00408         else if ( layer1 == 2  ) {
00409           //temp_dphi = scaledPhi(temp_dphi, CSC12_3[3] );
00410           pt  = getPt( CSC02, eta , temp_dphi )[0];
00411           spt = getPt( CSC02, eta , temp_dphi )[1];
00412         }
00413         // ME3 is outer-most
00414         else if ( layer1 == 3 ) {
00415           //temp_dphi = scaledPhi(temp_dphi, CSC13_3[3] );
00416           pt  = getPt( CSC03, eta , temp_dphi )[0];
00417           spt = getPt( CSC03, eta , temp_dphi )[1];
00418         }
00419         // ME4 is outer-most
00420         else {
00421           //temp_dphi = scaledPhi(temp_dphi, CSC14_3[3]);
00422           pt  = getPt( CSC14, eta , temp_dphi )[0];
00423           spt = getPt( CSC14, eta , temp_dphi )[1];
00424         }
00425         ptEstimate.push_back( pt*sign );
00426         sptEstimate.push_back( spt );
00427       }
00428 
00429       // ME1/2,ME1/3 is inner-most
00430       if ( layer0 == 1 ) {
00431         // ME2 is outer-most
00432         if ( layer1 == 2 ) {
00433 
00434           //if ( eta <= 1.2 )  {   temp_dphi = scaledPhi(temp_dphi, CSC12_1[3]); }
00435           //if ( eta >  1.2 )  {   temp_dphi = scaledPhi(temp_dphi, CSC12_2[3]); }
00436           pt  = getPt( CSC12, eta , temp_dphi )[0];
00437           spt = getPt( CSC12, eta , temp_dphi )[1];
00438         }
00439         // ME3 is outer-most
00440         else if ( layer1 == 3 ) {
00441           temp_dphi = scaledPhi(temp_dphi, CSC13_2[3]);
00442           pt  = getPt( CSC13, eta , temp_dphi )[0];
00443           spt = getPt( CSC13, eta , temp_dphi )[1];
00444         }
00445         // ME4 is outer-most
00446         else {
00447           temp_dphi = scaledPhi(temp_dphi, CSC14_3[3]);
00448           pt  = getPt( CSC14, eta , temp_dphi )[0];
00449           spt = getPt( CSC14, eta , temp_dphi )[1];
00450         }
00451         ptEstimate.push_back( pt*sign );
00452         sptEstimate.push_back( spt );
00453       }
00454 
00455       // ME2 is inner-most
00456       if ( layer0 == 2 && temp_dphi > 0.0001 ) {
00457 
00458         // ME4 is outer-most
00459         bool ME4av =false;
00460         if ( layer1 == 4 )  {
00461           temp_dphi = scaledPhi(temp_dphi, CSC24_1[3]);
00462           pt  = getPt( CSC24, eta , temp_dphi )[0];
00463           spt = getPt( CSC24, eta , temp_dphi )[1];
00464           ME4av = true;
00465         }
00466         // ME3 is outer-most
00467         else {
00468           // if ME2-4 is availabe , discard ME2-3 
00469           if ( !ME4av ) {
00470             if ( eta <= 1.7 )  {   temp_dphi = scaledPhi(temp_dphi, CSC23_1[3]); }
00471             if ( eta >  1.7 )  {   temp_dphi = scaledPhi(temp_dphi, CSC23_2[3]); }
00472             pt  = getPt( CSC23, eta , temp_dphi )[0];
00473             spt = getPt( CSC23, eta , temp_dphi )[1];
00474           }
00475         }
00476         ptEstimate.push_back( pt*sign );   
00477         sptEstimate.push_back( spt );
00478       }
00479 
00480       // ME3 is inner-most
00481       if ( layer0 == 3 && temp_dphi > 0.0001 ) {
00482 
00483         temp_dphi = scaledPhi(temp_dphi, CSC34_1[3]);
00484         pt  = getPt( CSC34, eta , temp_dphi )[0];
00485         spt = getPt( CSC34, eta , temp_dphi )[1];
00486         ptEstimate.push_back( pt*sign );   
00487         sptEstimate.push_back( spt );
00488       }
00489 
00490     } 
00491   }
00492 
00493   // Compute weighted average if have more than one estimator
00494   if ( ptEstimate.size() > 0 ) weightedPt( ptEstimate, sptEstimate, thePt, theSpt);
00495 
00496 }
00497 
00498 
00499 /*
00500  * estimatePtDT
00501  *
00502  * Look at delta phi between segments to determine pt as:
00503  * pt = (c_1 * eta + c_2) / dphi
00504  */
00505 void MuonSeedCreator::estimatePtDT(SegmentContainer seg, std::vector<int> layers, double& thePt, double& theSpt) {
00506 
00507   unsigned size = seg.size();
00508   if (size < 2) return;
00509   
00510   std::vector<double> ptEstimate;
00511   std::vector<double> sptEstimate;
00512 
00513   thePt  = defaultMomentum;
00514   theSpt = defaultMomentum;
00515 
00516   double pt = 0.;
00517   double spt = 0.;   
00518   GlobalPoint segPos[2];
00519 
00520   int layer0 = layers[0];
00521   segPos[0] = seg[0]->globalPosition();
00522   float eta = fabs(segPos[0].eta());
00523 
00524   //std::cout<<" estimate DT "<<std::endl;
00525   // inner-most layer
00526   //for ( unsigned idx0 = 0; idx0 < size-1; ++idx0 ) {
00527   //  layer0 = layers[idx0];
00528   //  segPos[0]  = seg[idx0]->globalPosition();
00529     // outer-most layer
00530     // for ( unsigned idx1 = idx0+1; idx1 < size; ++idx1 ) {
00531     for ( unsigned idx1 = 1; idx1 <size ;  ++idx1 ) {
00532 
00533       int layer1 = layers[idx1];
00534       segPos[1] = seg[idx1]->globalPosition();      
00535  
00536       //eta = fabs(segPos[1].eta());  
00537       //if (layer1 == -4) eta = fabs(segPos[0].eta());
00538 
00539       double dphi = segPos[0].phi() - segPos[1].phi();
00540       double temp_dphi = dphi;
00541 
00542       // Ensure that delta phi is not too small to prevent pt from blowing up
00543       
00544       double sign = 1.0;  
00545       if (temp_dphi < 0.) {
00546         temp_dphi = -temp_dphi;
00547         sign = -1.0;
00548       }
00549       
00550       if (temp_dphi < 0.0001 ) { 
00551          temp_dphi = 0.0001 ;
00552          pt = theMaxMomentum ;
00553          spt = theMaxMomentum*0.25 ; 
00554          ptEstimate.push_back( pt*sign );
00555          sptEstimate.push_back( spt );
00556       }
00557 
00558       // MB1 is inner-most
00559       bool MB23av = false;
00560       if (layer0 == -1 && temp_dphi > 0.0001 ) {
00561         // MB2 is outer-most
00562         if (layer1 == -2) {
00563 
00564           if ( eta <= 0.7 )  {   temp_dphi = scaledPhi(temp_dphi, DT12_1[3]); }
00565           if ( eta >  0.7 )  {   temp_dphi = scaledPhi(temp_dphi, DT12_2[3]); }
00566           pt  = getPt( DT12, eta , temp_dphi )[0];
00567           spt = getPt( DT12, eta , temp_dphi )[1];
00568           MB23av = true;
00569         }
00570         // MB3 is outer-most
00571         else if (layer1 == -3) {
00572 
00573           if ( eta <= 0.6 )  {   temp_dphi = scaledPhi(temp_dphi, DT13_1[3]); }
00574           if ( eta >  0.6 )  {   temp_dphi = scaledPhi(temp_dphi, DT13_2[3]); }
00575           pt  = getPt( DT13, eta , temp_dphi )[0];
00576           spt = getPt( DT13, eta , temp_dphi )[1];
00577           MB23av = true;
00578         }
00579         // MB4 is outer-most
00580         else {
00581           if ( !MB23av ) {
00582              if ( eta <= 0.52 )  {   temp_dphi = scaledPhi(temp_dphi, DT14_1[3]); }
00583              if ( eta >  0.52 )  {   temp_dphi = scaledPhi(temp_dphi, DT14_2[3]); }
00584              pt  = getPt( DT14, eta , temp_dphi )[0];
00585              spt = getPt( DT14, eta , temp_dphi )[1];
00586           }
00587         }
00588         ptEstimate.push_back( pt*sign );
00589         sptEstimate.push_back( spt );
00590       }
00591 
00592       // MB2 is inner-most
00593       if (layer0 == -2 && temp_dphi > 0.0001 ) {
00594         // MB3 is outer-most
00595         if ( layer1 == -3) {
00596 
00597           if ( eta <= 0.6 )  {   temp_dphi = scaledPhi(temp_dphi, DT23_1[3]); }
00598           if ( eta >  0.6 )  {   temp_dphi = scaledPhi(temp_dphi, DT23_2[3]); }
00599           pt  = getPt( DT23, eta , temp_dphi )[0];
00600           spt = getPt( DT23, eta , temp_dphi )[1];
00601         }
00602         // MB4 is outer-most
00603         else {
00604 
00605           if ( eta <= 0.52 )  {   temp_dphi = scaledPhi(temp_dphi, DT24_1[3]); }
00606           if ( eta >  0.52 )  {   temp_dphi = scaledPhi(temp_dphi, DT24_2[3]); }
00607           pt  = getPt( DT24, eta , temp_dphi )[0];
00608           spt = getPt( DT24, eta , temp_dphi )[1];
00609         }
00610         ptEstimate.push_back( pt*sign );
00611         sptEstimate.push_back( spt );
00612       }
00613 
00614       // MB3 is inner-most    -> only marginally useful to pick up the charge
00615       if (layer0 == -3 && temp_dphi > 0.0001 ) {
00616         // MB4 is outer-most
00617 
00618         if ( eta <= 0.51 )  {   temp_dphi = scaledPhi(temp_dphi, DT34_1[3]); }
00619         if ( eta >  0.51 )  {   temp_dphi = scaledPhi(temp_dphi, DT34_2[3]); }
00620         pt  = getPt( DT34, eta , temp_dphi )[0];
00621         spt = getPt( DT34, eta , temp_dphi )[1];
00622         ptEstimate.push_back( pt*sign );   
00623         sptEstimate.push_back( spt );
00624       }
00625     }   
00626   //}
00627   
00628   
00629   // Compute weighted average if have more than one estimator
00630   if (ptEstimate.size() > 0 ) weightedPt( ptEstimate, sptEstimate, thePt, theSpt);
00631 
00632 }
00633 
00634 
00635 /*
00636  * estimatePtOverlap
00637  *
00638  */
00639 void MuonSeedCreator::estimatePtOverlap(SegmentContainer seg, std::vector<int> layers, double& thePt, double& theSpt) {
00640 
00641   int size = layers.size();
00642 
00643   thePt  = defaultMomentum;
00644   theSpt = defaultMomentum;
00645 
00646   SegmentContainer segCSC;
00647   std::vector<int> layersCSC;
00648   SegmentContainer segDT;
00649   std::vector<int> layersDT;
00650 
00651   // DT layers are numbered as -4 to -1, whereas CSC layers go from 0 to 4:
00652   for ( unsigned j = 0; j < layers.size(); ++j ) {
00653     if ( layers[j] > -1 ) {
00654       segCSC.push_back(seg[j]);
00655       layersCSC.push_back(layers[j]);
00656     } 
00657     else {
00658       segDT.push_back(seg[j]);
00659       layersDT.push_back(layers[j]);
00660     } 
00661   }
00662 
00663   std::vector<double> ptEstimate;
00664   std::vector<double> sptEstimate;
00665 
00666   GlobalPoint segPos[2];
00667   int layer0 = layers[0];
00668   segPos[0] = seg[0]->globalPosition();
00669   float eta = fabs(segPos[0].eta());
00670   //std::cout<<" estimate OL "<<std::endl;
00671     
00672   if ( segDT.size() > 0 && segCSC.size() > 0 ) {
00673     int layer1 = layers[size-1];
00674     segPos[1] = seg[size-1]->globalPosition();
00675   
00676     double dphi = segPos[0].phi() - segPos[1].phi();
00677     double temp_dphi = dphi;
00678 
00679     // Ensure that delta phi is not too small to prevent pt from blowing up
00680     
00681     double sign = 1.0;
00682     if (temp_dphi < 0.) {      
00683       temp_dphi = -temp_dphi;
00684       sign = -1.0;  
00685     } 
00686      
00687     if (temp_dphi < 0.0001 ) { 
00688          temp_dphi = 0.0001 ;
00689          thePt = theMaxMomentum ;
00690          theSpt = theMaxMomentum*0.25 ; 
00691          ptEstimate.push_back( thePt*sign );
00692          sptEstimate.push_back( theSpt );
00693     }
00694   
00695     // MB1 is inner-most
00696     if ( layer0 == -1 && temp_dphi > 0.0001 ) {
00697       // ME1/3 is outer-most
00698       if ( layer1 == 1 ) {
00699         temp_dphi = scaledPhi(temp_dphi, OL_1213[3]);
00700         thePt  = getPt( OL1213, eta , temp_dphi )[0];
00701         theSpt = getPt( OL1213, eta , temp_dphi )[1];
00702       }
00703       // ME2 is outer-most
00704       else if ( layer1 == 2) {
00705         temp_dphi = scaledPhi(temp_dphi, OL_1222[3]);
00706         thePt  = getPt( OL1222, eta , temp_dphi )[0];
00707         theSpt = getPt( OL1222, eta , temp_dphi )[1];
00708       }
00709       // ME3 is outer-most
00710       else {
00711         temp_dphi = scaledPhi(temp_dphi, OL_1232[3]);
00712         thePt  = getPt( OL1232, eta , temp_dphi )[0];
00713         theSpt = getPt( OL1232, eta , temp_dphi )[1];
00714       }
00715       ptEstimate.push_back(thePt*sign);
00716       sptEstimate.push_back(theSpt);
00717     } 
00718     // MB2 is inner-most
00719     if ( layer0 == -2 && temp_dphi > 0.0001 ) {
00720       // ME1/3 is outer-most
00721       if ( layer1 == 1 ) {
00722         temp_dphi = scaledPhi(temp_dphi, OL_2213[3]);
00723         thePt  = getPt( OL2213, eta , temp_dphi )[0];
00724         theSpt = getPt( OL2213, eta , temp_dphi )[1];
00725         ptEstimate.push_back(thePt*sign);
00726         sptEstimate.push_back(theSpt);
00727       }
00728       // ME2 is outer-most
00729       if ( layer1 == 2) {
00730         temp_dphi = scaledPhi(temp_dphi, OL_2222[3]);
00731         thePt  = getPt( OL2222, eta , temp_dphi )[0];
00732         theSpt = getPt( OL2222, eta , temp_dphi )[1];
00733       }
00734     }
00735   } 
00736 
00737   if ( segDT.size() > 1 ) {
00738     estimatePtDT(segDT, layersDT, thePt, theSpt);
00739     ptEstimate.push_back(thePt);
00740     sptEstimate.push_back(theSpt);
00741   } 
00742 
00743   /*
00744   // not useful ....and pt estimation is bad
00745   if ( segCSC.size() > 1 ) {
00746     // don't estimate pt without ME1 information
00747     bool CSCLayer1=false;
00748     for (unsigned i=0; i< layersCSC.size(); i++) {
00749         if ( layersCSC[i]==0 || layersCSC[i]==1 ) CSCLayer1 = true;
00750     }
00751     if (CSCLayer1) {
00752        estimatePtCSC(segCSC, layersCSC, thePt, theSpt);
00753        ptEstimate.push_back(thePt);
00754        sptEstimate.push_back(theSpt);
00755     }
00756   }
00757   */
00758 
00759   // Compute weighted average if have more than one estimator
00760   if (ptEstimate.size() > 0 ) weightedPt( ptEstimate, sptEstimate, thePt, theSpt);
00761 
00762 }
00763 /*
00764  *
00765  *   estimate Pt for single segment events
00766  *
00767  */
00768 void MuonSeedCreator::estimatePtSingle(SegmentContainer seg, std::vector<int> layers, double& thePt, double& theSpt) {
00769 
00770   thePt  = defaultMomentum;
00771   theSpt = defaultMomentum;
00772 
00773   GlobalPoint segPos = seg[0]->globalPosition();
00774   double eta = segPos.eta();
00775   GlobalVector gv = seg[0]->globalDirection();
00776 
00777   // Psi is angle between the segment origin and segment direction
00778   // Use dot product between two vectors to get Psi in global x-y plane
00779   double cosDpsi  = (gv.x()*segPos.x() + gv.y()*segPos.y());
00780   cosDpsi /= sqrt(segPos.x()*segPos.x() + segPos.y()*segPos.y());
00781   cosDpsi /= sqrt(gv.x()*gv.x() + gv.y()*gv.y());
00782 
00783   double axb = ( segPos.x()*gv.y() ) - ( segPos.y()*gv.x() ) ;
00784   double sign = (axb < 0.) ? 1.0 : -1.0;
00785 
00786   double dpsi = fabs(acos(cosDpsi)) ;
00787   if ( dpsi > 1.570796 ) {
00788       dpsi = 3.141592 - dpsi;
00789       sign = -1.*sign ;
00790   }
00791   if (fabs(dpsi) < 0.00005) {
00792      dpsi = 0.00005;
00793   }
00794 
00795   // the 1st layer
00796   if ( layers[0] == -1 ) {
00797      // MB10
00798      if ( fabs(eta) < 0.3 ) {
00799         dpsi = scaledPhi(dpsi, SMB_10S[3] );
00800         thePt  = getPt( SMB10, eta , dpsi )[0];
00801         theSpt = getPt( SMB10, eta , dpsi )[1];
00802      }
00803      // MB11
00804      if ( fabs(eta) >= 0.3 && fabs(eta) < 0.82 ) {
00805         dpsi = scaledPhi(dpsi, SMB_11S[3] );
00806         thePt  = getPt( SMB11, eta , dpsi )[0];
00807         theSpt = getPt( SMB11, eta , dpsi )[1];
00808      }
00809      // MB12
00810      if ( fabs(eta) >= 0.82 && fabs(eta) < 1.2 ) {
00811         dpsi = scaledPhi(dpsi, SMB_12S[3] );
00812         thePt  = getPt( SMB12, eta , dpsi )[0];
00813         theSpt = getPt( SMB12, eta , dpsi )[1];
00814      }
00815   }
00816   if ( layers[0] == 1 ) {
00817      // ME13
00818      if ( fabs(eta) > 0.92 && fabs(eta) < 1.16 ) {
00819         dpsi = scaledPhi(dpsi, SME_13S[3] );
00820         thePt  = getPt( SME13, eta , dpsi )[0];
00821         theSpt = getPt( SME13, eta , dpsi )[1];
00822      }
00823      // ME12
00824      if ( fabs(eta) >= 1.16 && fabs(eta) <= 1.6 ) {
00825         dpsi = scaledPhi(dpsi, SME_12S[3] );
00826         thePt  = getPt( SME12, eta , dpsi )[0];
00827         theSpt = getPt( SME12, eta , dpsi )[1];
00828      }
00829   }
00830   if ( layers[0] == 0  ) {
00831      // ME11
00832      if ( fabs(eta) > 1.6 ) {
00833         dpsi = scaledPhi(dpsi, SMB_11S[3] );
00834         thePt  = getPt( SME11, eta , dpsi )[0];
00835         theSpt = getPt( SME11, eta , dpsi )[1];
00836      }
00837   }
00838   // the 2nd layer
00839   if ( layers[0] == -2 ) {
00840      // MB20
00841      if ( fabs(eta) < 0.25 ) {
00842         dpsi = scaledPhi(dpsi, SMB_20S[3] );
00843         thePt  = getPt( SMB20, eta , dpsi )[0];
00844         theSpt = getPt( SMB20, eta , dpsi )[1];
00845      }
00846      // MB21
00847      if ( fabs(eta) >= 0.25 && fabs(eta) < 0.72 ) {
00848         dpsi = scaledPhi(dpsi, SMB_21S[3] );
00849         thePt  = getPt( SMB21, eta , dpsi )[0];
00850         theSpt = getPt( SMB21, eta , dpsi )[1];
00851      }
00852      // MB22
00853      if ( fabs(eta) >= 0.72 && fabs(eta) < 1.04 ) {
00854         dpsi = scaledPhi(dpsi, SMB_22S[3] );
00855         thePt  = getPt( SMB22, eta , dpsi )[0];
00856         theSpt = getPt( SMB22, eta , dpsi )[1];
00857      }
00858   }
00859   if ( layers[0] == 2 ) {
00860      // ME22
00861      if ( fabs(eta) > 0.95 && fabs(eta) <= 1.6 ) {
00862         dpsi = scaledPhi(dpsi, SME_22S[3] );
00863         thePt  = getPt( SME22, eta , dpsi )[0];
00864         theSpt = getPt( SME22, eta , dpsi )[1];
00865      }
00866      // ME21
00867      if ( fabs(eta) > 1.6 && fabs(eta) < 2.45 ) {
00868         dpsi = scaledPhi(dpsi, SME_21S[3] );
00869         thePt  = getPt( SME21, eta , dpsi )[0];
00870         theSpt = getPt( SME21, eta , dpsi )[1];
00871      }
00872   }
00873 
00874   // the 3rd layer
00875   if ( layers[0] == -3 ) {
00876      // MB30
00877      if ( fabs(eta) <= 0.22 ) {
00878         dpsi = scaledPhi(dpsi, SMB_30S[3] );
00879         thePt  = getPt( SMB30, eta , dpsi )[0];
00880         theSpt = getPt( SMB30, eta , dpsi )[1];
00881      }
00882      // MB31
00883      if ( fabs(eta) > 0.22 && fabs(eta) <= 0.6 ) {
00884         dpsi = scaledPhi(dpsi, SMB_31S[3] );
00885         thePt  = getPt( SMB31, eta , dpsi )[0];
00886         theSpt = getPt( SMB31, eta , dpsi )[1];
00887      }
00888      // MB32
00889      if ( fabs(eta) > 0.6 && fabs(eta) < 0.95 ) {
00890         dpsi = scaledPhi(dpsi, SMB_32S[3] );
00891         thePt  = getPt( SMB32, eta , dpsi )[0];
00892         theSpt = getPt( SMB32, eta , dpsi )[1];
00893      }
00894   }
00895   thePt = fabs(thePt)*sign;
00896   theSpt = fabs(theSpt);
00897 
00898   return;
00899 }
00900 
00901 // setup the minimum value for obvious showering cases  
00902 void MuonSeedCreator::estimatePtShowering(int& NShowers, int& NShowerSegments,  double& thePt, double& theSpt) {
00903 
00904   if ( NShowers > 2 && thePt < 300. ) {
00905      thePt  = 800. ;
00906      theSpt = 200. ; 
00907   } 
00908   if ( NShowers == 2 && NShowerSegments >  11 && thePt < 150. ) {
00909      thePt = 280. ;
00910      theSpt = 70. ; 
00911   }
00912   if ( NShowers == 2 && NShowerSegments <= 11 && thePt < 50.  ) {
00913      thePt =  80.;
00914      theSpt = 40. ;
00915   }
00916   if ( NShowers == 1 && NShowerSegments <= 5 && thePt < 10. ) {
00917      thePt = 16. ;
00918      theSpt = 8. ; 
00919   }
00920 
00921 }
00922 
00923 /*
00924  * weightedPt
00925  *
00926  * Look at delta phi between segments to determine pt as:
00927  * pt = (c_1 * eta + c_2) / dphi
00928  */
00929 void MuonSeedCreator::weightedPt(std::vector<double> ptEstimate, std::vector<double> sptEstimate, double& thePt, double& theSpt) {
00930 
00931  
00932   int size = ptEstimate.size();
00933 
00934   // If only one element, by-pass computation below
00935   if (size < 2) {
00936     thePt = ptEstimate[0];
00937     theSpt = sptEstimate[0];
00938     return;
00939   }
00940 
00941   double charge = 0.;
00942   // If have more than one pt estimator, first look if any estimator is biased
00943   // by comparing the charge of each estimator
00944 
00945   for ( unsigned j = 0; j < ptEstimate.size(); j++ ) {
00946     //std::cout<<" weighting pt: "<< ptEstimate[j] <<std::endl; 
00947     if ( ptEstimate[j] < 0. ) {
00948       // To prevent from blowing up, add 0.1 
00949       charge -= 1. * (ptEstimate[j]*ptEstimate[j]) / (sptEstimate[j]*sptEstimate[j] );  // weight by relative error on pt
00950     } else {
00951       charge += 1. * (ptEstimate[j]*ptEstimate[j]) / (sptEstimate[j]*sptEstimate[j] );  // weight by relative error on pt
00952     }
00953   }
00954  
00955   // No need to normalize as we want to know only sign ( + or - )
00956   if (charge < 0.) {
00957     charge = -1.;
00958   } else {
00959     charge = 1.;
00960   }
00961 
00962   //int n = 0;
00963   double weightPtSum  = 0.;
00964   double sigmaSqr_sum = 0.;
00965           
00966   // Now, we want to compute average Pt using estimators with "correct" charge
00967   // This is to remove biases
00968   for ( unsigned j = 0; j < ptEstimate.size(); ++j ) {
00969     //if ( (minpt_ratio < 0.5) && (fabs(ptEstimate[j]) < 5.0) ) continue;
00970     //if ( ptEstimate[j] * charge > 0. ) {
00971       //n++;
00972       sigmaSqr_sum += 1.0 / (sptEstimate[j]*sptEstimate[j]);
00973       weightPtSum  += fabs(ptEstimate[j])/(sptEstimate[j]*sptEstimate[j]);
00974     //}
00975   }
00976   /*  
00977   if (n < 1) {
00978     thePt  = defaultMomentum*charge;
00979     theSpt = defaultMomentum; 
00980     return;
00981   } 
00982   */
00983   // Compute weighted mean and error
00984 
00985   thePt  = (charge*weightPtSum) / sigmaSqr_sum;
00986   theSpt = sqrt( 1.0 / sigmaSqr_sum ) ;
00987 
00988   //std::cout<<" final weighting : "<< thePt <<" ~ "<< fabs( theSpt/thePt ) <<std::endl;
00989 
00990   return;
00991 }
00992 
00993 std::vector<double> MuonSeedCreator::getPt(std::vector<double> vPara, double eta, double dPhi ) {
00994 
00995        double h  = fabs(eta);
00996        double estPt  = ( vPara[0] + vPara[1]*h + vPara[2]*h*h ) / dPhi;
00997        double estSPt = ( vPara[3] + vPara[4]*h + vPara[5]*h*h ) * estPt;
00998        std::vector<double> paraPt ;
00999        paraPt.push_back( estPt );
01000        paraPt.push_back( estSPt ) ;
01001 
01002        //std::cout<<"      pt:"<<estPt<<" +/-"<< estSPt<<"   h:"<<eta<<"  df:"<<dPhi<<std::endl;
01003        return paraPt ;
01004 }
01005 
01006 double MuonSeedCreator::scaledPhi( double dphi, double t1) {
01007 
01008   if (dphi != 0. ) {
01009 
01010     double oPhi = 1./dphi ;
01011     dphi = dphi /( 1. + t1/( oPhi + 10. ) ) ;
01012     return dphi ;
01013 
01014   } else {
01015     return dphi ;
01016   } 
01017 
01018 }
01019