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