00001 #include <iostream>
00002 #include <vector>
00003 #include <memory>
00004
00005
00006 #include "FWCore/Framework/interface/Event.h"
00007 #include "FWCore/Framework/interface/EventSetup.h"
00008 #include "DataFormats/Common/interface/Handle.h"
00009 #include "FWCore/Framework/interface/ESHandle.h"
00010 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00011 #include "FWCore/Utilities/interface/Exception.h"
00012
00013 #include "DataFormats/EgammaReco/interface/BasicCluster.h"
00014 #include "DataFormats/EgammaReco/interface/SuperCluster.h"
00015 #include "DataFormats/CaloRecHit/interface/CaloCluster.h"
00016
00017
00018 #include "DataFormats/EgammaTrackReco/interface/TrackCaloClusterAssociation.h"
00019 #include "DataFormats/EgammaCandidates/interface/Photon.h"
00020 #include "DataFormats/EgammaCandidates/interface/PhotonFwd.h"
00021 #include "DataFormats/EgammaCandidates/interface/Conversion.h"
00022 #include "DataFormats/EgammaCandidates/interface/ConversionFwd.h"
00023 #include "DataFormats/TrackReco/interface/Track.h"
00024 #include "DataFormats/TrackReco/interface/TrackExtra.h"
00025 #include "DataFormats/VertexReco/interface/Vertex.h"
00026 #include "DataFormats/VertexReco/interface/VertexFwd.h"
00027
00028 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00029
00030 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00031
00032 #include "RecoEgamma/EgammaPhotonAlgos/interface/ConversionTrackEcalImpactPoint.h"
00033 #include "RecoEgamma/EgammaPhotonAlgos/interface/ConversionTrackPairFinder.h"
00034 #include "RecoEgamma/EgammaPhotonAlgos/interface/ConversionVertexFinder.h"
00035 #include "RecoEgamma/EgammaPhotonProducers/interface/ConvertedPhotonProducer.h"
00036
00037 #include "RecoTracker/Record/interface/CkfComponentsRecord.h"
00038 #include "RecoTracker/Record/interface/TrackerRecoGeometryRecord.h"
00039
00040 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
00041 #include "TrackingTools/TransientTrack/interface/TrackTransientTrack.h"
00042 #include "TrackingTools/PatternTools/interface/TwoTrackMinimumDistance.h"
00043 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
00044 #include "RecoEgamma/EgammaIsolationAlgos/interface/EgammaTowerIsolation.h"
00045
00046 ConvertedPhotonProducer::ConvertedPhotonProducer(const edm::ParameterSet& config) :
00047 conf_(config),
00048 theTrackPairFinder_(0),
00049 theVertexFinder_(0),
00050 theLikelihoodCalc_(0)
00051 {
00052
00053
00054
00055
00056
00057
00058
00059
00060 bcBarrelCollection_ = conf_.getParameter<edm::InputTag>("bcBarrelCollection");
00061 bcEndcapCollection_ = conf_.getParameter<edm::InputTag>("bcEndcapCollection");
00062
00063 scHybridBarrelProducer_ = conf_.getParameter<edm::InputTag>("scHybridBarrelProducer");
00064 scIslandEndcapProducer_ = conf_.getParameter<edm::InputTag>("scIslandEndcapProducer");
00065
00066 conversionOITrackProducer_ = conf_.getParameter<std::string>("conversionOITrackProducer");
00067 conversionIOTrackProducer_ = conf_.getParameter<std::string>("conversionIOTrackProducer");
00068
00069 outInTrackSCAssociationCollection_ = conf_.getParameter<std::string>("outInTrackSCAssociation");
00070 inOutTrackSCAssociationCollection_ = conf_.getParameter<std::string>("inOutTrackSCAssociation");
00071
00072 algoName_ = conf_.getParameter<std::string>( "AlgorithmName" );
00073
00074 hcalTowers_ = conf_.getParameter<edm::InputTag>("hcalTowers");
00075 hOverEConeSize_ = conf_.getParameter<double>("hOverEConeSize");
00076 maxHOverE_ = conf_.getParameter<double>("maxHOverE");
00077 minSCEt_ = conf_.getParameter<double>("minSCEt");
00078 recoverOneTrackCase_ = conf_.getParameter<bool>( "recoverOneTrackCase" );
00079 dRForConversionRecovery_ = conf_.getParameter<double>("dRForConversionRecovery");
00080 deltaCotCut_ = conf_.getParameter<double>("deltaCotCut");
00081 minApproachDisCut_ = conf_.getParameter<double>("minApproachDisCut");
00082
00083 maxNumOfCandidates_ = conf_.getParameter<int>("maxNumOfCandidates");
00084 risolveAmbiguity_ = conf_.getParameter<bool>("risolveConversionAmbiguity");
00085 likelihoodWeights_= conf_.getParameter<std::string>("MVA_weights_location");
00086
00087
00088
00089 ConvertedPhotonCollection_ = conf_.getParameter<std::string>("convertedPhotonCollection");
00090 CleanedConvertedPhotonCollection_ = conf_.getParameter<std::string>("cleanedConvertedPhotonCollection");
00091
00092
00093
00094 produces< reco::ConversionCollection >(ConvertedPhotonCollection_);
00095 produces< reco::ConversionCollection >(CleanedConvertedPhotonCollection_);
00096
00097
00098 theTrackPairFinder_ = new ConversionTrackPairFinder ();
00099 edm::FileInPath path_mvaWeightFile(likelihoodWeights_.c_str() );
00100 theLikelihoodCalc_ = new ConversionLikelihoodCalculator();
00101 theLikelihoodCalc_->setWeightsFile(path_mvaWeightFile.fullPath().c_str());
00102
00103 theVertexFinder_ = new ConversionVertexFinder ( conf_);
00104
00105
00106
00107 nEvt_=0;
00108
00109 }
00110
00111 ConvertedPhotonProducer::~ConvertedPhotonProducer() {
00112 delete theTrackPairFinder_;
00113 delete theLikelihoodCalc_;
00114 delete theVertexFinder_;
00115 }
00116
00117
00118
00119 void ConvertedPhotonProducer::beginRun (edm::Run& r, edm::EventSetup const & theEventSetup) {
00120
00121
00122
00123
00124 theEventSetup.get<IdealMagneticFieldRecord>().get(theMF_);
00125
00126
00127 theEventSetup.get<TransientTrackRecord>().get("TransientTrackBuilder",theTransientTrackBuilder_);
00128
00129
00130 }
00131
00132
00133 void ConvertedPhotonProducer::endRun (edm::Run& r, edm::EventSetup const & theEventSetup) {
00134 }
00135
00136
00137 void ConvertedPhotonProducer::endJob () {
00138
00139
00140
00141
00142
00143 }
00144
00145
00146
00147 void ConvertedPhotonProducer::produce(edm::Event& theEvent, const edm::EventSetup& theEventSetup) {
00148
00149 using namespace edm;
00150 nEvt_++;
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 reco::ConversionCollection outputConvPhotonCollection;
00161 std::auto_ptr<reco::ConversionCollection> outputConvPhotonCollection_p(new reco::ConversionCollection);
00162
00163 reco::ConversionCollection cleanedConversionCollection;
00164 std::auto_ptr<reco::ConversionCollection> cleanedConversionCollection_p(new reco::ConversionCollection);
00165
00166
00167
00168 bool validBarrelSCHandle=true;
00169 edm::Handle<edm::View<reco::CaloCluster> > scBarrelHandle;
00170 theEvent.getByLabel(scHybridBarrelProducer_,scBarrelHandle);
00171 if (!scBarrelHandle.isValid()) {
00172 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the product "<<scHybridBarrelProducer_.label();
00173 validBarrelSCHandle=false;
00174 }
00175
00176
00177 bool validEndcapSCHandle=true;
00178 edm::Handle<edm::View<reco::CaloCluster> > scEndcapHandle;
00179 theEvent.getByLabel(scIslandEndcapProducer_,scEndcapHandle);
00180 if (!scEndcapHandle.isValid()) {
00181 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the product "<<scIslandEndcapProducer_.label();
00182 validEndcapSCHandle=false;
00183 }
00184
00185
00187 bool validTrackInputs=true;
00188 Handle<reco::TrackCollection> outInTrkHandle;
00189 theEvent.getByLabel(conversionOITrackProducer_, outInTrkHandle);
00190 if (!outInTrkHandle.isValid()) {
00191
00192 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the conversionOITrack " << "\n";
00193 validTrackInputs=false;
00194 }
00195
00196
00197
00199 Handle<reco::TrackCaloClusterPtrAssociation> outInTrkSCAssocHandle;
00200 theEvent.getByLabel( conversionOITrackProducer_, outInTrackSCAssociationCollection_, outInTrkSCAssocHandle);
00201 if (!outInTrkSCAssocHandle.isValid()) {
00202
00203 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the product " << outInTrackSCAssociationCollection_.c_str() <<"\n";
00204 validTrackInputs=false;
00205 }
00206
00208 Handle<reco::TrackCollection> inOutTrkHandle;
00209 theEvent.getByLabel(conversionIOTrackProducer_, inOutTrkHandle);
00210 if (!inOutTrkHandle.isValid()) {
00211
00212 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the conversionIOTrack " << "\n";
00213 validTrackInputs=false;
00214 }
00215
00216
00217
00219
00220 Handle<reco::TrackCollection> generalTrkHandle;
00221 if ( recoverOneTrackCase_ ) {
00222 theEvent.getByLabel("generalTracks", generalTrkHandle);
00223 if (!generalTrkHandle.isValid()) {
00224
00225 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the genralTracks " << "\n";
00226 }
00227 }
00228
00230 Handle<reco::TrackCaloClusterPtrAssociation> inOutTrkSCAssocHandle;
00231 theEvent.getByLabel( conversionIOTrackProducer_, inOutTrackSCAssociationCollection_, inOutTrkSCAssocHandle);
00232 if (!inOutTrkSCAssocHandle.isValid()) {
00233
00234 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the product " << inOutTrackSCAssociationCollection_.c_str() <<"\n";
00235 validTrackInputs=false;
00236 }
00237
00238
00239
00240
00241
00242 bool validBarrelBCHandle=true;
00243 edm::Handle<edm::View<reco::CaloCluster> > bcBarrelHandle;
00244 theEvent.getByLabel( bcBarrelCollection_, bcBarrelHandle);
00245 if (!bcBarrelHandle.isValid()) {
00246 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the product "<<bcBarrelCollection_.label();
00247 validBarrelBCHandle=false;
00248 }
00249
00250
00251
00252 bool validEndcapBCHandle=true;
00253 edm::Handle<edm::View<reco::CaloCluster> > bcEndcapHandle;
00254 theEvent.getByLabel( bcEndcapCollection_, bcEndcapHandle);
00255 if (!bcEndcapHandle.isValid()) {
00256 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the product "<<bcEndcapCollection_.label();
00257 validEndcapBCHandle=true;
00258 }
00259
00260
00261
00262 Handle<CaloTowerCollection> hcalTowersHandle;
00263 theEvent.getByLabel(hcalTowers_, hcalTowersHandle);
00264
00265
00266 theEventSetup.get<CaloGeometryRecord>().get(theCaloGeom_);
00267
00268
00269 if ( validTrackInputs ) {
00270
00271 std::vector<reco::TransientTrack> t_outInTrk = ( *theTransientTrackBuilder_ ).build(outInTrkHandle );
00272 std::vector<reco::TransientTrack> t_inOutTrk = ( *theTransientTrackBuilder_ ).build(inOutTrkHandle );
00273
00274
00276
00277 std::map<std::vector<reco::TransientTrack>, reco::CaloClusterPtr> allPairs;
00278 allPairs = theTrackPairFinder_->run(t_outInTrk, outInTrkHandle, outInTrkSCAssocHandle, t_inOutTrk, inOutTrkHandle, inOutTrkSCAssocHandle );
00279
00280
00281 buildCollections(theEventSetup, scBarrelHandle, bcBarrelHandle, hcalTowersHandle, generalTrkHandle, allPairs, outputConvPhotonCollection);
00282 buildCollections(theEventSetup, scEndcapHandle, bcEndcapHandle, hcalTowersHandle, generalTrkHandle, allPairs, outputConvPhotonCollection);
00283 }
00284
00285
00286 outputConvPhotonCollection_p->assign(outputConvPhotonCollection.begin(),outputConvPhotonCollection.end());
00287
00288 const edm::OrphanHandle<reco::ConversionCollection> conversionHandle= theEvent.put( outputConvPhotonCollection_p, ConvertedPhotonCollection_);
00289
00290
00291
00292 if ( validBarrelSCHandle) cleanCollections(scBarrelHandle,
00293 conversionHandle,
00294 cleanedConversionCollection);
00295 if ( validEndcapSCHandle) cleanCollections(scEndcapHandle,
00296 conversionHandle,
00297 cleanedConversionCollection);
00298
00299
00300 cleanedConversionCollection_p->assign(cleanedConversionCollection.begin(),cleanedConversionCollection.end());
00301 theEvent.put( cleanedConversionCollection_p, CleanedConvertedPhotonCollection_);
00302
00303
00304 }
00305
00306
00307 void ConvertedPhotonProducer::buildCollections ( edm::EventSetup const & es,
00308 const edm::Handle<edm::View<reco::CaloCluster> > & scHandle,
00309 const edm::Handle<edm::View<reco::CaloCluster> > & bcHandle,
00310 const edm::Handle<CaloTowerCollection> & hcalTowersHandle,
00311 const edm::Handle<reco::TrackCollection> & generalTrkHandle,
00312 std::map<std::vector<reco::TransientTrack>, reco::CaloClusterPtr>& allPairs,
00313 reco::ConversionCollection & outputConvPhotonCollection)
00314
00315 {
00316
00317
00318 ConversionTrackEcalImpactPoint theEcalImpactPositionFinder( &(*theMF_) );
00319
00320
00321 reco::Conversion::ConversionAlgorithm algo = reco::Conversion::algoByName(algoName_);
00322
00323 std::vector<reco::TransientTrack> t_generalTrk;
00324 if ( recoverOneTrackCase_ ) t_generalTrk = ( *theTransientTrackBuilder_ ).build(generalTrkHandle );
00325
00326
00327
00328 int myCands=0;
00329 reco::CaloClusterPtrVector scPtrVec;
00330 for (unsigned i = 0; i < scHandle->size(); ++i ) {
00331 reco::CaloClusterPtr aClus= scHandle->ptrAt(i);
00332
00333
00334 if (aClus->energy()/cosh(aClus->eta()) <= minSCEt_) continue;
00335 const reco::CaloCluster* pClus=&(*aClus);
00336 const reco::SuperCluster* sc=dynamic_cast<const reco::SuperCluster*>(pClus);
00337 const CaloTowerCollection* hcalTowersColl = hcalTowersHandle.product();
00338 EgammaTowerIsolation towerIso(hOverEConeSize_,0.,0.,-1,hcalTowersColl) ;
00339 double HoE=towerIso.getTowerESum(sc)/sc->energy();
00340 if (HoE>=maxHOverE_) continue;
00342
00343
00344 std::vector<edm::Ref<reco::TrackCollection> > trackPairRef;
00345 std::vector<math::XYZPointF> trackInnPos;
00346 std::vector<math::XYZVectorF> trackPin;
00347 std::vector<math::XYZVectorF> trackPout;
00348 float minAppDist=-99;
00349
00350
00351
00352
00354 const reco::Particle::Point vtx( 0, 0, 0 );
00355 reco::Vertex theConversionVertex;
00356
00357 math::XYZVector direction =aClus->position() - vtx;
00358 math::XYZVector momentum = direction.unit() * aClus->energy();
00359 const reco::Particle::LorentzVector p4(momentum.x(), momentum.y(), momentum.z(), aClus->energy() );
00360
00361 int nFound=0;
00362 if ( allPairs.size() ) {
00363
00364 nFound=0;
00365
00366
00367 for ( std::map<std::vector<reco::TransientTrack>, reco::CaloClusterPtr>::const_iterator iPair= allPairs.begin(); iPair!= allPairs.end(); ++iPair ) {
00368 scPtrVec.clear();
00369
00370 reco::CaloClusterPtr caloPtr=iPair->second;
00371 if ( !( aClus == caloPtr ) ) continue;
00372
00373 scPtrVec.push_back(aClus);
00374 nFound++;
00375
00376 std::vector<math::XYZPointF> trkPositionAtEcal = theEcalImpactPositionFinder.find( iPair->first, bcHandle );
00377 std::vector<reco::CaloClusterPtr> matchingBC = theEcalImpactPositionFinder.matchingBC();
00378
00379
00380 minAppDist=-99;
00381 const std::string metname = "ConvertedPhotons|ConvertedPhotonProducer";
00382 if ( (iPair->first).size() > 1 ) {
00383 try{
00384
00385 theVertexFinder_->run(iPair->first, theConversionVertex );
00386
00387
00388 }
00389 catch ( cms::Exception& e ) {
00390
00391 edm::LogWarning(metname) << "cms::Exception caught in ConvertedPhotonProducer::produce\n"
00392 << e.explainSelf();
00393
00394 }
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00416 trackPairRef.clear();
00417 trackInnPos.clear();
00418 trackPin.clear();
00419 trackPout.clear();
00420
00421
00422 for ( std::vector<reco::TransientTrack>::const_iterator iTk=(iPair->first).begin(); iTk!= (iPair->first).end(); ++iTk) {
00423
00424
00425 const reco::TrackTransientTrack* ttt = dynamic_cast<const reco::TrackTransientTrack*>(iTk->basicTransientTrack());
00426 reco::TrackRef myTkRef= ttt->persistentTrackRef();
00427
00428
00429 if ( myTkRef->extra().isNonnull() ) {
00430 trackInnPos.push_back( toFConverterP(myTkRef->innerPosition()));
00431 trackPin.push_back( toFConverterV( myTkRef->innerMomentum()));
00432 trackPout.push_back( toFConverterV(myTkRef->outerMomentum()));
00433 }
00434 trackPairRef.push_back(myTkRef);
00435
00436 }
00437
00438
00439
00440
00441
00442 if( theConversionVertex.isValid() ) {
00443
00444
00445
00446 }
00447
00448
00449
00450 minAppDist=calculateMinApproachDistance( trackPairRef[0], trackPairRef[1]);
00451
00452 double like = -999.;
00453 reco::Conversion newCandidate(scPtrVec, trackPairRef, trkPositionAtEcal, theConversionVertex, matchingBC, minAppDist, trackInnPos, trackPin, trackPout, like, algo);
00454
00455 like = theLikelihoodCalc_->calculateLikelihood( newCandidate );
00456
00457 newCandidate.setMVAout(like);
00458 outputConvPhotonCollection.push_back(newCandidate);
00459
00460
00461 myCands++;
00462
00463
00464 } else {
00465
00466
00467
00468
00469
00470 trackPairRef.clear();
00471 trackInnPos.clear();
00472 trackPin.clear();
00473 trackPout.clear();
00474 std::vector<reco::TransientTrack>::const_iterator iTk=(iPair->first).begin();
00475
00476 const reco::TrackTransientTrack* ttt = dynamic_cast<const reco::TrackTransientTrack*>(iTk->basicTransientTrack());
00477 reco::TrackRef myTk= ttt->persistentTrackRef();
00478 if ( myTk->extra().isNonnull() ) {
00479 trackInnPos.push_back( toFConverterP(myTk->innerPosition()));
00480 trackPin.push_back( toFConverterV(myTk->innerMomentum()));
00481 trackPout.push_back( toFConverterV(myTk->outerMomentum()));
00482 }
00483 trackPairRef.push_back(myTk);
00484
00485
00486 if ( recoverOneTrackCase_ ) {
00487 float theta1 = myTk->innerMomentum().Theta();
00488 float dCot=999.;
00489 float dCotTheta=-999.;
00490 reco::TrackRef goodRef;
00491 std::vector<reco::TransientTrack>::const_iterator iGoodGenTran;
00492 for ( std::vector<reco::TransientTrack>::const_iterator iTran= t_generalTrk.begin(); iTran != t_generalTrk.end(); ++iTran) {
00493 const reco::TrackTransientTrack* ttt = dynamic_cast<const reco::TrackTransientTrack*>(iTran->basicTransientTrack());
00494 reco::TrackRef trRef= ttt->persistentTrackRef();
00495 if ( trRef->charge()*myTk->charge() > 0 ) continue;
00496 float dEta = trRef->eta() - myTk->eta();
00497 float dPhi = trRef->phi() - myTk->phi();
00498 if ( sqrt (dEta*dEta + dPhi*dPhi) > dRForConversionRecovery_ ) continue;
00499 float theta2 = trRef->innerMomentum().Theta();
00500 dCotTheta = 1./tan(theta1) - 1./tan(theta2) ;
00501
00502 if ( fabs(dCotTheta) < dCot ) {
00503 dCot = fabs(dCotTheta);
00504 goodRef = trRef;
00505 iGoodGenTran=iTran;
00506 }
00507 }
00508
00509 if ( goodRef.isNonnull() ) {
00510
00511 minAppDist=calculateMinApproachDistance( myTk, goodRef);
00512
00513
00514 if ( fabs(dCotTheta) < deltaCotCut_ && minAppDist > minApproachDisCut_ ) {
00515 trackInnPos.push_back( toFConverterP(goodRef->innerPosition()));
00516 trackPin.push_back( toFConverterV(goodRef->innerMomentum()));
00517 trackPout.push_back( toFConverterV(goodRef->outerMomentum()));
00518 trackPairRef.push_back( goodRef );
00519
00520
00521 std::vector<reco::TransientTrack> mypair;
00522 mypair.push_back(*iTk);
00523 mypair.push_back(*iGoodGenTran);
00524
00525 try{
00526 theVertexFinder_->run(iPair->first, theConversionVertex );
00527
00528 }
00529 catch ( cms::Exception& e ) {
00530
00531 edm::LogWarning(metname) << "cms::Exception caught in ConvertedPhotonProducer::produce\n"
00532 << e.explainSelf();
00533
00534 }
00535 }
00536
00537 }
00538
00539 }
00540 double like = -999.;
00541 reco::Conversion newCandidate(scPtrVec, trackPairRef, trkPositionAtEcal, theConversionVertex, matchingBC, minAppDist, trackInnPos, trackPin, trackPout, like, algo);
00542 like = theLikelihoodCalc_->calculateLikelihood(newCandidate);
00543 newCandidate.setMVAout(like);
00544 outputConvPhotonCollection.push_back(newCandidate);
00545
00546
00547
00548
00549 }
00550
00551
00552
00553
00554 }
00555
00556 }
00557
00558
00559
00560
00561 }
00562
00563
00564
00565
00566
00567 }
00568
00569
00570 void ConvertedPhotonProducer::cleanCollections(const edm::Handle<edm::View<reco::CaloCluster> > & scHandle,
00571 const edm::OrphanHandle<reco::ConversionCollection> & conversionHandle,
00572 reco::ConversionCollection & outputConversionCollection) {
00573
00574
00575 reco::Conversion* newCandidate=0;
00576 for(unsigned int lSC=0; lSC < scHandle->size(); lSC++) {
00577
00578
00579 reco::CaloClusterPtr aClus= scHandle->ptrAt(lSC);
00580
00581
00582 if (aClus->energy()/cosh(aClus->eta()) <= minSCEt_) continue;
00583
00584
00585 if ( conversionHandle.isValid() ) {
00586
00587 if ( risolveAmbiguity_ ) {
00588 std::vector<reco::ConversionRef> bestRef=solveAmbiguity( conversionHandle , aClus);
00589
00590 for ( std::vector<reco::ConversionRef>::iterator iRef=bestRef.begin(); iRef!=bestRef.end(); iRef++ ) {
00591 if ( iRef->isNonnull() ) {
00592 newCandidate= (*iRef)->clone();
00593 outputConversionCollection.push_back(*newCandidate);
00594 delete newCandidate;
00595 }
00596 }
00597
00598 } else {
00599
00600
00601 for( unsigned int icp = 0; icp < conversionHandle->size(); icp++) {
00602 reco::ConversionRef cpRef(reco::ConversionRef(conversionHandle,icp));
00603 if (!( aClus.id() == cpRef->caloCluster()[0].id() && aClus.key() == cpRef->caloCluster()[0].key() )) continue;
00604 if ( !cpRef->isConverted() ) continue;
00605 if ( cpRef->nTracks() <2 ) continue;
00606 newCandidate= (&(*cpRef))->clone();
00607 outputConversionCollection.push_back(*newCandidate);
00608 delete newCandidate;
00609
00610 }
00611
00612 }
00613
00614 }
00615
00616
00617 }
00618 }
00619
00620
00621
00622
00623 std::vector<reco::ConversionRef> ConvertedPhotonProducer::solveAmbiguity(const edm::OrphanHandle<reco::ConversionCollection> & conversionHandle, reco::CaloClusterPtr& scRef) {
00624 std::multimap<double, reco::ConversionRef, std::greater<double> > convMap;
00625
00626 for ( unsigned int icp=0; icp< conversionHandle->size(); icp++) {
00627 reco::ConversionRef cpRef(reco::ConversionRef(conversionHandle,icp));
00628
00629
00630 if (!( scRef.id() == cpRef->caloCluster()[0].id() && scRef.key() == cpRef->caloCluster()[0].key() )) continue;
00631 if ( !cpRef->isConverted() ) continue;
00632 double like = cpRef->MVAout();
00633 if ( cpRef->nTracks() <2 ) continue;
00634
00635 convMap.insert ( std::make_pair(like,cpRef) );
00636
00637 }
00638
00639
00640
00641 std::multimap<double, reco::ConversionRef>::iterator iMap;
00642 std::vector<reco::ConversionRef> bestRefs;
00643 for (iMap=convMap.begin(); iMap!=convMap.end(); iMap++) {
00644
00645 bestRefs.push_back( iMap->second );
00646 if ( int(bestRefs.size()) == maxNumOfCandidates_ ) break;
00647 }
00648
00649
00650 return bestRefs;
00651
00652
00653 }
00654
00655
00656
00657
00658
00659 float ConvertedPhotonProducer::calculateMinApproachDistance ( const reco::TrackRef& track1, const reco::TrackRef& track2) {
00660 float dist=9999.;
00661
00662 double x1, x2, y1, y2;
00663 double xx_1 = track1->innerPosition().x(), yy_1 = track1->innerPosition().y(), zz_1 = track1->innerPosition().z();
00664 double xx_2 = track2->innerPosition().x(), yy_2 = track2->innerPosition().y(), zz_2 = track2->innerPosition().z();
00665 double radius1 = track1->innerMomentum().Rho()/(.3*(theMF_->inTesla(GlobalPoint(xx_1, yy_1, zz_1)).z()))*100;
00666 double radius2 = track2->innerMomentum().Rho()/(.3*(theMF_->inTesla(GlobalPoint(xx_2, yy_2, zz_2)).z()))*100;
00667 getCircleCenter(track1, radius1, x1, y1);
00668 getCircleCenter(track2, radius2, x2, y2);
00669 dist = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) - radius1 - radius2;
00670
00671 return dist;
00672
00673 }
00674
00675
00676 void ConvertedPhotonProducer::getCircleCenter(const reco::TrackRef& tk, double r, double& x0, double& y0){
00677 double x1, y1, phi;
00678 x1 = tk->innerPosition().x();
00679 y1 = tk->innerPosition().y();
00680 phi = tk->innerMomentum().phi();
00681 const int charge = tk->charge();
00682 x0 = x1 + r*sin(phi)*charge;
00683 y0 = y1 - r*cos(phi)*charge;
00684
00685 }