CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC4_patch1/src/RecoEgamma/EgammaPhotonProducers/src/ConvertedPhotonProducer.cc

Go to the documentation of this file.
00001 #include <iostream>
00002 #include <vector>
00003 #include <memory>
00004 
00005 // Framework
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   //cout<< " ConvertedPhotonProducer CTOR " << "\n";
00056   
00057   
00058   
00059   // use onfiguration file to setup input collection names
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   // use onfiguration file to setup output collection names
00089   ConvertedPhotonCollection_     = conf_.getParameter<std::string>("convertedPhotonCollection");
00090   CleanedConvertedPhotonCollection_     = conf_.getParameter<std::string>("cleanedConvertedPhotonCollection");
00091   
00092   
00093   // Register the product
00094   produces< reco::ConversionCollection >(ConvertedPhotonCollection_);
00095   produces< reco::ConversionCollection >(CleanedConvertedPhotonCollection_);
00096   
00097   // instantiate the Track Pair Finder algorithm
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   // instantiate the Vertex Finder algorithm
00103   theVertexFinder_ = new ConversionVertexFinder ( conf_);
00104 
00105 
00106   // Inizilize my global event counter
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     //get magnetic field
00123   //edm::LogInfo("ConvertedPhotonProducer") << " get magnetic field" << "\n";
00124   theEventSetup.get<IdealMagneticFieldRecord>().get(theMF_);  
00125 
00126   // Transform Track into TransientTrack (needed by the Vertex fitter)
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   //LogDebug("ConvertedPhotonProducer") << "ConvertedPhotonProducer::endJob Processed " << nEvt_ << " events " << "\n";
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   //  LogDebug("ConvertedPhotonProducer")   << "ConvertedPhotonProduce::produce event number " <<   theEvent.id() << " Global counter " << nEvt_ << "\n";
00154   //  std::cout    << "ConvertedPhotonProduce::produce event number " <<   theEvent.id() << " Global counter " << nEvt_ << "\n";
00155   
00156   //
00157   // create empty output collections
00158   //
00159   // Converted photon candidates
00160   reco::ConversionCollection outputConvPhotonCollection;
00161   std::auto_ptr<reco::ConversionCollection> outputConvPhotonCollection_p(new reco::ConversionCollection);
00162   // Converted photon candidates
00163   reco::ConversionCollection cleanedConversionCollection;
00164   std::auto_ptr<reco::ConversionCollection> cleanedConversionCollection_p(new reco::ConversionCollection);
00165 
00166   
00167   // Get the Super Cluster collection in the Barrel
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   // Get the Super Cluster collection in the Endcap
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     //std::cout << "Error! Can't get the conversionOITrack " << "\n";
00192     edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the conversionOITrack " << "\n";
00193     validTrackInputs=false;
00194   }
00195   //  LogDebug("ConvertedPhotonProducer")<< "ConvertedPhotonProducer  outInTrack collection size " << (*outInTrkHandle).size() << "\n";
00196   
00197    
00199   Handle<reco::TrackCaloClusterPtrAssociation> outInTrkSCAssocHandle;
00200   theEvent.getByLabel( conversionOITrackProducer_, outInTrackSCAssociationCollection_, outInTrkSCAssocHandle);
00201   if (!outInTrkSCAssocHandle.isValid()) {
00202     //  std::cout << "Error! Can't get the product " <<  outInTrackSCAssociationCollection_.c_str() <<"\n";
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     // std::cout << "Error! Can't get the conversionIOTrack " << "\n";
00212     edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the conversionIOTrack " << "\n";
00213     validTrackInputs=false;
00214   }
00215   //  LogDebug("ConvertedPhotonProducer") << " ConvertedPhotonProducer inOutTrack collection size " << (*inOutTrkHandle).size() << "\n";
00216 
00217 
00219 
00220   Handle<reco::TrackCollection> generalTrkHandle;
00221   if (  recoverOneTrackCase_ ) {
00222     theEvent.getByLabel("generalTracks", generalTrkHandle);
00223     if (!generalTrkHandle.isValid()) {
00224       //std::cout << "Error! Can't get the genralTracks " << "\n";
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     //std::cout << "Error! Can't get the product " <<  inOutTrackSCAssociationCollection_.c_str() <<"\n";
00234     edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the product " <<  inOutTrackSCAssociationCollection_.c_str() <<"\n";
00235     validTrackInputs=false;
00236   }
00237 
00238 
00239   
00240 
00241   // Get the basic cluster collection in the Barrel 
00242   edm::Handle<edm::View<reco::CaloCluster> > bcBarrelHandle;
00243   theEvent.getByLabel( bcBarrelCollection_, bcBarrelHandle);
00244   if (!bcBarrelHandle.isValid()) {
00245     edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the product "<<bcBarrelCollection_.label();
00246   }
00247 
00248     
00249   // Get the basic cluster collection in the Endcap 
00250   edm::Handle<edm::View<reco::CaloCluster> > bcEndcapHandle;
00251   theEvent.getByLabel( bcEndcapCollection_, bcEndcapHandle);
00252   if (!bcEndcapHandle.isValid()) {
00253     edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the product "<<bcEndcapCollection_.label();
00254   }
00255  
00256 
00257 // get Hcal towers collection 
00258   Handle<CaloTowerCollection> hcalTowersHandle;
00259   theEvent.getByLabel(hcalTowers_, hcalTowersHandle);
00260 
00261   // get the geometry from the event setup:
00262   theEventSetup.get<CaloGeometryRecord>().get(theCaloGeom_);
00263 
00264 
00265   if (  validTrackInputs ) {
00266     //do the conversion:
00267     std::vector<reco::TransientTrack> t_outInTrk = ( *theTransientTrackBuilder_ ).build(outInTrkHandle );
00268     std::vector<reco::TransientTrack> t_inOutTrk = ( *theTransientTrackBuilder_ ).build(inOutTrkHandle );
00269     
00270     
00272     std::map<std::vector<reco::TransientTrack>, reco::CaloClusterPtr, CompareTwoTracksVectors> allPairs;
00273     allPairs = theTrackPairFinder_->run(t_outInTrk, outInTrkHandle, outInTrkSCAssocHandle, t_inOutTrk, inOutTrkHandle, inOutTrkSCAssocHandle  );
00274     //LogDebug("ConvertedPhotonProducer")  << "ConvertedPhotonProducer  allPairs.size " << allPairs.size() << "\n";      
00275 
00276     buildCollections(theEventSetup, scBarrelHandle, bcBarrelHandle, hcalTowersHandle, generalTrkHandle, allPairs, outputConvPhotonCollection);
00277     buildCollections(theEventSetup, scEndcapHandle, bcEndcapHandle, hcalTowersHandle, generalTrkHandle, allPairs, outputConvPhotonCollection);
00278   }
00279   
00280   // put the product in the event
00281   outputConvPhotonCollection_p->assign(outputConvPhotonCollection.begin(),outputConvPhotonCollection.end());
00282   //LogDebug("ConvertedPhotonProducer") << " ConvertedPhotonProducer Putting in the event    converted photon candidates " << (*outputConvPhotonCollection_p).size() << "\n";  
00283   const edm::OrphanHandle<reco::ConversionCollection> conversionHandle= theEvent.put( outputConvPhotonCollection_p, ConvertedPhotonCollection_);
00284 
00285 
00286   // Loop over barrel and endcap SC collections and fill the  photon collection
00287   if ( validBarrelSCHandle) cleanCollections(scBarrelHandle,
00288                                              conversionHandle,
00289                                              cleanedConversionCollection);
00290   if ( validEndcapSCHandle) cleanCollections(scEndcapHandle,
00291                                              conversionHandle,
00292                                              cleanedConversionCollection);
00293                                                 
00294 
00295   cleanedConversionCollection_p->assign(cleanedConversionCollection.begin(),cleanedConversionCollection.end());   
00296   theEvent.put( cleanedConversionCollection_p, CleanedConvertedPhotonCollection_);
00297 
00298   
00299 }
00300 
00301 
00302 void ConvertedPhotonProducer::buildCollections ( edm::EventSetup const & es,  
00303                                                  const edm::Handle<edm::View<reco::CaloCluster> > & scHandle,
00304                                                  const edm::Handle<edm::View<reco::CaloCluster> > & bcHandle,
00305                                                  const edm::Handle<CaloTowerCollection> & hcalTowersHandle, 
00306                                                  const edm::Handle<reco::TrackCollection>  & generalTrkHandle,
00307                                                  std::map<std::vector<reco::TransientTrack>, reco::CaloClusterPtr, CompareTwoTracksVectors>& allPairs,
00308                                                  reco::ConversionCollection & outputConvPhotonCollection)
00309 
00310 {
00311 
00312  // instantiate the algorithm for finding the position of the track extrapolation at the Ecal front face
00313   ConversionTrackEcalImpactPoint theEcalImpactPositionFinder( &(*theMF_) );
00314   
00315 
00316   reco::Conversion::ConversionAlgorithm algo = reco::Conversion::algoByName(algoName_);
00317  
00318   std::vector<reco::TransientTrack> t_generalTrk;
00319   if (  recoverOneTrackCase_ )  t_generalTrk = ( *theTransientTrackBuilder_ ).build(generalTrkHandle );
00320   //const CaloGeometry* geometry = theCaloGeom_.product(); 
00321 
00322   //  Loop over SC in the barrel and reconstruct converted photons
00323   int myCands=0;
00324   reco::CaloClusterPtrVector scPtrVec;
00325   for (unsigned i = 0; i < scHandle->size(); ++i ) {
00326     reco::CaloClusterPtr aClus= scHandle->ptrAt(i);
00327 
00328     // preselection based in Et and H/E cut
00329     if (aClus->energy()/cosh(aClus->eta()) <= minSCEt_) continue;
00330     const reco::CaloCluster* pClus=&(*aClus);
00331     const reco::SuperCluster*  sc=dynamic_cast<const reco::SuperCluster*>(pClus);
00332     const CaloTowerCollection* hcalTowersColl = hcalTowersHandle.product();
00333     EgammaTowerIsolation towerIso(hOverEConeSize_,0.,0.,-1,hcalTowersColl) ;
00334     double HoE=towerIso.getTowerESum(sc)/sc->energy();
00335     if (HoE>=maxHOverE_)  continue;
00337 
00338 
00339     std::vector<edm::Ref<reco::TrackCollection> > trackPairRef;
00340     std::vector<math::XYZPointF> trackInnPos;
00341     std::vector<math::XYZVectorF> trackPin;
00342     std::vector<math::XYZVectorF> trackPout;
00343     float minAppDist=-99;
00344 
00345     //LogDebug("ConvertedPhotonProducer") << "ConvertedPhotonProducer SC energy " << aClus->energy() << " eta " <<  aClus->eta() << " phi " <<  aClus->phi() << "\n";
00346 
00347     
00349     const reco::Particle::Point  vtx( 0, 0, 0 );
00350 
00351    
00352     math::XYZVector direction =aClus->position() - vtx;
00353     math::XYZVector momentum = direction.unit() * aClus->energy();
00354     const reco::Particle::LorentzVector  p4(momentum.x(), momentum.y(), momentum.z(), aClus->energy() );
00355     
00356     int nFound=0;    
00357     if ( allPairs.size() ) {
00358 
00359       nFound=0;
00360 
00361 
00362       for (  std::map<std::vector<reco::TransientTrack>, reco::CaloClusterPtr>::const_iterator iPair= allPairs.begin(); iPair!= allPairs.end(); ++iPair ) {
00363         scPtrVec.clear();
00364 
00365         reco::Vertex  theConversionVertex;       
00366         reco::CaloClusterPtr caloPtr=iPair->second;
00367         if ( !( aClus == caloPtr ) ) continue;
00368             
00369         scPtrVec.push_back(aClus);     
00370         nFound++;
00371 
00372         std::vector<math::XYZPointF> trkPositionAtEcal = theEcalImpactPositionFinder.find(  iPair->first, bcHandle );
00373         std::vector<reco::CaloClusterPtr>  matchingBC = theEcalImpactPositionFinder.matchingBC();
00374         
00375 
00376         minAppDist=-99;
00377         const std::string metname = "ConvertedPhotons|ConvertedPhotonProducer";
00378         if ( (iPair->first).size()  > 1 ) {
00379           try{
00380             
00381             theVertexFinder_->run(iPair->first, theConversionVertex ); 
00382             
00383             
00384           }
00385           catch ( cms::Exception& e ) {
00386             //std::cout << " cms::Exception caught in ConvertedPhotonProducer::produce" << "\n" ;
00387             edm::LogWarning(metname) << "cms::Exception caught in ConvertedPhotonProducer::produce\n"
00388                                      << e.explainSelf();
00389             
00390           }
00391          
00392           // Old TwoTrackMinimumDistance md;
00393           // Old md.calculate  (  (iPair->first)[0].initialFreeState(),  (iPair->first)[1].initialFreeState() );
00394           // Old minAppDist = md.distance(); 
00395  
00396         
00397         
00398 
00399         
00400         
00401 
00402         /*
00403         for ( unsigned int i=0; i< matchingBC.size(); ++i) {
00404           if (  matchingBC[i].isNull() )  std::cout << " This ref to BC is null: skipping " <<  "\n";
00405           else 
00406             std::cout << " BC energy " << matchingBC[i]->energy() <<  "\n";
00407         }
00408         */
00409 
00410 
00412         trackPairRef.clear();
00413         trackInnPos.clear();
00414         trackPin.clear();
00415         trackPout.clear();
00416       
00417         
00418         for ( std::vector<reco::TransientTrack>::const_iterator iTk=(iPair->first).begin(); iTk!= (iPair->first).end(); ++iTk) {
00419           //LogDebug("ConvertedPhotonProducer")  << "  ConvertedPhotonProducer Transient Tracks in the pair  charge " << iTk->charge() << " Num of RecHits " << iTk->recHitsSize() << " inner momentum " << iTk->track().innerMomentum() << "\n";  
00420           
00421           const reco::TrackTransientTrack* ttt = dynamic_cast<const reco::TrackTransientTrack*>(iTk->basicTransientTrack());
00422           reco::TrackRef myTkRef= ttt->persistentTrackRef(); 
00423           
00424           //LogDebug("ConvertedPhotonProducer")  << " ConvertedPhotonProducer Ref to Rec Tracks in the pair  charge " << myTkRef->charge() << " Num of RecHits " << myTkRef->recHitsSize() << " inner momentum " << myTkRef->innerMomentum() << "\n";  
00425           if ( myTkRef->extra().isNonnull() ) {
00426             trackInnPos.push_back(  toFConverterP(myTkRef->innerPosition()));
00427             trackPin.push_back(  toFConverterV( myTkRef->innerMomentum()));
00428             trackPout.push_back(  toFConverterV(myTkRef->outerMomentum()));
00429           }
00430           trackPairRef.push_back(myTkRef);
00431           
00432         }
00433         
00434         //      std::cout << " ConvertedPhotonProducer trackPin size " << trackPin.size() << std::endl;
00435         //LogDebug("ConvertedPhotonProducer")  << " ConvertedPhotonProducer SC energy " <<  aClus->energy() << "\n";
00436         //LogDebug("ConvertedPhotonProducer") << " ConvertedPhotonProducer photon p4 " << p4  << "\n";
00437         //LogDebug("ConvertedPhotonProducer") << " ConvertedPhotonProducer vtx " << vtx.x() << " " << vtx.y() << " " << vtx.z() << "\n";
00438         if( theConversionVertex.isValid() ) {
00439           
00440           //LogDebug("ConvertedPhotonProducer") << " ConvertedPhotonProducer theConversionVertex " << theConversionVertex.position().x() << " " << theConversionVertex.position().y() << " " << theConversionVertex.position().z() << "\n";
00441           
00442         }
00443         //LogDebug("ConvertedPhotonProducer") << " ConvertedPhotonProducer trackPairRef  " << trackPairRef.size() <<  "\n";
00444 
00445         
00446         minAppDist=calculateMinApproachDistance( trackPairRef[0],  trackPairRef[1]);
00447 
00448         double like = -999.;
00449         reco::Conversion  newCandidate(scPtrVec,  trackPairRef,  trkPositionAtEcal, theConversionVertex, matchingBC,  minAppDist, trackInnPos, trackPin, trackPout, like, algo);
00450 //    like = theLikelihoodCalc_->calculateLikelihood(newCandidate, es );
00451         like = theLikelihoodCalc_->calculateLikelihood( newCandidate );
00452 //    std::cout << "like = " << like << std::endl;
00453     newCandidate.setMVAout(like);
00454         outputConvPhotonCollection.push_back(newCandidate);
00455         
00456         
00457         myCands++;
00458         //LogDebug("ConvertedPhotonProducer") << " ConvertedPhotonProducer Put the ConvertedPhotonCollection a candidate in the Barrel " << "\n";
00459         
00460         } else {
00461           
00462           
00463           //      std::cout << "   ConvertedPhotonProducer case with only one track found " <<  "\n";
00464  
00465             //std::cout << "   ConvertedPhotonProducer recovering one track " <<  "\n";
00466             trackPairRef.clear();
00467             trackInnPos.clear();
00468             trackPin.clear();
00469             trackPout.clear();
00470             std::vector<reco::TransientTrack>::const_iterator iTk=(iPair->first).begin();
00471             //std::cout  << "  ConvertedPhotonProducer Transient Tracks in the pair  charge " << iTk->charge() << " Num of RecHits " << iTk->recHitsSize() << " inner momentum " << iTk->track().innerMomentum() << " pt " << sqrt(iTk->track().innerMomentum().perp2()) << "\n";         
00472             const reco::TrackTransientTrack* ttt = dynamic_cast<const reco::TrackTransientTrack*>(iTk->basicTransientTrack());
00473             reco::TrackRef myTk= ttt->persistentTrackRef(); 
00474             if ( myTk->extra().isNonnull() ) {
00475               trackInnPos.push_back(  toFConverterP(myTk->innerPosition()));
00476               trackPin.push_back(  toFConverterV(myTk->innerMomentum()));
00477               trackPout.push_back(  toFConverterV(myTk->outerMomentum()));
00478             }
00479             trackPairRef.push_back(myTk);
00480             //std::cout << " Provenance " << myTk->algoName() << std::endl;
00481         
00482             if (  recoverOneTrackCase_ ) {    
00483               float theta1 = myTk->innerMomentum().Theta();
00484               float dCot=999.;
00485               float dCotTheta=-999.;
00486               reco::TrackRef goodRef;
00487               std::vector<reco::TransientTrack>::const_iterator iGoodGenTran;
00488               for ( std::vector<reco::TransientTrack>::const_iterator iTran= t_generalTrk.begin(); iTran != t_generalTrk.end(); ++iTran) {
00489                 const reco::TrackTransientTrack* ttt = dynamic_cast<const reco::TrackTransientTrack*>(iTran->basicTransientTrack());
00490                 reco::TrackRef trRef= ttt->persistentTrackRef(); 
00491                 if ( trRef->charge()*myTk->charge() > 0 ) continue;
00492                 float dEta =  trRef->eta() - myTk->eta();
00493                 float dPhi =  trRef->phi() - myTk->phi();
00494                 if ( sqrt (dEta*dEta + dPhi*dPhi) > dRForConversionRecovery_ ) continue; 
00495                 float theta2 = trRef->innerMomentum().Theta();
00496                 dCotTheta =  1./tan(theta1) - 1./tan(theta2) ;
00497                 //      std::cout << "  ConvertedPhotonProducer recovering general transient track charge " << trRef->charge() << " momentum " << trRef->innerMomentum() << " dcotTheta " << fabs(dCotTheta) << std::endl;
00498                 if ( fabs(dCotTheta) < dCot ) {
00499                   dCot = fabs(dCotTheta);
00500                   goodRef = trRef;
00501                   iGoodGenTran=iTran;
00502                 }
00503               }
00504               
00505               if ( goodRef.isNonnull() ) {
00506                 
00507                 minAppDist=calculateMinApproachDistance( myTk, goodRef);
00508                 
00509                 // std::cout << "  ConvertedPhotonProducer chosen dCotTheta " <<  fabs(dCotTheta) << std::endl;
00510                 if ( fabs(dCotTheta) < deltaCotCut_ && minAppDist > minApproachDisCut_ ) {
00511                   trackInnPos.push_back(  toFConverterP(goodRef->innerPosition()));     
00512                   trackPin.push_back(  toFConverterV(goodRef->innerMomentum()));
00513                   trackPout.push_back(  toFConverterV(goodRef->outerMomentum()));
00514                   trackPairRef.push_back( goodRef );
00515                   //        std::cout << " ConvertedPhotonProducer adding opposite charge track from generalTrackCollection charge " <<  goodRef ->charge() << " pt " << sqrt(goodRef->innerMomentum().perp2())  << " trackPairRef size " << trackPairRef.size() << std::endl;            
00516                   //std::cout << " Track Provenenance " << goodRef->algoName() << std::endl; 
00517                   std::vector<reco::TransientTrack> mypair;
00518                   mypair.push_back(*iTk); 
00519                   mypair.push_back(*iGoodGenTran); 
00520                   
00521                   try{
00522                     theVertexFinder_->run(iPair->first, theConversionVertex ); 
00523                     
00524                   }
00525                   catch ( cms::Exception& e ) {
00526                     //std::cout << " cms::Exception caught in ConvertedPhotonProducer::produce" << "\n" ;
00527                     edm::LogWarning(metname) << "cms::Exception caught in ConvertedPhotonProducer::produce\n"
00528                                              << e.explainSelf();
00529                     
00530                   }
00531                 } 
00532                 
00533               }     
00534               
00535             } // bool On/Off one track case recovery using generalTracks  
00536             double like = -999.;
00537             reco::Conversion  newCandidate(scPtrVec,  trackPairRef,  trkPositionAtEcal, theConversionVertex, matchingBC,  minAppDist, trackInnPos, trackPin, trackPout, like, algo);
00538             like = theLikelihoodCalc_->calculateLikelihood(newCandidate);
00539             newCandidate.setMVAout(like);
00540             outputConvPhotonCollection.push_back(newCandidate);
00541               
00542               
00543               
00544             
00545         } // case with only on track: looking in general tracks
00546         
00547         
00548         
00549         
00550       } 
00551       
00552     }
00553     
00554 
00555 
00556     
00557   }
00558   
00559 
00560 
00561 
00562 
00563 }
00564 
00565 
00566 void ConvertedPhotonProducer::cleanCollections(const edm::Handle<edm::View<reco::CaloCluster> > & scHandle,
00567                                               const edm::OrphanHandle<reco::ConversionCollection> & conversionHandle,
00568                                               reco::ConversionCollection & outputConversionCollection) {
00569 
00570 
00571   reco::Conversion* newCandidate=0;
00572   for(unsigned int lSC=0; lSC < scHandle->size(); lSC++) {
00573     
00574     // get pointer to SC
00575     reco::CaloClusterPtr aClus= scHandle->ptrAt(lSC);    
00576         
00577     // SC energy preselection
00578     if (aClus->energy()/cosh(aClus->eta()) <= minSCEt_) continue;
00579 
00580 
00581     if (  conversionHandle.isValid() ) {
00582 
00583       if ( risolveAmbiguity_ ) {
00584         std::vector<reco::ConversionRef> bestRef=solveAmbiguity( conversionHandle , aClus);
00585    
00586         for ( std::vector<reco::ConversionRef>::iterator iRef=bestRef.begin(); iRef!=bestRef.end(); iRef++ ) {
00587           if ( iRef->isNonnull() )  {
00588             newCandidate= (*iRef)->clone();
00589             outputConversionCollection.push_back(*newCandidate);
00590             delete newCandidate;
00591           }
00592         }
00593         
00594       } else {
00595         
00596 
00597         for( unsigned int icp = 0;  icp < conversionHandle->size(); icp++) {
00598           reco::ConversionRef cpRef(reco::ConversionRef(conversionHandle,icp));
00599           if (!( aClus.id() == cpRef->caloCluster()[0].id() && aClus.key() == cpRef->caloCluster()[0].key() )) continue; 
00600           if ( !cpRef->isConverted() ) continue;  
00601           if ( cpRef->nTracks() <2 ) continue;
00602           newCandidate= (&(*cpRef))->clone();    
00603           outputConversionCollection.push_back(*newCandidate);
00604           delete newCandidate;
00605 
00606         }         
00607         
00608       } // solve or not the ambiguity of many conversion candidates     
00609         
00610     }     
00611 
00612    
00613   }    
00614 }
00615 
00616 
00617 
00618 
00619 std::vector<reco::ConversionRef>  ConvertedPhotonProducer::solveAmbiguity(const edm::OrphanHandle<reco::ConversionCollection> & conversionHandle, reco::CaloClusterPtr& scRef) {
00620   std::multimap<double, reco::ConversionRef, std::greater<double> >   convMap;
00621 
00622   for ( unsigned int icp=0; icp< conversionHandle->size(); icp++) {
00623     reco::ConversionRef cpRef(reco::ConversionRef(conversionHandle,icp));
00624     
00625     //std::cout << " cpRef " << cpRef->nTracks() << " " <<  cpRef ->caloCluster()[0]->energy() << std::endl;    
00626     if (!( scRef.id() == cpRef->caloCluster()[0].id() && scRef.key() == cpRef->caloCluster()[0].key() )) continue;    
00627     if ( !cpRef->isConverted() ) continue;  
00628     double like = cpRef->MVAout();
00629     if ( cpRef->nTracks() <2 ) continue;
00630     //    std::cout << " Like " << like << std::endl;
00631     convMap.insert ( std::make_pair(like,cpRef) );
00632     
00633   }                  
00634   
00635   //  std::cout << " convMap size " << convMap.size() << std::endl;
00636 
00637   std::multimap<double, reco::ConversionRef>::iterator  iMap; 
00638   std::vector<reco::ConversionRef> bestRefs;
00639   for (iMap=convMap.begin();  iMap!=convMap.end(); iMap++) {
00640     //    std::cout << " Like list in the map " <<  iMap->first << " " << (iMap->second)->EoverP() << std::endl;
00641     bestRefs.push_back(  iMap->second );
00642     if (  int(bestRefs.size()) ==  maxNumOfCandidates_ ) break;   
00643   }
00644 
00645 
00646    return bestRefs;
00647   
00648   
00649 } 
00650 
00651 
00652 
00653 
00654 
00655 float ConvertedPhotonProducer::calculateMinApproachDistance ( const reco::TrackRef& track1, const reco::TrackRef& track2) {
00656   float dist=9999.;
00657 
00658   double x1, x2, y1, y2;
00659   double xx_1 = track1->innerPosition().x(), yy_1 = track1->innerPosition().y(), zz_1 = track1->innerPosition().z();
00660   double xx_2 = track2->innerPosition().x(), yy_2 = track2->innerPosition().y(), zz_2 = track2->innerPosition().z();
00661   double radius1 = track1->innerMomentum().Rho()/(.3*(theMF_->inTesla(GlobalPoint(xx_1, yy_1, zz_1)).z()))*100;
00662   double radius2 = track2->innerMomentum().Rho()/(.3*(theMF_->inTesla(GlobalPoint(xx_2, yy_2, zz_2)).z()))*100;
00663   getCircleCenter(track1, radius1, x1, y1);
00664   getCircleCenter(track2, radius2, x2, y2);
00665   dist = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) - radius1 - radius2;
00666   
00667  return dist;
00668 
00669 } 
00670 
00671 
00672 void ConvertedPhotonProducer::getCircleCenter(const reco::TrackRef& tk, double r, double& x0, double& y0){
00673   double x1, y1, phi;
00674   x1 = tk->innerPosition().x();//inner position and inner momentum need track Extra!
00675   y1 = tk->innerPosition().y();
00676   phi = tk->innerMomentum().phi();
00677   const int charge = tk->charge();
00678   x0 = x1 + r*sin(phi)*charge;
00679   y0 = y1 - r*cos(phi)*charge;
00680 
00681 }