CMS 3D CMS Logo

PFBlockAlgo.cc

Go to the documentation of this file.
00001 #include "RecoParticleFlow/PFBlockAlgo/interface/PFBlockAlgo.h"
00002 #include "RecoParticleFlow/PFBlockAlgo/interface/Utils.h"
00003 #include "RecoParticleFlow/PFClusterTools/interface/PFResolutionMap.h"
00004 #include "DataFormats/ParticleFlowReco/interface/PFBlock.h"
00005 #include "DataFormats/TrackReco/interface/Track.h"
00006 
00007 #include "DataFormats/ParticleFlowReco/interface/PFRecHit.h"
00008 
00009 #include <stdexcept>
00010 #include "TMath.h"
00011 
00012 using namespace std;
00013 using namespace reco;
00014 
00015 //for debug only 
00016 // #define PFLOW_DEBUG
00017 
00018 const PFBlockAlgo::Mask PFBlockAlgo::dummyMask_;
00019 
00020 PFBlockAlgo::PFBlockAlgo() : 
00021   blocks_( new reco::PFBlockCollection ),
00022   //   tracks_(tracks),
00023   //   clustersECAL_(clustersECAL),
00024   //   clustersHCAL_(clustersHCAL),
00025   resMapEtaECAL_(0),
00026   resMapPhiECAL_(0),
00027   resMapEtaHCAL_(0),
00028   resMapPhiHCAL_(0), 
00029   DPtovPtCut_(999),
00030   chi2TrackECAL_(-1),
00031   chi2GSFECAL_(-1),
00032   chi2TrackHCAL_(-1), 
00033   chi2ECALHCAL_ (-1),
00034   chi2PSECAL_ (-1), 
00035   chi2PSTrack_ (-1), 
00036   chi2PSHV_ (-1), 
00037   resPSpitch_ (0),
00038   resPSlength_ (0),
00039   debug_(false) {}
00040 
00041 
00042 
00043 void PFBlockAlgo::setParameters( const char* resMapEtaECAL,
00044                                  const char* resMapPhiECAL,
00045                                  const char* resMapEtaHCAL,
00046                                  const char* resMapPhiHCAL, 
00047                                  double DPtovPtCut,
00048                                  double chi2TrackECAL,
00049                                  double chi2GSFECAL,
00050                                  double chi2TrackHCAL,
00051                                  double chi2ECALHCAL,
00052                                  double chi2PSECAL,
00053                                  double chi2PSTrack,
00054                                  double chi2PSHV,
00055                                  bool   multiLink ) {
00056   
00057   try {
00058     resMapEtaECAL_ = new PFResolutionMap("resmapEtaECAL",resMapEtaECAL);
00059     resMapPhiECAL_ = new PFResolutionMap("resmapPhiECAL",resMapPhiECAL);
00060     resMapEtaHCAL_ = new PFResolutionMap("resmapEtaHCAL",resMapEtaHCAL);
00061     resMapPhiHCAL_ = new PFResolutionMap("resmapPhiHCAL",resMapPhiHCAL);
00062   }
00063   catch(std::exception& err ) {
00064     // cout<<err.what()<<endl;
00065     throw;
00066   }
00067 
00068   DPtovPtCut_    = DPtovPtCut;
00069   chi2TrackECAL_ = chi2TrackECAL;
00070   chi2GSFECAL_   = chi2GSFECAL;
00071   chi2TrackHCAL_ = chi2TrackHCAL; 
00072   chi2ECALHCAL_  = chi2ECALHCAL;
00073   chi2PSECAL_    = chi2PSECAL;
00074   chi2PSTrack_   = chi2PSTrack;
00075   chi2PSHV_      = chi2PSHV;
00076   double strip_pitch = 0.19;
00077   double strip_length = 6.1;
00078   resPSpitch_    = strip_pitch/sqrt(12.);
00079   resPSlength_   = strip_length/sqrt(12.);
00080 
00081   multipleLink_  = multiLink;
00082 }
00083 
00084 PFBlockAlgo::~PFBlockAlgo() {
00085 
00086 #ifdef PFLOW_DEBUG
00087   if(debug_)
00088     cout<<"~PFBlockAlgo - number of remaining elements: "
00089         <<elements_.size()<<endl;
00090 #endif
00091   
00092   if(resMapEtaECAL_) delete resMapEtaECAL_;
00093   
00094   if(resMapPhiECAL_) delete resMapPhiECAL_;
00095   
00096   if(resMapEtaHCAL_) delete resMapEtaHCAL_;
00097 
00098   if(resMapPhiHCAL_) delete resMapPhiHCAL_;
00099 
00100 }
00101 
00102 void PFBlockAlgo::findBlocks() {
00103 
00104   //  cout<<"findBlocks : "<<blocks_.get()<<endl;
00105   
00106   // the blocks have not been passed to the event, and need to be cleared
00107   if(blocks_.get() )blocks_->clear();
00108   else 
00109     blocks_.reset( new reco::PFBlockCollection );
00110 
00111   blocks_->reserve(elements_.size());
00112   for(IE ie = elements_.begin(); 
00113       ie != elements_.end();) {
00114     
00115 #ifdef PFLOW_DEBUG
00116     if(debug_) {
00117       cout<<" PFBlockAlgo::findBlocks() ----------------------"<<endl;
00118       cout<<" element "<<**ie<<endl;
00119       cout<<" creating new block"<<endl;
00120     }
00121 #endif
00122     
00123     blocks_->push_back( PFBlock() );
00124     
00125     vector< PFBlockLink > links;
00126 
00127     //    list< IE > used;
00128     ie = associate( elements_.end() , ie, links );
00129 
00130     // build remaining links in current block
00131     packLinks( blocks_->back(), links );
00132   }       
00133 }
00134 
00135 
00136 
00137 
00138 PFBlockAlgo::IE PFBlockAlgo::associate( IE last, 
00139                                         IE next, 
00140                                         vector<PFBlockLink>& links ) {
00141 
00142     
00143 #ifdef PFLOW_DEBUG
00144   if(debug_ ) cout<<"PFBlockAlgo::associate start ----"<<endl;
00145 #endif
00146 
00147   if( last!= elements_.end() ) {
00148     PFBlockLink::Type linktype = PFBlockLink::NONE;
00149     double chi2 = -1; 
00150     double dist = -1;
00151     PFBlock::LinkTest linktest = PFBlock::LINKTEST_CHI2;
00152     link( *last, *next, linktype, linktest, chi2, dist ); 
00153 
00154    
00155     if(chi2<-0.5) {
00156 #ifdef PFLOW_DEBUG
00157       if(debug_ ) cout<<"link failed"<<endl;
00158 #endif
00159       return ++next; // association failed
00160     }
00161     else {
00162       // add next element to the current pflowblock
00163       blocks_->back().addElement( *next );  
00164 
00165       // (*next)->setIndex( blocks_->back()->indexToLastElement() );
00166       
00167       // this is not necessary? 
00168       // next->setPFBlock(this);
00169       
00170       // create a link between next and last
00171       links.push_back( PFBlockLink(linktype, 
00172                                    linktest,
00173                                    chi2, 
00174                                    dist,
00175                                    (*last)->index(), 
00176                                    (*next)->index() ) );
00177       // not necessary ?
00178       //       next->connect( links_.size()-1 );
00179       //       last->connect( links_.size()-1 );      
00180     }
00181   }
00182   else {
00183     // add next element to this eflowblock
00184 #ifdef PFLOW_DEBUG
00185     if(debug_ ) cout<<"adding to block element "<<(**next)<<endl;
00186 #endif
00187     blocks_->back().addElement( *next );
00188     // (*next)->setIndex( blocks_->back()->indexToLastElement() );   
00189     // next->setPFBlock(this);
00190   }
00191 
00192   // recursive call: associate next and other unused elements 
00193   
00194   //   IE afterNext = next;
00195   //   ++afterNext;
00196   //  cout<<"last "<<**last<<" next "<<**next<<endl;
00197   
00198   for(IE ie = elements_.begin(); 
00199       ie != elements_.end();) {
00200     
00201     if( ie == last || ie == next ) {
00202       ++ie;
00203       continue;
00204     } 
00205     
00206     // *ie already included to a block
00207     if( (*ie)->locked() ) {
00208 #ifdef PFLOW_DEBUG
00209       if(debug_ ) cout<<"element "<<(**ie)<<"already used"<<endl;
00210 #endif
00211       ++ie;
00212       continue;
00213     }    
00214     
00215     
00216 #ifdef PFLOW_DEBUG
00217     if(debug_ ) cout<<"calling associate "<<(**next)<<" & "<<(**ie)<<endl;
00218 #endif
00219     ie = associate(next, ie, links);
00220   }       
00221 
00222 #ifdef PFLOW_DEBUG
00223   if(debug_ ) {
00224     cout<<"**** deleting element "<<endl;
00225     cout<<**next<<endl;
00226   }
00227 #endif
00228   delete *next;
00229 
00230 #ifdef PFLOW_DEBUG
00231   if(debug_ ) {
00232     cout<<"**** removing element "<<endl;
00233   }
00234 #endif
00235 
00236   IE iteratorToNextFreeElement = elements_.erase( next );
00237 
00238 #ifdef PFLOW_DEBUG
00239   if(debug_ ) cout<<"PFBlockAlgo::associate stop ----"<<endl;
00240 #endif
00241 
00242   return iteratorToNextFreeElement;
00243 }
00244 
00245 
00246 
00247 void PFBlockAlgo::packLinks( reco::PFBlock& block, 
00248                              const vector<PFBlockLink>& links ) const {
00249   
00250   
00251   const edm::OwnVector< reco::PFBlockElement >& els = block.elements();
00252   
00253   block.bookLinkData();
00254 
00255   //First Loop: update all link data
00256   for( unsigned i1=0; i1<els.size(); i1++ ) {
00257     for( unsigned i2=0; i2<els.size(); i2++ ) {
00258       
00259       // no reflexive link
00260       if( i1==i2 ) continue;
00261       
00262       double chi2 = -1;
00263       double dist = -1;
00264       
00265       bool linked = false;
00266       PFBlock::LinkTest linktest 
00267         = PFBlock::LINKTEST_CHI2; 
00268 
00269       // are these elements already linked ?
00270       // this can be optimized
00271 
00272       for( unsigned il=0; il<links.size(); il++ ) {
00273         if( (links[il].element1() == i1 && 
00274              links[il].element2() == i2) || 
00275             (links[il].element1() == i2 && 
00276              links[il].element2() == i1) ) { // yes
00277           
00278           chi2 = links[il].chi2();
00279           dist = links[il].dist();
00280           linked = true;
00281 
00282           //modif-beg     
00283           //retrieve type of test used to get chi2
00284           linktest = links[il].test();
00285 #ifdef PFLOW_DEBUG
00286           if( debug_ )
00287             cout << "Reading link vector: linktest used=" 
00288                  << linktest 
00289                  << " chi2= " << chi2 
00290                  << endl; 
00291 #endif
00292           //modif-end
00293           
00294           break;
00295         } 
00296       }
00297       
00298       if(!linked) {
00299         PFBlockLink::Type linktype = PFBlockLink::NONE;
00300         link( & els[i1], & els[i2], linktype, linktest, chi2, dist);
00301       }
00302 
00303       //loading link data according to link test used: CHI2, RECHIT 
00304       //block.setLink( i1, i2, chi2, block.linkData() );
00305 #ifdef PFLOW_DEBUG
00306       if( debug_ )
00307         cout << "Setting link between elements " << i1 << " and " << i2
00308              << " of chi2 =" << chi2 << " computed from link test "
00309              << linktest << endl;
00310 #endif
00311       block.setLink( i1, i2, chi2, dist, block.linkData(), linktest );
00312     }
00313   }
00314 
00315   //Second Loop: checking the link by rechit for HCAL 
00316   //A Hcal-Track link by rechit is preserved  
00317   //only of the cluster is linked to another track.
00318 
00319   // PJ Keep all link by rechit, even for one track !
00320   // PJ Indeed, the logic of the link by rechit also applies to the 
00321   // PJ case where there is only one tracks (and e.g., a neutral 
00322   // PJ hadron that biasses the cluster position
00323   /*
00324   if( multipleLink_ ) {
00325     for( unsigned i1=0; i1<els.size(); i1++ ) {
00326       for( unsigned i2=0; i2<els.size(); i2++ ) {
00327         
00328         // no reflexive link
00329         if( i1==i2 ) continue;
00330         
00331         //Only checking link by rechit 
00332         double chi2 = block.chi2( i1, i2, block.linkData(), 
00333                                   PFBlock::LINKTEST_RECHIT );
00334 
00335         double dist = block.dist( i1, i2, block.linkData(), 
00336                                   PFBlock::LINKTEST_RECHIT );
00337 
00338         
00339         //if( chi2 < chi2TrackHCAL_ || chi2<0 ) continue;
00340         //if not linked, continue 
00341         if( chi2<0 ) continue; 
00342         
00343         bool keeplink = false;
00344 #ifdef PFLOW_DEBUG
00345         if( debug_ )
00346           cout << "This is a link by rechit concerning elements: " 
00347                << i1  << " and " << i2 << endl;
00348 #endif
00349         
00350         unsigned int idCluster = i1;
00351         unsigned int idTrack   = i2;
00352         PFBlockElement::Type type2 = els[i2].type();
00353         if( type2 == PFBlockElement::HCAL ){
00354           idCluster = i2; 
00355           idTrack = i1;
00356         }
00357 
00358         //protection: only considering possible HCAL-TRACK
00359         //link by rechit in what follows
00360         if( els[idCluster].type() != PFBlockElement::HCAL )
00361           continue;
00362         if( els[idTrack].type()   != PFBlockElement::TRACK )
00363           continue;
00364  
00365 #ifdef PFLOW_DEBUG
00366         if( debug_ ){
00367           cout << "Hcal Cluster is element " << idCluster << endl;
00368           cout << "Track is element "        << idTrack << endl;
00369           cout << "Checking if cluster "     << idCluster 
00370                << " is linked to another track" << endl;
00371         }
00372 #endif
00373         
00374         for( unsigned k1=0; k1<els.size(); k1++ ) {
00375           for( unsigned k2=0; k2<els.size(); k2++ ) {
00376             
00377             // no reflexive link
00378             if( k1==k2 ) continue;
00379             
00380             if( ( k1 != idTrack && 
00381                   k2 == idCluster ) || 
00382                 ( k1 == idCluster && 
00383                   k2 != idTrack ) ) { // yes
00384               
00385               //retrieving chi2 values for each possible link tests
00386               double chi2loc_chi2   
00387                 = block.chi2( i1, i2, block.linkData(), 
00388                               PFBlock::LINKTEST_CHI2 ); 
00389               double chi2loc_rechit 
00390                 = block.chi2( i1, i2, block.linkData(), 
00391                               PFBlock::LINKTEST_RECHIT ); 
00392               
00393               PFBlockElement::Type type1loc = els[k1].type();
00394               PFBlockElement::Type type2loc = els[k2].type();
00395 
00396               //              cout << "  elements: " << k1 << " " << k2  << endl;
00397               //              cout << "  types: "    << type1loc  << " " << type2loc << endl;
00398               //              cout << "  chi2 from chi2 test="    << chi2loc_chi2    << endl;
00399               //              cout << "  chi2 from rechit test= " << chi2loc_rechit  << endl;
00400               
00401               if( type1loc == 1 || type2loc == 1 )
00402                 //if( chi2loc > 0 ){
00403                 //if either track is linked to that cluster by rechit of chi2
00404                 if( chi2loc_chi2 > 0 || chi2loc_rechit > 0 ){
00405 #ifdef PFLOW_DEBUG
00406                   if( debug_ )
00407                     cout << "This cluster is linked to another tracks:"
00408                          << "keep this link" << endl; 
00409 #endif
00410                   keeplink = true;
00411                   break;
00412                 }
00413             }//finding other track
00414             
00415           }//loop ele1
00416         }//loop ele2
00417         
00418         if(!keeplink) 
00419           { 
00420 #ifdef PFLOW_DEBUG
00421             if( debug_ ) 
00422               cout << "This cluster is not linked to any other tracks:" 
00423                    << "link by rechit must be removed" << endl;
00424 #endif
00425             //block.setLink( i1, i2, -1, -1, block.linkData() );
00426             block.setLink( i1, i2, -1, -1, block.linkData(),
00427                            PFBlock::LINKTEST_RECHIT );
00428           }//destroy link by rechit
00429       }// loop ele2
00430     }//loop ele1
00431   }//mulipleLink
00432   */
00433 
00434   checkNuclearLinks( block );
00435 }
00436 
00437 
00438 
00439 void PFBlockAlgo::buildGraph() {
00440   // loop on all blocks and create a big graph
00441 }
00442 
00443 
00444 
00445 void PFBlockAlgo::link( const reco::PFBlockElement* el1, 
00446                         const reco::PFBlockElement* el2, 
00447                         PFBlockLink::Type& linktype, 
00448                         reco::PFBlock::LinkTest& linktest,
00449                         double& chi2, double& dist) const {
00450   
00451 
00452 
00453   chi2=-1;
00454   dist=-1.;
00455   std::pair<double,double> lnk(chi2,dist);
00456   linktest = PFBlock::LINKTEST_CHI2; //chi2 by default 
00457 
00458   PFBlockElement::Type type1 = el1->type();
00459   PFBlockElement::Type type2 = el2->type();
00460 
00461   if( type1==type2 ) {
00462     // cannot link 2 elements of the same type. 
00463     // except if the elements are 2 tracks
00464     if( type1!=PFBlockElement::TRACK ) return;
00465     // cannot link two primary tracks  (except if they come from a V0)
00466     else if ( 
00467              ((!el1->isSecondary()) && (!el2->isSecondary())) && 
00468              ((!el1->trackType(reco::PFBlockElement::T_FROM_V0)) || 
00469               (!el2->trackType(reco::PFBlockElement::T_FROM_V0)))
00470              ) return;
00471   }
00472 
00473   linktype = static_cast<PFBlockLink::Type>
00474     ((1<< (type1-1) ) | (1<< (type2-1) ));
00475 
00476   if(debug_ ) std::cout << " PFBlockAlgo links type1 " << type1 << " type2 " << type2 << std::endl;
00477 
00478   PFBlockElement::Type lowType = type1;
00479   PFBlockElement::Type highType = type2;
00480   const PFBlockElement* lowEl = el1;
00481   const PFBlockElement* highEl = el2;
00482   
00483   if(type1>type2) {
00484     lowType = type2;
00485     highType = type1;
00486     lowEl = el2;
00487     highEl = el1;
00488   }
00489   
00490   switch(linktype) {
00491   case PFBlockLink::TRACKandPS1:
00492   case PFBlockLink::TRACKandPS2:
00493     {
00494       //       cout<<"TRACKandPS"<<endl;
00495       PFRecTrackRef trackref = lowEl->trackRefPF();
00496       PFClusterRef  clusterref = highEl->clusterRef();
00497       assert( !trackref.isNull() );
00498       assert( !clusterref.isNull() );
00499       lnk = testTrackAndPS( *trackref, *clusterref );
00500       chi2 = lnk.first;
00501       dist = lnk.second;
00502       break;
00503     }
00504 
00505   case PFBlockLink::TRACKandECAL:
00506     {
00507       if(debug_ ) cout<<"TRACKandECAL"<<endl;
00508       PFRecTrackRef trackref = lowEl->trackRefPF();
00509 
00510       if(debug_ ) std::cout << " Track pt " << trackref->trackRef()->pt() << std::endl;
00511 
00512       PFClusterRef  clusterref = highEl->clusterRef();
00513       assert( !trackref.isNull() );
00514       assert( !clusterref.isNull() );
00515       lnk = testTrackAndECAL( *trackref, *clusterref );
00516       chi2 = lnk.first;
00517       dist = lnk.second;
00518       if(debug_ )  std::cout << " chi2 from testTrackAndECAL " << chi2 << std::endl;
00519       //Link by rechit for ECAL
00520       if( ( chi2 > chi2TrackECAL_ || chi2 < 0 )
00521           && multipleLink_ ){   
00522         //If Chi2 failed checking if Track can be linked by rechit
00523         //to a ECAL cluster. Definition:
00524         // A cluster can be linked to a track by rechit if the 
00525         // extrapolated position of the track to the ECALShowerMax 
00526         // falls within the boundaries of any cell that belongs 
00527         // to this cluster.
00528         if(debug_ ) std::cout << " try  testLinkByRecHit " << std::endl;
00529         lnk = testLinkByRecHit( *trackref, *clusterref );
00530         chi2 = lnk.first;
00531         dist = lnk.second;
00532         if(debug_ ) std::cout << " chi2 testLinkByRecHit " << chi2 << std::endl;
00533         linktest = PFBlock::LINKTEST_RECHIT;
00534       }//link by rechit  
00535 
00536       if ( chi2>0) {
00537         if(debug_ ) std::cout << " Here a link has been established between a track an Ecal with chi2  " << chi2 <<  std::endl;
00538       } else {
00539         if(debug_ ) std::cout << " No link found " << std::endl;
00540       }
00541 
00542 
00543 
00544       break;
00545     }
00546   case PFBlockLink::TRACKandHCAL:
00547     {
00548       //       cout<<"TRACKandHCAL"<<endl;
00549       PFRecTrackRef trackref = lowEl->trackRefPF();
00550       PFClusterRef  clusterref = highEl->clusterRef();
00551       assert( !trackref.isNull() );
00552       assert( !clusterref.isNull() );
00553       lnk = testTrackAndHCAL( *trackref, *clusterref );
00554       chi2 = lnk.first;
00555       dist = lnk.second;
00556   
00557       if( ( chi2 > chi2TrackHCAL_ || chi2 < 0 )
00558           && multipleLink_ ){   
00559         //If Chi2 failed checking if Track can be linked by rechit
00560         //to a HCAL cluster. Definition:
00561         // A cluster can be linked to a track by rechit if the 
00562         // extrapolated position of the track to the HCAL entrance 
00563         // falls within the boundaries of any cell that belongs 
00564         // to this cluster.
00565         
00566         lnk = testLinkByRecHit( *trackref, *clusterref );
00567         chi2 = lnk.first;
00568         dist = lnk.second;
00569         linktest = PFBlock::LINKTEST_RECHIT;
00570       }//link by rechit  
00571       
00572       break;
00573     }
00574   case PFBlockLink::ECALandHCAL:
00575     {
00576       //       cout<<"ECALandHCAL"<<endl;
00577       PFClusterRef  ecalref = lowEl->clusterRef();
00578       PFClusterRef  hcalref = highEl->clusterRef();
00579       assert( !ecalref.isNull() );
00580       assert( !hcalref.isNull() );
00581       lnk = testECALAndHCAL( *ecalref, *hcalref );
00582       chi2 = lnk.first;
00583       dist = lnk.second;
00584       break;
00585     }
00586   case PFBlockLink::PS1andECAL:
00587   case PFBlockLink::PS2andECAL:
00588     {
00589       //       cout<<"PSandECAL"<<endl;
00590       PFClusterRef  psref = lowEl->clusterRef();
00591       PFClusterRef  ecalref = highEl->clusterRef();
00592       assert( !psref.isNull() );
00593       assert( !ecalref.isNull() );
00594       lnk = testPSAndECAL( *psref, *ecalref );
00595       chi2 = lnk.first;
00596       dist = lnk.second;
00597       break;
00598     }
00599   case PFBlockLink::PS1andPS2:
00600     {
00601       PFClusterRef  ps1ref = lowEl->clusterRef();
00602       PFClusterRef  ps2ref = highEl->clusterRef();
00603       assert( !ps1ref.isNull() );
00604       assert( !ps2ref.isNull() );
00605       lnk = testPS1AndPS2( *ps1ref, *ps2ref );
00606       chi2 = lnk.first;
00607       dist = lnk.second;
00608       break;
00609     }
00610   case PFBlockLink::TRACKandTRACK:
00611     {
00612       if(debug_ ) cout<<"TRACKandTRACK"<<endl;
00613       lnk = testLinkByVertex(lowEl, highEl);
00614       chi2 = lnk.first;
00615       dist = lnk.second;
00616       if(debug_ ) std::cout << " PFBlockLink::TRACKandTRACK chi2 " << chi2 << std::endl;
00617       break;
00618     }
00619   case PFBlockLink::ECALandGSF:
00620     {
00621       PFClusterRef  clusterref = lowEl->clusterRef();
00622       assert( !clusterref.isNull() );
00623       const reco::PFBlockElementGsfTrack *  GsfEl =  dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00624       const PFRecTrack * myTrack =  &(GsfEl->GsftrackPF());
00625       lnk = testTrackAndECAL( *myTrack, *clusterref);
00626       chi2 = lnk.first;
00627       dist = lnk.second;
00628       break;
00629     }
00630   case PFBlockLink::TRACKandGSF:
00631     {
00632       PFRecTrackRef trackref = lowEl->trackRefPF();
00633       assert( !trackref.isNull() );
00634       const reco::PFBlockElementGsfTrack *  GsfEl =  dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00635       GsfPFRecTrackRef gsfref = GsfEl->GsftrackRefPF();
00636       reco::TrackRef kftrackref= (*trackref).trackRef();
00637       assert( !gsfref.isNull() );
00638       PFRecTrackRef refkf = (*gsfref).kfPFRecTrackRef();
00639       if(refkf.isNonnull())
00640         {
00641           reco::TrackRef gsftrackref = (*refkf).trackRef();
00642           if (gsftrackref.isNonnull()&&kftrackref.isNonnull()) {
00643             if (kftrackref == gsftrackref) { 
00644               chi2 = 1;
00645               dist = 0.001;
00646               //              std::cout <<  " Linked " << std::endl;
00647             } else { 
00648               chi2 = -1;
00649               dist = -1.;
00650               //              std::cout <<  " Not Linked " << std::endl;
00651             }
00652           }
00653           else { 
00654             chi2 = -1;
00655             dist = -1.;
00656             //      std::cout <<  " Not Linked " << std::endl;
00657           }
00658         }
00659       else
00660         {
00661           chi2 = -1;
00662           dist = -1.;
00663           //      std::cout <<  " Not Linked " << std::endl;
00664         }
00665       break;      
00666     }
00667          
00668   case PFBlockLink::GSFandBREM:
00669     {
00670       const reco::PFBlockElementGsfTrack * GsfEl  =  dynamic_cast<const reco::PFBlockElementGsfTrack*>(lowEl);
00671       const reco::PFBlockElementBrem * BremEl =  dynamic_cast<const reco::PFBlockElementBrem*>(highEl);
00672       GsfPFRecTrackRef gsfref = GsfEl->GsftrackRefPF();
00673       GsfPFRecTrackRef bremref = BremEl->GsftrackRefPF();
00674       assert( !gsfref.isNull() );
00675       assert( !bremref.isNull() );
00676       if (gsfref == bremref)  { 
00677         chi2 = 1;
00678         dist = 0.001;
00679       } else { 
00680         chi2 = -1;
00681         dist = -1.;
00682       }
00683       break;
00684     }
00685   case PFBlockLink::ECALandBREM:
00686     {
00687       PFClusterRef  clusterref = lowEl->clusterRef();
00688       assert( !clusterref.isNull() );
00689       const reco::PFBlockElementBrem * BremEl =  dynamic_cast<const reco::PFBlockElementBrem*>(highEl);
00690       const PFRecTrack * myTrack = &(BremEl->trackPF());
00691       double DP = (BremEl->DeltaP())*(-1.);
00692       double SigmaDP = BremEl->SigmaDeltaP();
00693       double SignBremDp = DP/SigmaDP;
00694       lnk = testTrackAndECAL( *myTrack, *clusterref, SignBremDp);
00695       chi2 = lnk.first;
00696       dist = lnk.second;
00697       break;
00698     }
00699   case PFBlockLink::PS1andGSF:
00700   case PFBlockLink::PS2andGSF:
00701     {
00702       PFClusterRef  psref = lowEl->clusterRef();
00703       assert( !psref.isNull() );
00704       const reco::PFBlockElementGsfTrack *  GsfEl =  dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00705       const PFRecTrack * myTrack =  &(GsfEl->GsftrackPF());
00706       lnk = testTrackAndPS( *myTrack, *psref );
00707       chi2 = lnk.first;
00708       dist = lnk.second;
00709       break;
00710     }
00711   case PFBlockLink::PS1andBREM:
00712   case PFBlockLink::PS2andBREM:
00713     {
00714       PFClusterRef  psref = lowEl->clusterRef();
00715       assert( !psref.isNull() );
00716       const reco::PFBlockElementBrem * BremEl =  dynamic_cast<const reco::PFBlockElementBrem*>(highEl);
00717       const PFRecTrack * myTrack = &(BremEl->trackPF());
00718       lnk = testTrackAndPS( *myTrack, *psref );
00719       chi2 = lnk.first;
00720       dist = lnk.second;
00721       break;
00722     }
00723   case PFBlockLink::HCALandGSF:
00724     {
00725       PFClusterRef  clusterref = lowEl->clusterRef();
00726       assert( !clusterref.isNull() );
00727       const reco::PFBlockElementGsfTrack *  GsfEl =  dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00728       const PFRecTrack * myTrack =  &(GsfEl->GsftrackPF());
00729       lnk = testTrackAndHCAL( *myTrack, *clusterref);
00730       chi2 = lnk.first;
00731       dist = lnk.second;
00732       break;
00733     }
00734   case PFBlockLink::HCALandBREM:
00735     {
00736       PFClusterRef  clusterref = lowEl->clusterRef();
00737       assert( !clusterref.isNull() );
00738       const reco::PFBlockElementBrem * BremEl =  dynamic_cast<const reco::PFBlockElementBrem*>(highEl);
00739       const PFRecTrack * myTrack = &(BremEl->trackPF());
00740       lnk = testTrackAndHCAL( *myTrack, *clusterref);
00741       chi2 = lnk.first;
00742       dist = lnk.second;
00743       break;
00744     }
00745 
00746     
00747   default:
00748     chi2 = -1.;
00749     dist = -1.;
00750     //   cout<<"link type not implemented yet"<< linktype << endl;
00751     //   assert(0);
00752     return;
00753   }
00754 }
00755 
00756 std::pair<double,double>
00757 PFBlockAlgo::testTrackAndPS(const PFRecTrack& track, 
00758                             const PFCluster& ps)  const {
00759 
00760   //   cout<<"entering testTrackAndPS"<<endl;
00761   // resolution of PS cluster dxdx and dydy from strip pitch and length
00762   double dx=0.;
00763   double dy=0.;
00764   
00765   unsigned layerid =0;
00766   // PS1: vertical strips  PS2: horizontal strips
00767   switch (ps.layer()) {
00768   case PFLayer::PS1:
00769     layerid = reco::PFTrajectoryPoint::PS1;
00770     
00771     // vertical strips in PS1, measure x with pitch precision
00772     dx = resPSpitch_;
00773     dy = resPSlength_; 
00774     break;
00775   case PFLayer::PS2:
00776     layerid = reco::PFTrajectoryPoint::PS2;
00777     // horizontal strips in PS2, measure y with pitch precision
00778     dy = resPSpitch_;
00779     dx = resPSlength_;
00780     break;
00781   default:
00782     break;
00783   }
00784   const reco::PFTrajectoryPoint& atPS
00785     = track.extrapolatedPoint( layerid );  
00786   // did not reach PS, cannot be associated with a cluster.
00787   if( ! atPS.isValid() ) return std::pair<double,double>(-1,-1);   
00788   
00789   double trackx = atPS.position().X();
00790   double tracky = atPS.position().Y();
00791   
00792   // ps position  x, y
00793   double psx = ps.position().X();
00794   double psy = ps.position().Y();
00795   
00796   // rec track resolution negligible compared to ps resolution?
00797   // compute chi2 PS_TRACK in x, y
00798   double trackresolx = 0.;
00799   double trackresoly = 0.;
00800   
00801   double chi2 = (psx-trackx)*(psx-trackx)/(dx*dx + trackresolx*trackresolx)
00802     + (psy-tracky)*(psy-tracky)/(dy*dy + trackresoly*trackresoly);
00803 
00804   double dist = std::sqrt( (psx-trackx)*(psx-trackx)
00805                          + (psy-tracky)*(psy-tracky));
00806 
00807   
00808 #ifdef PFLOW_DEBUG
00809   if(debug_) cout<<"testTrackAndPS "<<chi2<<" "<<endl;
00810   if(debug_){
00811     cout<<" trackx " << trackx << " trackresolx " << trackresolx
00812         <<" tracky " << tracky << " trackresoly " << trackresoly << endl
00813         <<" psx "    <<  psx   << "  dx "         << dx
00814         <<" psy "    << psy    << "  dy "         << dy << endl;
00815   }
00816 #endif
00817   
00818   
00819   if(chi2<chi2PSTrack_ || chi2PSTrack_<0 )
00820     return std::pair<double,double>(chi2,dist);
00821   else 
00822     return std::pair<double,double>(-1,-1);
00823 }
00824 
00825 
00826 
00827 std::pair<double,double> 
00828 PFBlockAlgo::testTrackAndECAL(const PFRecTrack& track, 
00829                               const PFCluster& ecal, 
00830                               double SignBremDp)  const {
00831   
00832   //   cout<<"entering testTrackAndECAL"<<endl;
00833   
00834   
00835   double tracketa;
00836   double trackphi;
00837 
00838   // special chi2 for GSF-ECAL matching
00839   double chi2cut = (track.algoType()!=PFRecTrack::GSF) ? chi2TrackECAL_ : chi2GSFECAL_;
00840 
00841   //  cout << " SignBremDp " << SignBremDp << endl;
00842   // The SignBremDp cut has to be optimized 
00843   if (SignBremDp > 3) {
00844     const reco::PFTrajectoryPoint& atECAL 
00845       = track.extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax );
00846     if( ! atECAL.isValid() ) return std::pair<double,double>(-1,-1);   
00847     tracketa = atECAL.positionREP().Eta();
00848     trackphi = atECAL.positionREP().Phi();
00849     //   cout<<"atECAL "<<atECAL.layer()<<" "
00850     //       <<atECAL.position().Eta()<<" "
00851     //       <<atECAL.position().Phi()<<endl;
00852   }
00853   else {
00854     // needed only for the brem when the momentum is bad estimated. 
00855     // The ECAL cluster energy is taken in these cases
00856 
00857     const reco::PFTrajectoryPoint& atECAL 
00858       = track.extrapolatedPoint( reco::PFTrajectoryPoint::ECALEntrance );
00859     if( ! atECAL.isValid() ) return std::pair<double,double>(-1,-1);   
00860     math::XYZVector posatecal( atECAL.position().x(),
00861                                atECAL.position().y(),
00862                                atECAL.position().z());
00863     
00864     bool isBelowPS=(fabs(ecal.positionREP().Eta())>1.65) ? true :false;
00865     double clusenergy = ecal.energy();
00866     double ecalShowerDepth 
00867       = reco::PFCluster::getDepthCorrection(clusenergy, isBelowPS,false);
00868     
00869     math::XYZVector direction(atECAL.momentum().x(),
00870                               atECAL.momentum().y(),
00871                               atECAL.momentum().z() );
00872 
00873     direction=direction.unit();
00874     posatecal += ecalShowerDepth*direction;
00875     tracketa = posatecal.eta();
00876     trackphi = posatecal.phi();
00877   }
00878 
00879 
00880   double ecaleta  = ecal.positionREP().Eta();
00881   double ecalphi  = ecal.positionREP().Phi();
00882   
00883 
00884   PFResolutionMap* mapeta = const_cast<PFResolutionMap*>(resMapEtaECAL_);
00885   PFResolutionMap* mapphi = const_cast<PFResolutionMap*>(resMapPhiECAL_);
00886 
00887   
00888   double ecaletares 
00889     = mapeta->GetBinContent(mapeta->FindBin(ecaleta, 
00890                                             ecal.energy() ) );
00891   double ecalphires 
00892     = mapphi->GetBinContent(mapphi->FindBin(ecaleta, 
00893                                             ecal.energy() ) );
00894   
00895   
00896   // rec track resolution should be negligible compared to ecal resolution
00897   double trackres = 0;
00898   
00899   std::pair<double,double> lnk = computeChi2( ecaleta, ecaletares, 
00900                                               ecalphi, ecalphires, 
00901                                               tracketa, trackres, 
00902                                               trackphi, trackres);
00903   double chi2 = lnk.first;
00904 
00905 #ifdef PFLOW_DEBUG
00906   if(debug_) cout<<"testTrackAndECAL "<<chi2<<" "<<endl;
00907   if(debug_){
00908     cout<<" ecaleta "  << ecaleta  << "  ecaletares " <<ecaletares
00909         <<" ecalphi "  << ecalphi  << "  ecalphires " <<ecalphires
00910         <<" tracketa " << tracketa << "  trackres "   <<trackres
00911         <<" trackphi " << trackphi << "  trackres "   <<trackres << endl;
00912   }
00913 #endif
00914   
00915 
00916   if(chi2<chi2cut || chi2TrackECAL_<0 )
00917     return lnk;
00918   else 
00919     return std::pair<double,double>(-1,-1);
00920 }
00921 
00922 
00923 
00924 std::pair<double,double> 
00925 PFBlockAlgo::testTrackAndHCAL(const PFRecTrack& track, 
00926                               const PFCluster& hcal)  const {
00927   
00928   
00929   //   cout<<"entering testTrackAndHCAL"<<endl;
00930 
00931   // this is the fake cluster for ps cells
00932   //   if( ! hcal.type() ) return -1;
00933   
00934   
00935   const reco::PFTrajectoryPoint& atHCAL 
00936     = track.extrapolatedPoint( reco::PFTrajectoryPoint::HCALEntrance );
00937   
00938   //   cout<<"atHCAL "<<atHCAL.layer()<<" "
00939   //       <<atHCAL.position().Eta()<<" "
00940   //       <<atHCAL.position().Phi()<<endl;
00941   
00942   // did not reach hcal, cannot be associated with a cluster.
00943   if( ! atHCAL.isValid() ) return std::pair<double,double>(-1,-1);   
00944   
00945   double tracketa = atHCAL.positionREP().Eta();
00946   double trackphi = atHCAL.positionREP().Phi();
00947   double hcaleta  = hcal.positionREP().Eta();
00948   double hcalphi  = hcal.positionREP().Phi();
00949   
00950   
00951   PFResolutionMap* mapeta = const_cast<PFResolutionMap*>(resMapEtaHCAL_);
00952   PFResolutionMap* mapphi = const_cast<PFResolutionMap*>(resMapPhiHCAL_);
00953   
00954   double hcaletares 
00955     = mapeta->GetBinContent(mapeta->FindBin(hcaleta, 
00956                                             hcal.energy() ) );
00957   double hcalphires 
00958     = mapphi->GetBinContent(mapphi->FindBin(hcaleta, 
00959                                             hcal.energy() ) );
00960   
00961   
00962   // rec track resolution should be negligible compared to hcal resolution
00963   double trackres = 0;
00964   
00965   std::pair<double,double> lnk = computeChi2( hcaleta, hcaletares, 
00966                                               hcalphi, hcalphires, 
00967                                               tracketa, trackres, 
00968                                               trackphi, trackres);
00969   double chi2 = lnk.first;
00970   
00971 #ifdef PFLOW_DEBUG
00972   if(debug_) cout<<"testTrackAndHCAL "<<chi2<<" "<<endl;
00973   if(debug_){
00974     cout<<" hcaleta "  << hcaleta << "  hcaletares "<<hcaletares
00975         <<" hcalphi "  << hcalphi << "  hcalphires "<<hcalphires
00976         <<" tracketa " << tracketa<< "  trackres "  <<trackres
00977         <<" trackphi " << trackphi<< "  trackres "  <<trackres << endl;
00978   }
00979 #endif
00980   
00981   if(chi2<chi2TrackHCAL_ || chi2TrackHCAL_<0 )
00982     return lnk;
00983   else 
00984     return std::pair<double,double>(-1,-1);
00985 }
00986 
00987 
00988 std::pair<double,double> 
00989 PFBlockAlgo::testECALAndHCAL(const PFCluster& ecal, 
00990                              const PFCluster& hcal)  const {
00991   
00992   //   cout<<"entering testECALAndHCAL"<<endl;
00993   
00994   
00995   PFResolutionMap* mapetaECAL = const_cast<PFResolutionMap*>(resMapEtaECAL_);
00996   PFResolutionMap* mapphiECAL = const_cast<PFResolutionMap*>(resMapPhiECAL_);
00997   
00998   PFResolutionMap* mapetaHCAL = const_cast<PFResolutionMap*>(resMapEtaHCAL_);
00999   PFResolutionMap* mapphiHCAL = const_cast<PFResolutionMap*>(resMapPhiHCAL_);
01000   
01001   // retrieve resolutions from resolution maps
01002   double ecaletares 
01003     = mapetaECAL->GetBinContent(mapetaECAL->FindBin(ecal.positionREP().Eta(), 
01004                                                     ecal.energy() ) );
01005   double ecalphires 
01006     = mapphiECAL->GetBinContent(mapphiECAL->FindBin(ecal.positionREP().Eta(), 
01007                                                     ecal.energy() ) );
01008                       
01009   double hcaletares 
01010     = mapetaHCAL->GetBinContent(mapetaHCAL->FindBin(hcal.positionREP().Eta(), 
01011                                                     hcal.energy() ) );
01012   double hcalphires 
01013     = mapphiHCAL->GetBinContent(mapphiHCAL->FindBin(hcal.positionREP().Eta(), 
01014                                                     hcal.energy() ) );
01015                       
01016   // compute chi2
01017   std::pair<double,double> lnk = 
01018     computeChi2( ecal.positionREP().Eta(), ecaletares, 
01019                  ecal.positionREP().Phi(), ecalphires, 
01020                  hcal.positionREP().Eta(), hcaletares, 
01021                  hcal.positionREP().Phi(), hcalphires );
01022   double chi2 = lnk.first;
01023   
01024 #ifdef PFLOW_DEBUG
01025   if(debug_) cout<<"testECALAndHCAL "<<chi2<<" "<<endl;
01026   if(debug_){
01027     cout<<" ecaleta " << ecal.positionREP().Eta()<< "  ecaletares "<<ecaletares
01028         <<" ecalphi " << ecal.positionREP().Phi()<< "  ecalphires "<<ecalphires
01029         <<" hcaleta " << hcal.positionREP().Eta()<< "  hcaletares "<<hcaletares
01030         <<" hcalphi " << hcal.positionREP().Phi()<< "  hcalphires "<<hcalphires<< endl;
01031   }
01032 #endif
01033 
01034 
01035   if(chi2<chi2ECALHCAL_ || chi2ECALHCAL_<0 )
01036     return lnk;
01037   else 
01038     return std::pair<double,double>(-1,-1);
01039 }
01040 std::pair<double,double> 
01041 PFBlockAlgo::testPSAndECAL(const PFCluster& ps, 
01042                            const PFCluster& ecal)  const {
01043   
01044   //   cout<<"entering testPSAndECAL"<<endl;
01045   
01046   PFResolutionMap* mapetaECAL = const_cast<PFResolutionMap*>(resMapEtaECAL_);
01047   PFResolutionMap* mapphiECAL = const_cast<PFResolutionMap*>(resMapPhiECAL_);
01048   
01049   // retrieve resolutions from resolution maps
01050   double ecaletares 
01051     = mapetaECAL->GetBinContent(mapetaECAL->FindBin(ecal.positionREP().Eta(), 
01052                                                     ecal.energy() ) );
01053   double ecalphires 
01054     = mapphiECAL->GetBinContent(mapphiECAL->FindBin(ecal.positionREP().Eta(), 
01055                                                     ecal.energy() ) );
01056   // ecal position in eta and phi
01057   double ecaleta = ecal.positionREP().Eta();
01058   double ecalphi = ecal.positionREP().Phi();
01059   
01060   
01061   // ps position x, y, z, R and  rho, eta, phi
01062   double pseta = ps.positionREP().Eta();
01063   double psphi = ps.positionREP().Phi();
01064   double psrho = ps.positionREP().Rho();
01065   double psrho2 = psrho*psrho;
01066   double psx = ps.position().X();
01067   double psy = ps.position().Y();
01068   double psz = ps.position().Z();
01069   double psR = ps.position().R();
01070   // resolution of PS cluster dxdx and dydy from strip pitch and length
01071   double dxdx =0.;
01072   double dydy =0.;
01073   switch (ps.layer()) {
01074   case PFLayer::PS1:
01075     // vertical strips, measure x with pitch precision
01076     dxdx = resPSpitch_*resPSpitch_;
01077     dydy = resPSlength_*resPSlength_;
01078     break;
01079   case PFLayer::PS2:
01080     // horizontal strips, measure y with pitch precision
01081     dydy = resPSpitch_*resPSpitch_;
01082     dxdx = resPSlength_*resPSlength_;
01083     break;
01084   default:
01085     break;
01086   }
01087   // derivatives deta/dx, deta/dy, dphi/dx, dphi/deta
01088   double detadx = psx*psz/(psrho2*psR);
01089   double detady = psy*psz/(psrho2*psR);
01090   double dphidx = -psy/psrho2;
01091   double dphidy = psx/psrho2;
01092   // propagate error matrix  x. y (diagonal) to eta, phi (non diagonal)
01093   double detadeta = detadx*detadx*dxdx + detady*detady*dydy;
01094   double dphidphi = dphidx*dphidx*dxdx + dphidy*dphidy*dydy;
01095   double detadphi = detadx*dphidx*dxdx + detady*dphidy*dydy;
01096   // add ecal resol in quadrature
01097   double detadetas = detadeta + ecaletares*ecaletares;
01098   double dphidphis = dphidphi + ecalphires*ecalphires;
01099   // compute chi2 in eta, phi with non diagonal error matrix (detadphi non zero)
01100   double deta = pseta - ecaleta;
01101   double dphi = Utils::mpi_pi(psphi - ecalphi);
01102   double det  = detadetas*dphidphis - detadphi*detadphi;
01103   double chi2 
01104     = (dphidphis*deta*deta + detadetas*dphi*dphi - 2.*detadphi*deta*dphi)/det;
01105   double dist = std::sqrt(deta*deta+dphi*dphi);
01106   
01107   
01108 #ifdef PFLOW_DEBUG
01109   if(debug_) cout<<"testPSAndECAL "<<chi2<<" "<<endl;
01110   if(debug_){
01111     double psetares = sqrt(detadeta);
01112     double psphires = sqrt (dphidphi);
01113     cout<< " pseta "  <<pseta   << " psetares "   << psetares
01114         << " psphi "  <<psphi   << " psphires "   << psphires << endl
01115         << " ecaleta "<<ecaleta << " ecaletares " << ecaletares
01116         << " ecalphi "<<ecalphi << " ecalphires " << ecalphires<< endl;
01117   }
01118 #endif
01119   
01120 
01121   if(chi2<chi2PSECAL_ || chi2PSECAL_<0 )
01122     return std::pair<double,double>(chi2,dist);
01123   else 
01124     return std::pair<double,double>(-1,-1);
01125 }
01126 
01127 
01128 std::pair<double,double> 
01129 PFBlockAlgo::testPS1AndPS2(const PFCluster& ps1, 
01130                            const PFCluster& ps2)  const {
01131   
01132   //   cout<<"entering testPS1AndPS2"<<endl;
01133   
01134   // compute chi2 in y, z using swimming formulae
01135   // y2 = y1 * z2/z1   and x2 = x1 *z2/z1
01136   
01137   // ps position1  x, y, z
01138   double x1 = ps1.position().X();
01139   double y1 = ps1.position().Y();
01140   double z1 = ps1.position().Z();
01141   double x2 = ps2.position().X();
01142   double y2 = ps2.position().Y();
01143   double z2 = ps2.position().Z();
01144   // swim to PS2
01145   double scale = z2/z1;
01146   double x1atPS2 = x1*scale;
01147   double y1atPS2 = y1*scale;
01148   // resolution of PS cluster dxdx and dydy from strip pitch and length
01149   // vertical strips in PS1, measure x with pitch precision
01150   double dx1dx1 = resPSpitch_*resPSpitch_*scale*scale;
01151   double dy1dy1 = resPSlength_*resPSlength_*scale*scale;
01152   // horizontal strips in PS2 , measure y with pitch precision
01153   double dy2dy2 = resPSpitch_*resPSpitch_;
01154   double dx2dx2 = resPSlength_*resPSlength_;
01155   
01156   double chi2 = (x2-x1atPS2)*(x2-x1atPS2)/(dx1dx1 + dx2dx2) 
01157     + (y2-y1atPS2)*(y2-y1atPS2)/(dy1dy1 + dy2dy2);
01158   
01159   double dist = std::sqrt( (x2-x1atPS2)*(x2-x1atPS2)
01160                          + (y2-y1atPS2)*(y2-y1atPS2));
01161     
01162 #ifdef PFLOW_DEBUG
01163   if(debug_) cout<<"testPS1AndPS2 "<<chi2<<" "<<endl;
01164   if(debug_){
01165     cout<<" x1atPS2 "<< x1atPS2 << " dx1 "<<resPSpitch_*scale
01166         <<" y1atPS2 "<< y1atPS2 << " dy1 "<<resPSlength_*scale<< endl
01167         <<" x2 " <<x2  << " dx2 "<<resPSlength_
01168         <<" y2 " << y2 << " dy2 "<<resPSpitch_<< endl;
01169   }
01170 #endif
01171   if(chi2<chi2PSHV_ || chi2PSHV_<0 )
01172     return std::pair<double,double>(chi2,dist);
01173   else 
01174     return std::pair<double,double>(-1,-1);
01175 }
01176 
01177 std::pair<double,double> 
01178 PFBlockAlgo::testLinkByVertex( const reco::PFBlockElement* elt1, 
01179                                const reco::PFBlockElement* elt2) const {
01180 
01181   double result=-1.;
01182   if( (elt1->trackType(reco::PFBlockElement::T_TO_NUCL) &&
01183        elt2->trackType(reco::PFBlockElement::T_FROM_NUCL)) ||
01184       (elt1->trackType(reco::PFBlockElement::T_FROM_NUCL) &&
01185        elt2->trackType(reco::PFBlockElement::T_TO_NUCL)) ||
01186       (elt1->trackType(reco::PFBlockElement::T_FROM_NUCL) &&
01187        elt2->trackType(reco::PFBlockElement::T_FROM_NUCL))) {
01188     
01189     NuclearInteractionRef ni1_ = elt1->nuclearRef(); 
01190     NuclearInteractionRef ni2_ = elt2->nuclearRef(); 
01191     if( ni1_.isNonnull() && ni2_.isNonnull() ) {
01192       if( ni1_ == ni2_ ) result= 1.0;
01193     }
01194   }
01195   else if (  elt1->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)  &&
01196              elt2->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)  ) {
01197     
01198     if(debug_ ) std::cout << " testLinkByVertex On Conversions " << std::endl;
01199     
01200     if ( elt1->convRef().isNonnull() && elt2->convRef().isNonnull() ) {
01201       if(debug_ ) std::cout << " PFBlockAlgo.cc testLinkByVertex  Cconversion Refs are non null  " << std::endl;      
01202       if ( elt1->convRef() ==  elt2->convRef() ) {
01203         result=1.0;
01204         if(debug_ ) std::cout << " testLinkByVertex  Cconversion Refs are equal  " << std::endl;           
01205       }
01206     } 
01207     
01208   }
01209   else if (  elt1->trackType(reco::PFBlockElement::T_FROM_V0)  &&
01210              elt2->trackType(reco::PFBlockElement::T_FROM_V0)  ) {
01211     if(debug_ ) std::cout << " testLinkByVertex On V0 " << std::endl;
01212     if ( elt1->V0Ref().isNonnull() && elt2->V0Ref().isNonnull() ) {
01213       if(debug_ ) std::cout << " PFBlockAlgo.cc testLinkByVertex  V0 Refs are non null  " << std::endl;
01214       if ( elt1->V0Ref() ==  elt2->V0Ref() ) {
01215         result=1.0;
01216         if(debug_ ) std::cout << " testLinkByVertex  V0 Refs are equal  " << std::endl;
01217       }
01218     }
01219   }
01220 
01221   return std::pair<double,double>(result,0.);
01222 }
01223 
01224 std::pair<double,double> 
01225 PFBlockAlgo::testLinkByRecHit( const PFRecTrack& track, 
01226                                const PFCluster&  cluster)  const {
01227   
01228 #ifdef PFLOW_DEBUG
01229   if( debug_ ) 
01230     cout<<"entering test link by rechit function"<<endl;
01231 #endif
01232 
01233   //cluster position
01234   double clustereta  = cluster.positionREP().Eta();
01235   double clusterphi  = cluster.positionREP().Phi();
01236 
01237   bool barrel = false;
01238 
01239   //track extrapolation
01240   const reco::PFTrajectoryPoint& atECAL 
01241     = track.extrapolatedPoint( reco::PFTrajectoryPoint::ECALShowerMax );
01242   const reco::PFTrajectoryPoint& atHCAL 
01243     = track.extrapolatedPoint( reco::PFTrajectoryPoint::HCALEntrance );
01244 
01245   //track
01246   double tracketa = 999999.9;
01247   double trackphi = 999999.9;
01248   double track_X  = 999999.9;
01249   double track_Y  = 999999.9;
01250 
01251   //retrieving resolution maps
01252   PFResolutionMap* mapeta;
01253   PFResolutionMap* mapphi;
01254   switch (cluster.layer()) {
01255   case PFLayer::ECAL_BARREL: barrel = true;
01256   case PFLayer::ECAL_ENDCAP:
01257 #ifdef PFLOW_DEBUG
01258     if( debug_ )
01259       cout << "Fetching Ecal Resolution Maps"
01260            << endl;
01261 #endif
01262     mapeta = const_cast<PFResolutionMap*>(resMapEtaECAL_);
01263     mapphi = const_cast<PFResolutionMap*>(resMapPhiECAL_);
01264 
01265     // did not reach ecal, cannot be associated with a cluster.
01266     if( ! atECAL.isValid() ) return std::pair<double,double>(-1,-1);   
01267     
01268     tracketa = atECAL.positionREP().Eta();
01269     trackphi = atECAL.positionREP().Phi();
01270     track_X  = atECAL.position().X();
01271     track_Y  = atECAL.position().Y();
01272     
01273     break;
01274   case PFLayer::HCAL_BARREL1: barrel = true;
01275   case PFLayer::HCAL_ENDCAP:
01276 #ifdef PFLOW_DEBUG
01277     if( debug_ )
01278       cout << "Fetching Hcal Resolution Maps"
01279            << endl;
01280 #endif
01281     mapeta = const_cast<PFResolutionMap*>(resMapEtaHCAL_);
01282     mapphi = const_cast<PFResolutionMap*>(resMapPhiHCAL_);
01283 
01284     // did not reach hcal, cannot be associated with a cluster.
01285     if( ! atHCAL.isValid() ) return std::pair<double,double>(-1,-1);   
01286     
01287     tracketa = atHCAL.positionREP().Eta();
01288     trackphi = atHCAL.positionREP().Phi();
01289     track_X  = atHCAL.position().X();
01290     track_Y  = atHCAL.position().Y();
01291 
01292     break;
01293   case PFLayer::PS1:
01294   case PFLayer::PS2:
01295     //Note Alex: Nothing implemented for the
01296     //PreShower (No resolution maps yet)
01297 #ifdef PFLOW_DEBUG
01298     if( debug_ )
01299       cout << "No link by rechit possible for pre-shower yet!"
01300            << endl;
01301 #endif
01302     return std::pair<double,double>(-1,-1);
01303   default:
01304     return std::pair<double,double>(-1,-1);
01305   }
01306 
01307   double clusteretares 
01308     = mapeta->GetBinContent(mapeta->FindBin(clustereta, 
01309                                             cluster.energy() ) );
01310   double clusterphires 
01311     = mapphi->GetBinContent(mapphi->FindBin(clustereta, 
01312                                             cluster.energy() ) );
01313   
01314   
01315   // rec track resolution should be negligible compared 
01316   // calo resolution
01317   double trackres = 0;
01318   
01319   std::pair<double,double> lnk = computeChi2( clustereta, clusteretares, 
01320                                               clusterphi, clusterphires, 
01321                                               tracketa, trackres, 
01322                                               trackphi, trackres);
01323   
01324 #ifdef PFLOW_DEBUG
01325   double chi2 = lnk.first;
01326   if(debug_) cout<<"test link by rechit "<<chi2<<" "<<endl;
01327   if(debug_){
01328     cout<<" clustereta "  << clustereta << "  clusteretares "<<clusteretares
01329         <<" clusterphi "  << clusterphi << "  clusterphires "<<clusterphires
01330         <<" tracketa " << tracketa<< "  trackres "  <<trackres
01331         <<" trackphi " << trackphi<< "  trackres "  <<trackres << endl;
01332   }
01333 #endif
01334   
01335   //Testing if Track can be linked by rechit to a cluster.
01336   //A cluster can be linked to a track if the extrapolated position 
01337   //of the track to the ECAL ShowerMax/HCAL entrance falls within 
01338   //the boundaries of any cell that belongs to this cluster.
01339 
01340   const std::vector< reco::PFRecHitFraction >& 
01341     fracs = cluster.recHitFractions();
01342   
01343   bool linkedbyrechit = false;
01344   //loop rechits
01345   for(unsigned int rhit = 0; rhit < fracs.size(); ++rhit){
01346 
01347     const reco::PFRecHitRef& rh = fracs[rhit].recHitRef();
01348     if(rh.isNull()) continue;
01349     
01350     //getting rechit center position
01351     const reco::PFRecHit& rechit_cluster = *rh;
01352     // const math::XYZPoint& posxyz 
01353     //   = rechit_cluster.position();
01354     const reco::PFRecHit::REPPoint& posrep 
01355       = rechit_cluster.positionREP();
01356     
01357     //getting rechit corners
01358     const std::vector< math::XYZPoint >& 
01359       cornersxyz = rechit_cluster.getCornersXYZ();
01360     const std::vector<reco::PFRecHit::REPPoint>& corners = 
01361       rechit_cluster.getCornersREP();
01362     assert(corners.size() == 4);
01363     
01364 
01365     if( barrel ){ //barrel case matching in eta/phi
01366 
01367       //rechit size determination
01368       double rhsizeEta 
01369         = fabs(corners[0].Eta() - corners[2].Eta());
01370       double rhsizePhi 
01371         = fabs(corners[0].Phi() - corners[2].Phi());
01372       if ( rhsizePhi > M_PI ) rhsizePhi = 2.*M_PI - rhsizePhi;
01373       
01374 #ifdef PFLOW_DEBUG
01375       if( debug_ ) {
01376         cout << rhit         << " Hcal RecHit=" 
01377              << posrep.Eta() << " " 
01378              << posrep.Phi() << " "
01379              << rechit_cluster.energy() 
01380              << endl; 
01381         for ( unsigned jc=0; jc<4; ++jc ) 
01382           cout<<"corners "<<jc<<" "<<corners[jc].Eta()
01383               <<" "<<corners[jc].Phi()<<endl;
01384         
01385         cout << "RecHit SizeEta=" << rhsizeEta
01386              << " SizePhi=" << rhsizePhi << endl;
01387       }
01388 #endif
01389     
01390       //distance track-rechit center
01391       // const math::XYZPoint& posxyz 
01392       // = rechit_cluster.position();
01393       double deta = fabs(posrep.Eta() - tracketa);
01394       double dphi = fabs(posrep.Phi() - trackphi);
01395       if ( dphi > M_PI ) dphi = 2.*M_PI - dphi;
01396 
01397 #ifdef PFLOW_DEBUG
01398       if( debug_ ){
01399         cout << "distance=" 
01400              << deta << " " 
01401              << dphi << " ";
01402         if(deta < (rhsizeEta/2.) && dphi < (rhsizePhi/2.))
01403           cout << " link here !" << endl;
01404         else cout << endl;
01405       }
01406 #endif
01407       
01408       if(deta < (rhsizeEta/2.) && dphi < (rhsizePhi/2.)){ 
01409         linkedbyrechit = true;
01410         break;
01411       }
01412     }
01413     else { //endcap case, matching in X,Y
01414 
01415 #ifdef PFLOW_DEBUG
01416       if( debug_ ){
01417         const math::XYZPoint& posxyz 
01418           = rechit_cluster.position();
01419        
01420         cout << "RH " << posxyz.X()
01421              << " "   << posxyz.Y()
01422              << endl;
01423         
01424         cout << "TRACK " << track_X
01425              << " "      << track_Y
01426              << endl;
01427       }
01428 #endif
01429       
01430       double x[5];
01431       double y[5];
01432       for ( unsigned jc=0; jc<4; ++jc ) {
01433         math::XYZPoint cornerposxyz = cornersxyz[jc];
01434         x[jc] = cornerposxyz.X();
01435         y[jc] = cornerposxyz.Y();
01436         
01437 #ifdef PFLOW_DEBUG
01438         if( debug_ ){
01439           cout<<"corners "<<jc
01440               << " " << cornerposxyz.X()
01441               << " " << cornerposxyz.Y()
01442               << endl;
01443         }
01444 #endif
01445       }//loop corners
01446 
01447       //need to close the polygon in order to
01448       //use the TMath::IsInside fonction from root lib
01449       x[4] = x[0];
01450       y[4] = y[0];
01451   
01452       //Check if the extrapolation point of the track falls 
01453       //within the rechit boundaries
01454       bool isinside = TMath::IsInside(track_X,
01455                                       track_Y,
01456                                       5,x,y);
01457       
01458       if( isinside ){
01459         linkedbyrechit = true;
01460         break;
01461       }
01462     }//
01463     
01464   }//loop rechits
01465   
01466   if( linkedbyrechit ) {
01467 #ifdef PFLOW_DEBUG
01468     if( debug_ ) 
01469       cout << "Track and Cluster LINKED BY RECHIT" << endl;
01470 #endif
01471     return lnk;
01472   }
01473   else
01474     return std::pair<double,double>(-1,-1);
01475 }
01476 
01477 std::pair<double,double> 
01478 PFBlockAlgo::computeChi2( double eta1, double reta1, 
01479                           double phi1, double rphi1, 
01480                           double eta2, double reta2, 
01481                           double phi2, double rphi2 ) const {
01482   
01483   double phicor = Utils::mpi_pi(phi1 - phi2);
01484   
01485   double chi2 =  
01486     (eta1 - eta2)*(eta1 - eta2) / ( reta1*reta1+ reta2*reta2 ) +
01487     phicor*phicor / ( rphi1*rphi1+ rphi2*rphi2 );
01488 
01489   double dist = std::sqrt( (eta1 - eta2)*(eta1 - eta2) 
01490                           + phicor*phicor);
01491 
01492   return std::pair<double,double>(chi2,dist);
01493 
01494 }
01495 
01496 void PFBlockAlgo::checkMaskSize( const reco::PFRecTrackCollection& tracks,
01497                                  const reco::GsfPFRecTrackCollection& gsftracks, 
01498                                  const reco::PFClusterCollection&  ecals,
01499                                  const reco::PFClusterCollection&  hcals,
01500                                  const reco::PFClusterCollection&  pss, 
01501                                  const Mask& trackMask, 
01502                                  const Mask& gsftrackMask,  
01503                                  const Mask& ecalMask,
01504                                  const Mask& hcalMask, 
01505                                  const Mask& psMask ) const {
01506 
01507   if( !trackMask.empty() && 
01508       trackMask.size() != tracks.size() ) {
01509     string err = "PFBlockAlgo::setInput: ";
01510     err += "The size of the track mask is different ";
01511     err += "from the size of the track vector.";
01512     throw std::length_error( err.c_str() );
01513   }
01514 
01515   if( !gsftrackMask.empty() && 
01516       gsftrackMask.size() != gsftracks.size() ) {
01517     string err = "PFBlockAlgo::setInput: ";
01518     err += "The size of the gsf track mask is different ";
01519     err += "from the size of the gsftrack vector.";
01520     throw std::length_error( err.c_str() );
01521   }
01522 
01523   if( !ecalMask.empty() && 
01524       ecalMask.size() != ecals.size() ) {
01525     string err = "PFBlockAlgo::setInput: ";
01526     err += "The size of the ecal mask is different ";
01527     err += "from the size of the ecal clusters vector.";
01528     throw std::length_error( err.c_str() );
01529   }
01530   
01531   if( !hcalMask.empty() && 
01532       hcalMask.size() != hcals.size() ) {
01533     string err = "PFBlockAlgo::setInput: ";
01534     err += "The size of the hcal mask is different ";
01535     err += "from the size of the hcal clusters vector.";
01536     throw std::length_error( err.c_str() );
01537   }
01538   if( !psMask.empty() && 
01539       psMask.size() != pss.size() ) {
01540     string err = "PFBlockAlgo::setInput: ";
01541     err += "The size of the ps mask is different ";
01542     err += "from the size of the ps clusters vector.";
01543     throw std::length_error( err.c_str() );
01544   }
01545   
01546 }
01547 
01548 
01549 std::ostream& operator<<(std::ostream& out, const PFBlockAlgo& a) {
01550   if(! out) return out;
01551   
01552   out<<"====== Particle Flow Block Algorithm ======= ";
01553   out<<endl;
01554   out<<"resMapEtaECAL "<<a.resMapEtaECAL_->GetMapFile()<<endl;
01555   out<<"resMapPhiECAL "<<a.resMapPhiECAL_->GetMapFile()<<endl;
01556   out<<"resMapEtaHCAL "<<a.resMapEtaHCAL_->GetMapFile()<<endl;
01557   out<<"resMapPhiHCAL "<<a.resMapPhiHCAL_->GetMapFile()<<endl;
01558   out<<"chi2TrackECAL "<<a.chi2TrackECAL_<<endl;
01559   out<<"chi2TrackHCAL "<<a.chi2TrackHCAL_<<endl;
01560   out<<"chi2ECALHCAL  "<<a.chi2ECALHCAL_<<endl;
01561   out<<"chi2PSECAL    "<<a.chi2PSECAL_  <<endl;
01562   out<<"chi2PSTRACK   "<<a.chi2PSTrack_ <<endl;
01563   out<<"chi2PSHV      "<<a.chi2PSHV_    <<endl;
01564   out<<endl;
01565   out<<"number of unassociated elements : "<<a.elements_.size()<<endl;
01566   out<<endl;
01567   
01568   for(PFBlockAlgo::IEC ie = a.elements_.begin(); 
01569       ie != a.elements_.end(); ie++) {
01570     out<<"\t"<<**ie <<endl;
01571   }
01572 
01573   
01574   //   const PFBlockCollection& blocks = a.blocks();
01575 
01576   const std::auto_ptr< reco::PFBlockCollection >& blocks
01577     = a.blocks(); 
01578     
01579   if(!blocks.get() ) {
01580     out<<"blocks already transfered"<<endl;
01581   }
01582   else {
01583     out<<"number of blocks : "<<blocks->size()<<endl;
01584     out<<endl;
01585     
01586     for(PFBlockAlgo::IBC ib=blocks->begin(); 
01587         ib != blocks->end(); ib++) {
01588       out<<(*ib)<<endl;
01589     }
01590   }
01591 
01592   return out;
01593 }
01594 
01595 bool PFBlockAlgo::goodPtResolution( const reco::TrackRef& trackref) {
01596   double Pt = trackref->pt();
01597   double DPt = trackref->ptError();
01598   if (debug_) cout << " PFBlockAlgo: PFrecTrack->Track Pt= "
01599                    << Pt << " DPt = " << DPt << endl;
01600   if (DPt/Pt > DPtovPtCut_ ) {
01601     if (debug_) cout << " PFBlockAlgo: skip badly measured track Pt= "
01602                      << Pt << " DPt = " << DPt << endl;
01603     if (debug_) cout << " cut is DPt/Pt < " << DPtovPtCut_<< endl;
01604     return false;
01605   }
01606   return true;
01607 }
01608 
01609 void PFBlockAlgo::fillSecondaries( const reco::PFNuclearInteractionRef& nuclref ) {
01610   // loop on secondaries
01611   for( reco::PFNuclearInteraction::pfTrackref_iterator
01612          pftkref = nuclref->secPFRecTracks_begin();
01613        pftkref != nuclref->secPFRecTracks_end(); ++pftkref) {
01614     if( !goodPtResolution( (*pftkref)->trackRef() ) ) continue;
01615     reco::PFBlockElement *secondaryTrack 
01616       = new reco::PFBlockElementTrack( *pftkref );
01617     secondaryTrack->setNuclearRef( nuclref->nuclInterRef(), 
01618                                    reco::PFBlockElement::T_FROM_NUCL );
01619             
01620     elements_.push_back( secondaryTrack ); 
01621   }
01622 }
01623 
01624 int PFBlockAlgo::niAssocToTrack( const reco::TrackRef& primTkRef,
01625                                  const edm::Handle<reco::PFNuclearInteractionCollection>& nuclh) const {
01626   if( nuclh.isValid() ) {
01627     // look for nuclear interaction associated to primTkRef
01628     for( unsigned int k=0; k<nuclh->size(); ++k) {
01629       const edm::RefToBase< reco::Track >& trk = nuclh->at(k).primaryTrack();
01630       if( trk.castTo<reco::TrackRef>() == primTkRef) return k;
01631     }
01632     return -1; // not found
01633   }
01634   else return -1;
01635 }
01636 
01637 // duplication due to limitation of LCG reflex dict from header file
01638 int PFBlockAlgo::niAssocToTrack( const reco::TrackRef& primTkRef,
01639                                  const edm::OrphanHandle<reco::PFNuclearInteractionCollection>& nuclh) const {
01640   if( nuclh.isValid() ) {
01641     // look for nuclear interaction associated to primTkRef
01642     for( unsigned int k=0; k<nuclh->size(); ++k) {
01643       const edm::RefToBase< reco::Track >& trk = nuclh->at(k).primaryTrack();
01644       if( trk.castTo<reco::TrackRef>() == primTkRef) return k;
01645     }
01646     return -1; // not found
01647   }
01648   else return -1;
01649 }
01650 
01651 int PFBlockAlgo::muAssocToTrack( const reco::TrackRef& trackref,
01652                                  const edm::Handle<reco::MuonCollection>& muonh) const {
01653   if(muonh.isValid() ) {
01654     for(unsigned j=0;j<muonh->size(); j++) {
01655       reco::MuonRef muonref( muonh, j );
01656       if (muonref->track().isNonnull()) 
01657         if( muonref->track() == trackref ) return j;
01658     }
01659   }
01660   return -1; // not found
01661 }
01662 
01663 int PFBlockAlgo::v0AssocToTrack( const reco::TrackRef& primTkRef,
01664                                  const edm::Handle<reco::PFV0Collection>& v0) const {
01665   if( v0.isValid() ) {
01666     // look for v0 associated to primTkRef
01667     for( unsigned int k=0; k<v0->size(); ++k) {
01668       for (uint itk=0;itk<(*v0)[k].Tracks().size();itk++){ 
01669         if( (*v0)[k].Tracks()[itk] == primTkRef) return k;
01670       }
01671     }
01672     return -1; // not found
01673   }
01674   else return -1;
01675 }
01676 
01677 // duplication due to limitation of LCG reflex dict from header file
01678 int PFBlockAlgo::v0AssocToTrack( const reco::TrackRef& primTkRef,
01679                                  const edm::OrphanHandle<reco::PFV0Collection>& v0) const {
01680   if( v0.isValid() ) {
01681     // look for v0 associated to primTkRef
01682     for( unsigned int k=0; k<v0->size(); ++k) {
01683       for (uint itk=0;itk<(*v0)[k].Tracks().size();itk++){
01684         if( (*v0)[k].Tracks()[itk] == primTkRef) return k;
01685       }
01686      
01687     }
01688     return -1; // not found
01689   }
01690   else return -1;
01691 }
01692 
01693 
01694 int PFBlockAlgo::muAssocToTrack( const reco::TrackRef& trackref,
01695                                  const edm::OrphanHandle<reco::MuonCollection>& muonh) const {
01696   if(muonh.isValid() ) {
01697     for(unsigned j=0;j<muonh->size(); j++) {
01698       reco::MuonRef muonref( muonh, j );
01699       if (muonref->track().isNonnull())
01700         if( muonref->track() == trackref ) return j;
01701     }
01702   }
01703   return -1; // not found
01704 }
01705 
01706 
01707 void PFBlockAlgo::checkNuclearLinks( reco::PFBlock& block ) const {
01708   // method which removes link between primary tracks and clusters
01709   // if at least one of the associated secondary tracks is closer 
01710   // to these same clusters
01711 
01712   typedef std::multimap<double, unsigned>::iterator IE;
01713 
01714   const edm::OwnVector< reco::PFBlockElement >& els = block.elements();
01715   // loop on all elements != TRACK
01716   for( unsigned i1=0; i1 != els.size(); ++i1 ) {
01717     if( els[i1].type() == PFBlockElement::TRACK ) continue;
01718     std::multimap<double, unsigned> assocTracks;
01719     // get associated tracks
01720     block.associatedElements( i1,  block.linkData(),
01721                               assocTracks,
01722                               reco::PFBlockElement::TRACK,
01723                               reco::PFBlock::LINKTEST_ALL );
01724     for( IE ie = assocTracks.begin(); ie != assocTracks.end(); ++ie) {
01725       double   chi2prim  = ie->first;
01726       unsigned iprim     = ie->second;
01727       // if this track a primary track (T_To_NUCL)
01728       if( els[iprim].trackType(PFBlockElement::T_TO_NUCL) )  {
01729         std::multimap<double, unsigned> secTracks; 
01730         // get associated secondary tracks
01731         block.associatedElements( iprim,  block.linkData(),
01732                                   secTracks,
01733                                   reco::PFBlockElement::TRACK,
01734                                   reco::PFBlock::LINKTEST_ALL );
01735         for( IE ie2 = secTracks.begin(); ie2 != secTracks.end(); ++ie2) { 
01736           unsigned isec = ie2->second;
01737           double chi2sec_rechit = block.chi2( i1, isec, block.linkData(),
01738                                               PFBlock::LINKTEST_RECHIT );
01739           double chi2sec_chi2 = block.chi2( i1, isec, block.linkData(),
01740                                             PFBlock::LINKTEST_CHI2 );
01741           double chi2sec;
01742 
01743           // at present associatedElement return first the chi2 by chi2
01744           // maybe in the futur return the min between chi2 and rechit! 
01745           if( chi2sec_chi2 > 0) chi2sec = chi2sec_chi2;
01746           else chi2sec=chi2sec_rechit;
01747 
01748           // if one secondary tracks has a chi2 < chi2prim 
01749           // remove the link between the element and the primary
01750           if( chi2sec < 0 ) continue;
01751           else if( chi2sec < chi2prim ) { 
01752             block.setLink( i1, iprim, -1, -1, block.linkData(),
01753                            PFBlock::LINKTEST_CHI2 );
01754             block.setLink( i1, iprim, -1, -1, block.linkData(),
01755                            PFBlock::LINKTEST_RECHIT );
01756             continue;
01757           }
01758         } // loop on all associated secondary tracks
01759       } // test if track is T_TO_NUCL
01760                              
01761     } // loop on all associated tracks
01762   } // loop on all elements
01763 }
01764 
01765 

Generated on Tue Jun 9 17:44:39 2009 for CMSSW by  doxygen 1.5.4