CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/RecoTracker/ConversionSeedGenerators/src/PhotonConversionTrajectorySeedProducerFromSingleLegAlgo.cc

Go to the documentation of this file.
00001 #include "RecoTracker/ConversionSeedGenerators/interface/PhotonConversionTrajectorySeedProducerFromSingleLegAlgo.h"
00002 #include "FWCore/Utilities/interface/Exception.h"
00003 #include "FWCore/Utilities/interface/isFinite.h"
00004 
00005 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00006 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00007 #include "FWCore/Framework/interface/ESHandle.h"
00008 #include "MagneticField/Engine/interface/MagneticField.h"
00009 
00010 
00011 //#define debugTSPFSLA
00012 
00013 inline double sqr(double a){return a*a;}
00014 
00015 PhotonConversionTrajectorySeedProducerFromSingleLegAlgo::
00016 PhotonConversionTrajectorySeedProducerFromSingleLegAlgo(const edm::ParameterSet & conf)
00017   :_conf(conf),seedCollection(0),seedCollectionOfSourceTracks(0),
00018    hitsfactoryPSet(conf.getParameter<edm::ParameterSet>("OrderedHitsFactoryPSet")),   
00019    creatorPSet(conf.getParameter<edm::ParameterSet>("SeedCreatorPSet")),
00020    regfactoryPSet(conf.getParameter<edm::ParameterSet>("RegionFactoryPSet")),
00021    theClusterCheck(conf.getParameter<edm::ParameterSet>("ClusterCheckPSet")),
00022    theSilentOnClusterCheck(conf.getParameter<edm::ParameterSet>("ClusterCheckPSet").getUntrackedParameter<bool>("silentClusterCheck",false)),
00023    _vtxMinDoF(conf.getParameter<double>("vtxMinDoF")),
00024    _maxDZSigmas(conf.getParameter<double>("maxDZSigmas")),
00025    _maxNumSelVtx(conf.getParameter<uint32_t>("maxNumSelVtx")),
00026    _applyTkVtxConstraint(conf.getParameter<bool>("applyTkVtxConstraint")),
00027    _countSeedTracks(0),
00028    _primaryVtxInputTag(conf.getParameter<edm::InputTag>("primaryVerticesTag")),
00029    _beamSpotInputTag(conf.getParameter<edm::InputTag>("beamSpotInputTag"))
00030 {
00031    init();  
00032 }
00033      
00034 void PhotonConversionTrajectorySeedProducerFromSingleLegAlgo::
00035 clear(){
00036   if(theHitsGenerator!=NULL)
00037     delete theHitsGenerator;
00038   if(theSeedCreator!=NULL)
00039     delete theSeedCreator;
00040   if(theRegionProducer!=NULL)
00041     delete theRegionProducer;
00042 }
00043 
00044 void PhotonConversionTrajectorySeedProducerFromSingleLegAlgo::
00045 init(){
00046   theHitsGenerator  = new CombinedHitPairGeneratorForPhotonConversion(hitsfactoryPSet);
00047   theSeedCreator    = new SeedForPhotonConversion1Leg(creatorPSet);
00048   theRegionProducer = new GlobalTrackingRegionProducerFromBeamSpot(regfactoryPSet);
00049 }
00050 
00051 void PhotonConversionTrajectorySeedProducerFromSingleLegAlgo::
00052 analyze(const edm::Event & event, const edm::EventSetup &setup){
00053 
00054   myEsetup = &setup;
00055   myEvent = &event;
00056 
00057   if(seedCollection!=0)
00058     delete seedCollection;
00059 
00060   if(seedCollectionOfSourceTracks!=0)
00061     delete seedCollectionOfSourceTracks;
00062 
00063   seedCollection= new TrajectorySeedCollection();
00064   seedCollectionOfSourceTracks= new TrajectorySeedCollection();
00065 
00066   size_t clustsOrZero = theClusterCheck.tooManyClusters(event);
00067   if (clustsOrZero){
00068     if (!theSilentOnClusterCheck)
00069       edm::LogError("TooManyClusters") << "Found too many clusters (" << clustsOrZero << "), bailing out.\n";
00070     return ;
00071   }
00072 
00073 
00074   edm::ESHandle<MagneticField> handleMagField;
00075   setup.get<IdealMagneticFieldRecord>().get(handleMagField);
00076   magField = handleMagField.product();
00077   if (unlikely(magField->inTesla(GlobalPoint(0.,0.,0.)).z()<0.01)) return;
00078 
00079   _IdealHelixParameters.setMagnField(magField);
00080 
00081 
00082   event.getByLabel(_primaryVtxInputTag, vertexHandle);
00083   if (!vertexHandle.isValid() || vertexHandle->empty()){
00084       edm::LogError("PhotonConversionFinderFromTracks") << "Error! Can't get the product primary Vertex Collection "<< _primaryVtxInputTag <<  "\n";
00085       return;
00086   }
00087 
00088   event.getByLabel(_beamSpotInputTag,recoBeamSpotHandle);
00089   
00090 
00091   regions = theRegionProducer->regions(event,setup);
00092   
00093   //Do the analysis
00094   loopOnTracks();
00095 
00096  
00097 #ifdef debugTSPFSLA 
00098   std::stringstream ss;
00099   ss.str("");
00100   ss << "\n++++++++++++++++++\n";
00101   ss << "seed collection size " << seedCollection->size();
00102   BOOST_FOREACH(TrajectorySeed tjS,*seedCollection){
00103     po.print(ss, tjS);
00104   }
00105   edm::LogInfo("debugTrajSeedFromSingleLeg") << ss.str();
00106   //-------------------------------------------------
00107 #endif
00108 
00109    // clear memory
00110   theHitsGenerator->clearLayerCache();
00111   for (IR ir=regions.begin(), irEnd=regions.end(); ir < irEnd; ++ir) delete (*ir);
00112 
00113 }
00114 
00115 
00116 void PhotonConversionTrajectorySeedProducerFromSingleLegAlgo::
00117 loopOnTracks(){
00118 
00119   //--- Get Tracks
00120   myEvent->getByLabel(_conf.getParameter<edm::InputTag>("TrackRefitter"),trackCollectionH);
00121 
00122   if(trackCollectionH.isValid()==0){
00123     edm::LogError("MissingInput")<<" could not find track collecion:"<<_conf.getParameter<edm::InputTag>("TrackRefitter");
00124     return;
00125   }
00126   size_t idx=0, sel=0;
00127   _countSeedTracks=0;
00128 
00129   ss.str("");
00130   
00131   for( reco::TrackCollection::const_iterator tr = trackCollectionH->begin(); 
00132        tr != trackCollectionH->end(); tr++, idx++) {
00133     
00134     // #ifdef debugTSPFSLA 
00135     //     ss << "\nStuding track Nb " << idx;
00136     // #endif
00137 
00138     if(rejectTrack(*tr))  continue;
00139     std::vector<reco::Vertex> selectedPriVtxCompatibleWithTrack;  
00140     if(!_applyTkVtxConstraint){
00141       selectedPriVtxCompatibleWithTrack.push_back(*(vertexHandle->begin())); //Same approach as before
00142     }else{
00143       if(!selectPriVtxCompatibleWithTrack(*tr,selectedPriVtxCompatibleWithTrack)) continue;
00144     }
00145 
00146     sel++;
00147     loopOnPriVtx(*tr,selectedPriVtxCompatibleWithTrack);
00148   }
00149 #ifdef debugTSPFSLA 
00150   edm::LogInfo("debugTrajSeedFromSingleLeg") << ss.str();
00151   edm::LogInfo("debugTrajSeedFromSingleLeg") << "Inspected " << sel << " tracks over " << idx << " tracks. \t # tracks providing at least one seed " << _countSeedTracks ;
00152 #endif
00153 }
00154 
00155 bool PhotonConversionTrajectorySeedProducerFromSingleLegAlgo::
00156 selectPriVtxCompatibleWithTrack(const reco::Track& tk, std::vector<reco::Vertex>& selectedPriVtxCompatibleWithTrack){
00157   
00158   std::vector< std::pair< double, short> > idx;
00159   short count=-1;
00160 
00161   double cosPhi=tk.px()/tk.pt();
00162   double sinPhi=tk.py()/tk.pt();
00163   double sphi2=tk.covariance(2,2);
00164   double stheta2=tk.covariance(1,1);
00165 
00166   BOOST_FOREACH(const reco::Vertex& vtx,  *vertexHandle){
00167     count++;
00168     if(vtx.ndof()<= _vtxMinDoF) continue;
00169 
00170     double _dz= tk.dz(vtx.position());
00171     double _dzError=tk.dzError();
00172 
00173     double cotTheta=tk.pz()/tk.pt();
00174     double dx = vtx.position().x();
00175     double dy = vtx.position().y();
00176     double sx2=vtx.covariance(0,0);
00177     double sy2=vtx.covariance(1,1);
00178 
00179     double sxy2= sqr(cosPhi*cotTheta)*sx2+
00180       sqr(sinPhi*cotTheta)*sy2+
00181       sqr(cotTheta*(-dx*sinPhi+dy*cosPhi))*sphi2+
00182       sqr((1+cotTheta*cotTheta)*(dx*cosPhi+dy*sinPhi))*stheta2;
00183       
00184     _dzError=sqrt(_dzError*_dzError+vtx.covariance(2,2)+sxy2); //there is a missing component, related to the element (vtx.x*px+vtx.y*py)/pt * pz/pt. since the tk ref point is at the point of closest approach, this scalar product should be almost zero.
00185 
00186 #ifdef debugTSPFSLA
00187     ss << " primary vtx " << vtx.position()  << " \tk vz " << tk.vz() << " vx " << tk.vx() << " vy " << tk.vy() << " pz/pt " << tk.pz()/tk.pt() << " \t dz " << _dz << " \t " << _dzError << " sxy2 "<< sxy2<< " \t dz/dzErr " << _dz/_dzError<< std::endl;
00188 #endif
00189 
00190     if(fabs(_dz)/_dzError > _maxDZSigmas) continue; 
00191       
00192     idx.push_back(std::pair<double,short>(fabs(_dz),count));
00193   }
00194   if(idx.size()==0) {
00195 #ifdef debugTSPFSLA
00196     ss << "no vertex selected " << std::endl; 
00197 #endif
00198     return false;
00199 }
00200   
00201   std::stable_sort(idx.begin(),idx.end(),lt_);
00202   for(size_t i=0;i<_maxNumSelVtx && i<idx.size();++i){
00203     selectedPriVtxCompatibleWithTrack.push_back((*vertexHandle)[idx[i].second]);
00204 #ifdef debugTSPFSLA
00205     ss << "selected vtx dz " << idx[0].first << "  position" << idx[0].second << std::endl;
00206 #endif
00207   }
00208 
00209   return true;
00210 }
00211 
00212 void PhotonConversionTrajectorySeedProducerFromSingleLegAlgo::
00213 loopOnPriVtx(const reco::Track& tk, const std::vector<reco::Vertex>& selectedPriVtxCompatibleWithTrack){
00214 
00215   bool foundAtLeastASeedCand=false;
00216   BOOST_FOREACH(const reco::Vertex vtx, selectedPriVtxCompatibleWithTrack){
00217 
00218     math::XYZPoint primaryVertexPoint=math::XYZPoint(vtx.position());
00219     
00220     for (IR ir=regions.begin(), irEnd=regions.end(); ir < irEnd; ++ir) {
00221       const TrackingRegion & region = **ir;
00222 
00223 #ifdef debugTSPFSLA 
00224       ss << "[PrintRegion] " << region.print() << std::endl;
00225 #endif
00226       
00227       //This if is just for the _countSeedTracks. otherwise 
00228       //inspectTrack(&tk,region, primaryVertexPoint);
00229       //would be enough
00230 
00231       if(
00232          inspectTrack(&tk,region, primaryVertexPoint)
00233          and
00234          !foundAtLeastASeedCand
00235          ){
00236         foundAtLeastASeedCand=true;
00237         _countSeedTracks++; 
00238       }
00239 
00240     }
00241   }
00242 }
00243   
00244 bool PhotonConversionTrajectorySeedProducerFromSingleLegAlgo::
00245 rejectTrack(const reco::Track& track){
00246   
00247   math::XYZVector beamSpot;
00248   if(recoBeamSpotHandle.isValid()) {
00249     beamSpot =  math::XYZVector(recoBeamSpotHandle->position());
00250 
00251     _IdealHelixParameters.setData(&track,beamSpot);   
00252     if(_IdealHelixParameters.GetTangentPoint().r()==0){
00253       //this case means a null results on the _IdealHelixParameters side
00254       return true;
00255       }
00256       
00257     float rMin=2.; //cm
00258     if(_IdealHelixParameters.GetTangentPoint().rho()<rMin){
00259       //this case means a track that has the tangent point nearby the primary vertex
00260       // if the track is primary, this number tends to be the primary vertex itself
00261       //Rejecting all the potential photon conversions having a "vertex" inside the beampipe
00262       //We should not miss too much, seen that the conversions at the beam pipe are the better reconstructed
00263       return true;
00264     }
00265   }
00266 
00267   //-------------------------------------------------------
00268   /*
00269   float maxPt2=64.; //Cut on pt^2 Indeed doesn't do almost nothing
00270   if(track.momentum().Perp2() > maxPt2)
00271     return true;
00272   */
00273   //-------------------------------------------------------
00274   //Cut in the barrel eta region FIXME: to be extended to endcaps
00275   /*
00276   float maxEta=1.3; 
00277   if(fabs(track.eta()) > maxEta)
00278     return true;
00279   */
00280   //-------------------------------------------------------
00281   //Reject tracks that have a first valid hit in the pixel barrel/endcap layer/disk 1
00282   //assume that the hits are aligned along momentum
00283   /*
00284   const reco::HitPattern& p=track.hitPattern();
00285   for (int i=0; i<p.numberOfHits(); i++) {
00286     uint32_t hit = p.getHitPattern(i);
00287     // if the hit is valid and in pixel barrel, print out the layer
00288     if (! p.validHitFilter(hit) ) continue;
00289     if( (p.pixelBarrelHitFilter(hit) || p.pixelEndcapHitFilter(hit))
00290         &&
00291         p.getLayer(hit) == 1
00292         )
00293       return true;
00294     else
00295       break; //because the first valid hit is in a different layer
00296   }
00297   */
00298   //-------------------------------------------------------
00299 
00300 
00301   return false;
00302 }
00303 
00304 
00305 bool PhotonConversionTrajectorySeedProducerFromSingleLegAlgo::
00306 inspectTrack(const reco::Track* track, const TrackingRegion & region, math::XYZPoint& primaryVertexPoint){
00307 
00308   _IdealHelixParameters.setData(track,primaryVertexPoint);   
00309     
00310   if (edm::isNotFinite(_IdealHelixParameters.GetTangentPoint().r()) || 
00311         (_IdealHelixParameters.GetTangentPoint().r()==0)){
00312     //this case means a null results on the _IdealHelixParameters side
00313     return false;
00314   }
00315 
00316   float rMin=3.; //cm
00317   if(_IdealHelixParameters.GetTangentPoint().rho()<rMin){
00318     //this case means a track that has the tangent point nearby the primary vertex
00319     // if the track is primary, this number tends to be the primary vertex itself
00320     //Rejecting all the potential photon conversions having a "vertex" inside the beampipe
00321     //We should not miss too much, seen that the conversions at the beam pipe are the better reconstructed
00322     return false;
00323   }
00324 
00325   float ptmin = 0.5;
00326   float originRBound = 3;
00327   float originZBound  = 3.;
00328 
00329   GlobalPoint originPos;
00330   originPos = GlobalPoint(_IdealHelixParameters.GetTangentPoint().x(),
00331                           _IdealHelixParameters.GetTangentPoint().y(),
00332                           _IdealHelixParameters.GetTangentPoint().z()
00333                           );
00334   float cotTheta;
00335   if( std::abs(_IdealHelixParameters.GetMomentumAtTangentPoint().rho()) > 1.e-4f ){
00336     cotTheta=_IdealHelixParameters.GetMomentumAtTangentPoint().z()/_IdealHelixParameters.GetMomentumAtTangentPoint().rho();
00337   }else{
00338     if(_IdealHelixParameters.GetMomentumAtTangentPoint().z()>0)
00339       cotTheta=99999.f; 
00340     else
00341       cotTheta=-99999.f; 
00342   }
00343   GlobalVector originBounds(originRBound,originRBound,originZBound);
00344 
00345   GlobalPoint pvtxPoint(primaryVertexPoint.x(),
00346                         primaryVertexPoint.y(),
00347                         primaryVertexPoint.z()
00348                         );
00349   ConversionRegion convRegion(originPos, pvtxPoint, cotTheta, track->thetaError(), -1*track->charge());
00350 
00351 #ifdef debugTSPFSLA 
00352   ss << "\nConversion Point " << originPos << " " << originPos.perp() << "\n";
00353 #endif
00354 
00355   const OrderedSeedingHits & hitss = theHitsGenerator->run(convRegion, region, *myEvent, *myEsetup);
00356   
00357   unsigned int nHitss =  hitss.size();
00358 
00359   if(nHitss==0)
00360     return false;
00361 
00362 #ifdef debugTSPFSLA 
00363   ss << "\n nHitss " << nHitss << "\n";
00364 #endif
00365 
00366   if (seedCollection->empty()) seedCollection->reserve(nHitss); // don't do multiple reserves in the case of multiple regions: it would make things even worse
00367                                                                // as it will cause N re-allocations instead of the normal log(N)/log(2)
00368   for (unsigned int iHits = 0; iHits < nHitss; ++iHits) { 
00369 
00370 #ifdef debugTSPFSLA 
00371     ss << "\n iHits " << iHits << "\n";
00372 #endif
00373     const SeedingHitSet & hits =  hitss[iHits];
00374     //if (!theComparitor || theComparitor->compatible( hits, es) ) {
00375     //try{
00376     theSeedCreator->trajectorySeed(*seedCollection,hits, originPos, originBounds, ptmin, *myEsetup,convRegion.cotTheta(),ss);
00377     //}catch(cms::Exception& er){
00378     //  edm::LogError("SeedingConversion") << " Problem in the Single Leg Seed creator " <<er.what()<<std::endl;
00379     //}catch(std::exception& er){
00380     //  edm::LogError("SeedingConversion") << " Problem in the Single Leg Seed creator " << er.what()<<std::endl;
00381     //}
00382   }
00383   return true;
00384 }
00385 
00386