FastJet 3.0beta1
ConeClusterAlgo.hpp
00001 //////////////////////////////////////////////////////////////
00002 //  File: ConeClusterAlgo.hpp                                 
00003 //
00004 //  Author: G. Le Meur & F. Touze
00005 //
00006 //  Created: 15-JUNE-1998        
00007 //
00008 //  Purpose: make jet clusters using fixed cone like algorithm
00009 //           implemented in RUNI.
00010 //
00011 //  Modified: 
00012 //  28-OCT-1998 to use KinemUtil (S. Protopopescu)
00013 //   8-JAN-1999: Laurent Duflot
00014 //     . correct bugs in getItemsInCone and updateEtaPhiEt for jets
00015 //       overlapping the phi=0 line
00016 //     . change abs(float) to fabs(float)
00017 //   1-NOV-1999: Laurent Duflot
00018 //     . correct bug in makeCluster: when the temporary jet was emptied the eta
00019 //       and phi were not set again. The main effect was a nearly zero 
00020 //       efficiency for jets at phi=pi (as seen by Volker Buescher)
00021 //   25-JAN-2000: Francois Touze
00022 //     . change in updateEtaPhiEt : the method E() which returns energy doesn't
00023 //       exist in MCparticle classe,... so use the 4-momentum components
00024 //     . declare const the EnergyClusterCollection of seeds in makeClusters
00025 //   01-FEB-2000: Laurent Duflot
00026 //     . add a missing break statement in the removal of shared items. Caused
00027 //       an infinite loop on some events.
00028 //     . correct typo in variable name. Change a variable name that was in 
00029 //       French.
00030 //     . leave some debug printout (commented)
00031 //   15-Sep-2009 Lars Sonnenschein
00032 //   extracted from D0 software framework and modified to remove subsequent dependencies
00033 //
00034 //////////////////////////////////////////////////////////////
00035 
00036 //#ifndef CONECLUSTERALGO_H
00037 //#define CONECLUSTERALGO_H
00038 
00039 #ifndef  D0RunIconeJets_CONECLUSTERALGO_H
00040 #define  D0RunIconeJets_CONECLUSTERALGO_H
00041 
00042 
00043 //#include "EnergyClusterReco.hpp"
00044 #include <vector>
00045 #include <list>
00046 #include <utility>
00047 //#include "kinem_util/AnglesUtil.hpp"
00048 
00049 #include <algorithm>
00050 #include <iostream>
00051 
00052 #include "inline_maths.h"
00053 
00054 namespace d0runi{
00055 
00056 using namespace std;
00057 
00058 //some utility functions
00059 inline float R2(float eta1, float phi1, float eta2, float phi2) {
00060   return (eta1-eta2)*(eta1-eta2)+(phi1-phi2)*(phi1-phi2); }
00061 
00062 inline float R2_bis(float eta1, float phi1, float eta2, float phi2) {
00063   //float dphi = kinem::delta_phi(phi1,phi2);
00064   float dphi = inline_maths::delta_phi(phi1,phi2);
00065   return (eta1-eta2)*(eta1-eta2)+dphi*dphi; }
00066 
00067 inline float DELTA_r(float eta1,float eta2,float phi1,float phi2) {
00068   //float dphi = kinem::delta_phi(phi1,phi2);
00069   float dphi = inline_maths::delta_phi(phi1,phi2);
00070   return sqrt((eta1-eta2)*(eta1-eta2)+dphi*dphi);
00071 }
00072 
00073 inline float E2eta(float* p) { 
00074    float small= 1.E-05;
00075    float E[3];
00076    if(p[3] < 0.0) {
00077     E[0]= -p[0];
00078     E[1]= -p[1];
00079     E[2]= -p[2];
00080    }
00081    else {
00082     E[0]= p[0];
00083     E[1]= p[1];
00084     E[2]= p[2];
00085    }
00086    float pperp= sqrt(E[0]*E[0]+E[1]*E[1])+small;
00087    float ptotal= sqrt(E[0]*E[0]+E[1]*E[1]+E[2]*E[2])+small;
00088    //float theta= atan2(pperp,E[2]);
00089  
00090    float eta= 0.0;
00091    if(E[2] > 0.0) eta= log((ptotal+E[2])/pperp);
00092    else eta= log(pperp/(ptotal-E[2]));
00093    return eta;
00094 }
00095 
00096 inline float E2phi(float* p) { 
00097    float small= 1.E-05;
00098    float E[3];
00099    if(p[3] < 0.0) {
00100     E[0]= -p[0];
00101     E[1]= -p[1];
00102     E[2]= -p[2];
00103    }
00104    else {
00105     E[0]= p[0];
00106     E[1]= p[1];
00107     E[2]= p[2];
00108    }
00109    float phi= atan2(E[1],E[0]+small);
00110    //if(phi < 0.0) phi+=kinem::TWOPI;
00111    if (phi < 0.0) phi += inline_maths::TWOPI;
00112    return phi;
00113 }
00114 
00115 //template < class CalItem,class CalItemAddress,class CalIClusterChunk >
00116 template < class CalItem >
00117 class ConeClusterAlgo {
00118   //
00119   // Purpose: make calorimeter clusters using a cone algorithm from 
00120   // preclusters created previously by the class ConePreClusterAlgo.
00121   // Items must have addresses and 4-momenta.
00122   // The algorithm is implemented with a template function makeClusters.
00123   //  
00124   public :
00125 
00126 
00127 //default constructor
00128 ConeClusterAlgo() {} 
00129 
00130 //constructor for cone jet algorithm
00131 ConeClusterAlgo( float CONErad,float JETmne,float SPLifr):
00132   _CONErad(fabs(CONErad)), 
00133   _JETmne(JETmne), 
00134   _SPLifr(SPLifr),
00135   _TWOrad(0.),
00136   _D0_Angle(false),
00137   _Increase_Delta_R(true),
00138   _Kill_Far_Clusters(true),
00139   _Jet_Et_Min_On_Iter(true),
00140   _Far_Ratio(0.5),
00141   _Eitem_Negdrop(-1.0),
00142   _Et_Min_Ratio(0.5),
00143   _Thresh_Diff_Et(0.01)
00144   {}
00145 
00146 //changing default thresholds & parameters
00147 // (declared by PARAMETER in RUNI code)
00148 ConeClusterAlgo( float CONErad,float JETmne,float SPLifr,float TWOrad, 
00149                  float Tresh_Diff_Et,bool D0_Angle,bool Increase_Delta_R,
00150                  bool Kill_Far_Clusters,bool Jet_Et_Min_On_Iter,
00151                  float Far_Ratio,float Eitem_Negdrop,float Et_Min_Ratio ):
00152   _CONErad(fabs(CONErad)), 
00153   _JETmne(JETmne),
00154   _SPLifr(SPLifr),
00155   _TWOrad(TWOrad),
00156   _D0_Angle(D0_Angle),
00157   _Increase_Delta_R(Increase_Delta_R),
00158   _Kill_Far_Clusters(Kill_Far_Clusters),
00159   _Jet_Et_Min_On_Iter(Jet_Et_Min_On_Iter),
00160   _Far_Ratio(Far_Ratio),
00161   _Eitem_Negdrop(Eitem_Negdrop),
00162   _Et_Min_Ratio(Et_Min_Ratio),
00163   _Thresh_Diff_Et(Tresh_Diff_Et)
00164   {}
00165 
00166 //destructor
00167 ~ConeClusterAlgo() {}
00168   
00169 //to make jet clusters using cone algorithm
00170 void makeClusters(//const EnergyClusterReco* r,
00171                   std::list<CalItem> &jets,
00172                   list<const CalItem*> &itemlist, float Zvertex 
00173                   //, const EnergyClusterCollection<CalItemAddress> &preclu,
00174                   //CalIClusterChunk* chunkptr
00175                   //) const;
00176                   );
00177 
00178 //print parameters of the algorithm
00179 void print(ostream &os)const;
00180 
00181   //vector< TemporaryJet > TempColl;  
00182 
00183 
00184   private :
00185   
00186   float _CONErad;
00187   float _JETmne;
00188   float _SPLifr;
00189 
00190   float _TWOrad;
00191   bool _D0_Angle;
00192   bool _Increase_Delta_R;
00193   bool _Kill_Far_Clusters;
00194   bool _Jet_Et_Min_On_Iter;
00195   float _Far_Ratio;
00196   float _Eitem_Negdrop;
00197   float _Et_Min_Ratio;
00198   float _Thresh_Diff_Et;
00199 
00200   class TemporaryJet {
00201 
00202   public:
00203 
00204 
00205 
00206     TemporaryJet() {}
00207 
00208     TemporaryJet(float eta,float phi) { 
00209       _Eta=eta; 
00210       _Phi=phi;
00211     }
00212 
00213     ~TemporaryJet() {}
00214 
00215     void addItem(const CalItem* tw) {
00216       _LItems.push_back(tw);
00217     }
00218 
00219     void setEtaPhiEt(float eta,float phi,float pT) {
00220       _Eta= eta;
00221       _Phi= phi;
00222       _Et = pT;
00223     }
00224 
00225     void erase() {
00226       _LItems.erase(_LItems.begin(),_LItems.end());
00227       _Eta= 0.0;
00228       _Phi= 0.0;
00229       _Et = 0.0;  
00230     }
00231 
00232     bool share_jets(TemporaryJet &NewJet,float SharedFr,float SPLifr) {
00233       //
00234       // combined
00235       //
00236       if(SharedFr >= SPLifr) {
00237         typename list<const CalItem*>::iterator it;
00238         typename list<const CalItem*>::iterator end_of_old=_LItems.end();
00239         for(it=NewJet._LItems.begin(); it!=NewJet._LItems.end(); it++) {
00240           typename list<const CalItem*>::iterator 
00241             where = find(_LItems.begin(),end_of_old,*it);
00242           // if the item is not shared, add to this jet
00243           if(where == end_of_old) {
00244             _LItems.push_back(*it);
00245           }
00246         }
00247         NewJet.erase();
00248         return false;
00249       } else {
00250         //
00251         // split
00252         //
00253         typename list<const CalItem*>::iterator it;
00254         for(it=NewJet._LItems.begin(); it!=NewJet._LItems.end(); ) {
00255           typename list<const CalItem*>::iterator 
00256             where = find(_LItems.begin(),_LItems.end(),*it);
00257           if(where != _LItems.end()) {
00258             //float EtaItem=(*it)->eta();
00259             //float PhiItem=(*it)->phi();
00260             // stay closer to the RUNI conventions for negative E cells
00261             float pz[4];
00262             (*it)->p4vec(pz);
00263             float EtaItem= E2eta(pz);
00264             float PhiItem= E2phi(pz);
00265 
00266             float RadOld=R2_bis(_Eta,_Phi,EtaItem,PhiItem);
00267             float RadNew=R2_bis(NewJet.Eta(),NewJet.Phi(),EtaItem,PhiItem);
00268             if (RadNew > RadOld) { 
00269               it = NewJet._LItems.erase(it);
00270             }
00271             else {
00272               _LItems.erase(where);
00273               ++it;
00274             }
00275           }
00276           else ++it;
00277         }
00278         return true;
00279       }
00280     }
00281   
00282 
00283     float dist_R2(TemporaryJet &jet) const {
00284       float deta= _Eta-jet.Eta();
00285       //float dphi= kinem::delta_phi(_Phi,jet.Phi());
00286       float dphi= inline_maths::delta_phi(_Phi,jet.Phi());
00287       return (deta*deta+dphi*dphi); 
00288     }
00289  
00290     bool ItemInJet(const CalItem* tw) const {
00291       typename list<const CalItem*>::const_iterator
00292         where= find(_LItems.begin(),_LItems.end(),tw);
00293       if(where != _LItems.end()) return true;
00294       else return false;
00295     }
00296   
00297     bool updateEtaPhiEt() { 
00298       float ETsum = 0.0;
00299       float ETAsum= 0.0;
00300       float PHIsum= 0.0;
00301       float Esum= 0.0;
00302       typename list<const CalItem*>::iterator it;
00303       for(it=_LItems.begin(); it!=_LItems.end(); it++) {
00304         float ETk = (*it)->pT();
00305         // now done in CalCell/CalTower if((*it)->E() < 0.0) ETk= -ETk;
00306 
00307         //float ETAk= (*it)->eta();
00308         //float PHIk= (*it)->phi();
00309         float pz[4];
00310         (*it)->p4vec(pz);
00311         float ETAk= E2eta(pz);
00312         // take care of the phi=0=2pi problem 
00313         float PHIk= E2phi(pz);
00314         //if(fabs(PHIk-_Phi) > kinem::TWOPI-fabs(PHIk-_Phi))
00315         if(fabs(PHIk-_Phi) > inline_maths::TWOPI-fabs(PHIk-_Phi))
00316           {
00317           if(_Phi < PHIk) 
00318             {
00319               //PHIk -= kinem::TWOPI;
00320               PHIk -= inline_maths::TWOPI;
00321             }
00322           else
00323             {
00324               //PHIk += kinem::TWOPI;
00325               PHIk += inline_maths::TWOPI;
00326             }
00327           }
00328         ETAsum+= ETAk*ETk;
00329         PHIsum+= PHIk*ETk;
00330         ETsum += ETk;
00331         // Esum+=(*it)->E(); use 4-momentum components 
00332         Esum+= pz[3];
00333       }
00334       if(ETsum <= 0.0) {
00335         _Eta= 0.0;
00336         _Phi= 0.0;
00337         _Et = 0.0;
00338         _E=0.;
00339         return false;
00340       }
00341       else {
00342          _Eta= ETAsum/ETsum;
00343          _Phi= PHIsum/ETsum; 
00344          //if ( _Phi<0 ) _Phi+=kinem::TWOPI;
00345          if ( _Phi<0 ) _Phi+=inline_maths::TWOPI;
00346          _Et = ETsum;
00347          _E  = Esum;
00348          return true;  
00349       }
00350     }
00351 
00352     void D0_Angle_updateEtaPhi() {
00353       float EXsum = 0.0;
00354       float EYsum = 0.0;
00355       float EZsum = 0.0;
00356       typename list<const CalItem*>::iterator it;
00357       for(it=_LItems.begin(); it!=_LItems.end(); it++) {
00358         float p[4];
00359         (*it)->p4vec(p);
00360         EXsum += p[0];
00361         EYsum += p[1];
00362         EZsum += p[2];
00363       }
00364       //_Phi=kinem::phi(EYsum,EXsum);
00365       _Phi=inline_maths::phi(EYsum,EXsum);
00366       //_Eta=kinem::eta(EXsum,EYsum,EZsum);
00367       _Eta=inline_maths::eta(EXsum,EYsum,EZsum);
00368     } 
00369 
00370     void getItems(list<const CalItem*> &ecv) const {
00371       ecv.clear(); //ls 27/Feb/2010
00372       typename list<const CalItem*>::const_iterator it;
00373       for(it=_LItems.begin(); it!=_LItems.end(); it++) {
00374         ecv.push_back(*it);
00375       }
00376     }
00377 
00378     float Eta() {return _Eta;}
00379     float Phi() {return _Phi;}
00380     float Et()  {return _Et;}
00381     float E()  {return _E;}
00382     list<const CalItem*> &LItems() {return _LItems;}
00383     
00384   private:
00385     list<const CalItem*> _LItems;
00386     float _Eta;
00387     float _Phi;
00388     float _Et;
00389     float _E;
00390   }; //class TemporaryJet
00391 
00392   void getItemsInCone(list<const CalItem*> &tlist, float etaJet, float phiJet,
00393                       float cone_radius, float zvertex_in) const; 
00394   void getItemsInCone_bis(list<const CalItem*> &tlist, float etaJet, 
00395                float phiJet,float cone_radius, float zvertex_in) const; 
00396   
00397 public:
00398   
00399   vector< TemporaryJet > TempColl;  
00400 
00401 };
00402   /////////////////////////////////////////////////////////
00403 
00404 //template < class CalItem,class CalItemAddress,class CalIClusterChunk >
00405 template < class CalItem >
00406 //void ConeClusterAlgo <CalItem,CalItemAddress,CalIClusterChunk >:: 
00407 void ConeClusterAlgo <CalItem >:: 
00408 getItemsInCone(list<const CalItem*> &tlist, float etaJet, float phiJet, 
00409                float cone_radius, float zvertex_in) const {
00410 //
00411 // provide the list of Items (towers, Cells...) containing the energy from a 
00412 // jet of a given cone size
00413 //
00414   float ZVERTEX_MAX=200.;
00415   float DMIN=80.;
00416   float DMAX=360.;
00417   float THETA_margin=0.022;
00418    
00419   float zvertex=zvertex_in;
00420   float d1,d2;
00421   float phi_d1, phi_d2;
00422   float theta_E1, r1, r2, z1, z2;
00423   float theta_d1, theta_d2, eta_d1, eta_d2;
00424 
00425   // Ignore very large vertex positions
00426   if (fabs(zvertex) > ZVERTEX_MAX ) zvertex=0.0;
00427  
00428   if (zvertex >=0. ) {
00429     d1=fabs(DMIN-zvertex);
00430     d2=fabs(DMAX+zvertex);
00431   } else {
00432     d1=fabs(DMAX-zvertex);
00433     d2=fabs(DMIN+zvertex);
00434   }
00435   
00436   // calculate theta of physics cone and find which eta's this intercepts
00437   // a the maximum points
00438   phi_d1 = phiJet+cone_radius;
00439   //theta_E1 = kinem::theta(etaJet+cone_radius);
00440   theta_E1 = inline_maths::theta(etaJet+cone_radius);
00441   z1 = zvertex+d1*cos(theta_E1);
00442   r1 = d1*sin(theta_E1);
00443 
00444   phi_d2 = phiJet-cone_radius;
00445   //theta_E1 = kinem::theta(etaJet-cone_radius);
00446   theta_E1 = inline_maths::theta(etaJet-cone_radius);
00447   z2 = zvertex+d2*cos(theta_E1);
00448   r2 = d2*sin(theta_E1);
00449 
00450   // maximum spread in detector theta
00451   theta_d1 = atan2(r1, z1);
00452   theta_d2 = atan2(r2, z2);
00453 
00454   // make sure they stay in the calorimeter 
00455   theta_d1=max(theta_d1, THETA_margin);
00456   theta_d2=max(theta_d2, THETA_margin);
00457   //theta_d1=min(kinem::PI-(double)THETA_margin, (double)theta_d1);
00458   theta_d1=min(inline_maths::PI-(double)THETA_margin, (double)theta_d1);
00459   //theta_d2=min(kinem::PI-(double)THETA_margin, (double)theta_d2);
00460   theta_d2=min(inline_maths::PI-(double)THETA_margin, (double)theta_d2);
00461 
00462   //eta_d1 = kinem::eta(theta_d1);
00463   eta_d1 = inline_maths::eta(theta_d1);
00464   //eta_d2 = kinem::eta(theta_d2);
00465   eta_d2 = inline_maths::eta(theta_d2);
00466 
00467 
00468   typename list<const CalItem*>::iterator it;
00469   for (it=tlist.begin() ; it != tlist.end() ; ) {
00470     //float eta_cur= (*it)->eta();
00471     //float phi_cur= (*it)->phi();
00472     float pz[4];
00473     (*it)->p4vec(pz);
00474     float eta_cur= E2eta(pz);
00475     float phi_cur= E2phi(pz);
00476 
00477     bool accepted = eta_cur < eta_d1 && eta_cur > eta_d2;
00478     //if ( phi_d2>0 && phi_d1<kinem::TWOPI ) {
00479     if ( phi_d2>0 && phi_d1<inline_maths::TWOPI ) {
00480       accepted = accepted && phi_cur<phi_d1 && phi_cur>phi_d2;
00481     }
00482     else{ // case the cone overlap the phi=0=2pi line
00483       if ( phi_d2>0 ){
00484         accepted = accepted && 
00485           //((phi_cur>phi_d2 && phi_cur<kinem::TWOPI) || phi_cur<phi_d1-kinem::TWOPI);
00486           ((phi_cur>phi_d2 && phi_cur<inline_maths::TWOPI) || phi_cur<phi_d1-inline_maths::TWOPI);
00487       }
00488       else{
00489         accepted = accepted && 
00490           //((phi_cur<phi_d1 && phi_cur>0) || phi_cur>phi_d2+kinem::TWOPI);
00491           ((phi_cur<phi_d1 && phi_cur>0) || phi_cur>phi_d2+inline_maths::TWOPI);
00492       }
00493     }
00494     if ( ! accepted ) it = tlist.erase(it);
00495     else ++it;
00496 
00497   }
00498 }
00499   /////////////////////////////////////////////////////////
00500 //template < class CalItem,class CalItemAddress,class CalIClusterChunk >
00501 template < class CalItem >
00502 //void ConeClusterAlgo <CalItem,CalItemAddress,CalIClusterChunk >:: 
00503 void ConeClusterAlgo <CalItem>:: 
00504 getItemsInCone_bis(list<const CalItem*> &tlist, float etaJet, float phiJet, 
00505                float cone_radius, float zvertex_in) const {
00506 //
00507 // provide the list of Items (towers, Cells...) containing the energy from a 
00508 // jet of a given cone size
00509 //
00510 // WARNING: this is only to be used to compare to RUN I cone jets
00511 // 
00512   float ZVERTEX_MAX=200.;
00513   float DMIN=80.;
00514   float DMAX=360.;
00515   float THETA_margin=0.022;
00516    
00517   float zvertex=zvertex_in;
00518   float d1,d2;
00519   float phi_d1, phi_d2;
00520   float theta_E1, r1, r2, z1, z2;
00521   float theta_d1, theta_d2, eta_d1, eta_d2;
00522 
00523   // Ignore very large vertex positions
00524   if (fabs(zvertex) > ZVERTEX_MAX ) zvertex=0.0;
00525  
00526   if (zvertex >=0. ) {
00527     d1=fabs(DMIN-zvertex);
00528     d2=fabs(DMAX+zvertex);
00529   } else {
00530     d1=fabs(DMAX-zvertex);
00531     d2=fabs(DMIN+zvertex);
00532   }
00533   
00534   // calculate theta of physics cone and find which eta's this intercepts
00535   // a the maximum points
00536   
00537   phi_d1 = phiJet+cone_radius;
00538   //theta_E1 = kinem::theta(etaJet+cone_radius);
00539   theta_E1 = inline_maths::theta(etaJet+cone_radius);
00540   z1 = zvertex+d1*cos(theta_E1);
00541   r1 = d1*sin(theta_E1);
00542 
00543   phi_d2 = phiJet-cone_radius;
00544   //theta_E1 = kinem::theta(etaJet-cone_radius);
00545   theta_E1 = inline_maths::theta(etaJet-cone_radius);
00546   z2 = zvertex+d2*cos(theta_E1);
00547   r2 = d2*sin(theta_E1);
00548 
00549   // maximum spread in detector theta
00550 
00551   theta_d1 = atan2(r1, z1);
00552   theta_d2 = atan2(r2, z2);
00553 
00554   // make sure they stay in the calorimeter 
00555 
00556   theta_d1=max(theta_d1, THETA_margin);
00557   theta_d2=max(theta_d2, THETA_margin);
00558   //theta_d1=min(kinem::PI-(double)THETA_margin, (double)theta_d1);
00559   theta_d1=min(inline_maths::PI-(double)THETA_margin, (double)theta_d1);
00560   //theta_d2=min(kinem::PI-(double)THETA_margin, (double)theta_d2);
00561   theta_d2=min(inline_maths::PI-(double)THETA_margin, (double)theta_d2);
00562 
00563 
00564   //eta_d1 = kinem::eta(theta_d1);
00565   eta_d1 = inline_maths::eta(theta_d1);
00566   //eta_d2 = kinem::eta(theta_d2);
00567   eta_d2 = inline_maths::eta(theta_d2);
00568 
00569   float signe;
00570  
00571   if( eta_d1>=0.0 ) signe= 1.0;
00572   else signe= -1.0;
00573   int ietaMAX= eta_d1/0.1+signe;
00574   if(fabs(eta_d1)>=4.45) ietaMAX= 37*signe; 
00575   else if(fabs(eta_d1)>=4.1) ietaMAX= 36*signe; 
00576   else if(fabs(eta_d1)>=3.7) ietaMAX= 35*signe; 
00577   else if(fabs(eta_d1)>=3.42) ietaMAX= 34*signe; 
00578   else if(fabs(eta_d1)>=3.2) ietaMAX= 33*signe; 
00579   
00580   if( eta_d2>=0.0 ) signe= 1.0;
00581   else signe= -1.0;
00582   int ietaMIN= eta_d2/0.1+signe;
00583   if(fabs(eta_d2)>=4.45) ietaMIN= 37*signe; 
00584   else if(fabs(eta_d2)>=4.1) ietaMIN= 36*signe; 
00585   else if(fabs(eta_d2)>=3.7) ietaMIN= 35*signe; 
00586   else if(fabs(eta_d2)>=3.42) ietaMIN= 34*signe; 
00587   else if(fabs(eta_d2)>=3.2) ietaMIN= 33*signe; 
00588 
00589   //int iphiMAX= 64*phi_d1/(2.*kinem::PI)+1;
00590   int iphiMAX= 64*phi_d1/(2.*inline_maths::PI)+1;
00591   //int iphiMIN= 64*phi_d2/(2.*kinem::PI)+1;
00592   int iphiMIN= 64*phi_d2/(2.*inline_maths::PI)+1;
00593  
00594   typename list<const CalItem*>::iterator it;
00595   for (it=tlist.begin() ; it != tlist.end() ; ) {
00596     //float eta_cur= (*it)->eta();
00597     //float phi_cur= (*it)->phi();
00598     int ieta= (*it)->address().ieta();
00599     int iphi= (*it)->address().iphi();
00600     
00601     bool accepted = ieta<ietaMAX && ieta>ietaMIN;
00602     if ( iphiMIN>0 && iphiMAX<=64 ) {
00603       accepted = accepted && iphi<iphiMAX && iphi>iphiMIN;
00604     }
00605     else{ // case the cone overlap the phi=0=2pi line
00606       if ( iphiMIN>0 ){
00607         accepted = accepted && 
00608           ((iphi>iphiMIN && iphi<=64) || iphi<iphiMAX-64);
00609       }
00610       else{
00611         accepted = accepted && 
00612           ((iphi<iphiMAX && iphi>0) || iphi>iphiMIN+64);
00613       }
00614     }
00615     if ( ! accepted ) it = tlist.erase(it);
00616     else ++it;
00617     
00618   }
00619 }
00620   /////////////////////////////////////////////////////////
00621 //template < class CalItem,class CalItemAddress,class CalIClusterChunk >
00622 template < class CalItem >
00623 //inline void ConeClusterAlgo <CalItem,CalItemAddress,CalIClusterChunk >:: 
00624 inline void ConeClusterAlgo <CalItem >:: 
00625 print(ostream &os) const {
00626     os<<endl<<" CONE ALGORITHM, cone radius= "<<_CONErad<<endl<<
00627     " min E_T fraction= "<<_JETmne<<endl<<
00628     " minimum Delta_R separation between cones= "<<_TWOrad<<endl<<
00629     " shared E_T fraction threshold for combining jets= "<<_SPLifr<<endl;
00630 }
00631   /////////////////////////////////////////////////////////
00632 
00633 //template < class CalItem,class CalItemAddress,class CalIClusterChunk >
00634 template < class CalItem >
00635 //void ConeClusterAlgo <CalItem,CalItemAddress,CalIClusterChunk >:: 
00636 void ConeClusterAlgo <CalItem >:: 
00637 makeClusters(//const EnergyClusterReco* r,
00638              std::list<CalItem> &jets,
00639              list<const CalItem*> &itemlist, float Zvertex 
00640              //, const EnergyClusterCollection<CalItemAddress> &preclu,
00641              //CalIClusterChunk* chunkptr
00642              //) const {
00643              ) {
00644 
00645   // create an energy cluster collection for jets 
00646   //EnergyClusterCollection<CalItemAddress>* ptrcol;
00647   //r->createClusterCollection(chunkptr, ptrcol);
00648   std::vector<const CalItem*> ecv;
00649   for ( typename std::list<const CalItem*>::iterator it = itemlist.begin(); 
00650         it != itemlist.end(); it++) {
00651     ecv.push_back(*it);
00652   }
00653 
00654 
00655   // Initialize
00656   float Rcut= 1.E-06;
00657   if(_Increase_Delta_R) Rcut= 1.E-04;
00658   bool nojets;
00659 
00660   //vector< TemporaryJet > TempColl;  
00661   list< pair<float,float> > LTrack;
00662 
00663   // get a vector with pointers to EnergyCluster in the collection
00664   //vector<const EnergyCluster<CalItemAddress>*> ecv;
00665   //preclu.getClusters(ecv);
00666 
00667   // loop over all preclusters
00668   //typename vector<const EnergyCluster<CalItemAddress>*>::iterator jclu;
00669   typename std::vector<const CalItem*>::iterator jclu;
00670   for( jclu=ecv.begin(); jclu!=ecv.end(); jclu++ ) {
00671     ////const EnergyCluster<CalItemAddress>* ptr= *jclu;
00672     const CalItem* ptr= *jclu;
00673     //float PHIst= ptr->phi();
00674     //float ETAst= ptr->eta();
00675     float pz[4];
00676     ptr->p4vec(pz);
00677     float ETAst= E2eta(pz);
00678     float PHIst= E2phi(pz);
00679 
00680     //cout << "seed 4-vec ";
00681     //for ( int i = 0; i < 4; i++) cout << pz[i] << " ";
00682     //cout << endl;
00683 
00684     nojets= false;
00685     // check to see if precluster is too close to a found jet
00686     if(_Kill_Far_Clusters) {
00687       list< pair<float,float> >::iterator kj;
00688       for(kj=LTrack.begin(); kj!=LTrack.end(); kj++) {
00689         if(DELTA_r((*kj).first,ETAst,(*kj).second,PHIst)<_Far_Ratio*_CONErad) {
00690           nojets= true;
00691           //cout << "seed too close ! skip " << endl;
00692           break;
00693         }
00694       }
00695     }
00696     if( nojets==false ) {
00697       TemporaryJet TJet(ETAst,PHIst);
00698       list< pair<int,float> > JETshare;
00699 
00700       // start of cone building loop
00701       int trial= 0;
00702       do{  
00703         trial++;
00704         //cout << " trial " << trial << endl;
00705 
00706         ETAst= TJet.Eta();
00707         PHIst= TJet.Phi();
00708         TJet.erase();
00709 
00710         //if(PHIst > kinem::TWOPI) PHIst= PHIst-kinem::TWOPI;
00711         if(PHIst > inline_maths::TWOPI) PHIst= PHIst-inline_maths::TWOPI;
00712         //if(PHIst < 0.0  ) PHIst= PHIst+kinem::TWOPI;
00713         if(PHIst < 0.0  ) PHIst= PHIst+inline_maths::TWOPI;
00714         //if( PHIst>kinem::TWOPI || PHIst<0.0 ) {
00715         if( PHIst>inline_maths::TWOPI || PHIst<0.0 ) {
00716           TJet.setEtaPhiEt(0.0,0.0,0.0);
00717           break; // end loop do (illegal jet PHI) 
00718         }
00719         TJet.setEtaPhiEt(ETAst,PHIst,0.0);
00720 
00721         // calculate eta & phi limits for cone
00722         list<const CalItem*> Twlist(itemlist);
00723 
00724         getItemsInCone(Twlist,ETAst,PHIst,_CONErad,Zvertex); 
00725         //  only to compare with RUN I cone jets !   getItemsInCone_bis(Twlist,ETAst,PHIst,_CONErad,Zvertex); 
00726 
00727         // loop over the possible items for this cone
00728         typename list<const CalItem*>::iterator tk;
00729         for( tk= Twlist.begin(); tk!=Twlist.end(); tk++ ) {
00730           float ETk =(*tk)->pT();
00731           // now done in CalCell/CalTower if((*tk)->E() < 0.0) ETk= -ETk;
00732 
00733           if( ETk > _Eitem_Negdrop ) { 
00734             //float ETAk=(*tk)->eta();
00735             //float PHIk=(*tk)->phi();
00736             float pz[4];
00737             (*tk)->p4vec(pz);
00738             float ETAk= E2eta(pz);
00739             float PHIk= E2phi(pz);
00740 
00741             float dphi= fabs(PHIk-PHIst);
00742             //if(dphi > kinem::TWOPI-dphi) {
00743             if(dphi > inline_maths::TWOPI-dphi) {
00744               //if(PHIst < PHIk) PHIk= PHIk-kinem::TWOPI;
00745               if(PHIst < PHIk) PHIk= PHIk-inline_maths::TWOPI;
00746               //else PHIk= PHIk+kinem::TWOPI; 
00747               else PHIk= PHIk+inline_maths::TWOPI; 
00748             }
00749 
00750             if( R2_bis(ETAk,PHIk,ETAst,PHIst) <= _CONErad*_CONErad ) { 
00751               TJet.addItem(*tk);
00752             }
00753           }
00754         }// end loop tk
00755  
00756         if(TJet.updateEtaPhiEt()==false) {
00757           //cout << " negative E jet ! drop " << endl;
00758           break;
00759         }
00760 
00761         // require some minimum ET on every iteration
00762         if(_Jet_Et_Min_On_Iter) {
00763           if( TJet.Et() < _JETmne*_Et_Min_Ratio ) {
00764             //cout << " too low ET jet ! drop " << endl;
00765             break; // end loop trial
00766           }
00767         }
00768   
00769         //cout << " R2 = " << R2_bis(TJet.Eta(),TJet.Phi(),ETAst,PHIst) << 
00770         //  " Rcut = " << Rcut << endl;
00771       }while(R2_bis(TJet.Eta(),TJet.Phi(),ETAst,PHIst)>=Rcut && trial<=50);
00772  
00773       if( TJet.Et() >= _JETmne ) {
00774         //cout << " jet accepted will check for overlaps " << endl; 
00775         if(_D0_Angle) TJet.D0_Angle_updateEtaPhi();
00776         //cout << "  after TJet.D0_Angle_updateEtaPhi() " << endl;
00777         
00778         // item also in another jet
00779         list<const CalItem*> Lst;
00780         TJet.getItems(Lst);
00781         typename list<const CalItem*>::iterator tk;
00782         for(tk=Lst.begin(); tk!=Lst.end(); tk++) {
00783           float ETk=(*tk)->pT();
00784           // now done in CalCell/CalTower if((*tk)->E() < 0.0) ETk= -ETk;
00785           for(unsigned int kj=0; kj<TempColl.size(); kj++) {
00786             if(TempColl[kj].ItemInJet(*tk)==true) {
00787               list< pair<int,float> >::iterator pit;
00788               bool jetok= false;
00789               for(pit=JETshare.begin(); pit!=JETshare.end();pit++) {
00790                 if((*pit).first == (int) kj) {
00791                   jetok= true;
00792                   (*pit).second+= ETk;
00793                   break;
00794                 }
00795               }
00796               if(jetok==false) JETshare.push_back(make_pair(kj,ETk));
00797             }
00798           }
00799         }
00800         
00801         if(JETshare.size() >0) {
00802           list< pair<int,float> >::iterator pit;
00803           float Ssum= 0.0;
00804           list< pair<int,float> >::iterator pitMAX=JETshare.begin();
00805           for(pit=JETshare.begin(); pit!=JETshare.end(); pit++) {
00806             Ssum+= (*pit).second;
00807             if((*pit).second > (*pitMAX).second) pitMAX= pit;
00808           }
00809 
00810           //int IJET= (*pitMAX).first;
00811           bool splshr;
00812           float Eleft= fabs(TJet.Et()-Ssum);
00813           float Djets= TempColl[(*pitMAX).first].dist_R2(TJet);
00814           if(Djets <= _TWOrad || Eleft <= _Thresh_Diff_Et) { 
00815             TJet.erase();
00816             splshr= false;
00817           }
00818           else {
00819             float SharedFr=Ssum/min(TempColl[(*pitMAX).first].Et(),TJet.Et());
00820             if(JETshare.size() >1) {
00821               typename list<const CalItem*>::iterator tk;
00822               for(tk=TJet.LItems().begin(); tk!=TJet.LItems().end(); ) {
00823                 bool found = false;
00824                 list< pair<int,float> >::iterator pit;
00825                 for(pit=JETshare.begin(); pit!=JETshare.end();pit++) {
00826                   if((*pit).first!=(*pitMAX).first) { 
00827                     if(TempColl[(*pit).first].ItemInJet(*tk)==true) {
00828                       tk = TJet.LItems().erase(tk);
00829                       found = true;
00830                       break;
00831                     }
00832                   }
00833                 }
00834                 if ( !found ) ++tk;
00835               }
00836             }
00837 
00838             splshr= TempColl[(*pitMAX).first].share_jets(TJet,SharedFr,_SPLifr);
00839 
00840             if( splshr==true ) {
00841               //cout << " jet splitted due to overlaps " << endl;
00842               TempColl[(*pitMAX).first].updateEtaPhiEt();
00843               TJet.updateEtaPhiEt();
00844               if(_D0_Angle) TJet.D0_Angle_updateEtaPhi();
00845               if(_D0_Angle) TempColl[(*pitMAX).first].D0_Angle_updateEtaPhi();
00846               TempColl.push_back(TJet);  
00847               LTrack.push_back(make_pair(TJet.Eta(),TJet.Phi()));
00848             }
00849             else {
00850               //cout << " jet merged due to overlaps " << endl;
00851               TempColl[(*pitMAX).first].updateEtaPhiEt();
00852               if(_D0_Angle) TempColl[(*pitMAX).first].D0_Angle_updateEtaPhi();
00853             }  
00854           }
00855         }
00856         else {
00857           TJet.updateEtaPhiEt();
00858           if(_D0_Angle) TJet.D0_Angle_updateEtaPhi();
00859           TempColl.push_back(TJet);  
00860           LTrack.push_back(make_pair(TJet.Eta(),TJet.Phi()));
00861         }
00862       } //JETmne
00863     } //nojets
00864   }// end loop jclu 
00865 
00866   for(unsigned int i=0; i<TempColl.size(); i++) {
00867     //EnergyCluster<CalItemAddress>* ptrclu;
00868     CalItem ptrclu;
00869     //r->createCluster(ptrcol,ptrclu);
00870     list<const CalItem*> Vi;
00871     TempColl[i].getItems(Vi);
00872     typename list<const CalItem*>::iterator it;
00873     for(it=Vi.begin(); it!=Vi.end(); it++) {
00874       const CalItem* ptr= *it;
00875       //CalItemAddress addr= ptr->address();
00876       float p[4];
00877       ptr->p4vec(p);
00878       //float emE= ptr->emE();
00879       //r->addClusterItem(ptrclu,addr,p,emE);
00880       ptrclu.Add(*ptr);
00881     }
00882     jets.push_back(ptrclu);
00883   }
00884 
00885 }// end 
00886 #endif  //  CONECLUSTERALGO_H
00887 
00888 
00889 } //namespace d0runi
00890 
00891 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends