CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/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   debug_(false) {}
00027 
00028 
00029 
00030 void PFBlockAlgo::setParameters( std::vector<double>& DPtovPtCut,
00031                                  std::vector<unsigned int>& NHitCut,
00032                                  bool useConvBremPFRecTracks,
00033                                  bool useIterTracking,
00034                                  int nuclearInteractionsPurity) {
00035   
00036   DPtovPtCut_    = DPtovPtCut;
00037   NHitCut_       = NHitCut;
00038   useIterTracking_ = useIterTracking;
00039   useConvBremPFRecTracks_ = useConvBremPFRecTracks;
00040   nuclearInteractionsPurity_ = nuclearInteractionsPurity;
00041 }
00042 
00043 PFBlockAlgo::~PFBlockAlgo() {
00044 
00045 #ifdef PFLOW_DEBUG
00046   if(debug_)
00047     cout<<"~PFBlockAlgo - number of remaining elements: "
00048         <<elements_.size()<<endl;
00049 #endif
00050   
00051 }
00052 
00053 void 
00054 PFBlockAlgo::findBlocks() {
00055 
00056   //  cout<<"findBlocks : "<<blocks_.get()<<endl;
00057   
00058   // the blocks have not been passed to the event, and need to be cleared
00059   if(blocks_.get() )blocks_->clear();
00060   else 
00061     blocks_.reset( new reco::PFBlockCollection );
00062 
00063   blocks_->reserve(elements_.size());
00064   for(IE ie = elements_.begin(); 
00065       ie != elements_.end();) {
00066     
00067 #ifdef PFLOW_DEBUG
00068     if(debug_) {
00069       cout<<" PFBlockAlgo::findBlocks() ----------------------"<<endl;
00070       cout<<" element "<<**ie<<endl;
00071       cout<<" creating new block"<<endl;
00072     }
00073 #endif
00074     
00075     blocks_->push_back( PFBlock() );
00076     
00077     vector< PFBlockLink > links;
00078 
00079     //    list< IE > used;
00080     ie = associate( elements_.end() , ie, links );
00081 
00082     // build remaining links in current block
00083     packLinks( blocks_->back(), links );
00084   }       
00085 }
00086 
00087 
00088 
00089 
00090 PFBlockAlgo::IE 
00091 PFBlockAlgo::associate( IE last, 
00092                         IE next, 
00093                         vector<PFBlockLink>& links ) {
00094 
00095     
00096 #ifdef PFLOW_DEBUG
00097   if(debug_ ) cout<<"PFBlockAlgo::associate start ----"<<endl;
00098 #endif
00099 
00100   if( last!= elements_.end() ) {
00101     PFBlockLink::Type linktype = PFBlockLink::NONE;
00102     double dist = -1;
00103     PFBlock::LinkTest linktest = PFBlock::LINKTEST_RECHIT;
00104     link( *last, *next, linktype, linktest, dist ); 
00105 
00106    
00107     if(dist<-0.5) {
00108 #ifdef PFLOW_DEBUG
00109       if(debug_ ) cout<<"link failed"<<endl;
00110 #endif
00111       return ++next; // association failed
00112     }
00113     else {
00114       // add next element to the current pflowblock
00115       blocks_->back().addElement( *next );  
00116 
00117       // (*next)->setIndex( blocks_->back()->indexToLastElement() );
00118       
00119       // this is not necessary? 
00120       // next->setPFBlock(this);
00121       
00122       // create a link between next and last
00123       links.push_back( PFBlockLink(linktype, 
00124                                    linktest,
00125                                    dist,
00126                                    (*last)->index(), 
00127                                    (*next)->index() ) );
00128       // not necessary ?
00129       //       next->connect( links_.size()-1 );
00130       //       last->connect( links_.size()-1 );      
00131     }
00132   }
00133   else {
00134     // add next element to this eflowblock
00135 #ifdef PFLOW_DEBUG
00136     if(debug_ ) cout<<"adding to block element "<<(**next)<<endl;
00137 #endif
00138     blocks_->back().addElement( *next );
00139     // (*next)->setIndex( blocks_->back()->indexToLastElement() );   
00140     // next->setPFBlock(this);
00141   }
00142 
00143   // recursive call: associate next and other unused elements 
00144   
00145   //   IE afterNext = next;
00146   //   ++afterNext;
00147   //  cout<<"last "<<**last<<" next "<<**next<<endl;
00148   
00149   for(IE ie = elements_.begin(); 
00150       ie != elements_.end();) {
00151     
00152     if( ie == last || ie == next ) {
00153       ++ie;
00154       continue;
00155     } 
00156     
00157     // *ie already included to a block
00158     if( (*ie)->locked() ) {
00159 #ifdef PFLOW_DEBUG
00160       if(debug_ ) cout<<"element "<<(**ie)<<"already used"<<endl;
00161 #endif
00162       ++ie;
00163       continue;
00164     }    
00165     
00166     
00167 #ifdef PFLOW_DEBUG
00168     if(debug_ ) cout<<"calling associate "<<(**next)<<" & "<<(**ie)<<endl;
00169 #endif
00170     ie = associate(next, ie, links);
00171   }       
00172 
00173 #ifdef PFLOW_DEBUG
00174   if(debug_ ) {
00175     cout<<"**** deleting element "<<endl;
00176     cout<<**next<<endl;
00177   }
00178 #endif
00179   delete *next;
00180 
00181 #ifdef PFLOW_DEBUG
00182   if(debug_ ) {
00183     cout<<"**** removing element "<<endl;
00184   }
00185 #endif
00186 
00187   IE iteratorToNextFreeElement = elements_.erase( next );
00188 
00189 #ifdef PFLOW_DEBUG
00190   if(debug_ ) cout<<"PFBlockAlgo::associate stop ----"<<endl;
00191 #endif
00192 
00193   return iteratorToNextFreeElement;
00194 }
00195 
00196 
00197 
00198 void 
00199 PFBlockAlgo::packLinks( reco::PFBlock& block, 
00200                         const vector<PFBlockLink>& links ) const {
00201   
00202   
00203   const edm::OwnVector< reco::PFBlockElement >& els = block.elements();
00204   
00205   block.bookLinkData();
00206 
00207   //First Loop: update all link data
00208   for( unsigned i1=0; i1<els.size(); i1++ ) {
00209     for( unsigned i2=0; i2<els.size(); i2++ ) {
00210       
00211       // no reflexive link
00212       if( i1==i2 ) continue;
00213       
00214       double dist = -1;
00215       
00216       bool linked = false;
00217       PFBlock::LinkTest linktest 
00218         = PFBlock::LINKTEST_RECHIT; 
00219 
00220       // are these elements already linked ?
00221       // this can be optimized
00222 
00223       for( unsigned il=0; il<links.size(); il++ ) {
00224         if( (links[il].element1() == i1 && 
00225              links[il].element2() == i2) || 
00226             (links[il].element1() == i2 && 
00227              links[il].element2() == i1) ) { // yes
00228           
00229           dist = links[il].dist();
00230           linked = true;
00231 
00232           //modif-beg     
00233           //retrieve type of test used to get distance
00234           linktest = links[il].test();
00235 #ifdef PFLOW_DEBUG
00236           if( debug_ )
00237             cout << "Reading link vector: linktest used=" 
00238                  << linktest 
00239                  << " distance = " << dist 
00240                  << endl; 
00241 #endif
00242           //modif-end
00243           
00244           break;
00245         } 
00246       }
00247       
00248       if(!linked) {
00249         PFBlockLink::Type linktype = PFBlockLink::NONE;
00250         link( & els[i1], & els[i2], linktype, linktest, dist);
00251       }
00252 
00253       //loading link data according to link test used: RECHIT 
00254       //block.setLink( i1, i2, chi2, block.linkData() );
00255 #ifdef PFLOW_DEBUG
00256       if( debug_ )
00257         cout << "Setting link between elements " << i1 << " and " << i2
00258              << " of dist =" << dist << " computed from link test "
00259              << linktest << endl;
00260 #endif
00261       block.setLink( i1, i2, dist, block.linkData(), linktest );
00262     }
00263   }
00264 
00265   // Do not cut the link between the primary track and the clusters. It would be analysed in the PFCandConnector.cc
00266   // checkDisplacedVertexLinks( block );
00267 }
00268 
00269 
00270 
00271 void 
00272 PFBlockAlgo::buildGraph() {
00273   // loop on all blocks and create a big graph
00274 }
00275 
00276 
00277 
00278 void 
00279 PFBlockAlgo::link( const reco::PFBlockElement* el1, 
00280                    const reco::PFBlockElement* el2, 
00281                    PFBlockLink::Type& linktype, 
00282                    reco::PFBlock::LinkTest& linktest,
00283                    double& dist) const {
00284   
00285 
00286 
00287   dist=-1.;
00288   linktest = PFBlock::LINKTEST_RECHIT; //rechit by default 
00289 
00290   PFBlockElement::Type type1 = el1->type();
00291   PFBlockElement::Type type2 = el2->type();
00292 
00293   if( type1==type2 ) {
00294     // cannot link 2 elements of the same type. 
00295     // except if the elements are 2 tracks or 2 ECAL
00296     if( type1!=PFBlockElement::TRACK && type1!=PFBlockElement::GSF &&
00297         type1!=PFBlockElement::ECAL) {
00298       return;
00299     }
00300 
00301     // cannot link two primary tracks  (except if they come from a V0)
00302     if( type1 ==PFBlockElement::TRACK) {
00303       if ( !el1->isLinkedToDisplacedVertex() || !el2->isLinkedToDisplacedVertex()) 
00304       return;
00305     }
00306   }
00307 
00308   linktype = static_cast<PFBlockLink::Type>
00309     ((1<< (type1-1) ) | (1<< (type2-1) ));
00310 
00311   if(debug_ ) std::cout << " PFBlockAlgo links type1 " << type1 << " type2 " << type2 << std::endl;
00312 
00313   PFBlockElement::Type lowType = type1;
00314   PFBlockElement::Type highType = type2;
00315   const PFBlockElement* lowEl = el1;
00316   const PFBlockElement* highEl = el2;
00317   
00318   if(type1>type2) {
00319     lowType = type2;
00320     highType = type1;
00321     lowEl = el2;
00322     highEl = el1;
00323   }
00324   
00325   switch(linktype) {
00326   case PFBlockLink::TRACKandPS1:
00327   case PFBlockLink::TRACKandPS2:
00328     {
00329       //       cout<<"TRACKandPS"<<endl;
00330       PFRecTrackRef trackref = lowEl->trackRefPF();
00331       PFClusterRef  clusterref = highEl->clusterRef();
00332       assert( !trackref.isNull() );
00333       assert( !clusterref.isNull() );
00334       // PJ - 14-May-09 : A link by rechit is needed here !
00335       dist = testTrackAndPS( *trackref, *clusterref );
00336       linktest = PFBlock::LINKTEST_RECHIT;
00337       break;
00338     }
00339     
00340   case PFBlockLink::TRACKandECAL:
00341     {
00342       if(debug_ ) cout<<"TRACKandECAL"<<endl;
00343       PFRecTrackRef trackref = lowEl->trackRefPF();
00344       
00345       if(debug_ ) std::cout << " Track pt " << trackref->trackRef()->pt() << std::endl;
00346       
00347       PFClusterRef  clusterref = highEl->clusterRef();
00348       assert( !trackref.isNull() );
00349       assert( !clusterref.isNull() );
00350       dist = LinkByRecHit::testTrackAndClusterByRecHit( *trackref, *clusterref, false, debug_ );
00351       linktest = PFBlock::LINKTEST_RECHIT;
00352 
00353       if ( debug_ ) { 
00354         if( dist > 0. ) { 
00355           std::cout << " Here a link has been established"
00356                     << " between a track an Ecal with dist  " 
00357                     << dist <<  std::endl;
00358         } else {
00359           std::cout << " No link found " << std::endl;
00360         }
00361       }
00362 
00363       break;
00364     }
00365   case PFBlockLink::TRACKandHCAL:
00366     {
00367       //       cout<<"TRACKandHCAL"<<endl;
00368       PFRecTrackRef trackref = lowEl->trackRefPF();
00369       PFClusterRef  clusterref = highEl->clusterRef();
00370       assert( !trackref.isNull() );
00371       assert( !clusterref.isNull() );
00372       dist = LinkByRecHit::testTrackAndClusterByRecHit( *trackref, *clusterref, false, debug_ );
00373       linktest = PFBlock::LINKTEST_RECHIT;      
00374       break;
00375     }
00376   case PFBlockLink::ECALandHCAL:
00377     {
00378       //       cout<<"ECALandHCAL"<<endl;
00379       PFClusterRef  ecalref = lowEl->clusterRef();
00380       PFClusterRef  hcalref = highEl->clusterRef();
00381       assert( !ecalref.isNull() );
00382       assert( !hcalref.isNull() );
00383       // PJ - 14-May-09 : A link by rechit is needed here !
00384       // dist = testECALAndHCAL( *ecalref, *hcalref );
00385       dist = -1.;
00386       linktest = PFBlock::LINKTEST_RECHIT;
00387       break;
00388     }
00389   case PFBlockLink::PS1andECAL:
00390   case PFBlockLink::PS2andECAL:
00391     {
00392       //       cout<<"PSandECAL"<<endl;
00393       PFClusterRef  psref = lowEl->clusterRef();
00394       PFClusterRef  ecalref = highEl->clusterRef();
00395       assert( !psref.isNull() );
00396       assert( !ecalref.isNull() );
00397       dist = LinkByRecHit::testECALAndPSByRecHit( *ecalref, *psref ,debug_);
00398       linktest = PFBlock::LINKTEST_RECHIT;      
00399       break;
00400     }
00401   case PFBlockLink::PS1andPS2:
00402     {
00403       PFClusterRef  ps1ref = lowEl->clusterRef();
00404       PFClusterRef  ps2ref = highEl->clusterRef();
00405       assert( !ps1ref.isNull() );
00406       assert( !ps2ref.isNull() );
00407       // PJ - 14-May-09 : A link by rechit is needed here !
00408       // dist = testPS1AndPS2( *ps1ref, *ps2ref );
00409       dist = -1.;
00410       linktest = PFBlock::LINKTEST_RECHIT;
00411       break;
00412     }
00413   case PFBlockLink::TRACKandTRACK:
00414     {
00415       if(debug_ ) 
00416         cout<<"TRACKandTRACK"<<endl;
00417       dist = testLinkByVertex(lowEl, highEl);
00418       if(debug_ ) 
00419         std::cout << " PFBlockLink::TRACKandTRACK dist " << dist << std::endl;
00420       linktest = PFBlock::LINKTEST_RECHIT;
00421       break;
00422     }
00423 
00424   case PFBlockLink::ECALandECAL:
00425       {
00426         
00427         PFClusterRef  ecal1ref = lowEl->clusterRef();
00428         PFClusterRef  ecal2ref = highEl->clusterRef();
00429         assert( !ecal1ref.isNull() );
00430         assert( !ecal2ref.isNull() );
00431         if(debug_)
00432           cout << " PFBlockLink::ECALandECAL" << endl;
00433         dist = testLinkBySuperCluster(ecal1ref,ecal2ref);
00434         break;
00435       }
00436 
00437   case PFBlockLink::ECALandGSF:
00438     {
00439       PFClusterRef  clusterref = lowEl->clusterRef();
00440       assert( !clusterref.isNull() );
00441       const reco::PFBlockElementGsfTrack *  GsfEl =  dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00442       const PFRecTrack * myTrack =  &(GsfEl->GsftrackPF());
00443       dist = LinkByRecHit::testTrackAndClusterByRecHit( *myTrack, *clusterref, false, debug_ );
00444       linktest = PFBlock::LINKTEST_RECHIT;
00445       
00446       if ( debug_ ) {
00447         if ( dist > 0. ) {
00448           std::cout << " Here a link has been established" 
00449                     << " between a GSF track an Ecal with dist  " 
00450                     << dist <<  std::endl;
00451         } else {
00452           if(debug_ ) std::cout << " No link found " << std::endl;
00453         }
00454       }
00455       break;
00456     }
00457   case PFBlockLink::TRACKandGSF:
00458     {
00459       PFRecTrackRef trackref = lowEl->trackRefPF();
00460       assert( !trackref.isNull() );
00461       const reco::PFBlockElementGsfTrack *  GsfEl =  
00462         dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00463       GsfPFRecTrackRef gsfref = GsfEl->GsftrackRefPF();
00464       reco::TrackRef kftrackref= (*trackref).trackRef();
00465       assert( !gsfref.isNull() );
00466       PFRecTrackRef refkf = (*gsfref).kfPFRecTrackRef();
00467       if(refkf.isNonnull()) {
00468         reco::TrackRef gsftrackref = (*refkf).trackRef();
00469         if (gsftrackref.isNonnull()&&kftrackref.isNonnull()) {
00470           if (kftrackref == gsftrackref) { 
00471             dist = 0.001;
00472           } else { 
00473             dist = -1.;
00474           }
00475         } else { 
00476           dist = -1.;
00477         }
00478       } else {
00479         dist = -1.;
00480       }
00481       
00482       
00483       if(useConvBremPFRecTracks_) {
00484         if(lowEl->isLinkedToDisplacedVertex()){
00485           vector<PFRecTrackRef> pfrectrack_vec = GsfEl->GsftrackRefPF()->convBremPFRecTrackRef();
00486           if(pfrectrack_vec.size() > 0){
00487             for(unsigned int iconv = 0; iconv <  pfrectrack_vec.size(); iconv++) {
00488               if( lowEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)) {
00489                 // use track ref
00490                 if(kftrackref == (*pfrectrack_vec[iconv]).trackRef()) {         
00491                   dist = 0.001;
00492                 }
00493               } 
00494               else{
00495                 // use the track base ref
00496                 reco::TrackBaseRef newTrackBaseRef((*pfrectrack_vec[iconv]).trackRef());
00497                 reco::TrackBaseRef elemTrackBaseRef(kftrackref);              
00498                 if(newTrackBaseRef == elemTrackBaseRef){
00499                   dist = 0.001;
00500                 } 
00501               }
00502             }
00503           }
00504         }
00505       }
00506  
00507 
00508       break;      
00509     }
00510          
00511   case PFBlockLink::GSFandBREM:
00512     {
00513       const reco::PFBlockElementGsfTrack * GsfEl  =  dynamic_cast<const reco::PFBlockElementGsfTrack*>(lowEl);
00514       const reco::PFBlockElementBrem * BremEl =  dynamic_cast<const reco::PFBlockElementBrem*>(highEl);
00515       GsfPFRecTrackRef gsfref = GsfEl->GsftrackRefPF();
00516       GsfPFRecTrackRef bremref = BremEl->GsftrackRefPF();
00517       assert( !gsfref.isNull() );
00518       assert( !bremref.isNull() );
00519       if (gsfref == bremref)  { 
00520         dist = 0.001;
00521       } else { 
00522         dist = -1.;
00523       }
00524       break;
00525     }
00526   case PFBlockLink::GSFandGSF:
00527     {
00528       const reco::PFBlockElementGsfTrack * lowGsfEl  =  
00529         dynamic_cast<const reco::PFBlockElementGsfTrack*>(lowEl);
00530       const reco::PFBlockElementGsfTrack * highGsfEl  =  
00531         dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00532       
00533       GsfPFRecTrackRef lowgsfref = lowGsfEl->GsftrackRefPF();
00534       GsfPFRecTrackRef highgsfref = highGsfEl->GsftrackRefPF();
00535       assert( !lowgsfref.isNull() );
00536       assert( !highgsfref.isNull() );
00537       
00538       if( (lowGsfEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false && 
00539            highGsfEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)) ||
00540           (highGsfEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false && 
00541            lowGsfEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV))) {
00542         if(lowgsfref->trackId() == highgsfref->trackId()) {
00543           dist = 0.001;
00544         }
00545         else {
00546           dist = -1.;
00547         }
00548       }
00549       break;
00550     }
00551   case PFBlockLink::ECALandBREM:
00552     {
00553       PFClusterRef  clusterref = lowEl->clusterRef();
00554       assert( !clusterref.isNull() );
00555       const reco::PFBlockElementBrem * BremEl =  
00556         dynamic_cast<const reco::PFBlockElementBrem*>(highEl);
00557       const PFRecTrack * myTrack = &(BremEl->trackPF());
00558       /*
00559       double DP = (BremEl->DeltaP())*(-1.);
00560       double SigmaDP = BremEl->SigmaDeltaP();
00561       double SignBremDp = DP/SigmaDP;
00562       */
00563       bool isBrem = true;
00564       dist = LinkByRecHit::testTrackAndClusterByRecHit( *myTrack, *clusterref, isBrem, debug_);
00565       if( debug_ && dist > 0. ) 
00566         std::cout << "ECALandBREM: dist testTrackAndClusterByRecHit " 
00567                   << dist << std::endl;
00568       linktest = PFBlock::LINKTEST_RECHIT;
00569       break;
00570     }
00571   case PFBlockLink::PS1andGSF:
00572   case PFBlockLink::PS2andGSF:
00573     {
00574       PFClusterRef  psref = lowEl->clusterRef();
00575       assert( !psref.isNull() );
00576       const reco::PFBlockElementGsfTrack *  GsfEl =  dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00577       const PFRecTrack * myTrack =  &(GsfEl->GsftrackPF());
00578       // PJ - 14-May-09 : A link by rechit is needed here !
00579       dist = testTrackAndPS( *myTrack, *psref );
00580       linktest = PFBlock::LINKTEST_RECHIT;
00581       break;
00582     }
00583   case PFBlockLink::PS1andBREM:
00584   case PFBlockLink::PS2andBREM:
00585     {
00586       PFClusterRef  psref = lowEl->clusterRef();
00587       assert( !psref.isNull() );
00588       const reco::PFBlockElementBrem * BremEl =  dynamic_cast<const reco::PFBlockElementBrem*>(highEl);
00589       const PFRecTrack * myTrack = &(BremEl->trackPF());
00590       // PJ - 14-May-09 : A link by rechit is needed here !
00591       dist = testTrackAndPS( *myTrack, *psref );
00592       linktest = PFBlock::LINKTEST_RECHIT;
00593       break;
00594     }
00595   case PFBlockLink::HCALandGSF:
00596     {
00597       PFClusterRef  clusterref = lowEl->clusterRef();
00598       assert( !clusterref.isNull() );
00599       const reco::PFBlockElementGsfTrack *  GsfEl =  dynamic_cast<const reco::PFBlockElementGsfTrack*>(highEl);
00600       const PFRecTrack * myTrack =  &(GsfEl->GsftrackPF());
00601       dist = LinkByRecHit::testTrackAndClusterByRecHit( *myTrack, *clusterref, false, debug_ );
00602       linktest = PFBlock::LINKTEST_RECHIT;
00603       break;
00604     }
00605   case PFBlockLink::HCALandBREM:
00606     {
00607       PFClusterRef  clusterref = lowEl->clusterRef();
00608       assert( !clusterref.isNull() );
00609       const reco::PFBlockElementBrem * BremEl =  dynamic_cast<const reco::PFBlockElementBrem*>(highEl);
00610       const PFRecTrack * myTrack = &(BremEl->trackPF());
00611       bool isBrem = true;
00612       dist = LinkByRecHit::testTrackAndClusterByRecHit( *myTrack, *clusterref, isBrem, debug_);
00613       break;
00614     }
00615   case PFBlockLink::HFEMandHFHAD:
00616     {
00617       // cout<<"HFEMandHFHAD"<<endl;
00618       PFClusterRef  eref = lowEl->clusterRef();
00619       PFClusterRef  href = highEl->clusterRef();
00620       assert( !eref.isNull() );
00621       assert( !href.isNull() );
00622       dist = LinkByRecHit::testHFEMAndHFHADByRecHit( *eref, *href, debug_ );
00623       linktest = PFBlock::LINKTEST_RECHIT;
00624       break;
00625       
00626       break;
00627     }
00628   default:
00629     dist = -1.;
00630     linktest = PFBlock::LINKTEST_RECHIT;
00631     // cerr<<"link type not implemented yet: 0x"<<hex<<linktype<<dec<<endl;
00632     // assert(0);
00633     return;
00634   }
00635 }
00636 
00637 double
00638 PFBlockAlgo::testTrackAndPS(const PFRecTrack& track, 
00639                             const PFCluster& ps)  const {
00640 
00641 #ifdef PFLOW_DEBUG
00642   //   cout<<"entering testTrackAndPS"<<endl;
00643   // resolution of PS cluster dxdx and dydy from strip pitch and length
00644   double dx=0.;
00645   double dy=0.;
00646   
00647   unsigned layerid =0;
00648   // PS1: vertical strips  PS2: horizontal strips
00649   switch (ps.layer()) {
00650   case PFLayer::PS1:
00651     layerid = reco::PFTrajectoryPoint::PS1;
00652     
00653     // vertical strips in PS1, measure x with pitch precision
00654     dx = resPSpitch_;
00655     dy = resPSlength_; 
00656     break;
00657   case PFLayer::PS2:
00658     layerid = reco::PFTrajectoryPoint::PS2;
00659     // horizontal strips in PS2, measure y with pitch precision
00660     dy = resPSpitch_;
00661     dx = resPSlength_;
00662     break;
00663   default:
00664     break;
00665   }
00666   const reco::PFTrajectoryPoint& atPS
00667     = track.extrapolatedPoint( layerid );  
00668   // did not reach PS, cannot be associated with a cluster.
00669   if( ! atPS.isValid() ) return -1.;   
00670   
00671   double trackx = atPS.position().X();
00672   double tracky = atPS.position().Y();
00673   double trackz = atPS.position().Z(); // MDN jan 09
00674   
00675   // ps position  x, y
00676   double psx = ps.position().X();
00677   double psy = ps.position().Y();
00678   // MDN Jan 09: check that trackz and psz have the same sign
00679   double psz = ps.position().Z();
00680   if( trackz*psz < 0.) return -1.; 
00681   
00682   // double chi2 = (psx-trackx)*(psx-trackx)/(dx*dx + trackresolx*trackresolx)
00683   //  + (psy-tracky)*(psy-tracky)/(dy*dy + trackresoly*trackresoly);
00684 
00685   double dist = std::sqrt( (psx-trackx)*(psx-trackx)
00686                          + (psy-tracky)*(psy-tracky));  
00687   if(debug_) cout<<"testTrackAndPS "<< dist <<" "<<endl;
00688   if(debug_){
00689     cout<<" trackx " << trackx 
00690         <<" tracky " << tracky 
00691         <<" psx "    <<  psx   
00692         <<" psy "    << psy    
00693         << endl;
00694   }
00695 #endif
00696   
00697   // Return -1. as long as no link by rechit is available
00698   return -1.;
00699 }
00700 
00701 double
00702 PFBlockAlgo::testECALAndHCAL(const PFCluster& ecal, 
00703                              const PFCluster& hcal)  const {
00704   
00705   //   cout<<"entering testECALAndHCAL"<<endl;
00706   
00707   /*
00708   double dist = 
00709     computeDist( ecal.positionREP().Eta(),
00710                  ecal.positionREP().Phi(), 
00711                  hcal.positionREP().Eta(), 
00712                  hcal.positionREP().Phi() );
00713   */
00714 
00715 #ifdef PFLOW_DEBUG
00716   if(debug_) cout<<"testECALAndHCAL "<< dist <<" "<<endl;
00717   if(debug_){
00718     cout<<" ecaleta " << ecal.positionREP().Eta()
00719         <<" ecalphi " << ecal.positionREP().Phi()
00720         <<" hcaleta " << hcal.positionREP().Eta()
00721         <<" hcalphi " << hcal.positionREP().Phi()
00722   }
00723 #endif
00724 
00725   // Need to implement a link by RecHit
00726   return -1.;
00727 }
00728 
00729 double
00730 PFBlockAlgo::testLinkBySuperCluster(const PFClusterRef& ecal1, 
00731                                     const PFClusterRef& ecal2)  const {
00732   
00733   //  cout<<"entering testECALAndECAL "<< pfcRefSCMap_.size() << endl;
00734   
00735   double dist = -1;
00736   
00737   // the first one is not in any super cluster
00738   int testindex=pfcSCVec_[ecal1.key()];
00739   if(testindex == -1.) return dist;
00740   //  if(itcheck==pfcRefSCMap_.end()) return dist;
00741   // now retrieve the of PFclusters in this super cluster  
00742 
00743   const std::vector<reco::PFClusterRef> & thePFClusters(scpfcRefs_[testindex]);
00744   
00745   unsigned npf=thePFClusters.size();
00746   for(unsigned i=0;i<npf;++i)
00747     {
00748       if(thePFClusters[i]==ecal2) // yes they are in the same SC 
00749         {
00750           dist=LinkByRecHit::computeDist( ecal1->positionREP().Eta(),
00751                                           ecal1->positionREP().Phi(), 
00752                                           ecal2->positionREP().Eta(), 
00753                                           ecal2->positionREP().Phi() );
00754 //        std::cout << " DETA " << fabs(ecal1->positionREP().Eta()-ecal2->positionREP().Eta()) << std::endl;
00755 //        if(fabs(ecal1->positionREP().Eta()-ecal2->positionREP().Eta())>0.2)
00756 //          {
00757 //            std::cout <<  " Super Cluster " <<  *(superClusters_[testindex]) << std::endl;
00758 //            std::cout <<  " Cluster1 " <<  *ecal1 << std::endl;
00759 //            std::cout <<  " Cluster2 " <<  *ecal2 << std::endl;
00760 //            ClusterClusterMapping::checkOverlap(*ecal1,superClusters_,0.01,true);
00761 //            ClusterClusterMapping::checkOverlap(*ecal2,superClusters_,0.01,true);
00762 //          }
00763           return dist;
00764         }
00765     }
00766   return dist;
00767 }
00768 
00769 
00770 
00771 double
00772 PFBlockAlgo::testPS1AndPS2(const PFCluster& ps1, 
00773                            const PFCluster& ps2)  const {
00774   
00775 #ifdef PFLOW_DEBUG
00776   //   cout<<"entering testPS1AndPS2"<<endl;
00777   
00778   // compute chi2 in y, z using swimming formulae
00779   // y2 = y1 * z2/z1   and x2 = x1 *z2/z1
00780   
00781   // ps position1  x, y, z
00782   double x1 = ps1.position().X();
00783   double y1 = ps1.position().Y();
00784   double z1 = ps1.position().Z();
00785   double x2 = ps2.position().X();
00786   double y2 = ps2.position().Y();
00787   double z2 = ps2.position().Z();
00788   // MDN Bug correction Jan 09: check that z1 and z2 have the same sign!
00789   if (z1*z2<0.) -1.;
00790   // swim to PS2
00791   double scale = z2/z1;
00792   double x1atPS2 = x1*scale;
00793   double y1atPS2 = y1*scale;
00794   // resolution of PS cluster dxdx and dydy from strip pitch and length
00795   // vertical strips in PS1, measure x with pitch precision
00796   double dx1dx1 = resPSpitch_*resPSpitch_*scale*scale;
00797   double dy1dy1 = resPSlength_*resPSlength_*scale*scale;
00798   // horizontal strips in PS2 , measure y with pitch precision
00799   double dy2dy2 = resPSpitch_*resPSpitch_;
00800   double dx2dx2 = resPSlength_*resPSlength_;
00801   
00802   // double chi2 = (x2-x1atPS2)*(x2-x1atPS2)/(dx1dx1 + dx2dx2) 
00803   //  + (y2-y1atPS2)*(y2-y1atPS2)/(dy1dy1 + dy2dy2);
00804   
00805   double dist = std::sqrt( (x2-x1atPS2)*(x2-x1atPS2)
00806                          + (y2-y1atPS2)*(y2-y1atPS2));
00807     
00808   if(debug_) cout<<"testPS1AndPS2 "<<dist<<" "<<endl;
00809   if(debug_){
00810     cout<<" x1atPS2 "<< x1atPS2 << " dx1 "<<resPSpitch_*scale
00811         <<" y1atPS2 "<< y1atPS2 << " dy1 "<<resPSlength_*scale<< endl
00812         <<" x2 " <<x2  << " dx2 "<<resPSlength_
00813         <<" y2 " << y2 << " dy2 "<<resPSpitch_<< endl;
00814   }
00815 #endif
00816 
00817   // Need a link by rechit here
00818   return -1.; 
00819 }
00820 
00821 
00822 
00823 double
00824 PFBlockAlgo::testLinkByVertex( const reco::PFBlockElement* elt1, 
00825                                const reco::PFBlockElement* elt2) const {
00826 
00827   //  cout << "Test link by vertex between" << endl << *elt1 << endl << " and " << endl << *elt2 << endl;
00828 
00829   double result=-1.;
00830 
00831   reco::PFBlockElement::TrackType T_TO_DISP = reco::PFBlockElement::T_TO_DISP;
00832   reco::PFBlockElement::TrackType T_FROM_DISP = reco::PFBlockElement::T_FROM_DISP;
00833   PFDisplacedTrackerVertexRef ni1_TO_DISP = elt1->displacedVertexRef(T_TO_DISP);
00834   PFDisplacedTrackerVertexRef ni2_TO_DISP = elt2->displacedVertexRef(T_TO_DISP);
00835   PFDisplacedTrackerVertexRef ni1_FROM_DISP = elt1->displacedVertexRef(T_FROM_DISP);
00836   PFDisplacedTrackerVertexRef ni2_FROM_DISP = elt2->displacedVertexRef(T_FROM_DISP);
00837   
00838   if( ni1_TO_DISP.isNonnull() && ni2_FROM_DISP.isNonnull())
00839     if( ni1_TO_DISP == ni2_FROM_DISP ) { result = 1.0; return result; }
00840 
00841   if( ni1_FROM_DISP.isNonnull() && ni2_TO_DISP.isNonnull())
00842     if( ni1_FROM_DISP == ni2_TO_DISP ) { result = 1.0; return result; }
00843 
00844   if( ni1_FROM_DISP.isNonnull() && ni2_FROM_DISP.isNonnull())
00845     if( ni1_FROM_DISP == ni2_FROM_DISP ) { result = 1.0; return result; }
00846     
00847   
00848   if (  elt1->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)  &&
00849              elt2->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)  ) {
00850     
00851     if(debug_ ) std::cout << " testLinkByVertex On Conversions " << std::endl;
00852     
00853     if ( elt1->convRef().isNonnull() && elt2->convRef().isNonnull() ) {
00854       if(debug_ ) std::cout << " PFBlockAlgo.cc testLinkByVertex  Cconversion Refs are non null  " << std::endl;      
00855       if ( elt1->convRef() ==  elt2->convRef() ) {
00856         result=1.0;
00857         if(debug_ ) std::cout << " testLinkByVertex  Cconversion Refs are equal  " << std::endl;      
00858         return result;
00859       }
00860     } 
00861     
00862   }
00863   
00864   if (  elt1->trackType(reco::PFBlockElement::T_FROM_V0)  &&
00865              elt2->trackType(reco::PFBlockElement::T_FROM_V0)  ) {
00866     if(debug_ ) std::cout << " testLinkByVertex On V0 " << std::endl;
00867     if ( elt1->V0Ref().isNonnull() && elt2->V0Ref().isNonnull() ) {
00868       if(debug_ ) std::cout << " PFBlockAlgo.cc testLinkByVertex  V0 Refs are non null  " << std::endl;
00869       if ( elt1->V0Ref() ==  elt2->V0Ref() ) {
00870         result=1.0;
00871         if(debug_ ) std::cout << " testLinkByVertex  V0 Refs are equal  " << std::endl;
00872         return result;
00873       }
00874     }
00875   }
00876 
00877   return result;
00878 }
00879 
00880 
00881 
00882 void 
00883 PFBlockAlgo::checkMaskSize( const reco::PFRecTrackCollection& tracks,
00884                             const reco::GsfPFRecTrackCollection& gsftracks, 
00885                             const reco::PFClusterCollection&  ecals,
00886                             const reco::PFClusterCollection&  hcals,
00887                             const reco::PFClusterCollection&  hfems,
00888                             const reco::PFClusterCollection&  hfhads,
00889                             const reco::PFClusterCollection&  pss, 
00890                             const Mask& trackMask, 
00891                             const Mask& gsftrackMask,  
00892                             const Mask& ecalMask,
00893                             const Mask& hcalMask, 
00894                             const Mask& hfemMask,
00895                             const Mask& hfhadMask,                    
00896                             const Mask& psMask ) const {
00897 
00898   if( !trackMask.empty() && 
00899       trackMask.size() != tracks.size() ) {
00900     string err = "PFBlockAlgo::setInput: ";
00901     err += "The size of the track mask is different ";
00902     err += "from the size of the track vector.";
00903     throw std::length_error( err.c_str() );
00904   }
00905 
00906   if( !gsftrackMask.empty() && 
00907       gsftrackMask.size() != gsftracks.size() ) {
00908     string err = "PFBlockAlgo::setInput: ";
00909     err += "The size of the gsf track mask is different ";
00910     err += "from the size of the gsftrack vector.";
00911     throw std::length_error( err.c_str() );
00912   }
00913 
00914   if( !ecalMask.empty() && 
00915       ecalMask.size() != ecals.size() ) {
00916     string err = "PFBlockAlgo::setInput: ";
00917     err += "The size of the ecal mask is different ";
00918     err += "from the size of the ecal clusters vector.";
00919     throw std::length_error( err.c_str() );
00920   }
00921   
00922   if( !hcalMask.empty() && 
00923       hcalMask.size() != hcals.size() ) {
00924     string err = "PFBlockAlgo::setInput: ";
00925     err += "The size of the hcal mask is different ";
00926     err += "from the size of the hcal clusters vector.";
00927     throw std::length_error( err.c_str() );
00928   }
00929 
00930   if( !hfemMask.empty() && 
00931       hfemMask.size() != hfems.size() ) {
00932     string err = "PFBlockAlgo::setInput: ";
00933     err += "The size of the hfem mask is different ";
00934     err += "from the size of the hfem clusters vector.";
00935     throw std::length_error( err.c_str() );
00936   }
00937 
00938   if( !hfhadMask.empty() && 
00939       hfhadMask.size() != hfhads.size() ) {
00940     string err = "PFBlockAlgo::setInput: ";
00941     err += "The size of the hfhad mask is different ";
00942     err += "from the size of the hfhad clusters vector.";
00943     throw std::length_error( err.c_str() );
00944   }
00945 
00946   if( !psMask.empty() && 
00947       psMask.size() != pss.size() ) {
00948     string err = "PFBlockAlgo::setInput: ";
00949     err += "The size of the ps mask is different ";
00950     err += "from the size of the ps clusters vector.";
00951     throw std::length_error( err.c_str() );
00952   }
00953   
00954 }
00955 
00956 
00957 std::ostream& operator<<(std::ostream& out, const PFBlockAlgo& a) {
00958   if(! out) return out;
00959   
00960   out<<"====== Particle Flow Block Algorithm ======= ";
00961   out<<endl;
00962   out<<"number of unassociated elements : "<<a.elements_.size()<<endl;
00963   out<<endl;
00964   
00965   for(PFBlockAlgo::IEC ie = a.elements_.begin(); 
00966       ie != a.elements_.end(); ie++) {
00967     out<<"\t"<<**ie <<endl;
00968   }
00969 
00970   
00971   //   const PFBlockCollection& blocks = a.blocks();
00972 
00973   const std::auto_ptr< reco::PFBlockCollection >& blocks
00974     = a.blocks(); 
00975     
00976   if(!blocks.get() ) {
00977     out<<"blocks already transfered"<<endl;
00978   }
00979   else {
00980     out<<"number of blocks : "<<blocks->size()<<endl;
00981     out<<endl;
00982     
00983     for(PFBlockAlgo::IBC ib=blocks->begin(); 
00984         ib != blocks->end(); ib++) {
00985       out<<(*ib)<<endl;
00986     }
00987   }
00988 
00989   return out;
00990 }
00991 
00992 bool 
00993 PFBlockAlgo::goodPtResolution( const reco::TrackRef& trackref) {
00994 
00995   double P = trackref->p();
00996   double Pt = trackref->pt();
00997   double DPt = trackref->ptError();
00998   unsigned int NHit = trackref->hitPattern().trackerLayersWithMeasurement();
00999   unsigned int NLostHit = trackref->hitPattern().trackerLayersWithoutMeasurement();
01000   unsigned int LostHits = trackref->numberOfLostHits();
01001   double sigmaHad = sqrt(1.20*1.20/P+0.06*0.06) / (1.+LostHits);
01002 
01003   // iteration 1,2,3,4,5 correspond to algo = 1/4,5,6,7,8,9
01004   unsigned int Algo = 0; 
01005   switch (trackref->algo()) {
01006   case TrackBase::ctf:
01007   case TrackBase::iter0:
01008   case TrackBase::iter1:
01009     Algo = 0;
01010     break;
01011   case TrackBase::iter2:
01012     Algo = 1;
01013     break;
01014   case TrackBase::iter3:
01015     Algo = 2;
01016     break;
01017   case TrackBase::iter4:
01018     Algo = 3;
01019     break;
01020   case TrackBase::iter5:
01021     Algo = 4;
01022     break;
01023   default:
01024     Algo = 5;
01025     break;
01026   }
01027 
01028   // Protection against 0 momentum tracks
01029   if ( P < 0.05 ) return false;
01030 
01031   if(useIterTracking_){
01032 
01033   // Temporary : Reject all tracking iteration beyond 5th step. 
01034   if ( Algo > 4 ) return false;
01035  
01036   if (debug_) cout << " PFBlockAlgo: PFrecTrack->Track Pt= "
01037                    << Pt << " DPt = " << DPt << endl;
01038   if ( ( DPtovPtCut_[Algo] > 0. && 
01039          DPt/Pt > DPtovPtCut_[Algo]*sigmaHad ) || 
01040        NHit < NHitCut_[Algo] ) { 
01041     // (Algo >= 3 && LostHits != 0) ) {
01042     if (debug_) cout << " PFBlockAlgo: skip badly measured track"
01043                      << ", P = " << P 
01044                      << ", Pt = " << Pt 
01045                      << " DPt = " << DPt 
01046                      << ", N(hits) = " << NHit << " (Lost : " << LostHits << "/" << NLostHit << ")"
01047                      << ", Algo = " << Algo
01048                      << endl;
01049     if (debug_) cout << " cut is DPt/Pt < " << DPtovPtCut_[Algo] * sigmaHad << endl;
01050     if (debug_) cout << " cut is NHit >= " << NHitCut_[Algo] << endl;
01051     /*
01052     std::cout << "Track REJECTED : ";
01053     std::cout << ", P = " << P 
01054               << ", Pt = " << Pt 
01055               << " DPt = " << DPt 
01056               << ", N(hits) = " << NHit << " (Lost : " << LostHits << "/" << NLostHit << ")"
01057               << ", Algo = " << Algo
01058               << std::endl;
01059     */
01060     return false;
01061   }
01062 
01063   }
01064   /*
01065   std::cout << "Track Accepted : ";
01066   std::cout << ", P = " << P 
01067        << ", Pt = " << Pt 
01068        << " DPt = " << DPt 
01069        << ", N(hits) = " << NHit << " (Lost : " << LostHits << "/" << NLostHit << ")"
01070        << ", Algo = " << Algo
01071        << std::endl;
01072   */
01073   return true;
01074 }
01075 
01076 int
01077 PFBlockAlgo::muAssocToTrack( const reco::TrackRef& trackref,
01078                              const edm::Handle<reco::MuonCollection>& muonh) const {
01079   if(muonh.isValid() ) {
01080     for(unsigned j=0;j<muonh->size(); j++) {
01081       reco::MuonRef muonref( muonh, j );
01082       if (muonref->track().isNonnull()) 
01083         if( muonref->track() == trackref ) return j;
01084     }
01085   }
01086   return -1; // not found
01087 }
01088 
01089 int 
01090 PFBlockAlgo::muAssocToTrack( const reco::TrackRef& trackref,
01091                              const edm::OrphanHandle<reco::MuonCollection>& muonh) const {
01092   if(muonh.isValid() ) {
01093     for(unsigned j=0;j<muonh->size(); j++) {
01094       reco::MuonRef muonref( muonh, j );
01095       if (muonref->track().isNonnull())
01096         if( muonref->track() == trackref ) return j;
01097     }
01098   }
01099   return -1; // not found
01100 }
01101 
01102 
01103 void 
01104 PFBlockAlgo::checkDisplacedVertexLinks( reco::PFBlock& block ) const {
01105   // method which removes link between primary tracks and the clusters
01106   
01107   typedef std::multimap<double, unsigned>::iterator IE;
01108 
01109   const edm::OwnVector< reco::PFBlockElement >& els = block.elements();
01110   // loop on all elements != TRACK
01111   for( unsigned i1=0; i1 != els.size(); ++i1 ) {
01112     if( els[i1].type() == PFBlockElement::TRACK ) continue;
01113     std::multimap<double, unsigned> assocTracks;
01114     // get associated tracks
01115     block.associatedElements( i1,  block.linkData(),
01116                               assocTracks,
01117                               reco::PFBlockElement::TRACK,
01118                               reco::PFBlock::LINKTEST_ALL );
01119     for( IE ie = assocTracks.begin(); ie != assocTracks.end(); ++ie) {
01120       //double   distprim  = ie->first;
01121       unsigned iprim     = ie->second;
01122       // if this track a primary track (T_TO_DISP)
01123       // the new strategy gouzevitch: remove all the links from primary track
01124       if( els[iprim].isPrimary()) {
01125 
01126             block.setLink( i1, iprim, -1, block.linkData(),
01127                            PFBlock::LINKTEST_RECHIT );      
01128       }
01129     } // loop on all associated tracks
01130   } // loop on all elements
01131  
01132 }
01133 
01134