CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/RecoMuon/MuonSeedGenerator/src/SETSeedFinder.cc

Go to the documentation of this file.
00001 
00005 #include "RecoMuon/MuonSeedGenerator/src/SETSeedFinder.h"
00006 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00007 #include "FWCore/Framework/interface/Event.h"
00008 #include "RecoMuon/TrackingTools/interface/MuonPatternRecoDumper.h"
00009 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00010 #include "TrackingTools/DetLayers/interface/DetLayer.h"
00011 #include "Geometry/CommonDetUnit/interface/GeomDet.h"
00012 #include "DataFormats/MuonDetId/interface/MuonSubdetId.h"
00013 #include "DataFormats/MuonDetId/interface/CSCDetId.h"
00014 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00015 
00016 #include "TMath.h"
00017 
00018 
00019 using namespace edm;
00020 using namespace std;
00021 
00022 const string metname = "Muon|RecoMuon|SETMuonSeedFinder";
00023 
00024 SETSeedFinder::SETSeedFinder(const ParameterSet& parameterSet)
00025 : MuonSeedVFinder()
00026 {
00027   // Parameter set for the Builder
00028   ParameterSet trajectoryBuilderParameters = parameterSet.getParameter<ParameterSet>("SETTrajBuilderParameters");
00029   apply_prePruning = trajectoryBuilderParameters.getParameter<bool>("Apply_prePruning");
00030   // load pT seed parameters
00031   thePtExtractor = new MuonSeedPtExtractor(trajectoryBuilderParameters);
00032 
00033 } 
00034 
00035 
00036 void SETSeedFinder::seeds(const MuonRecHitContainer & cluster,
00037                           std::vector<TrajectorySeed> & result)
00038 {
00039 }
00040 
00041 
00042 
00043 // there is an existing sorter somewhere in the CMSSW code (I think) - delete that
00044 struct sorter{
00045   bool operator() (MuonTransientTrackingRecHit::MuonRecHitPointer const & hit_1,
00046                    MuonTransientTrackingRecHit::MuonRecHitPointer const & hit_2){
00047     return (hit_1->globalPosition().mag2()<hit_2->globalPosition().mag2());
00048 
00049   }
00050 } sortSegRadius;// smaller first
00051 
00052 
00053 
00054 std::vector<SETSeedFinder::MuonRecHitContainer>
00055 SETSeedFinder::sortByLayer(MuonRecHitContainer & cluster) const
00056 {
00057   stable_sort(cluster.begin(), cluster.end(),sortSegRadius);
00058     //---- group hits in detector layers (if in same layer); the idea is that
00059     //---- some hits could not belong to a track simultaneously - these will be in a
00060     //---- group; two hits from one and the same group will not go to the same track
00061   std::vector< MuonRecHitContainer > MuonRecHitContainer_perLayer;
00062   if(cluster.size()){
00063     int iHit =0;
00064     MuonRecHitContainer hitsInThisLayer;
00065     hitsInThisLayer.push_back(cluster[iHit]);
00066     DetId  detId = cluster[iHit]->hit()->geographicalId();
00067     const GeomDet* geomDet = theService->trackingGeometry()->idToDet( detId );
00068     while(iHit<int(cluster.size())-1){
00069       DetId  detId_2 = cluster[iHit+1]->hit()->geographicalId();
00070       const GlobalPoint gp_nextHit = cluster[iHit+1]->globalPosition();
00071 
00072       // this is the distance of the "second" hit to the "first" detector (containing the "first hit")
00073       float distanceToDetector = fabs(geomDet->surface().localZ(gp_nextHit));
00074 
00075       //---- hits from DT and CSC  could be very close in angle but incosistent with
00076       //---- belonging to a common track (and these are different surfaces);
00077       //---- also DT (and CSC now - 090822) hits from a station (in a pre-cluster) should be always in a group together;
00078       //---- take this into account and put such hits in a group together
00079 
00080       bool specialCase = false;
00081       if( detId.subdetId()   == MuonSubdetId::DT &&
00082           detId_2.subdetId() == MuonSubdetId::DT    ){
00083         DTChamberId dtCh(detId);
00084         DTChamberId dtCh_2(detId_2);
00085         specialCase =  (dtCh.station() == dtCh_2.station());
00086       }
00087       else if(detId.subdetId()   == MuonSubdetId::CSC &&
00088               detId_2.subdetId()   == MuonSubdetId::CSC){
00089         CSCDetId cscCh(detId);
00090         CSCDetId cscCh_2(detId_2);
00091         specialCase = (cscCh.station() == cscCh_2.station() && cscCh.ring() == cscCh_2.ring());
00092       } 
00093 
00094       if(distanceToDetector<0.001 || true==specialCase){ // hardcoded value - remove!
00095         hitsInThisLayer.push_back(cluster[iHit+1]);
00096       }
00097       else{
00098         specialCase = false;
00099         if(( (cluster[iHit]->isDT() &&
00100               cluster[iHit+1]->isCSC()) ||
00101              (cluster[iHit]->isCSC() &&
00102               cluster[iHit+1]->isDT())) &&
00103          //---- what is the minimal distance between a DT and a CSC hit belonging
00104          //---- to a common track? (well, with "reasonable" errors; put 10 cm for now)
00105            fabs(cluster[iHit+1]->globalPosition().mag() -
00106                 cluster[iHit]->globalPosition().mag())<10.){
00107           hitsInThisLayer.push_back(cluster[iHit+1]);
00108           // change to Stoyan - now we also update the detID here... give it a try. IBL 080905
00109           detId = cluster[iHit+1]->hit()->geographicalId();
00110           geomDet = theService->trackingGeometry()->idToDet( detId );
00111         }
00112         else if(!specialCase){
00113           //---- put the group of hits in the vector (containing the groups of hits)
00114           //---- and continue with next layer (group)
00115           MuonRecHitContainer_perLayer.push_back(hitsInThisLayer);
00116           hitsInThisLayer.clear();
00117           hitsInThisLayer.push_back(cluster[iHit+1]);
00118           detId = cluster[iHit+1]->hit()->geographicalId();
00119           geomDet = theService->trackingGeometry()->idToDet( detId );
00120         }
00121       }
00122       ++iHit;
00123     }
00124     MuonRecHitContainer_perLayer.push_back(hitsInThisLayer);
00125   }
00126   return MuonRecHitContainer_perLayer;
00127 }
00128 //
00129 void SETSeedFinder::limitCombinatorics(std::vector< MuonRecHitContainer > & MuonRecHitContainer_perLayer){
00130   const int maximumNumberOfCombinations = 1000000;
00131   unsigned nLayers = MuonRecHitContainer_perLayer.size();
00132   if(1==nLayers){
00133     return ;
00134   }
00135   // maximal number of (segment) layers would be upto ~12; see next function
00136   // below is just a quick fix for a rare "overflow"
00137   if(MuonRecHitContainer_perLayer.size()>15){
00138     MuonRecHitContainer_perLayer.resize(1);
00139     return;
00140   }
00141                 
00142   std::vector <double> sizeOfLayer(nLayers);
00143   //std::cout<<" nLayers = "<<nLayers<<std::endl;
00144   double nAllCombinations = 1.;
00145   for(unsigned int i = 0;i<nLayers;++i ){
00146     //std::cout<<" i = "<<i<<" size = "<<MuonRecHitContainer_perLayer.at(i).size()<<std::endl;
00147     sizeOfLayer.at(i) = MuonRecHitContainer_perLayer.at(i).size();
00148     nAllCombinations*=MuonRecHitContainer_perLayer.at(i).size();
00149   }
00150   //std::cout<<"nAllCombinations = "<<nAllCombinations<<std::endl;
00151   //---- Erase most busy detector layers until we get less than maximumNumberOfCombinations combinations
00152   int iCycle = 0;
00153   while(nAllCombinations > float(maximumNumberOfCombinations)){
00154     ++iCycle;
00155     std::vector <double>::iterator maxEl_it = max_element(sizeOfLayer.begin(),sizeOfLayer.end());
00156     int maxEl = maxEl_it - sizeOfLayer.begin();
00157     nAllCombinations/=MuonRecHitContainer_perLayer.at(maxEl).size();
00158     //std::cout<<" iCycle = "<<iCycle<<" nAllCombinations = "<<nAllCombinations<<std::endl;
00159     MuonRecHitContainer_perLayer.erase(MuonRecHitContainer_perLayer.begin()+maxEl);
00160     sizeOfLayer.erase(sizeOfLayer.begin()+maxEl);
00161   }
00162   return;
00163 }
00164 //
00165 std::vector<SETSeedFinder::MuonRecHitContainer>
00166 SETSeedFinder::findAllValidSets(const std::vector<SETSeedFinder::MuonRecHitContainer> & MuonRecHitContainer_perLayer)
00167 {
00168   std::vector <MuonRecHitContainer> allValidSets;
00169   // build all possible combinations (i.e valid sets; the algorithm name is after this feature -
00170   // SET algorithm)
00171   //
00172   // ugly... use recursive function?!
00173   // or implement Ingo's suggestion (a la ST)
00174   unsigned nLayers = MuonRecHitContainer_perLayer.size();
00175   if(1==nLayers){
00176     return allValidSets;
00177   }
00178   MuonRecHitContainer validSet;
00179   unsigned int iPos0 = 0;
00180   std::vector <unsigned int> iLayer(12);// could there be more than 11 layers?
00181   std::vector <unsigned int> size(12);
00182   if(iPos0<nLayers){
00183     size.at(iPos0) =  MuonRecHitContainer_perLayer.at(iPos0).size();
00184     for(iLayer[iPos0] = 0; iLayer[iPos0]<size[iPos0];++iLayer[iPos0]){
00185       validSet.clear();
00186       validSet.push_back(MuonRecHitContainer_perLayer[iPos0][iLayer[iPos0]]);
00187       unsigned int iPos1 = 1;
00188       if(iPos1<nLayers){
00189         size.at(iPos1) =  MuonRecHitContainer_perLayer.at(iPos1).size();
00190         for(iLayer[iPos1] = 0; iLayer[iPos1]<size[iPos1];++iLayer[iPos1]){
00191           validSet.resize(iPos1);
00192           validSet.push_back(MuonRecHitContainer_perLayer[iPos1][iLayer[iPos1]]);
00193           unsigned int iPos2 = 2;
00194           if(iPos2<nLayers){
00195             size.at(iPos2) =  MuonRecHitContainer_perLayer.at(iPos2).size();
00196             for(iLayer[iPos2] = 0; iLayer[iPos2]<size[iPos2];++iLayer[iPos2]){
00197               validSet.resize(iPos2);
00198               validSet.push_back(MuonRecHitContainer_perLayer[iPos2][iLayer[iPos2]]);
00199               unsigned int iPos3 = 3;
00200               if(iPos3<nLayers){
00201                 size.at(iPos3) =  MuonRecHitContainer_perLayer.at(iPos3).size();
00202                 for(iLayer[iPos3] = 0; iLayer[iPos3]<size[iPos3];++iLayer[iPos3]){
00203                   validSet.resize(iPos3);
00204                   validSet.push_back(MuonRecHitContainer_perLayer[iPos3][iLayer[iPos3]]);
00205                   unsigned int iPos4 = 4;
00206                   if(iPos4<nLayers){
00207                     size.at(iPos4) =  MuonRecHitContainer_perLayer.at(iPos4).size();
00208                     for(iLayer[iPos4] = 0; iLayer[iPos4]<size[iPos4];++iLayer[iPos4]){
00209                       validSet.resize(iPos4);
00210                       validSet.push_back(MuonRecHitContainer_perLayer[iPos4][iLayer[iPos4]]);
00211                       unsigned int iPos5 = 5;
00212                       if(iPos5<nLayers){
00213                         size.at(iPos5) =  MuonRecHitContainer_perLayer.at(iPos5).size();
00214                         for(iLayer[iPos5] = 0; iLayer[iPos5]<size[iPos5];++iLayer[iPos5]){
00215                           validSet.resize(iPos5);
00216                           validSet.push_back(MuonRecHitContainer_perLayer[iPos5][iLayer[iPos5]]);
00217                           unsigned int iPos6 = 6;
00218                           if(iPos6<nLayers){
00219                             size.at(iPos6) =  MuonRecHitContainer_perLayer.at(iPos6).size();
00220                             for(iLayer[iPos6] = 0; iLayer[iPos6]<size[iPos6];++iLayer[iPos6]){
00221                               validSet.resize(iPos6);
00222                               validSet.push_back(MuonRecHitContainer_perLayer[iPos6][iLayer[iPos6]]);
00223                               unsigned int iPos7 = 7;
00224                               if(iPos7<nLayers){
00225                                 size.at(iPos7) =  MuonRecHitContainer_perLayer.at(iPos7).size();
00226                                 for(iLayer[iPos7] = 0; iLayer[iPos7]<size[iPos7];++iLayer[iPos7]){
00227                                   validSet.resize(iPos7);
00228                                   validSet.push_back(MuonRecHitContainer_perLayer[iPos7][iLayer[iPos7]]);
00229                                   unsigned int iPos8 = 8;
00230                                   if(iPos8<nLayers){
00231                                     size.at(iPos8) =  MuonRecHitContainer_perLayer.at(iPos8).size();
00232                                     for(iLayer[iPos8] = 0; iLayer[iPos8]<size[iPos8];++iLayer[iPos8]){
00233                                       validSet.resize(iPos8);
00234                                       validSet.push_back(MuonRecHitContainer_perLayer[iPos8][iLayer[iPos8]]);
00235                                       unsigned int iPos9 = 9;
00236                                       if(iPos9<nLayers){
00237                                         size.at(iPos9) =  MuonRecHitContainer_perLayer.at(iPos9).size();
00238                                         for(iLayer[iPos9] = 0; iLayer[iPos9]<size[iPos9];++iLayer[iPos9]){
00239                                           validSet.resize(iPos9);
00240                                           validSet.push_back(MuonRecHitContainer_perLayer[iPos9][iLayer[iPos9]]);
00241                                           unsigned int iPos10 = 10;
00242                                           if(iPos10<nLayers){
00243                                             size.at(iPos10) =  MuonRecHitContainer_perLayer.at(iPos10).size();
00244                                             for(iLayer[iPos10] = 0; iLayer[iPos10]<size[iPos10];++iLayer[iPos10]){
00245                                               validSet.resize(iPos10);
00246                                               validSet.push_back(MuonRecHitContainer_perLayer[iPos10][iLayer[iPos10]]);
00247                                               unsigned int iPos11 = 11;// more?
00248                                               if(iPos11<nLayers){
00249                                                 size.at(iPos11) =  MuonRecHitContainer_perLayer.at(iPos11).size();
00250                                                 for(iLayer[iPos11] = 0; iLayer[iPos11]<size[iPos11];++iLayer[iPos11]){
00251                                                }
00252                                               }
00253                                               else{
00254                                                 allValidSets.push_back(validSet);
00255 
00256                                               }
00257                                             }
00258                                           }
00259                                           else{
00260                                             allValidSets.push_back(validSet);
00261                                           }
00262                                         }
00263                                       }
00264                                       else{
00265                                         allValidSets.push_back(validSet);
00266                                       }
00267                                     }
00268                                   }
00269                                   else{
00270                                     allValidSets.push_back(validSet);
00271                                   }
00272                                 }
00273                               }
00274                               else{
00275                                 allValidSets.push_back(validSet);
00276                               }
00277                             }
00278                           }
00279                           else{
00280                             allValidSets.push_back(validSet);
00281                           }
00282                         }
00283                       }
00284                       else{
00285                         allValidSets.push_back(validSet);
00286                       }
00287                     }
00288                   }
00289                   else{
00290                     allValidSets.push_back(validSet);
00291                   }
00292                 }
00293               }
00294               else{
00295                 allValidSets.push_back(validSet);
00296               }
00297             }
00298           }
00299           else{
00300             allValidSets.push_back(validSet);
00301           }
00302         }
00303       }
00304       else{
00305         allValidSets.push_back(validSet);
00306       }
00307     }
00308   }
00309   else{
00310     allValidSets.push_back(validSet);
00311   }
00312   return allValidSets;
00313 }
00314 
00315 
00316 std::pair <int, int> // or <bool, bool>
00317 SETSeedFinder::checkAngleDeviation(double dPhi_1, double dPhi_2) const
00318 {
00319   // Two conditions:
00320   // a) deviations should be only to one side (above some absolute value cut to avoid
00321   //    material effects; this should be refined)
00322   // b) deviatiation in preceding steps should be bigger due to higher magnetic field
00323   //    (again - a minimal value cut should be in place; this also should account for
00324   //     the small (Z) distances in overlaping CSC chambers)
00325 
00326   double mult = dPhi_1 * dPhi_2;
00327   int signVal = 1;
00328   if(fabs(dPhi_1)<fabs(dPhi_2)){
00329     signVal = -1;
00330   }
00331   int signMult = -1;
00332   if(mult>0) signMult = 1;
00333   std::pair <int, int> sign;
00334   sign = make_pair (signVal, signMult);
00335 
00336   return sign;
00337 }
00338 
00339 
00340 void SETSeedFinder::validSetsPrePruning(std::vector<SETSeedFinder::MuonRecHitContainer> & allValidSets)
00341 {
00342   //---- this actually is a pre-pruning; it does not include any fit information;
00343   //---- it is intended to remove only very "wild" segments from a set;
00344   //---- no "good" segment is to be lost (otherwise - widen the parameters)
00345 
00346   for(unsigned int iSet = 0;iSet<allValidSets.size();++iSet){
00347     pre_prune(allValidSets[iSet]);
00348   }
00349 }
00350 
00351 
00352 void SETSeedFinder::pre_prune(SETSeedFinder::MuonRecHitContainer & validSet) const
00353 {
00354   unsigned nHits = validSet.size();
00355   if(nHits>3){ // to decide we need at least 4 measurements
00356     // any information could be used to make a decision for pruning
00357     // maybe dPhi (delta Phi) is enough
00358     std::vector <double> dPhi;
00359     double dPhi_tmp;
00360     bool wildCandidate;
00361     int pruneHit_tmp;
00362 
00363     for(unsigned int iHit = 1;iHit<nHits;++iHit){
00364       dPhi_tmp = validSet[iHit]->globalPosition().phi() -
00365                  validSet[iHit-1]->globalPosition().phi();
00366       dPhi.push_back(dPhi_tmp);
00367     }
00368     std::vector <int> pruneHit;
00369     //---- loop over all the hits in a set
00370 
00371     for(unsigned int iHit = 0;iHit<nHits;++iHit){
00372       double dPHI_MIN = 0.02;//?? hardcoded - remove it
00373       if(iHit){
00374         // if we have to remove the very first hit (iHit == 0) then
00375         // we'll probably be in trouble already
00376         wildCandidate = false;
00377         // actually 2D is bad only if not r-phi... Should I refine it?
00378         // a hit is a candidate for pruning only if dPhi > dPHI_MIN;
00379         // pruning decision is based on combination of hits characteristics
00380         if(4==validSet[iHit-1]->dimension() && 4 == validSet[iHit]->dimension() &&
00381            fabs(validSet[iHit]->globalPosition().phi() -
00382                 validSet[iHit-1]->globalPosition().phi())>dPHI_MIN ){
00383           wildCandidate = true;
00384         }
00385         pruneHit_tmp = -1;
00386         if(wildCandidate){
00387           // OK - this couple doesn't look good (and is from 4D segments); proceed...
00388           if(1==iHit){// the first  and the last hits are special case
00389             if(4==validSet[iHit+1]->dimension() && 4 == validSet[iHit+2]->dimension()){//4D?
00390               // is the picture better if we remove the second hit?
00391               dPhi_tmp = validSet[iHit+1]->globalPosition().phi() -
00392                 validSet[iHit-1]->globalPosition().phi();
00393               // is the deviation what we expect (sign, not magnitude)?
00394               std::pair <int, int> sign = checkAngleDeviation(dPhi_tmp, dPhi[2]);
00395               if( 1==sign.first && 1==sign.second){
00396                 pruneHit_tmp = iHit;// mark the hit 1 for removing
00397               }
00398             }
00399           }
00400           else if(iHit>1 && iHit<validSet.size()-1){
00401             if(4 == validSet[0]->dimension() && // we rely on the first (most important) couple
00402                4 == validSet[1]->dimension() &&
00403                pruneHit.back()!=int(iHit-1) && pruneHit.back()!=1){// check if hits are already marked
00404               // decide which of the two hits should be removed (if any; preferably the outer one i.e.
00405               // iHit rather than iHit-1); here - check what we get by removing iHit
00406               dPhi_tmp = validSet[iHit+1]->globalPosition().phi() -
00407                 validSet[iHit-1]->globalPosition().phi();
00408               // first couple is most important anyway so again compare to it
00409               std::pair <int, int> sign = checkAngleDeviation(dPhi[0],dPhi_tmp);
00410               if( 1==sign.first && 1==sign.second){
00411                 pruneHit_tmp = iHit; // mark the hit iHit for removing
00412               }
00413               else{ // iHit is not to be removed; proceed...
00414                 // what if we remove (iHit - 1) instead of iHit?
00415                 dPhi_tmp = validSet[iHit+1]->globalPosition().phi() -
00416                   validSet[iHit]->globalPosition().phi();
00417                 std::pair <int, int> sign = checkAngleDeviation(dPhi[0],dPhi_tmp);
00418                 if( 1==sign.first && 1==sign.second){
00419                   pruneHit_tmp = iHit-1;// mark the hit (iHit -1) for removing
00420                 }
00421               }
00422             }
00423           }
00424           else{
00425             // the last hit: if picture is not good - remove it
00426             if(pruneHit.size()>1 && pruneHit[pruneHit.size()-1]<0 && pruneHit[pruneHit.size()-2]<0){
00427               std::pair <int, int> sign = checkAngleDeviation(dPhi[dPhi.size()-2], dPhi[dPhi.size()-1]);
00428               if( -1==sign.first && -1==sign.second){// here logic is a bit twisted
00429                 pruneHit_tmp = iHit; // mark the last hit for removing
00430               }
00431             }
00432           }
00433         }
00434         pruneHit.push_back(pruneHit_tmp);
00435       }
00436     }
00437       // }
00438      // actual pruning
00439      for(unsigned int iHit = 1;iHit<nHits;++iHit){
00440         int count = 0;
00441       if(pruneHit[iHit-1]>0){
00442         validSet.erase(validSet.begin()+pruneHit[iHit-1]-count);
00443         ++count;
00444       }
00445     }
00446   }
00447 }
00448 
00449 
00450 std::vector <SeedCandidate> SETSeedFinder::
00451 fillSeedCandidates(std::vector <MuonRecHitContainer> & allValidSets){
00452   //---- we have the valid sets constructed; transform the information in an
00453   //---- apropriate form; meanwhile - estimate the momentum for a given set
00454 
00455   // RPCs should not be used (no parametrization)
00456   std::vector <SeedCandidate> seedCandidates_inCluster;
00457   // calculate and fill the inputs needed
00458   // loop over all valid sets
00459   for(unsigned int iSet = 0;iSet<allValidSets.size();++iSet){
00460     //
00461     //std::cout<<"  This is SET number : "<<iSet<<std::endl; 
00462     //for(unsigned int iHit = 0;iHit<allValidSets[iSet].size();++iHit){
00463     //std::cout<<"   measurements in the SET:  iHit = "<<iHit<<" pos = "<<allValidSets[iSet][iHit]->globalPosition()<<
00464     //" dim = "<<allValidSets[iSet][iHit]->dimension()<<std::endl;
00465     //}
00466 
00467 
00468     CLHEP::Hep3Vector momEstimate;
00469     int chargeEstimate;
00470     estimateMomentum(allValidSets[iSet], momEstimate, chargeEstimate);
00471     MuonRecHitContainer MuonRecHitContainer_theSet_prep;
00472     // currently hardcoded - will be in proper loop of course:
00473 
00474     SeedCandidate seedCandidates_inCluster_prep;
00475     seedCandidates_inCluster_prep.theSet   = allValidSets[iSet];
00476     seedCandidates_inCluster_prep.momentum = momEstimate;
00477     seedCandidates_inCluster_prep.charge   = chargeEstimate;
00478     seedCandidates_inCluster.push_back(seedCandidates_inCluster_prep);
00479     // END estimateMomentum
00480   }
00481   return seedCandidates_inCluster;
00482 }
00483 
00484 void SETSeedFinder::estimateMomentum(const MuonRecHitContainer & validSet,
00485                                      CLHEP::Hep3Vector & momEstimate, int & charge) const
00486 {
00487   int firstMeasurement = -1;
00488   int lastMeasurement = -1;
00489 
00490   // don't use 2D measurements for momentum estimation 
00491 
00492   //if( 4==allValidSets[iSet].front()->dimension() &&
00493   //(allValidSets[iSet].front()->isCSC() || allValidSets[iSet].front()->isDT())){
00494   //firstMeasurement = 0;
00495   //}
00496   //else{
00497   // which is the "first" hit (4D)?
00498   for(unsigned int iMeas = 0;iMeas<validSet.size();++iMeas){
00499     if(4==validSet[iMeas]->dimension() &&
00500        (validSet[iMeas]->isCSC() || validSet[iMeas]->isDT())){
00501       firstMeasurement = iMeas;
00502       break;
00503     }
00504   }
00505     //}
00506 
00507   std::vector<double> momentum_estimate;
00508   double pT = 0.;
00509   MuonTransientTrackingRecHit::ConstMuonRecHitPointer  firstHit;
00510   MuonTransientTrackingRecHit::ConstMuonRecHitPointer  secondHit;
00511   // which is the second hit?
00512   for(int loop = 0; loop<2; ++loop){// it is actually not used; to be removed
00513     // this is the last measurement
00514     if(!loop){// this is what is used currently
00515       // 23.04.09 : it becomes a problem with introduction of ME42 chambers -
00516       // the initial pT parametrization is incorrect for them
00517       for(int iMeas = validSet.size()-1;iMeas>-1;--iMeas){
00518         if(4==validSet[iMeas]->dimension() &&
00519            (validSet[iMeas]->isCSC() || validSet[iMeas]->isDT()) &&
00520         // below is a fix saying "don't use ME4 chambers for initial pT estimation";
00521         // not using ME41 should not be a big loss too (and is more "symmetric" solution)
00522           fabs(validSet[iMeas]->globalPosition().z())<1000.){
00523           lastMeasurement = iMeas;
00524           break;
00525         }
00526       }
00527     }
00528     else{
00529       // this is the second measurement
00530       for(unsigned int iMeas = 1;iMeas<validSet.size();++iMeas){
00531         if(4==validSet[iMeas]->dimension() &&
00532            (validSet[iMeas]->isCSC() || validSet[iMeas]->isDT())){
00533           lastMeasurement = iMeas;
00534           break;
00535         }
00536       }
00537     }
00538     // only 2D measurements (it should have been already abandoned)
00539     if(-1==lastMeasurement && -1==firstMeasurement){
00540        firstMeasurement = 0;
00541        lastMeasurement = validSet.size()-1;
00542     }
00543     // because of the ME42 above lastMeasurement could be -1
00544     else if(-1==lastMeasurement){
00545       lastMeasurement = firstMeasurement;
00546     }
00547    else if(-1==firstMeasurement){
00548      firstMeasurement = lastMeasurement;        
00549    }
00550 
00551     firstHit = validSet[firstMeasurement];
00552     secondHit = validSet[lastMeasurement];
00553       if(firstHit->isRPC() && secondHit->isRPC()){ // remove all RPCs from here?
00554         momentum_estimate.push_back(300.);
00555      momentum_estimate.push_back(300.);
00556     }
00557     else{
00558       if(firstHit->isRPC()){
00559         firstHit = secondHit;
00560       }
00561       else if(secondHit->isRPC()){
00562         secondHit  = firstHit;
00563       }
00564       //---- estimate pT given two hits
00565       //std::cout<<"   hits for initial pT estimate: first -> dim = "<<firstHit->dimension()<<" pos = "<<firstHit->globalPosition()<<
00566       //" , second -> "<<" dim = "<<secondHit->dimension()<<" pos = "<<secondHit->globalPosition()<<std::endl;
00567      //---- pT throws exception if hits are MB4 
00568      // (no coding for them - 2D hits in the outer station) 
00569      if(2==firstHit->dimension() && 2==secondHit->dimension()){
00570         momentum_estimate.push_back(999999999.);
00571         momentum_estimate.push_back(999999999.);
00572       }
00573       else{
00574         momentum_estimate = thePtExtractor->pT_extract(firstHit, secondHit);
00575       } 
00576     }
00577     pT = fabs(momentum_estimate[0]);
00578     if(1 || pT>40.){ //it is skipped; we have to look at least into number of hits in the chamber actually...
00579       // and then decide which segment to use
00580       // use the last measurement, otherwise use the second; this is to be investigated
00581       break;
00582     }
00583   }
00584 
00585   const float pT_min = 1.99;// many hardcoded - remove them!
00586   if(pT>3000.){
00587     pT=3000.;
00588   }
00589   else if(pT<pT_min ){
00590     if(pT>0){
00591       pT=pT_min ;
00592     }
00593     else if(pT>(-1)*pT_min ){
00594       pT=(-1)*pT_min ;
00595     }
00596     else if (pT<-3000.){
00597       pT= -3000;
00598     }
00599   }
00600   //std::cout<<"  THE pT from the parametrization: "<<momentum_estimate[0]<<std::endl;
00601   // estimate the charge of the track candidate from the delta phi of two segments:
00602   //int charge      = dPhi > 0 ? 1 : -1; // what we want is: dphi < 0 => charge = -1
00603   charge =  momentum_estimate[0]> 0 ? 1 : -1;
00604 
00605   // we have the pT - get the 3D momentum estimate as well
00606 
00607   // this is already final info:
00608   double xHit     = validSet[firstMeasurement]->globalPosition().x();
00609   double yHit     = validSet[firstMeasurement]->globalPosition().y();
00610   double rHit     = TMath::Sqrt(pow(xHit,2) + pow(yHit,2));
00611 
00612   double thetaInner = validSet[firstMeasurement]->globalPosition().theta();
00613   // if some of the segments is missing r-phi measurement then we should
00614   // use only the 4D phi estimate (also use 4D eta estimate only)
00615   // the direction is not so important (it will be corrected)
00616 
00617   double rTrack   = (pT /(0.3*3.8))*100.; //times 100 for conversion to cm!
00618 
00619   double par      = -1.*(2./charge)*(TMath::ASin(rHit/(2*rTrack)));
00620   double sinPar     = TMath::Sin( par );
00621   double cosPar     = TMath::Cos( par );
00622 
00623   // calculate phi at coordinate origin (0,0,0).
00624   double sinPhiH  = 1./(2.*charge*rTrack)*(xHit + ((sinPar)/(cosPar-1.))*yHit);
00625   double cosPhiH  = -1./(2.*charge*rTrack)*(((sinPar)/(1.-cosPar))*xHit + yHit);
00626 
00627   // finally set the return vector
00628 
00629   // try out the reco info:
00630   momEstimate = CLHEP::Hep3Vector(pT*cosPhiH, pT*sinPhiH, pT/TMath::Tan(thetaInner)); // should used into to theta directly here (rather than tan(atan2(...)))
00631   //Hep3Vector momEstimate(6.97961,      5.89732,     -50.0855);
00632   const float minMomenum = 5.; //hardcoded - remove it! same in SETFilter
00633   if (momEstimate.mag()<minMomenum){
00634     int sign = (pT<0.) ? -1: 1;
00635     pT = sign * (fabs(pT)+1);
00636     CLHEP::Hep3Vector momEstimate2(pT*cosPhiH, pT*sinPhiH, pT/TMath::Tan(thetaInner));
00637     momEstimate = momEstimate2;
00638     if (momEstimate.mag()<minMomenum){
00639       pT = sign * (fabs(pT)+1);
00640       CLHEP::Hep3Vector momEstimate3(pT*cosPhiH, pT*sinPhiH, pT/TMath::Tan(thetaInner));
00641       momEstimate = momEstimate3;
00642       if (momEstimate.mag()<minMomenum){
00643         pT = sign * (fabs(pT)+1);
00644         CLHEP::Hep3Vector momEstimate4(pT*cosPhiH, pT*sinPhiH, pT/TMath::Tan(thetaInner));
00645         momEstimate = momEstimate4;
00646       }
00647     }
00648   }
00649 }
00650 
00651 
00652 
00653 TrajectorySeed SETSeedFinder::makeSeed(const TrajectoryStateOnSurface & firstTSOS, 
00654                                        const TransientTrackingRecHit::ConstRecHitContainer & hits) const
00655 {
00656   edm::OwnVector<TrackingRecHit> recHitsContainer;
00657   for(unsigned int iHit = 0;iHit < hits.size();++iHit){
00658     recHitsContainer.push_back(hits.at(iHit)->hit()->clone());
00659   }
00660   PropagationDirection dir = oppositeToMomentum;
00661   if(useSegmentsInTrajectory){
00662     dir = alongMomentum;// why forward (for rechits) later?
00663   }
00664   
00665   PTrajectoryStateOnDet const & seedTSOS =
00666   trajectoryStateTransform::persistentState( firstTSOS, hits.at(0)->geographicalId().rawId());
00667   TrajectorySeed seed(seedTSOS,recHitsContainer,dir);
00668 
00669   //MuonPatternRecoDumper debug;
00670   //std::cout<<" firstTSOS = "<<debug.dumpTSOS(firstTSOS)<<std::endl;
00671   //std::cout<<" iTraj = ???"<<" hits = "<<range.second-range.first<<std::endl;
00672   //std::cout<<" nhits = "<<hits.size()<<std::endl;
00673   //for(unsigned int iRH=0;iRH<hits.size();++iRH){
00674   //std::cout<<" RH = "<<iRH+1<<" globPos = "<<hits.at(iRH)->globalPosition()<<std::endl;
00675   //}
00676   return seed;
00677 }
00678 
00679