CMS 3D CMS Logo

Pi0Algo.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    Pi0Algo
00004 // Class:      Pi0Algo
00005 // 
00015 //
00016 // Original Author:  Dongwook Jang
00017 //         Created:  Tue Jan  9 16:40:36 CST 2007
00018 // $Id: Pi0Algo.cc,v 1.2 2007/04/05 19:27:50 dwjang Exp $
00019 //
00020 //
00021 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00022 
00023 #include "DataFormats/VertexReco/interface/Vertex.h"
00024 #include "RecoTauTag/Pi0Tau/interface/Pi0Algo.h"
00025 
00026 #include "Math/GenVector/VectorUtil.h"
00027 
00028 #include <iostream>
00029 #include <algorithm>
00030 #include <cmath>
00031 
00032 
00033 using namespace reco;
00034 
00035 //
00036 // constructors and destructor
00037 //
00038 Pi0Algo::Pi0Algo(reco::TrackRef seedTrack){
00039   coneSize_  = 0.524; // corresponding to 30 degree if 3D angle used
00040   use3DAngle_ = false;
00041   ecalEntrance_ = 129.0;
00042   massRes_ = 0.03;
00043   seedTrack_ = seedTrack;
00044   pi0Collection_.clear();
00045 }
00046 
00047 
00048 Pi0Algo::~Pi0Algo()
00049 {
00050   pi0Collection_.clear();
00051 }
00052 
00053 
00054 void Pi0Algo::fillPi0sUsingPF(edm::Handle<reco::PFCandidateCollection> &pFCandidateHandle){
00055 
00056   LogDebug("Pi0Algo") << "The validity of seedTrack is " << (seedTrack_.isNull() ? 0 : 1) << "\n";
00057 
00058   if(seedTrack_.isNull()){
00059     LogDebug("Pi0Algo") << "seedTrack is not valid";
00060     return;
00061   }
00062 
00063   LogDebug("Pi0Algo") << "vertex of seedTrack : ("
00064                       << seedTrack_->vertex().x() << ","
00065                       << seedTrack_->vertex().y() << ","
00066                       << seedTrack_->vertex().z() << ")\n";
00067   
00068   if(!pFCandidateHandle.isValid()) {
00069     LogDebug("Pi0Algo") << "PFCandidateCollection is not valid";
00070     return;
00071   }
00072 
00073   const reco::PFCandidateCollection& pFCandidateCollection = *(pFCandidateHandle.product());
00074 
00075   reco::PFCandidateRefVector photonCands;
00076   int icand = 0;
00077   for(reco::PFCandidateCollection::const_iterator  ic = pFCandidateCollection.begin();
00078        ic != pFCandidateCollection.end(); ++ic) {
00079     const reco::PFCandidate *cand = &(*ic);
00080     reco::PFCandidateRef candRef(pFCandidateHandle,icand);
00081     icand++;
00082     if(cand->particleId() != reco::PFCandidate::gamma) continue;
00083 
00084     double dist = use3DAngle_ ? ROOT::Math::VectorUtil::Angle(seedTrack_->momentum(),cand->momentum()) :
00085       ROOT::Math::VectorUtil::DeltaR(seedTrack_->momentum(),cand->momentum());
00086 
00087     if(dist > coneSize_) continue;
00088     photonCands.push_back(candRef);
00089   }
00090 
00091   LogDebug("Pi0Algo") << " size of photonCandidates : " << photonCands.size() << "\n";
00092 
00093   reco::PFCandidateRefVector usedPhotons;
00094   int nPhotons = photonCands.size();
00095   for(reco::PFCandidateRefVector::const_iterator ip = photonCands.begin();
00096       ip != photonCands.end(); ++ip){
00097     const reco::PFCandidateRef candRef = *ip;
00098     reco::PFCandidateRefVector pi0Cands;
00099     if(binary_search(usedPhotons.begin(),usedPhotons.end(),candRef)) continue;
00100     else {
00101       usedPhotons.push_back(candRef);
00102       pi0Cands.push_back(candRef);
00103     }
00104 
00105     int type = reco::Pi0::UnResolved;
00106 
00107     math::XYZPoint pos = calculatePositionAtEcal(candRef->p4());
00108     math::XYZTLorentzVector p4 = calculateMomentumWRT(candRef->p4(),seedTrack_->vertex());
00109 
00110     LogDebug("Pi0Algo") << "Compare original and calculated photon momentum and position ------------\n"
00111                         << " The position at ecal : ("
00112                         << pos.x() << ","
00113                         << pos.y() << ","
00114                         << pos.z() << ")\n"
00115                         << " The original  momentum : (" 
00116                         << candRef->p4().px() << ","
00117                         << candRef->p4().py() << ","
00118                         << candRef->p4().pz() << ","
00119                         << candRef->p4().energy() << ")\n"
00120                         << " The corrected momentum : ("
00121                         << p4.px() << ","
00122                         << p4.py() << ","
00123                         << p4.pz() << ","
00124                         << p4.energy() << ")\n";
00125 
00126     // Now find a pair of photons which have a minimum invariant mass.
00127     // The second photon shouldn't be used previously, say, not an element of usedPhotons.
00128 
00129     double minMass = 999.0;
00130     reco::PFCandidateRef pho2;
00131     if((nPhotons > 1) && (ip != photonCands.end())){
00132       for(reco::PFCandidateRefVector::const_iterator ip2 = ip+1;
00133           ip2 != photonCands.end(); ++ip2){
00134         reco::PFCandidateRef candRef2 = *ip2;
00135         if(binary_search(usedPhotons.begin(),usedPhotons.end(),candRef2)) continue;
00136         math::XYZTLorentzVector sum = p4 + calculateMomentumWRT(candRef2->p4(),seedTrack_->vertex());
00137         double massDiff = std::abs(sum.M()-PI0MASS);
00138         if(massDiff < minMass){
00139           minMass = massDiff;
00140           pho2 = candRef2;
00141         }
00142       }
00143     }
00144 
00145     LogDebug("Pi0Algo") << "minMass of two photons : " << minMass << "\n";
00146 
00147     if(pho2.isNull()){
00148       reco::Pi0 pi0(type,p4.energy(),pos,p4,pi0Cands);
00149       pi0Collection_.push_back(pi0);
00150     }
00151     else if(minMass < massRes_){
00152       usedPhotons.push_back(pho2);
00153       pi0Cands.push_back(pho2);
00154       math::XYZPoint pos2 = calculatePositionAtEcal(pho2->p4());
00155       math::XYZPoint avPos(0.5*(pos.x()+pos2.x()),0.5*(pos.y()+pos2.y()),0.5*(pos.z()+pos2.z()));
00156       math::XYZTLorentzVector sumP4 = p4 + calculateMomentumWRT(pho2->p4(),seedTrack_->vertex());
00157       type = reco::Pi0::Resolved;
00158       reco::Pi0 pi0(type,sumP4.energy(),avPos,sumP4,pi0Cands);
00159       pi0Collection_.push_back(pi0);
00160 
00161       LogDebug("Pi0Algo") << "Found resolved photons -----------------------\n"
00162                           << "pos   : (" << pos.x() << "," << pos.y() << "," << pos.z() << ")\n"
00163                           << "pos2  : (" << pos2.x() << "," << pos2.y() << "," << pos2.z() << ")\n"
00164                           << "avPos : (" << avPos.x() << "," << avPos.y() << "," << avPos.z() << ")\n"
00165                           << "sumP4 : (" << sumP4.px() << "," << sumP4.py() << "," << sumP4.pz() << "," << sumP4.energy() << ")\n";
00166 
00167     }// else if
00168 
00169     pi0Cands.clear();
00170   }// for cluster
00171 
00172 
00173   // clear temporary vector's
00174   photonCands.clear();
00175   usedPhotons.clear();
00176 
00177 }
00178 
00179 
00180 math::XYZPoint Pi0Algo::calculatePositionAtEcal(const math::XYZTLorentzVector &momentum) const {
00181 
00182   // This is also temporary.
00183   // Position at ECAL can be obtained from ecal cluster links from candidates
00184   // when PFCandidate object is made.
00185 
00186   double phi = momentum.phi();
00187   double theta = momentum.theta();
00188 
00189   // ecalEntrance will be replaced by the official geometry constant later.
00190   // This works only for barrels, but I think it should work for endcap as well because
00191   // this is just a reference point to recalculate momentum w.r.t a given vertex.
00192 
00193   math::XYZPoint pos(ecalEntrance_*std::cos(phi),ecalEntrance_*std::sin(phi),ecalEntrance_/std::tan(theta));
00194 
00195   return pos;
00196 }
00197 
00198 
00199 math::XYZTLorentzVector Pi0Algo::calculateMomentumWRT(const math::XYZTLorentzVector &momentum, const math::XYZPoint &vertex) const {
00200 
00201   math::XYZVector dir = calculatePositionAtEcal(momentum) - vertex;
00202   math::XYZVector pos = dir.unit() * momentum.energy();
00203 
00204   math::XYZTLorentzVector p4(pos.x(),pos.y(),pos.z(),momentum.energy());
00205 
00206   return p4;
00207 }

Generated on Tue Jun 9 17:45:00 2009 for CMSSW by  doxygen 1.5.4