CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/RecoParticleFlow/PFProducer/src/PFBlockAlgo.cc

Go to the documentation of this file.
00001 #include "RecoParticleFlow/PFProducer/interface/PFBlockAlgo.h"
00002 #include "RecoParticleFlow/PFProducer/interface/Utils.h"
00003 #include "RecoParticleFlow/PFClusterTools/interface/LinkByRecHit.h"
00004 #include "DataFormats/ParticleFlowReco/interface/PFBlock.h"
00005 #include "DataFormats/TrackReco/interface/Track.h"
00006 #include "DataFormats/ParticleFlowReco/interface/PFDisplacedVertex.h" // gouzevitch
00007 
00008 #include "DataFormats/ParticleFlowReco/interface/PFRecHit.h"
00009 
00010 #include <stdexcept>
00011 #include "TMath.h"
00012 
00013 using namespace std;
00014 using namespace reco;
00015 
00016 //for debug only 
00017 //#define PFLOW_DEBUG
00018 
00019 const PFBlockAlgo::Mask PFBlockAlgo::dummyMask_;
00020 
00021 PFBlockAlgo::PFBlockAlgo() : 
00022   blocks_( new reco::PFBlockCollection ),
00023   DPtovPtCut_(std::vector<double>(4,static_cast<double>(999.))),
00024   NHitCut_(std::vector<unsigned int>(4,static_cast<unsigned>(0))), 
00025   useIterTracking_(true),
00026   photonSelector_(0),
00027   debug_(false) {}
00028 
00029 
00030 
00031 void PFBlockAlgo::setParameters( std::vector<double>& DPtovPtCut,
00032                                  std::vector<unsigned int>& NHitCut,
00033                                  bool useConvBremPFRecTracks,
00034                                  bool useIterTracking,
00035                                  int nuclearInteractionsPurity,
00036                                  bool useEGPhotons,
00037                                  std::vector<double>& photonSelectionCuts,
00038                                  bool useSuperClusters) {
00039   
00040   DPtovPtCut_    = DPtovPtCut;
00041   NHitCut_       = NHitCut;
00042   useIterTracking_ = useIterTracking;
00043   useConvBremPFRecTracks_ = useConvBremPFRecTracks;
00044   nuclearInteractionsPurity_ = nuclearInteractionsPurity;
00045   useEGPhotons_ = useEGPhotons;
00046   // Pt cut; Track iso (constant + slope), Ecal iso (constant + slope), HCAL iso (constant+slope), H/E
00047   if(useEGPhotons_)
00048     photonSelector_ = new PhotonSelectorAlgo(photonSelectionCuts[0],   
00049                                              photonSelectionCuts[1], photonSelectionCuts[2],   
00050                                              photonSelectionCuts[3], photonSelectionCuts[4],    
00051                                              photonSelectionCuts[5], photonSelectionCuts[6],    
00052                                              photonSelectionCuts[7],
00053                                              photonSelectionCuts[8],
00054                                              photonSelectionCuts[9],
00055                                              photonSelectionCuts[10]
00056                                              );
00057 
00058 
00059   useSuperClusters_ = useSuperClusters;
00060     
00061 }
00062 
00063 // Glowinski & Gouzevitch
00064 void PFBlockAlgo::setUseOptimization(bool useKDTreeTrackEcalLinker)
00065 {
00066   useKDTreeTrackEcalLinker_ = useKDTreeTrackEcalLinker;
00067 }
00068 // !Glowinski & Gouzevitch
00069 
00070 
00071 PFBlockAlgo::~PFBlockAlgo() {
00072 
00073 #ifdef PFLOW_DEBUG
00074   if(debug_)
00075     cout<<"~PFBlockAlgo - number of remaining elements: "
00076         <<elements_.size()<<endl;
00077 #endif
00078 
00079   if(photonSelector_) delete photonSelector_;
00080 
00081 }
00082 
00083 void 
00084 PFBlockAlgo::findBlocks() {
00085 
00086   // Glowinski & Gouzevitch
00087   if (useKDTreeTrackEcalLinker_) {
00088     TELinker_.process();
00089     THLinker_.process();
00090     PSELinker_.process();
00091   }
00092   // !Glowinski & Gouzevitch
00093 
00094   // the blocks have not been passed to the event, and need to be cleared
00095   if(blocks_.get() )blocks_->clear();
00096   else 
00097     blocks_.reset( new reco::PFBlockCollection );
00098 
00099   blocks_->reserve(elements_.size());
00100   for(IE ie = elements_.begin(); 
00101       ie != elements_.end();) {
00102     
00103 #ifdef PFLOW_DEBUG
00104     if(debug_) {
00105       cout<<" PFBlockAlgo::findBlocks() ----------------------"<<endl;
00106       cout<<" element "<<**ie<<endl;
00107       cout<<" creating new block"<<endl;
00108     }
00109 #endif
00110 
00111     blocks_->push_back( PFBlock() );
00112     
00113     vector< PFBlockLink > links;
00114 
00115     //    list< IE > used;
00116     ie = associate( elements_.end() , ie, links );
00117 
00118     packLinks( blocks_->back(), links );
00119   }
00120 }
00121 
00122 
00123 
00124 
00125 PFBlockAlgo::IE 
00126 PFBlockAlgo::associate( IE last, 
00127                         IE next, 
00128                         vector<PFBlockLink>& links ) {
00129 
00130     
00131 #ifdef PFLOW_DEBUG
00132   if(debug_ ) cout<<"PFBlockAlgo::associate start ----"<<endl;
00133 #endif
00134 
00135   if( last!= elements_.end() ) {
00136     PFBlockLink::Type linktype = PFBlockLink::NONE;
00137     double dist = -1;
00138     PFBlock::LinkTest linktest = PFBlock::LINKTEST_RECHIT;
00139     link( *last, *next, linktype, linktest, dist ); 
00140 
00141     
00142     if(dist<-0.5) {
00143 #ifdef PFLOW_DEBUG
00144       if(debug_ ) cout<<"link failed"<<endl;
00145 #endif
00146       return ++next; // association failed
00147     }
00148     else {
00149       // add next element to the current pflowblock
00150       blocks_->back().addElement( *next );  
00151 
00152       // (*next)->setIndex( blocks_->back()->indexToLastElement() );
00153       
00154       // this is not necessary? 
00155       // next->setPFBlock(this);
00156       
00157       // create a link between next and last      
00158       links.push_back( PFBlockLink(linktype, 
00159                                    linktest,
00160                                    dist,
00161                                    (*last)->index(), 
00162                                    (*next)->index() ) );
00163       // not necessary ?
00164       //       next->connect( links_.size()-1 );
00165       //       last->connect( links_.size()-1 );      
00166     }
00167   }
00168   else {
00169     // add next element to this eflowblock
00170 #ifdef PFLOW_DEBUG
00171     if(debug_ ) cout<<"adding to block element "<<(**next)<<endl;
00172 #endif
00173     blocks_->back().addElement( *next );
00174     // (*next)->setIndex( blocks_->back()->indexToLastElement() );   
00175     // next->setPFBlock(this);
00176   }
00177 
00178   // recursive call: associate next and other unused elements 
00179   
00180   //   IE afterNext = next;
00181   //   ++afterNext;
00182   //  cout<<"last "<<**last<<" next "<<**next<<endl;
00183   
00184   for(IE ie = elements_.begin(); 
00185       ie != elements_.end();) {
00186     
00187     if( ie == last || ie == next ) {
00188       ++ie;
00189       continue;
00190     } 
00191     bool bTestLink = linkPrefilter(*next, *ie);
00192 
00193     if(!bTestLink) {
00194       ++ie;
00195       continue;
00196     }
00197     
00198     // *ie already included to a block
00199     if( (*ie)->locked() ) {
00200 #ifdef PFLOW_DEBUG
00201       if(debug_ ) cout<<"element "<<(**ie)<<"already used"<<endl;
00202 #endif
00203       ++ie;
00204       continue;
00205     }    
00206     
00207     
00208 #ifdef PFLOW_DEBUG
00209     if(debug_ ) cout<<"calling associate "<<(**next)<<" & "<<(**ie)<<endl;
00210 #endif
00211     ie = associate(next, ie, links);
00212   }       
00213 
00214 #ifdef PFLOW_DEBUG
00215   if(debug_ ) {
00216     cout<<"**** deleting element "<<endl;
00217     cout<<**next<<endl;
00218   }
00219 #endif
00220   delete *next;
00221 
00222 #ifdef PFLOW_DEBUG
00223   if(debug_ ) {
00224     cout<<"**** removing element "<<endl;
00225   }
00226 #endif
00227 
00228   IE iteratorToNextFreeElement = elements_.erase( next );
00229 
00230 #ifdef PFLOW_DEBUG
00231   if(debug_ ) cout<<"PFBlockAlgo::associate stop ----"<<endl;
00232 #endif
00233 
00234   return iteratorToNextFreeElement;
00235 }
00236 
00237 
00238 
00239 void 
00240 PFBlockAlgo::packLinks( reco::PFBlock& block, 
00241                         const vector<PFBlockLink>& links ) const {
00242   
00243   
00244   const edm::OwnVector< reco::PFBlockElement >& els = block.elements();
00245   
00246   block.bookLinkData();
00247   unsigned elsize = els.size();
00248   unsigned ilStart = 0;
00249   //First Loop: update all link data
00250   for( unsigned i1=0; i1<elsize; ++i1 ) {
00251     for( unsigned i2=0; i2<i1; ++i2 ) {
00252       
00253       // no reflexive link
00254       //if( i1==i2 ) continue;
00255       
00256       double dist = -1;
00257       
00258       bool linked = false;
00259       PFBlock::LinkTest linktest 
00260         = PFBlock::LINKTEST_RECHIT; 
00261 
00262       // are these elements already linked ?
00263       // this can be optimized
00264       unsigned linksize = links.size();
00265       for( unsigned il = ilStart; il<linksize; ++il ) {
00266         // The following three lines exploits the increasing-element2 ordering of links.
00267         if ( links[il].element2() < i1 ) ilStart = il;
00268         if ( links[il].element2() > i1 ) break;
00269         if( (links[il].element1() == i2 &&
00270              links[il].element2() == i1) ) {  // yes
00271           
00272           dist = links[il].dist();
00273           linked = true;
00274 
00275           //modif-beg     
00276           //retrieve type of test used to get distance
00277           linktest = links[il].test();
00278 #ifdef PFLOW_DEBUG
00279           if( debug_ )
00280             cout << "Reading link vector: linktest used=" 
00281                  << linktest 
00282                  << " distance = " << dist 
00283                  << endl; 
00284 #endif
00285           //modif-end
00286           
00287           break;
00288         } 
00289       }
00290       
00291       if(!linked) {
00292         PFBlockLink::Type linktype = PFBlockLink::NONE;
00293         bool bTestLink = linkPrefilter(&els[i1], &els[i2]);
00294         if (bTestLink) link( & els[i1], & els[i2], linktype, linktest, dist);
00295       }
00296 
00297       //loading link data according to link test used: RECHIT 
00298       //block.setLink( i1, i2, chi2, block.linkData() );
00299 #ifdef PFLOW_DEBUG
00300       if( debug_ )
00301         cout << "Setting link between elements " << i1 << " and " << i2
00302              << " of dist =" << dist << " computed from link test "
00303              << linktest << endl;
00304 #endif
00305       block.setLink( i1, i2, dist, block.linkData(), linktest );
00306     }
00307   }
00308 
00309 }
00310 
00311 
00312 
00313 void 
00314 PFBlockAlgo::buildGraph() {
00315   // loop on all blocks and create a big graph
00316 }
00317 
00318 
00319 
00320 void 
00321 PFBlockAlgo::link( const reco::PFBlockElement* el1, 
00322                    const reco::PFBlockElement* el2, 
00323                    PFBlockLink::Type& linktype, 
00324                    reco::PFBlock::LinkTest& linktest,
00325                    double& dist) const {
00326   
00327   // ACHTUNG!!!! If you introduce new links check that they are not desabled in linkPrefilter!!!!
00328 
00329 
00330   dist=-1.;
00331   linktest = PFBlock::LINKTEST_RECHIT; //rechit by default 
00332 
00333   PFBlockElement::Type type1 = el1->type();
00334   PFBlockElement::Type type2 = el2->type();
00335 
00336   linktype = static_cast<PFBlockLink::Type>
00337     ((1<< (type1-1) ) | (1<< (type2-1) ));
00338 
00339   if(debug_ ) std::cout << " PFBlockAlgo links type1 " << type1 << " type2 " << type2 << std::endl;
00340 
00341   const PFBlockElement* lowEl = el1;
00342   const PFBlockElement* highEl = el2;
00343   
00344   if(type1>type2) {
00345     lowEl = el2;
00346     highEl = el1;
00347   }
00348   
00349   switch(linktype) {
00350   // Track and preshower cluster links are not used for now - disable
00351   case PFBlockLink::PS1andECAL:
00352   case PFBlockLink::PS2andECAL:
00353     {
00354       // if(debug_ ) cout<< "PSandECAL" <<endl;
00355       PFClusterRef  psref = lowEl->clusterRef();
00356       PFClusterRef  ecalref = highEl->clusterRef();
00357       assert( !psref.isNull() );
00358       assert( !ecalref.isNull() );
00359 
00360       // Check if the linking has been done using the KDTree algo
00361       // Glowinski & Gouzevitch
00362       if ( useKDTreeTrackEcalLinker_ && lowEl->isMultilinksValide() ) { // KDTree algo
00363         const reco::PFMultilinksType& multilinks = lowEl->getMultilinks();
00364         
00365         double ecalPhi = ecalref->positionREP().Phi();
00366         double ecalEta = ecalref->positionREP().Eta();
00367         
00368         // Check if the link PS/Ecal exist
00369         reco::PFMultilinksType::const_iterator mlit = multilinks.begin();
00370         for (; mlit != multilinks.end(); ++mlit)
00371           if ((mlit->first == ecalPhi) && (mlit->second == ecalEta))
00372             break;
00373         
00374         // If the link exist, we fill dist and linktest. We use old algorithme method.
00375         if (mlit != multilinks.end()){
00376           double xPS = psref->position().X();
00377           double yPS = psref->position().Y();
00378           double xECAL  = ecalref->position().X();
00379           double yECAL  = ecalref->position().Y();
00380 
00381           dist = LinkByRecHit::computeDist(xECAL/1000.,yECAL/1000.,xPS/1000.  ,yPS/1000, false);
00382         }
00383 
00384       } else { //Old algorithm
00385         dist = LinkByRecHit::testECALAndPSByRecHit( *ecalref, *psref ,debug_);
00386       }
00387 
00388       //      linktest = PFBlock::LINKTEST_RECHIT;
00389       
00390       break;
00391     }
00392   case PFBlockLink::TRACKandECAL:
00393     {
00394       if(debug_ ) cout<<"TRACKandECAL"<<endl;
00395 
00396       PFRecTrackRef trackref = lowEl->trackRefPF();
00397       PFClusterRef  clusterref = highEl->clusterRef();
00398       assert( !trackref.isNull() );
00399       assert( !clusterref.isNull() );
00400 
00401       if(debug_ ) std::cout << " Track pt " << trackref->trackRef()->pt() << std::endl;
00402 
00403       // Check if the linking has been done using the KDTree algo
00404       // Glowinski & Gouzevitch
00405       if ( useKDTreeTrackEcalLinker_ && lowEl->isMultilinksValide() ) { //KDTree Algo
00406 
00407         const reco::PFMultilinksType& multilinks = lowEl->getMultilinks();
00408         double ecalphi = clusterref->positionREP().Phi();
00409         double ecaleta = clusterref->positionREP().Eta();
00410 
00411         // Check if the link Track/Ecal exist
00412         reco::PFMultilinksType::const_iterator mlit = multilinks.begin();
00413         for (; mlit != multilinks.end(); ++mlit)
00414           if ((mlit->first == ecalphi) && (mlit->second == ecaleta))
00415             break;
00416 
00417         
00418         // If the link exist, we fill dist and linktest. We use old algorithme method.
00419         if (mlit != multilinks.end()){
00420 
00421 
00422           //Should be something like this :
00423           //      const reco::PFRecTrack& track = *trackref;
00424           //instead of this :
00425           /*
00426           reco::PFRecTrack track (*trackref);
00427           const reco::PFTrajectoryPoint& atECAL_tmp = 
00428             (*trackref).extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax );
00429           if(std::abs(atECAL_tmp.positionREP().Eta())<1E-9 &&
00430              std::abs(atECAL_tmp.positionREP().Phi())<1E-9 &&
00431              atECAL_tmp.positionREP().R()<1E-9) 
00432             track.calculatePositionREP();
00433           */
00434 
00435           const reco::PFTrajectoryPoint& atECAL = 
00436             trackref->extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax );
00437           
00438           double tracketa = atECAL.positionREP().Eta();
00439           double trackphi = atECAL.positionREP().Phi();
00440 
00441           dist = LinkByRecHit::computeDist(ecaleta, ecalphi, tracketa, trackphi);
00442         }
00443 
00444       } else {// Old algorithm
00445         if ( trackref->extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax ).isValid() )
00446           dist = LinkByRecHit::testTrackAndClusterByRecHit( *trackref, *clusterref, false, debug_ );
00447         else
00448           dist = -1.;
00449       }
00450 
00451       if ( debug_ ) { 
00452         if( dist > 0. ) { 
00453           std::cout << " Here a link has been established"
00454                     << " between a track an Ecal with dist  " 
00455                     << dist <<  std::endl;
00456         } else
00457           std::cout << " No link found " << std::endl;
00458       }
00459       
00460       //     linktest = PFBlock::LINKTEST_RECHIT;
00461       break;
00462     }
00463   case PFBlockLink::TRACKandHCAL:
00464     {
00465       //      if(debug_ ) cout<<"TRACKandHCAL"<<endl;
00466 
00467       PFRecTrackRef trackref = lowEl->trackRefPF();
00468       PFClusterRef  clusterref = highEl->clusterRef();
00469       assert( !trackref.isNull() );
00470       assert( !clusterref.isNull() );
00471 
00472       // Check if the linking has been done using the KDTree algo
00473       // Glowinski & Gouzevitch
00474       if ( useKDTreeTrackEcalLinker_ && highEl->isMultilinksValide() ) { //KDTree Algo
00475         
00476         const reco::PFMultilinksType& multilinks = highEl->getMultilinks();
00477 
00478         /*
00479         reco::PFRecTrack track (*trackref);
00480         const reco::PFTrajectoryPoint& atHCALEntrance_tmp = 
00481           (*trackref).extrapolatedPoint( reco::PFTrajectoryPoint::HCALEntrance);
00482         if (std::abs(atHCALEntrance_tmp.positionREP().Eta())<1E-9 &&
00483             std::abs(atHCALEntrance_tmp.positionREP().Phi())<1E-9 &&
00484             atHCALEntrance_tmp.positionREP().R()<1E-9)   
00485           track.calculatePositionREP();
00486         */
00487 
00488         const reco::PFTrajectoryPoint& atHCAL = 
00489           trackref->extrapolatedPoint(reco::PFTrajectoryPoint::HCALEntrance);
00490         
00491           
00492         double tracketa = atHCAL.positionREP().Eta();
00493         double trackphi = atHCAL.positionREP().Phi();
00494 
00495         // Check if the link Track/Ecal exist
00496         reco::PFMultilinksType::const_iterator mlit = multilinks.begin();
00497         for (; mlit != multilinks.end(); ++mlit)
00498           if ((mlit->first == trackphi) && (mlit->second == tracketa))
00499             break;
00500 
00501         // If the link exist, we fill dist and linktest. We use old algorithme method.
00502         if (mlit != multilinks.end()){
00503 
00504           const reco::PFTrajectoryPoint& atHCALExit = 
00505             trackref->extrapolatedPoint(reco::PFTrajectoryPoint::HCALExit);
00506           double dHEta = 0.0;
00507           double dHPhi = 0.0;
00508           if (atHCALExit.position().R()>atHCAL.position().R()) {
00509             dHEta = atHCALExit.positionREP().Eta()-atHCAL.positionREP().Eta();
00510             dHPhi = atHCALExit.positionREP().Phi()-atHCAL.positionREP().Phi(); 
00511             if ( dHPhi > M_PI ) dHPhi = dHPhi - 2.*M_PI;
00512             else if ( dHPhi < -M_PI ) dHPhi = dHPhi + 2.*M_PI; 
00513           } else {
00514             std::cout << "Qu'est ce que c'est que ce gag ? " 
00515                       << atHCALExit.position().R() << " is larger than " 
00516                       << atHCAL.position().R() << " !" << std::endl;
00517           }
00518 
00519           tracketa += 0.1 * dHEta;
00520           trackphi += 0.1 * dHPhi;
00521 
00522           double clusterphi = clusterref->positionREP().Phi();
00523           double clustereta = clusterref->positionREP().Eta();
00524           
00525           dist = LinkByRecHit::computeDist(clustereta, clusterphi, tracketa, trackphi);
00526         }       
00527 
00528       } else {// Old algorithm
00529         if ( trackref->extrapolatedPoint( reco::PFTrajectoryPoint::HCALEntrance ).isValid() )
00530           dist = LinkByRecHit::testTrackAndClusterByRecHit( *trackref, *clusterref, false, debug_ );
00531         else
00532           dist = -1.;
00533       }
00534       
00535       //      linktest = PFBlock::LINKTEST_RECHIT;
00536       break;
00537     }
00538   case PFBlockLink::TRACKandHO:
00539     {
00540       if(debug_ ) cout<<"TRACKandHO"<<endl;
00541 
00542       PFRecTrackRef trackref = lowEl->trackRefPF();
00543       PFClusterRef  clusterref = highEl->clusterRef();
00544       
00545       assert( !trackref.isNull() );
00546       assert( !clusterref.isNull() );
00547 
00548       
00549       // Old algorithm
00550       //      cout<<"TRACKandHO1"<<trackref->pt()<<" "<<trackref->eta()<<" "<<trackref->phi()<<endl;
00551       //Same value is used in PFTrackTransformer::addPoints() for HOLayer, but allow for some rounding precision
00552       if ( lowEl->trackRef()->pt() > 3.00001 && trackref->extrapolatedPoint( reco::PFTrajectoryPoint::HOLayer ).isValid() ) {
00553         //      cout<<"TRACKandHO2"<<endl;
00554         dist = LinkByRecHit::testTrackAndClusterByRecHit( *trackref, *clusterref, false, debug_ );
00555         
00556         //      cout <<"dist TRACKandHO "<<dist<<endl;
00557       } else {
00558         dist = -1.;
00559       }
00560       //      linktest = PFBlock::LINKTEST_RECHIT;
00561       break;
00562     }
00563   case PFBlockLink::ECALandHCAL:
00564     {
00565       //       cout<<"ECALandHCAL"<<endl;
00566       PFClusterRef  ecalref = lowEl->clusterRef();
00567       PFClusterRef  hcalref = highEl->clusterRef();
00568       assert( !ecalref.isNull() );
00569       assert( !hcalref.isNull() );
00570       // PJ - 14-May-09 : A link by rechit is needed here !
00571       dist = testECALAndHCAL( *ecalref, *hcalref );
00572       // dist = -1.;
00573       //     linktest = PFBlock::LINKTEST_RECHIT;
00574       break;
00575     }
00576   case PFBlockLink::HCALandHO:
00577     {
00578       //       cout<<"HCALandH0"<<endl;
00579       PFClusterRef  hcalref = lowEl->clusterRef();
00580       PFClusterRef  horef = highEl->clusterRef();
00581       assert( !hcalref.isNull() );
00582       assert( !horef.isNull() );
00583       // PJ - 14-May-09 : A link by rechit is needed here !
00584       dist = testHCALAndHO( *hcalref, *horef );
00585       // dist = -1.;
00586       //      cout <<"Dist "<<dist<<endl;
00587       //     linktest = PFBlock::LINKTEST_RECHIT;
00588       break;
00589     }
00590   case PFBlockLink::HFEMandHFHAD:
00591     {
00592       // cout<<"HFEMandHFHAD"<<endl;
00593       PFClusterRef  eref = lowEl->clusterRef();
00594       PFClusterRef  href = highEl->clusterRef();
00595       assert( !eref.isNull() );
00596       assert( !href.isNull() );
00597       dist = LinkByRecHit::testHFEMAndHFHADByRecHit( *eref, *href, debug_ );
00598       //    linktest = PFBlock::LINKTEST_RECHIT;
00599       break;      
00600     }
00601 
00602   case PFBlockLink::TRACKandTRACK:
00603     {
00604       if(debug_ ) 
00605         cout<<"TRACKandTRACK"<<endl;
00606       dist = testLinkByVertex(lowEl, highEl);
00607       if(debug_ ) 
00608         std::cout << " PFBlockLink::TRACKandTRACK dist " << dist << std::endl;
00609       //   linktest = PFBlock::LINKTEST_RECHIT;
00610       break;
00611     }
00612 
00613   case PFBlockLink::ECALandECAL:
00614       {
00615         
00616         PFClusterRef  ecal1ref = lowEl->clusterRef();
00617         PFClusterRef  ecal2ref = highEl->clusterRef();
00618         assert( !ecal1ref.isNull() );
00619         assert( !ecal2ref.isNull() );
00620         if(debug_)
00621           cout << " PFBlockLink::ECALandECAL" << endl;
00622         dist = testLinkBySuperCluster(ecal1ref,ecal2ref);
00623         break;
00624       }
00625 
00626   case PFBlockLink::ECALandGSF:
00627     {
00628       PFClusterRef  clusterref = lowEl->clusterRef();
00629       assert( !clusterref.isNull() );
00630       const reco::PFBlockElementGsfTrack *  GsfEl =  dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00631       const PFRecTrack * myTrack =  &(GsfEl->GsftrackPF());
00632       if ( myTrack->extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax ).isValid() )
00633         dist = LinkByRecHit::testTrackAndClusterByRecHit( *myTrack, *clusterref, false, debug_ );
00634       else
00635         dist = -1.;
00636       //   linktest = PFBlock::LINKTEST_RECHIT;
00637       
00638       if ( debug_ ) {
00639         if ( dist > 0. ) {
00640           std::cout << " Here a link has been established" 
00641                     << " between a GSF track an Ecal with dist  " 
00642                     << dist <<  std::endl;
00643         } else {
00644           if(debug_ ) std::cout << " No link found " << std::endl;
00645         }
00646       }
00647       break;
00648     }
00649   case PFBlockLink::TRACKandGSF:
00650     {
00651       PFRecTrackRef trackref = lowEl->trackRefPF();
00652       assert( !trackref.isNull() );
00653       const reco::PFBlockElementGsfTrack *  GsfEl =  
00654         dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00655       GsfPFRecTrackRef gsfref = GsfEl->GsftrackRefPF();
00656       reco::TrackRef kftrackref= (*trackref).trackRef();
00657       assert( !gsfref.isNull() );
00658       PFRecTrackRef refkf = (*gsfref).kfPFRecTrackRef();
00659       if(refkf.isNonnull()) {
00660         reco::TrackRef gsftrackref = (*refkf).trackRef();
00661         if (gsftrackref.isNonnull()&&kftrackref.isNonnull()) {
00662           if (kftrackref == gsftrackref) { 
00663             dist = 0.001;
00664           } else { 
00665             dist = -1.;
00666           }
00667         } else { 
00668           dist = -1.;
00669         }
00670       } else {
00671         dist = -1.;
00672       }
00673       
00674       
00675       if(useConvBremPFRecTracks_) {
00676         if(lowEl->isLinkedToDisplacedVertex()){
00677           vector<PFRecTrackRef> pfrectrack_vec = GsfEl->GsftrackRefPF()->convBremPFRecTrackRef();
00678           if(pfrectrack_vec.size() > 0){
00679             for(unsigned int iconv = 0; iconv <  pfrectrack_vec.size(); ++iconv) {
00680               if( lowEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)) {
00681                 // use track ref
00682                 if(kftrackref == (*pfrectrack_vec[iconv]).trackRef()) {         
00683                   dist = 0.001;
00684                 }
00685               } 
00686               else{
00687                 // use the track base ref
00688                 reco::TrackBaseRef newTrackBaseRef((*pfrectrack_vec[iconv]).trackRef());
00689                 reco::TrackBaseRef elemTrackBaseRef(kftrackref);              
00690                 if(newTrackBaseRef == elemTrackBaseRef){
00691                   dist = 0.001;
00692                 } 
00693               }
00694             }
00695           }
00696         }
00697       }
00698  
00699 
00700       break;      
00701     }
00702          
00703   case PFBlockLink::GSFandBREM:
00704     {
00705       const reco::PFBlockElementGsfTrack * GsfEl  =  dynamic_cast<const reco::PFBlockElementGsfTrack*>(lowEl);
00706       const reco::PFBlockElementBrem * BremEl =  dynamic_cast<const reco::PFBlockElementBrem*>(highEl);
00707       GsfPFRecTrackRef gsfref = GsfEl->GsftrackRefPF();
00708       GsfPFRecTrackRef bremref = BremEl->GsftrackRefPF();
00709       assert( !gsfref.isNull() );
00710       assert( !bremref.isNull() );
00711       if (gsfref == bremref)  { 
00712         dist = 0.001;
00713       } else { 
00714         dist = -1.;
00715       }
00716       break;
00717     }
00718   case PFBlockLink::GSFandGSF:
00719     {
00720       const reco::PFBlockElementGsfTrack * lowGsfEl  =  
00721         dynamic_cast<const reco::PFBlockElementGsfTrack*>(lowEl);
00722       const reco::PFBlockElementGsfTrack * highGsfEl  =  
00723         dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00724       
00725       GsfPFRecTrackRef lowgsfref = lowGsfEl->GsftrackRefPF();
00726       GsfPFRecTrackRef highgsfref = highGsfEl->GsftrackRefPF();
00727       assert( !lowgsfref.isNull() );
00728       assert( !highgsfref.isNull() );
00729       
00730       if( (lowGsfEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false && 
00731            highGsfEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)) ||
00732           (highGsfEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false && 
00733            lowGsfEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV))) {
00734         if(lowgsfref->trackId() == highgsfref->trackId()) {
00735           dist = 0.001;
00736         }
00737         else {
00738           dist = -1.;
00739         }
00740       }
00741       break;
00742     }
00743   case PFBlockLink::ECALandBREM:
00744     {
00745       PFClusterRef  clusterref = lowEl->clusterRef();
00746       assert( !clusterref.isNull() );
00747       const reco::PFBlockElementBrem * BremEl =  
00748         dynamic_cast<const reco::PFBlockElementBrem*>(highEl);
00749       const PFRecTrack * myTrack = &(BremEl->trackPF());
00750       /*
00751       double DP = (BremEl->DeltaP())*(-1.);
00752       double SigmaDP = BremEl->SigmaDeltaP();
00753       double SignBremDp = DP/SigmaDP;
00754       */
00755       bool isBrem = true;
00756       if ( myTrack->extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax ).isValid() )
00757         dist = LinkByRecHit::testTrackAndClusterByRecHit( *myTrack, *clusterref, isBrem, debug_);
00758       else
00759         dist = -1.;
00760       if( debug_ && dist > 0. ) 
00761         std::cout << "ECALandBREM: dist testTrackAndClusterByRecHit " 
00762                   << dist << std::endl;
00763       //   linktest = PFBlock::LINKTEST_RECHIT;
00764       break;
00765     }
00766   case PFBlockLink::HCALandGSF:
00767     {
00768       PFClusterRef  clusterref = lowEl->clusterRef();
00769       assert( !clusterref.isNull() );
00770       const reco::PFBlockElementGsfTrack *  GsfEl =  dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00771       const PFRecTrack * myTrack =  &(GsfEl->GsftrackPF());
00772       if ( myTrack->extrapolatedPoint( reco::PFTrajectoryPoint::HCALEntrance ).isValid() )
00773         dist = LinkByRecHit::testTrackAndClusterByRecHit( *myTrack, *clusterref, false, debug_ );
00774       else
00775         dist = -1.;
00776 
00777       //    linktest = PFBlock::LINKTEST_RECHIT;
00778       break;
00779     }
00780   case PFBlockLink::HCALandBREM:
00781     {
00782       PFClusterRef  clusterref = lowEl->clusterRef();
00783       assert( !clusterref.isNull() );
00784       const reco::PFBlockElementBrem * BremEl =  dynamic_cast<const reco::PFBlockElementBrem*>(highEl);
00785       const PFRecTrack * myTrack = &(BremEl->trackPF());
00786       bool isBrem = true;
00787       if ( myTrack->extrapolatedPoint( reco::PFTrajectoryPoint::HCALEntrance ).isValid() )
00788         dist = LinkByRecHit::testTrackAndClusterByRecHit( *myTrack, *clusterref, isBrem, debug_);
00789       else
00790         dist = -1.;
00791       break;
00792     }
00793   case PFBlockLink::SCandECAL:
00794     {
00795       PFClusterRef  clusterref = lowEl->clusterRef();
00796 
00797       assert( !clusterref.isNull() );
00798       
00799       const reco::PFBlockElementSuperCluster * scEl = 
00800         dynamic_cast<const reco::PFBlockElementSuperCluster*>(highEl);
00801       assert (!scEl->superClusterRef().isNull());
00802       dist = testSuperClusterPFCluster(scEl->superClusterRef(),
00803                                        clusterref);
00804       break;
00805     }
00806     /*
00807   // Links between the two preshower layers are not used for now - disable
00808   case PFBlockLink::PS1andPS2:
00809     {
00810       PFClusterRef  ps1ref = lowEl->clusterRef();
00811       PFClusterRef  ps2ref = highEl->clusterRef();
00812       assert( !ps1ref.isNull() );
00813       assert( !ps2ref.isNull() );
00814       // PJ - 14-May-09 : A link by rechit is needed here !
00815       // dist = testPS1AndPS2( *ps1ref, *ps2ref );
00816       dist = -1.;
00817       linktest = PFBlock::LINKTEST_RECHIT;
00818       break;
00819     }
00820   case PFBlockLink::TRACKandPS1:
00821   case PFBlockLink::TRACKandPS2:
00822     {
00823       //cout<<"TRACKandPS"<<endl;
00824       PFRecTrackRef trackref = lowEl->trackRefPF();
00825       PFClusterRef  clusterref = highEl->clusterRef();
00826       assert( !trackref.isNull() );
00827       assert( !clusterref.isNull() );
00828       // PJ - 14-May-09 : A link by rechit is needed here !
00829       dist = testTrackAndPS( *trackref, *clusterref );
00830       linktest = PFBlock::LINKTEST_RECHIT;
00831       break;
00832     }
00833     // GSF Track/Brem Track and preshower cluster links are not used for now - disable
00834   case PFBlockLink::PS1andGSF:
00835   case PFBlockLink::PS2andGSF:
00836     {
00837       PFClusterRef  psref = lowEl->clusterRef();
00838       assert( !psref.isNull() );
00839       const reco::PFBlockElementGsfTrack *  GsfEl =  dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00840       const PFRecTrack * myTrack =  &(GsfEl->GsftrackPF());
00841       // PJ - 14-May-09 : A link by rechit is needed here !
00842       dist = testTrackAndPS( *myTrack, *psref );
00843       linktest = PFBlock::LINKTEST_RECHIT;
00844       break;
00845     }
00846   case PFBlockLink::PS1andBREM:
00847   case PFBlockLink::PS2andBREM:
00848     {
00849       PFClusterRef  psref = lowEl->clusterRef();
00850       assert( !psref.isNull() );
00851       const reco::PFBlockElementBrem * BremEl =  dynamic_cast<const reco::PFBlockElementBrem*>(highEl);
00852       const PFRecTrack * myTrack = &(BremEl->trackPF());
00853       // PJ - 14-May-09 : A link by rechit is needed here !
00854       dist = testTrackAndPS( *myTrack, *psref );
00855       linktest = PFBlock::LINKTEST_RECHIT;
00856       break;
00857     }
00858     */
00859 
00860   default:
00861     dist = -1.;
00862     //   linktest = PFBlock::LINKTEST_RECHIT;
00863     // cerr<<"link type not implemented yet: 0x"<<hex<<linktype<<dec<<endl;
00864     // assert(0);
00865     return;
00866   }
00867 }
00868 
00869 double
00870 PFBlockAlgo::testTrackAndPS(const PFRecTrack& track, 
00871                             const PFCluster& ps)  const {
00872 
00873 #ifdef PFLOW_DEBUG
00874   //   cout<<"entering testTrackAndPS"<<endl;
00875   // resolution of PS cluster dxdx and dydy from strip pitch and length
00876   double dx=0.;
00877   double dy=0.;
00878   
00879   unsigned layerid =0;
00880   // PS1: vertical strips  PS2: horizontal strips
00881   switch (ps.layer()) {
00882   case PFLayer::PS1:
00883     layerid = reco::PFTrajectoryPoint::PS1;
00884     
00885     // vertical strips in PS1, measure x with pitch precision
00886     dx = resPSpitch_;
00887     dy = resPSlength_; 
00888     break;
00889   case PFLayer::PS2:
00890     layerid = reco::PFTrajectoryPoint::PS2;
00891     // horizontal strips in PS2, measure y with pitch precision
00892     dy = resPSpitch_;
00893     dx = resPSlength_;
00894     break;
00895   default:
00896     break;
00897   }
00898   const reco::PFTrajectoryPoint& atPS
00899     = track.extrapolatedPoint( layerid );  
00900   // did not reach PS, cannot be associated with a cluster.
00901   if( ! atPS.isValid() ) return -1.;   
00902   
00903   double trackx = atPS.position().X();
00904   double tracky = atPS.position().Y();
00905   double trackz = atPS.position().Z(); // MDN jan 09
00906   
00907   // ps position  x, y
00908   double psx = ps.position().X();
00909   double psy = ps.position().Y();
00910   // MDN Jan 09: check that trackz and psz have the same sign
00911   double psz = ps.position().Z();
00912   if( trackz*psz < 0.) return -1.; 
00913   
00914   // double chi2 = (psx-trackx)*(psx-trackx)/(dx*dx + trackresolx*trackresolx)
00915   //  + (psy-tracky)*(psy-tracky)/(dy*dy + trackresoly*trackresoly);
00916 
00917   double dist = std::sqrt( (psx-trackx)*(psx-trackx)
00918                          + (psy-tracky)*(psy-tracky));  
00919   if(debug_) cout<<"testTrackAndPS "<< dist <<" "<<endl;
00920   if(debug_){
00921     cout<<" trackx " << trackx 
00922         <<" tracky " << tracky 
00923         <<" psx "    <<  psx   
00924         <<" psy "    << psy    
00925         << endl;
00926   }
00927 #endif
00928   
00929   // Return -1. as long as no link by rechit is available
00930   return -1.;
00931 }
00932 
00933 double
00934 PFBlockAlgo::testECALAndHCAL(const PFCluster& ecal, 
00935                              const PFCluster& hcal)  const {
00936   
00937   //   cout<<"entering testECALAndHCAL"<<endl;
00938   
00939   double dist = fabs(ecal.positionREP().Eta()) > 2.5 ?
00940     LinkByRecHit::computeDist( ecal.positionREP().Eta(),
00941                                ecal.positionREP().Phi(), 
00942                                hcal.positionREP().Eta(), 
00943                                hcal.positionREP().Phi() )
00944     : 
00945     -1.;
00946 
00947 #ifdef PFLOW_DEBUG
00948   if(debug_) cout<<"testECALAndHCAL "<< dist <<" "<<endl;
00949   if(debug_){
00950     cout<<" ecaleta " << ecal.positionREP().Eta()
00951         <<" ecalphi " << ecal.positionREP().Phi()
00952         <<" hcaleta " << hcal.positionREP().Eta()
00953         <<" hcalphi " << hcal.positionREP().Phi()
00954   }
00955 #endif
00956 
00957   if ( dist < 0.2 ) return dist; 
00958  
00959   // Need to implement a link by RecHit
00960   return -1.;
00961 }
00962 
00963 double
00964 PFBlockAlgo::testHCALAndHO(const PFCluster& hcal, 
00965                              const PFCluster& ho)  const {
00966   
00967   double dist = fabs(hcal.positionREP().Eta()) < 1.5 ?
00968     LinkByRecHit::computeDist( hcal.positionREP().Eta(),
00969                                hcal.positionREP().Phi(), 
00970                                ho.positionREP().Eta(), 
00971                                ho.positionREP().Phi() )
00972     : 
00973     -1.;
00974 
00975 #ifdef PFLOW_DEBUG
00976   if(debug_) cout<<"testHCALAndHO "<< dist <<" "<<endl;
00977   if(debug_){
00978     cout<<" hcaleta " << hcal.positionREP().Eta()
00979         <<" hcalphi " << hcal.positionREP().Phi()
00980         <<" hoeta " << ho.positionREP().Eta()
00981         <<" hophi " << ho.positionREP().Phi()
00982         <<" dist " << dist<<endl;
00983   }
00984 #endif
00985 
00986   if ( dist < 0.20 ) return dist; 
00987  
00988   // Need to implement a link by RecHit
00989   return -1.;
00990 }
00991 
00992 
00993 
00994 double
00995 PFBlockAlgo::testLinkBySuperCluster(const PFClusterRef& ecal1, 
00996                                     const PFClusterRef& ecal2)  const {
00997   
00998   //  cout<<"entering testECALAndECAL "<< pfcRefSCMap_.size() << endl;
00999   
01000   double dist = -1;
01001   
01002   // the first one is not in any super cluster
01003   int testindex=pfcSCVec_[ecal1.key()];
01004   if(testindex == -1.) return dist;
01005   //  if(itcheck==pfcRefSCMap_.end()) return dist;
01006   // now retrieve the of PFclusters in this super cluster  
01007 
01008   const std::vector<reco::PFClusterRef> & thePFClusters(scpfcRefs_[testindex]);
01009   
01010   unsigned npf=thePFClusters.size();
01011   for(unsigned i=0;i<npf;++i)
01012     {
01013       if(thePFClusters[i]==ecal2) // yes they are in the same SC 
01014         {
01015           dist=LinkByRecHit::computeDist( ecal1->positionREP().Eta(),
01016                                           ecal1->positionREP().Phi(), 
01017                                           ecal2->positionREP().Eta(), 
01018                                           ecal2->positionREP().Phi() );
01019 //        std::cout << " DETA " << fabs(ecal1->positionREP().Eta()-ecal2->positionREP().Eta()) << std::endl;
01020 //        if(fabs(ecal1->positionREP().Eta()-ecal2->positionREP().Eta())>0.2)
01021 //          {
01022 //            std::cout <<  " Super Cluster " <<  *(superClusters_[testindex]) << std::endl;
01023 //            std::cout <<  " Cluster1 " <<  *ecal1 << std::endl;
01024 //            std::cout <<  " Cluster2 " <<  *ecal2 << std::endl;
01025 //            ClusterClusterMapping::checkOverlap(*ecal1,superClusters_,0.01,true);
01026 //            ClusterClusterMapping::checkOverlap(*ecal2,superClusters_,0.01,true);
01027 //          }
01028           return dist;
01029         }
01030     }
01031   return dist;
01032 }
01033 
01034 
01035 double
01036 PFBlockAlgo::testSuperClusterPFCluster(const SuperClusterRef& ecal1, 
01037                                        const PFClusterRef& ecal2)  const {
01038   
01039   //  cout<<"entering testECALAndECAL "<< pfcRefSCMap_.size() << endl;
01040   
01041   double dist = -1;
01042   
01043   bool overlap=ClusterClusterMapping::overlap(*ecal1,*ecal2);
01044   
01045   if(overlap)   {
01046     dist=LinkByRecHit::computeDist( ecal1->position().eta(),
01047                                     ecal1->position().phi(), 
01048                                     ecal2->positionREP().Eta(), 
01049                                     ecal2->positionREP().Phi() );
01050     return dist;
01051   }
01052   return dist;
01053 }
01054 
01055 
01056 
01057 double
01058 PFBlockAlgo::testPS1AndPS2(const PFCluster& ps1, 
01059                            const PFCluster& ps2)  const {
01060   
01061 #ifdef PFLOW_DEBUG
01062   //   cout<<"entering testPS1AndPS2"<<endl;
01063   
01064   // compute chi2 in y, z using swimming formulae
01065   // y2 = y1 * z2/z1   and x2 = x1 *z2/z1
01066   
01067   // ps position1  x, y, z
01068   double x1 = ps1.position().X();
01069   double y1 = ps1.position().Y();
01070   double z1 = ps1.position().Z();
01071   double x2 = ps2.position().X();
01072   double y2 = ps2.position().Y();
01073   double z2 = ps2.position().Z();
01074   // MDN Bug correction Jan 09: check that z1 and z2 have the same sign!
01075   if (z1*z2<0.) -1.;
01076   // swim to PS2
01077   double scale = z2/z1;
01078   double x1atPS2 = x1*scale;
01079   double y1atPS2 = y1*scale;
01080   // resolution of PS cluster dxdx and dydy from strip pitch and length
01081   // vertical strips in PS1, measure x with pitch precision
01082   double dx1dx1 = resPSpitch_*resPSpitch_*scale*scale;
01083   double dy1dy1 = resPSlength_*resPSlength_*scale*scale;
01084   // horizontal strips in PS2 , measure y with pitch precision
01085   double dy2dy2 = resPSpitch_*resPSpitch_;
01086   double dx2dx2 = resPSlength_*resPSlength_;
01087   
01088   // double chi2 = (x2-x1atPS2)*(x2-x1atPS2)/(dx1dx1 + dx2dx2) 
01089   //  + (y2-y1atPS2)*(y2-y1atPS2)/(dy1dy1 + dy2dy2);
01090   
01091   double dist = std::sqrt( (x2-x1atPS2)*(x2-x1atPS2)
01092                          + (y2-y1atPS2)*(y2-y1atPS2));
01093     
01094   if(debug_) cout<<"testPS1AndPS2 "<<dist<<" "<<endl;
01095   if(debug_){
01096     cout<<" x1atPS2 "<< x1atPS2 << " dx1 "<<resPSpitch_*scale
01097         <<" y1atPS2 "<< y1atPS2 << " dy1 "<<resPSlength_*scale<< endl
01098         <<" x2 " <<x2  << " dx2 "<<resPSlength_
01099         <<" y2 " << y2 << " dy2 "<<resPSpitch_<< endl;
01100   }
01101 #endif
01102 
01103   // Need a link by rechit here
01104   return -1.; 
01105 }
01106 
01107 
01108 
01109 double
01110 PFBlockAlgo::testLinkByVertex( const reco::PFBlockElement* elt1, 
01111                                const reco::PFBlockElement* elt2) const {
01112 
01113   //  cout << "Test link by vertex between" << endl << *elt1 << endl << " and " << endl << *elt2 << endl;
01114 
01115   double result=-1.;
01116 
01117   reco::PFBlockElement::TrackType T_TO_DISP = reco::PFBlockElement::T_TO_DISP;
01118   reco::PFBlockElement::TrackType T_FROM_DISP = reco::PFBlockElement::T_FROM_DISP;
01119   PFDisplacedTrackerVertexRef ni1_TO_DISP = elt1->displacedVertexRef(T_TO_DISP);
01120   PFDisplacedTrackerVertexRef ni2_TO_DISP = elt2->displacedVertexRef(T_TO_DISP);
01121   PFDisplacedTrackerVertexRef ni1_FROM_DISP = elt1->displacedVertexRef(T_FROM_DISP);
01122   PFDisplacedTrackerVertexRef ni2_FROM_DISP = elt2->displacedVertexRef(T_FROM_DISP);
01123   
01124   if( ni1_TO_DISP.isNonnull() && ni2_FROM_DISP.isNonnull())
01125     if( ni1_TO_DISP == ni2_FROM_DISP ) { result = 1.0; return result; }
01126 
01127   if( ni1_FROM_DISP.isNonnull() && ni2_TO_DISP.isNonnull())
01128     if( ni1_FROM_DISP == ni2_TO_DISP ) { result = 1.0; return result; }
01129 
01130   if( ni1_FROM_DISP.isNonnull() && ni2_FROM_DISP.isNonnull())
01131     if( ni1_FROM_DISP == ni2_FROM_DISP ) { result = 1.0; return result; }
01132     
01133   
01134   if (  elt1->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)  &&
01135              elt2->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)  ) {
01136     
01137     if(debug_ ) std::cout << " testLinkByVertex On Conversions " << std::endl;
01138     
01139     if ( elt1->convRef().isNonnull() && elt2->convRef().isNonnull() ) {
01140       if(debug_ ) std::cout << " PFBlockAlgo.cc testLinkByVertex  Cconversion Refs are non null  " << std::endl;      
01141       if ( elt1->convRef() ==  elt2->convRef() ) {
01142         result=1.0;
01143         if(debug_ ) std::cout << " testLinkByVertex  Cconversion Refs are equal  " << std::endl;      
01144         return result;
01145       }
01146     } 
01147     
01148   }
01149   
01150   if (  elt1->trackType(reco::PFBlockElement::T_FROM_V0)  &&
01151              elt2->trackType(reco::PFBlockElement::T_FROM_V0)  ) {
01152     if(debug_ ) std::cout << " testLinkByVertex On V0 " << std::endl;
01153     if ( elt1->V0Ref().isNonnull() && elt2->V0Ref().isNonnull() ) {
01154       if(debug_ ) std::cout << " PFBlockAlgo.cc testLinkByVertex  V0 Refs are non null  " << std::endl;
01155       if ( elt1->V0Ref() ==  elt2->V0Ref() ) {
01156         result=1.0;
01157         if(debug_ ) std::cout << " testLinkByVertex  V0 Refs are equal  " << std::endl;
01158         return result;
01159       }
01160     }
01161   }
01162 
01163   return result;
01164 }
01165 
01166 
01167 
01168 void 
01169 PFBlockAlgo::checkMaskSize( const reco::PFRecTrackCollection& tracks,
01170                             const reco::GsfPFRecTrackCollection& gsftracks, 
01171                             const reco::PFClusterCollection&  ecals,
01172                             const reco::PFClusterCollection&  hcals,
01173                             const reco::PFClusterCollection&  hos,
01174                             const reco::PFClusterCollection&  hfems,
01175                             const reco::PFClusterCollection&  hfhads,
01176                             const reco::PFClusterCollection&  pss, 
01177                             const reco::PhotonCollection&  egphh, 
01178                             const reco::SuperClusterCollection&  sceb, 
01179                             const reco::SuperClusterCollection&  scee,                      
01180                             const Mask& trackMask, 
01181                             const Mask& gsftrackMask,  
01182                             const Mask& ecalMask,
01183                             const Mask& hcalMask,
01184                             const Mask& hoMask, 
01185                             const Mask& hfemMask,
01186                             const Mask& hfhadMask,                    
01187                             const Mask& psMask,
01188                             const Mask& phMask,
01189                             const Mask& scMask) const {
01190 
01191   if( !trackMask.empty() && 
01192       trackMask.size() != tracks.size() ) {
01193     string err = "PFBlockAlgo::setInput: ";
01194     err += "The size of the track mask is different ";
01195     err += "from the size of the track vector.";
01196     throw std::length_error( err.c_str() );
01197   }
01198 
01199   if( !gsftrackMask.empty() && 
01200       gsftrackMask.size() != gsftracks.size() ) {
01201     string err = "PFBlockAlgo::setInput: ";
01202     err += "The size of the gsf track mask is different ";
01203     err += "from the size of the gsftrack vector.";
01204     throw std::length_error( err.c_str() );
01205   }
01206 
01207   if( !ecalMask.empty() && 
01208       ecalMask.size() != ecals.size() ) {
01209     string err = "PFBlockAlgo::setInput: ";
01210     err += "The size of the ecal mask is different ";
01211     err += "from the size of the ecal clusters vector.";
01212     throw std::length_error( err.c_str() );
01213   }
01214   
01215   if( !hcalMask.empty() && 
01216       hcalMask.size() != hcals.size() ) {
01217     string err = "PFBlockAlgo::setInput: ";
01218     err += "The size of the hcal mask is different ";
01219     err += "from the size of the hcal clusters vector.";
01220     throw std::length_error( err.c_str() );
01221   }
01222 
01223   if( !hoMask.empty() && 
01224       hoMask.size() != hos.size() ) {
01225     string err = "PFBlockAlgo::setInput: ";
01226     err += "The size of the ho mask is different ";
01227     err += "from the size of the ho clusters vector.";
01228     throw std::length_error( err.c_str() );
01229   }
01230 
01231 
01232   if( !hfemMask.empty() && 
01233       hfemMask.size() != hfems.size() ) {
01234     string err = "PFBlockAlgo::setInput: ";
01235     err += "The size of the hfem mask is different ";
01236     err += "from the size of the hfem clusters vector.";
01237     throw std::length_error( err.c_str() );
01238   }
01239 
01240   if( !hfhadMask.empty() && 
01241       hfhadMask.size() != hfhads.size() ) {
01242     string err = "PFBlockAlgo::setInput: ";
01243     err += "The size of the hfhad mask is different ";
01244     err += "from the size of the hfhad clusters vector.";
01245     throw std::length_error( err.c_str() );
01246   }
01247 
01248   if( !psMask.empty() && 
01249       psMask.size() != pss.size() ) {
01250     string err = "PFBlockAlgo::setInput: ";
01251     err += "The size of the ps mask is different ";
01252     err += "from the size of the ps clusters vector.";
01253     throw std::length_error( err.c_str() );
01254   }
01255   
01256   if( !phMask.empty() && 
01257       phMask.size() != egphh.size() ) {
01258     string err = "PFBlockAlgo::setInput: ";
01259     err += "The size of the photon mask is different ";
01260     err += "from the size of the photon vector.";
01261     throw std::length_error( err.c_str() );
01262   }
01263   
01264   if( !scMask.empty() && 
01265       scMask.size() != (sceb.size() + scee.size()) ) {
01266     string err = "PFBlockAlgo::setInput: ";
01267     err += "The size of the SC mask is different ";
01268     err += "from the size of the SC vectors.";
01269     throw std::length_error( err.c_str() );
01270   }  
01271 
01272 }
01273 
01274 
01275 std::ostream& operator<<(std::ostream& out, const PFBlockAlgo& a) {
01276   if(! out) return out;
01277   
01278   out<<"====== Particle Flow Block Algorithm ======= ";
01279   out<<endl;
01280   out<<"number of unassociated elements : "<<a.elements_.size()<<endl;
01281   out<<endl;
01282   
01283   for(PFBlockAlgo::IEC ie = a.elements_.begin(); 
01284       ie != a.elements_.end(); ++ie) {
01285     out<<"\t"<<**ie <<endl;
01286   }
01287 
01288   
01289   //   const PFBlockCollection& blocks = a.blocks();
01290 
01291   const std::auto_ptr< reco::PFBlockCollection >& blocks
01292     = a.blocks(); 
01293     
01294   if(!blocks.get() ) {
01295     out<<"blocks already transfered"<<endl;
01296   }
01297   else {
01298     out<<"number of blocks : "<<blocks->size()<<endl;
01299     out<<endl;
01300     
01301     for(PFBlockAlgo::IBC ib=blocks->begin(); 
01302         ib != blocks->end(); ++ib) {
01303       out<<(*ib)<<endl;
01304     }
01305   }
01306 
01307   return out;
01308 }
01309 
01310 bool 
01311 PFBlockAlgo::goodPtResolution( const reco::TrackRef& trackref) {
01312 
01313   double P = trackref->p();
01314   double Pt = trackref->pt();
01315   double DPt = trackref->ptError();
01316   unsigned int NHit = trackref->hitPattern().trackerLayersWithMeasurement();
01317   unsigned int NLostHit = trackref->hitPattern().trackerLayersWithoutMeasurement();
01318   unsigned int LostHits = trackref->numberOfLostHits();
01319   double sigmaHad = sqrt(1.20*1.20/P+0.06*0.06) / (1.+LostHits);
01320 
01321   // iteration 1,2,3,4,5 correspond to algo = 1/4,5,6,7,8,9
01322   unsigned int Algo = 0; 
01323   switch (trackref->algo()) {
01324   case TrackBase::ctf:
01325   case TrackBase::iter0:
01326   case TrackBase::iter1:
01327   case TrackBase::iter2:
01328     Algo = 0;
01329     break;
01330   case TrackBase::iter3:
01331     Algo = 1;
01332     break;
01333   case TrackBase::iter4:
01334     Algo = 2;
01335     break;
01336   case TrackBase::iter5:
01337     Algo = 3;
01338     break;
01339   case TrackBase::iter6:
01340     Algo = 4;
01341     break;
01342   default:
01343     Algo = useIterTracking_ ? 5 : 0;
01344     break;
01345   }
01346 
01347   // Protection against 0 momentum tracks
01348   if ( P < 0.05 ) return false;
01349 
01350   // Temporary : Reject all tracking iteration beyond 5th step. 
01351   if ( Algo > 4 ) return false;
01352  
01353   if (debug_) cout << " PFBlockAlgo: PFrecTrack->Track Pt= "
01354                    << Pt << " DPt = " << DPt << endl;
01355   if ( ( DPtovPtCut_[Algo] > 0. && 
01356          DPt/Pt > DPtovPtCut_[Algo]*sigmaHad ) || 
01357        NHit < NHitCut_[Algo] ) { 
01358     // (Algo >= 3 && LostHits != 0) ) {
01359     if (debug_) cout << " PFBlockAlgo: skip badly measured track"
01360                      << ", P = " << P 
01361                      << ", Pt = " << Pt 
01362                      << " DPt = " << DPt 
01363                      << ", N(hits) = " << NHit << " (Lost : " << LostHits << "/" << NLostHit << ")"
01364                      << ", Algo = " << Algo
01365                      << endl;
01366     if (debug_) cout << " cut is DPt/Pt < " << DPtovPtCut_[Algo] * sigmaHad << endl;
01367     if (debug_) cout << " cut is NHit >= " << NHitCut_[Algo] << endl;
01368     /*
01369     std::cout << "Track REJECTED : ";
01370     std::cout << ", P = " << P 
01371               << ", Pt = " << Pt 
01372               << " DPt = " << DPt 
01373               << ", N(hits) = " << NHit << " (Lost : " << LostHits << "/" << NLostHit << ")"
01374               << ", Algo = " << Algo
01375               << std::endl;
01376     */
01377     return false;
01378   }
01379 
01380   /*
01381   std::cout << "Track Accepted : ";
01382   std::cout << ", P = " << P 
01383        << ", Pt = " << Pt 
01384        << " DPt = " << DPt 
01385        << ", N(hits) = " << NHit << " (Lost : " << LostHits << "/" << NLostHit << ")"
01386        << ", Algo = " << Algo
01387        << std::endl;
01388   */
01389   return true;
01390 }
01391 
01392 int
01393 PFBlockAlgo::muAssocToTrack( const reco::TrackRef& trackref,
01394                              const edm::Handle<reco::MuonCollection>& muonh) const {
01395   if(muonh.isValid() ) {
01396     for(unsigned j=0;j<muonh->size(); ++j) {
01397       reco::MuonRef muonref( muonh, j );
01398       if (muonref->track().isNonnull()) 
01399         if( muonref->track() == trackref ) return j;
01400     }
01401   }
01402   return -1; // not found
01403 }
01404 
01405 int 
01406 PFBlockAlgo::muAssocToTrack( const reco::TrackRef& trackref,
01407                              const edm::OrphanHandle<reco::MuonCollection>& muonh) const {
01408   if(muonh.isValid() ) {
01409     for(unsigned j=0;j<muonh->size(); ++j) {
01410       reco::MuonRef muonref( muonh, j );
01411       if (muonref->track().isNonnull())
01412         if( muonref->track() == trackref ) return j;
01413     }
01414   }
01415   return -1; // not found
01416 }
01417 
01418 
01419 // This prefilter avoid to call associate when not necessary.
01420 // ACHTUNG!!!! If you introduce new links check that they are not desables here
01421 inline bool
01422 PFBlockAlgo::linkPrefilter(const reco::PFBlockElement* last, const reco::PFBlockElement* next) const {
01423 
01424   PFBlockElement::Type type1 = (last)->type();
01425   PFBlockElement::Type type2 = (next)->type();
01426 
01427   if( type1==type2 ) {
01428     // cannot link 2 elements of the same type. 
01429     // except if the elements are 2 tracks or 2 ECAL
01430     if( type1!=PFBlockElement::TRACK && type1!=PFBlockElement::GSF &&
01431         type1!=PFBlockElement::ECAL) { // && type1!=PFBlockElement::HCAL) {
01432       return false;
01433     }
01434 
01435     if (type1==PFBlockElement::ECAL && bNoSuperclus_) return false;
01436 
01437     // cannot link two primary tracks  (except if they come from a V0)
01438     if( type1 ==PFBlockElement::TRACK) {
01439       if ( !((last)->isLinkedToDisplacedVertex()) || !((next)->isLinkedToDisplacedVertex())) 
01440       return false;
01441     }
01442   }
01443 
01444   if ((type1 == PFBlockElement::PS1 || type1 == PFBlockElement::PS2) && (type2 != PFBlockElement::ECAL)) return false;
01445   if ((type2 == PFBlockElement::PS1 || type2 == PFBlockElement::PS2) && (type1 != PFBlockElement::ECAL)) return false;
01446   if ((type1 == PFBlockElement::HFEM && type2 != PFBlockElement::HFHAD) || (type1 == PFBlockElement::HFHAD && type2 != PFBlockElement::HFEM)) return false;
01447 
01448   if (useKDTreeTrackEcalLinker_){ 
01449   
01450     if ( type1 == PFBlockElement::TRACK && type2 == PFBlockElement::ECAL)
01451       if ( last->isMultilinksValide()  && last->getMultilinks().size()==0 ) return false;
01452     if ( type2 == PFBlockElement::TRACK && type1 == PFBlockElement::ECAL)
01453       if ( next->isMultilinksValide() && next->getMultilinks().size()==0 ) return false;
01454     if ( type1 == PFBlockElement::PS1 || type1 == PFBlockElement::PS2)
01455       if ( last->isMultilinksValide()  && last->getMultilinks().size()==0 ) return false;
01456     if ( type2 == PFBlockElement::PS1 || type2 == PFBlockElement::PS2)
01457       if ( next->isMultilinksValide() && next->getMultilinks().size()==0 ) return false;
01458 
01459   }
01460 
01461   return true;
01462 
01463 }
01464