CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/RecoEgamma/EgammaHFProducers/plugins/HFClusterAlgo.cc

Go to the documentation of this file.
00001 #include "HFClusterAlgo.h"
00002 #include <sstream>
00003 #include <iostream>
00004 #include <algorithm>
00005 #include <list> 
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007 #include "RecoLocalCalo/HcalRecAlgos/interface/HcalCaloFlagLabels.h"
00008 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00009 
00010 using namespace std;
00011 using namespace reco;
00020 HFClusterAlgo::HFClusterAlgo() 
00021 {
00022   m_isMC=true; // safest
00023   
00024 }
00025 
00026 class CompareHFCompleteHitET {
00027 public:
00028   bool operator()(const HFClusterAlgo::HFCompleteHit& h1,const HFClusterAlgo::HFCompleteHit& h2) const {
00029     return h1.et>h2.et;
00030   }
00031 };
00032 
00033 class CompareHFCore {
00034 public:
00035   bool operator()(const double c1,const double c2) const {
00036     return c1>c2;
00037   }
00038 };
00039 
00040 static int indexByEta(HcalDetId id) {
00041   return (id.zside()>0)?(id.ietaAbs()-29+13):(41-id.ietaAbs());
00042 }
00043 static const double MCMaterialCorrections_3XX[] = {  1.000,1.000,1.105,0.970,0.965,0.975,0.956,0.958,0.981,1.005,0.986,1.086,1.000,
00044                                                  1.000,1.086,0.986,1.005,0.981,0.958,0.956,0.975,0.965,0.970,1.105,1.000,1.000 };
00045 
00046     
00047 
00048 void HFClusterAlgo::setup(double minTowerEnergy, double seedThreshold,double maximumSL,double maximumRenergy,
00049                           bool usePMTflag,bool usePulseflag, bool forcePulseFlagMC, int correctionSet){
00050   m_seedThreshold=seedThreshold;
00051   m_minTowerEnergy=minTowerEnergy;
00052   m_maximumSL=maximumSL;
00053   m_usePMTFlag=usePMTflag;
00054   m_usePulseFlag=usePulseflag;
00055   m_forcePulseFlagMC=forcePulseFlagMC;
00056   m_maximumRenergy=maximumRenergy;
00057   m_correctionSet = correctionSet;
00058 
00059   for(int ii=0;ii<13;ii++){
00060     m_cutByEta.push_back(-1);
00061     m_seedmnEta.push_back(99);
00062     m_seedMXeta.push_back(-1);
00063   }
00064  for(int ii=0;ii<73;ii++){
00065     double minphi=0.0872664*(ii-1);
00066     double maxphi=0.0872664*(ii+1);
00067     while (minphi < -M_PI)
00068       minphi+=2*M_PI;
00069     while (minphi > M_PI)
00070       minphi-=2*M_PI;
00071     while (maxphi < -M_PI)
00072       maxphi+=2*M_PI;
00073     while (maxphi > M_PI)
00074       maxphi-=2*M_PI;
00075     if(ii==37)
00076       minphi=-3.1415904;
00077     m_seedmnPhi.push_back(minphi);
00078     m_seedMXphi.push_back(maxphi);
00079  }
00080  
00081  // always set all the corrections to one...
00082  for (int ii=0; ii<13*2; ii++) 
00083    m_correctionByEta.push_back(1.0);
00084  if (m_correctionSet==1) { // corrections for material from MC
00085    for (int ii=0; ii<13*2; ii++) 
00086      m_correctionByEta[ii]=MCMaterialCorrections_3XX[ii];
00087  } 
00088 }
00089 
00091 void HFClusterAlgo::clusterize(const HFRecHitCollection& hf, 
00092                                const CaloGeometry& geom,
00093                                HFEMClusterShapeCollection& clusterShapes,
00094                                SuperClusterCollection& SuperClusters) {
00095   
00096   std::vector<HFCompleteHit> protoseeds, seeds;
00097   HFRecHitCollection::const_iterator j,j2;
00098   std::vector<HFCompleteHit>::iterator i;
00099   std::vector<HFCompleteHit>::iterator k;
00100   int dP, dE, PWrap;
00101   bool isok=true;
00102   HFEMClusterShape clusShp;
00103  
00104   SuperCluster Sclus;
00105   bool doCluster=false;
00106   
00107   for (j=hf.begin(); j!= hf.end(); j++)  {
00108     const int aieta=j->id().ietaAbs();
00109     int iz=(aieta-29);
00110     // only long fibers and not 29,40,41 allowed to be considered as seeds
00111     if (j->id().depth()!=1) continue;
00112     if (aieta==40 || aieta==41 || aieta==29) continue;
00113    
00114 
00115     if (iz<0 || iz>12) {
00116       edm::LogWarning("HFClusterAlgo") << "Strange invalid HF hit: " << j->id();
00117       continue;
00118     }
00119 
00120     if (m_cutByEta[iz]<0) {
00121       double eta=geom.getPosition(j->id()).eta();
00122       m_cutByEta[iz]=m_seedThreshold*cosh(eta); // convert ET to E for this ring
00123       const CaloCellGeometry* ccg=geom.getGeometry(j->id()); 
00124       const CaloCellGeometry::CornersVec& CellCorners=ccg->getCorners();
00125       for(size_t sc=0;sc<CellCorners.size();sc++){
00126         if(fabs(CellCorners[sc].z())<1200){
00127           if(fabs(CellCorners[sc].eta())<m_seedmnEta[iz])m_seedmnEta[iz]=fabs(CellCorners[sc].eta());
00128           if(fabs(CellCorners[sc].eta())>m_seedMXeta[iz])m_seedMXeta[iz]=fabs(CellCorners[sc].eta());
00129         }
00130       }
00131     }
00132     double elong=j->energy()*m_correctionByEta[indexByEta(j->id())];
00133     if (elong>m_cutByEta[iz]) {
00134       j2=hf.find(HcalDetId(HcalForward,j->id().ieta(),j->id().iphi(),2));
00135       double eshort=(j2==hf.end())?(0):(j2->energy());
00136       if (j2!=hf.end())
00137          eshort*=m_correctionByEta[indexByEta(j2->id())];
00138       if (((elong-eshort)/(elong+eshort))>m_maximumSL) continue;
00139       //if ((m_usePMTFlag)&&(j->flagField(4,1))) continue;
00140       //if ((m_usePulseFlag)&&(j->flagField(1,1))) continue;
00141       if(isPMTHit(*j)) continue;
00142 
00143       HFCompleteHit ahit;
00144       double eta=geom.getPosition(j->id()).eta();
00145       ahit.id=j->id();
00146       ahit.energy=elong;
00147       ahit.et=ahit.energy/cosh(eta);
00148       protoseeds.push_back(ahit);
00149     }
00150   }
00151 
00152   if(!protoseeds.empty()){   
00153     std::sort(protoseeds.begin(), protoseeds.end(), CompareHFCompleteHitET());
00154     for (i=protoseeds.begin(); i!= protoseeds.end(); i++)  {
00155       isok=true;
00156       doCluster=false;
00157 
00158       if ( (i==protoseeds.begin()) && (isok) ) {
00159         doCluster=true;
00160       }else {
00161         // check for overlap with existing clusters 
00162         for (k=seeds.begin(); isok && k!=seeds.end(); k++) { //i->hits, k->seeds
00163           
00164           for (dE=-2; dE<=2; dE++)
00165             for (dP=-4;dP<=4; dP+=2) {
00166               PWrap=k->id.iphi()+dP;    
00167               if (PWrap<0) 
00168                 PWrap+=72;
00169               if (PWrap>72)
00170                 PWrap-=72;
00171               
00172               if ( (i->id.iphi()==PWrap) && (i->id.ieta()==k->id.ieta()+dE))
00173                 isok = false;
00174             }
00175         }
00176         if (isok) {
00177           doCluster=true;
00178         }
00179       }
00180       if (doCluster) { 
00181         seeds.push_back(*i);
00182 
00183         bool clusterOk=makeCluster( i->id(),hf, geom,clusShp,Sclus);
00184         if (clusterOk) { // cluster is _not_ ok if seed is rejected due to other cuts
00185           clusterShapes.push_back(clusShp);
00186           SuperClusters.push_back(Sclus);
00187         }
00188 
00189       }
00190     }//end protoseed loop
00191   }//end if seeCount
00192 }
00193 
00194 
00195 bool HFClusterAlgo::makeCluster(const HcalDetId& seedid,
00196                                 const HFRecHitCollection& hf, 
00197                                 const CaloGeometry& geom,
00198                                 HFEMClusterShape& clusShp,
00199                                 SuperCluster& Sclus)  {
00200                         
00201 
00202   double w=0;//sum over all log E's
00203   double wgt=0;
00204   double w_e=0;//sum over ieat*energy
00205   double w_x=0;
00206   double w_y=0;
00207   double w_z=0;
00208   double wp_e=0;//sum over iphi*energy
00209   double e_e=0;//nonwieghted eta sum
00210   double e_ep=0; //nonweighted phi sum
00211  
00212   double l_3=0;//sum for enenergy in 3x3 long fibers etc.
00213   double s_3=0;
00214   double l_5=0;
00215   double s_5=0;
00216   double l_1=0;
00217   double s_1=0;
00218   int de, dp, phiWrap;
00219   double l_1e=0;
00220   GlobalPoint sp=geom.getPosition(seedid);
00221   std::vector<double> coreCanid;
00222   std::vector<double>::const_iterator ci;
00223   HFRecHitCollection::const_iterator i,is,il;
00224   std::vector<DetId> usedHits; 
00225  
00226   HFRecHitCollection::const_iterator si;
00227   HcalDetId sid(HcalForward,seedid.ieta(),seedid.iphi(),1);
00228   si=hf.find(sid);  
00229 
00230   bool clusterOk=true; // assume the best to start...
00231 
00232   // lots happens here
00233   // edge type 1 has 40/41 in 3x3 and 5x5
00234   bool edge_type1=seedid.ietaAbs()==39 && (seedid.iphi()%4)==3;
00235 
00236   double e_seed=si->energy()*m_correctionByEta[indexByEta(si->id())];
00237   
00238   for (de=-2; de<=2; de++)
00239     for (dp=-4;dp<=4; dp+=2) {
00240       phiWrap=seedid.iphi()+dp; 
00241       if (phiWrap<0) 
00242         phiWrap+=72;
00243       if (phiWrap>72)
00244         phiWrap-=72;
00245 
00246   
00247       /* Handling of phi-width change problems */
00248       if (edge_type1 && de==seedid.zside()) {
00249         if (dp==-2) { // we want it in the 3x3
00250           phiWrap-=2;
00251           if (phiWrap<0) 
00252             phiWrap+=72;
00253         } 
00254         else if (dp==-4) {
00255           continue; // but not double counted in 5x5
00256         }
00257       }
00258 
00259       HcalDetId idl(HcalForward,seedid.ieta()+de,phiWrap,1);
00260       HcalDetId ids(HcalForward,seedid.ieta()+de,phiWrap,2);
00261 
00262         
00263       il=hf.find(idl);
00264       is=hf.find(ids);        
00265 
00266 
00267 
00268 
00269       double e_long=1.0; 
00270       double e_short=0.0; 
00271       if (il!=hf.end()) e_long=il->energy()*m_correctionByEta[indexByEta(il->id())];
00272       if (e_long <= m_minTowerEnergy) e_long=0.0;
00273       if (is!=hf.end()) e_short=is->energy()*m_correctionByEta[indexByEta(is->id())];
00274       if (e_short <= m_minTowerEnergy) e_short=0.0;
00275       double eRatio=(e_long-e_short)/std::max(1.0,(e_long+e_short));
00276         
00277       // require S/L > a minimum amount for inclusion
00278       if ((abs(eRatio) > m_maximumSL)&&(std::max(e_long,e_short) > m_maximumRenergy)) {
00279         if (dp==0 && de==0) clusterOk=false; // somehow, the seed is hosed
00280         continue;
00281       }
00282          
00283       if((il!=hf.end())&&(isPMTHit(*il))){
00284         if (dp==0 && de==0) clusterOk=false; // somehow, the seed is hosed
00285         continue;//continue to next hit, do not include this one in cluster
00286       }
00287         
00288 
00289 
00290 
00291 
00292       if (e_long > m_minTowerEnergy && il!=hf.end()) {
00293 
00294         // record usage
00295         usedHits.push_back(idl.rawId());
00296         // always in the 5x5
00297         l_5+=e_long;
00298         // maybe in the 3x3
00299         if ((de>-2)&&(de<2)&&(dp>-4)&&(dp<4)) {
00300           l_3+=e_long;
00301         
00302           // sometimes in the 1x1
00303           if ((dp==0)&&(de==0)) {
00304             l_1=e_long;
00305           }
00306 
00307           // maybe in the core?
00308           if ((de>-2)&&(de<2)&&(dp>-4)&&(dp<4)&&(e_long>(.5*e_seed))) {
00309             coreCanid.push_back(e_long);
00310           }
00311           
00312           // position calculation
00313           GlobalPoint p=geom.getPosition(idl);
00314           
00315           double d_p = p.phi()-sp.phi();
00316           while (d_p < -M_PI)
00317             d_p+=2*M_PI;
00318           while (d_p > M_PI)
00319             d_p-=2*M_PI;
00320           double d_e = p.eta()-sp.eta();
00321           
00322           wgt=log((e_long));
00323           if (wgt>0){
00324             w+=wgt;
00325             w_e+=(d_e)*wgt;
00326             wp_e+=(d_p)*wgt;
00327             e_e+=d_e;
00328             e_ep+=d_p;
00329            
00330             w_x+=(p.x())*wgt;//(p.x()-sp.x())*wgt;
00331             w_y+=(p.y())*wgt;
00332             w_z+=(p.z())*wgt;
00333           }
00334         }
00335       } else {
00336         if (dp==0 && de==0) clusterOk=false; // somehow, the seed is hosed
00337       }
00338         
00339       if (e_short > m_minTowerEnergy && is!=hf.end()) {
00340         // record usage
00341         usedHits.push_back(ids.rawId());
00342         // always in the 5x5
00343         s_5+=e_short;
00344         // maybe in the 3x3
00345         if ((de>-2)&&(de<2)&&(dp>-4)&&(dp<4)) {
00346           s_3+=e_short;
00347         }
00348         // sometimes in the 1x1
00349         if ((dp==0)&&(de==0)) {
00350           s_1=e_short;
00351         }
00352       }
00353     }
00354 
00355 
00356   if (!clusterOk) return false;
00357 
00358   //Core sorting done here
00359   std::sort(coreCanid.begin(), coreCanid.end(), CompareHFCore());
00360   for (ci=coreCanid.begin();ci!=coreCanid.end();ci++){
00361     if(ci==coreCanid.begin()){
00362       l_1e=*ci;
00363     }else if (*ci>.5*l_1e){
00364       l_1e+=*ci;
00365     }
00366   }//core sorting end 
00367   
00368   double z_=w_z/w;    
00369   double x_=w_x/w;
00370   double y_=w_y/w;
00371   math::XYZPoint xyzclus(x_,y_,z_);
00372   //calcualte position, final
00373   double eta=xyzclus.eta();//w_e/w+sp.eta();
00374   
00375   double phi=xyzclus.phi();//(wp_e/w)+sp.phi();
00376   
00377   while (phi < -M_PI)
00378     phi+=2*M_PI;
00379   while (phi > M_PI)
00380     phi-=2*M_PI;
00381   
00382   //calculate cell phi and cell eta
00383   int idx= fabs(seedid.ieta())-29;
00384   int ipx=seedid.iphi();
00385   double Cphi =(phi-m_seedmnPhi[ipx])/(m_seedMXphi[ipx]-m_seedmnPhi[ipx]);
00386   double Ceta=(fabs(eta)- m_seedmnEta[idx])/(m_seedMXeta[idx]-m_seedmnEta[idx]);
00387     
00388   //return  HFEMClusterShape, SuperCluster
00389   HFEMClusterShape myClusShp(l_1, s_1, l_3, s_3, l_5,s_5, l_1e,Ceta, Cphi,seedid);
00390   clusShp = myClusShp;
00391       
00392   SuperCluster MySclus(l_3,xyzclus);
00393   Sclus=MySclus;
00394 
00395   return clusterOk;
00396   
00397 }
00398 bool HFClusterAlgo::isPMTHit(const HFRecHit& hfr){
00399 
00400   bool pmthit=false;
00401 
00402   if((hfr.flagField(HcalCaloFlagLabels::HFLongShort))&&(m_usePMTFlag)) pmthit=true;
00403   if (!(m_isMC && !m_forcePulseFlagMC))
00404     if((hfr.flagField(HcalCaloFlagLabels::HFDigiTime))&&(m_usePulseFlag)) pmthit=true;
00405  
00406   return pmthit;
00407 }
00408 void HFClusterAlgo::resetForRun() {
00409   edm::LogInfo("HFClusterAlgo")<<"Resetting for Run!";
00410   for(int ii=0;ii<13;ii++){
00411     m_cutByEta.push_back(-1);
00412     m_seedmnEta.push_back(99);
00413     m_seedMXeta.push_back(-1);
00414   }
00415 }
00416