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