56#ifndef  D0RunIconeJets_CONECLUSTERALGO_H 
   57#define  D0RunIconeJets_CONECLUSTERALGO_H 
   69#include "inline_maths.h" 
   70#include <fastjet/internal/base.hh> 
   72FASTJET_BEGIN_NAMESPACE
 
   79inline float R2(
float eta1, 
float phi1, 
float eta2, 
float phi2) {
 
   80  return (eta1-eta2)*(eta1-eta2)+(phi1-phi2)*(phi1-phi2); }
 
   82inline float R2_bis(
float eta1, 
float phi1, 
float eta2, 
float phi2) {
 
   84  float dphi = inline_maths::delta_phi(phi1,phi2);
 
   85  return (eta1-eta2)*(eta1-eta2)+dphi*dphi; }
 
   87inline float DELTA_r(
float eta1,
float eta2,
float phi1,
float phi2) {
 
   89  float dphi = inline_maths::delta_phi(phi1,phi2);
 
   90  return sqrt((eta1-eta2)*(eta1-eta2)+dphi*dphi);
 
   93inline float E2eta(
float* p) { 
 
  106   float pperp= sqrt(E[0]*E[0]+E[1]*E[1])+small;
 
  107   float ptotal= sqrt(E[0]*E[0]+E[1]*E[1]+E[2]*E[2])+small;
 
  111   if(E[2] > 0.0) eta= log((ptotal+E[2])/pperp);
 
  112   else eta= log(pperp/(ptotal-E[2]));
 
  116inline float E2phi(
float* p) { 
 
  129   float phi= atan2(E[1],E[0]+small);
 
  131   if (phi < 0.0) phi += inline_maths::TWOPI;
 
  136template < 
class CalItem >
 
  137class ConeClusterAlgo {
 
  151ConeClusterAlgo( 
float CONErad,
float JETmne,
float SPLifr):
 
  152  _CONErad(fabs(CONErad)), 
 
  157  _Increase_Delta_R(true),
 
  158  _Kill_Far_Clusters(true),
 
  159  _Jet_Et_Min_On_Iter(true),
 
  161  _Eitem_Negdrop(-1.0),
 
  163  _Thresh_Diff_Et(0.01)
 
  168ConeClusterAlgo( 
float CONErad,
float JETmne,
float SPLifr,
float TWOrad, 
 
  169                 float Tresh_Diff_Et,
bool D0_Angle,
bool Increase_Delta_R,
 
  170                 bool Kill_Far_Clusters,
bool Jet_Et_Min_On_Iter,
 
  171                 float Far_Ratio,
float Eitem_Negdrop,
float Et_Min_Ratio ):
 
  172  _CONErad(fabs(CONErad)), 
 
  177  _Increase_Delta_R(Increase_Delta_R),
 
  178  _Kill_Far_Clusters(Kill_Far_Clusters),
 
  179  _Jet_Et_Min_On_Iter(Jet_Et_Min_On_Iter),
 
  180  _Far_Ratio(Far_Ratio),
 
  181  _Eitem_Negdrop(Eitem_Negdrop),
 
  182  _Et_Min_Ratio(Et_Min_Ratio),
 
  183  _Thresh_Diff_Et(Tresh_Diff_Et)
 
  191                  std::list<CalItem> &jets,
 
  192                  list<const CalItem*> &itemlist, 
float Zvertex 
 
  199void print(ostream &os)
const;
 
  212  bool _Increase_Delta_R;
 
  213  bool _Kill_Far_Clusters;
 
  214  bool _Jet_Et_Min_On_Iter;
 
  216  float _Eitem_Negdrop;
 
  218  float _Thresh_Diff_Et;
 
  228    TemporaryJet(
float eta,
float phi) { 
 
  235    void addItem(
const CalItem* tw) {
 
  236      _LItems.push_back(tw);
 
  239    void setEtaPhiEt(
float eta,
float phi,
float pT) {
 
  246      _LItems.erase(_LItems.begin(),_LItems.end());
 
  252    bool share_jets(TemporaryJet &NewJet,
float SharedFr,
float SPLifr) {
 
  256      if(SharedFr >= SPLifr) {
 
  257        typename list<const CalItem*>::iterator it;
 
  258        typename list<const CalItem*>::iterator end_of_old=_LItems.end();
 
  259        for(it=NewJet._LItems.begin(); it!=NewJet._LItems.end(); it++) {
 
  260          typename list<const CalItem*>::iterator 
 
  261            where = find(_LItems.begin(),end_of_old,*it);
 
  263          if(where == end_of_old) {
 
  264            _LItems.push_back(*it);
 
  273        typename list<const CalItem*>::iterator it;
 
  274        for(it=NewJet._LItems.begin(); it!=NewJet._LItems.end(); ) {
 
  275          typename list<const CalItem*>::iterator 
 
  276            where = find(_LItems.begin(),_LItems.end(),*it);
 
  277          if(where != _LItems.end()) {
 
  283            float EtaItem= E2eta(pz);
 
  284            float PhiItem= E2phi(pz);
 
  286            float RadOld=R2_bis(_Eta,_Phi,EtaItem,PhiItem);
 
  287            float RadNew=R2_bis(NewJet.Eta(),NewJet.Phi(),EtaItem,PhiItem);
 
  288            if (RadNew > RadOld) { 
 
  289              it = NewJet._LItems.erase(it);
 
  292              _LItems.erase(where);
 
  303    float dist_R2(TemporaryJet &jet)
 const {
 
  304      float deta= _Eta-jet.Eta();
 
  306      float dphi= inline_maths::delta_phi(_Phi,jet.Phi());
 
  307      return (deta*deta+dphi*dphi); 
 
  310    bool ItemInJet(
const CalItem* tw)
 const {
 
  311      typename list<const CalItem*>::const_iterator
 
  312        where= find(_LItems.begin(),_LItems.end(),tw);
 
  313      if(where != _LItems.end()) 
return true;
 
  317    bool updateEtaPhiEt() { 
 
  322      typename list<const CalItem*>::iterator it;
 
  323      for(it=_LItems.begin(); it!=_LItems.end(); it++) {
 
  324        float ETk = (*it)->pT();
 
  331        float ETAk= E2eta(pz);
 
  333        float PHIk= E2phi(pz);
 
  335        if(fabs(PHIk-_Phi) > inline_maths::TWOPI-fabs(PHIk-_Phi))
 
  340              PHIk -= inline_maths::TWOPI;
 
  345              PHIk += inline_maths::TWOPI;
 
  365         if ( _Phi<0 ) _Phi+=inline_maths::TWOPI;
 
  372    void D0_Angle_updateEtaPhi() {
 
  376      typename list<const CalItem*>::iterator it;
 
  377      for(it=_LItems.begin(); it!=_LItems.end(); it++) {
 
  385      _Phi=inline_maths::phi(EYsum,EXsum);
 
  387      _Eta=inline_maths::eta(EXsum,EYsum,EZsum);
 
  390    void getItems(list<const CalItem*> &ecv)
 const {
 
  392      typename list<const CalItem*>::const_iterator it;
 
  393      for(it=_LItems.begin(); it!=_LItems.end(); it++) {
 
  398    float Eta() {
return _Eta;}
 
  399    float Phi() {
return _Phi;}
 
  400    float Et()  {
return _Et;}
 
  401    float E()  {
return _E;}
 
  402    list<const CalItem*> &LItems() {
return _LItems;}
 
  405    list<const CalItem*> _LItems;
 
  412  void getItemsInCone(list<const CalItem*> &tlist, 
float etaJet, 
float phiJet,
 
  413                      float cone_radius, 
float zvertex_in) 
const; 
 
  414  void getItemsInCone_bis(list<const CalItem*> &tlist, 
float etaJet, 
 
  415               float phiJet,
float cone_radius, 
float zvertex_in) 
const; 
 
  419  vector< TemporaryJet > TempColl;  
 
  425template < 
class CalItem >
 
  427void ConeClusterAlgo <CalItem >:: 
 
  428getItemsInCone(list<const CalItem*> &tlist, 
float etaJet, 
float phiJet, 
 
  429               float cone_radius, 
float zvertex_in)
 const {
 
  434  float ZVERTEX_MAX=200.;
 
  437  float THETA_margin=0.022;
 
  439  float zvertex=zvertex_in;
 
  441  float phi_d1, phi_d2;
 
  442  float theta_E1, r1, r2, z1, z2;
 
  443  float theta_d1, theta_d2, eta_d1, eta_d2;
 
  446  if (fabs(zvertex) > ZVERTEX_MAX ) zvertex=0.0;
 
  449    d1=fabs(DMIN-zvertex);
 
  450    d2=fabs(DMAX+zvertex);
 
  452    d1=fabs(DMAX-zvertex);
 
  453    d2=fabs(DMIN+zvertex);
 
  458  phi_d1 = phiJet+cone_radius;
 
  460  theta_E1 = inline_maths::theta(etaJet+cone_radius);
 
  461  z1 = zvertex+d1*cos(theta_E1);
 
  462  r1 = d1*sin(theta_E1);
 
  464  phi_d2 = phiJet-cone_radius;
 
  466  theta_E1 = inline_maths::theta(etaJet-cone_radius);
 
  467  z2 = zvertex+d2*cos(theta_E1);
 
  468  r2 = d2*sin(theta_E1);
 
  471  theta_d1 = atan2(r1, z1);
 
  472  theta_d2 = atan2(r2, z2);
 
  475  theta_d1=max(theta_d1, THETA_margin);
 
  476  theta_d2=max(theta_d2, THETA_margin);
 
  478  theta_d1=min(inline_maths::PI-(
double)THETA_margin, (
double)theta_d1);
 
  480  theta_d2=min(inline_maths::PI-(
double)THETA_margin, (
double)theta_d2);
 
  483  eta_d1 = inline_maths::eta(theta_d1);
 
  485  eta_d2 = inline_maths::eta(theta_d2);
 
  488  typename list<const CalItem*>::iterator it;
 
  489  for (it=tlist.begin() ; it != tlist.end() ; ) {
 
  494    float eta_cur= E2eta(pz);
 
  495    float phi_cur= E2phi(pz);
 
  497    bool accepted = eta_cur < eta_d1 && eta_cur > eta_d2;
 
  499    if ( phi_d2>0 && phi_d1<inline_maths::TWOPI ) {
 
  500      accepted = accepted && phi_cur<phi_d1 && phi_cur>phi_d2;
 
  504        accepted = accepted && 
 
  506          ((phi_cur>phi_d2 && phi_cur<inline_maths::TWOPI) || phi_cur<phi_d1-inline_maths::TWOPI);
 
  509        accepted = accepted && 
 
  511          ((phi_cur<phi_d1 && phi_cur>0) || phi_cur>phi_d2+inline_maths::TWOPI);
 
  514    if ( ! accepted ) it = tlist.erase(it);
 
  521template < 
class CalItem >
 
  523void ConeClusterAlgo <CalItem>:: 
 
  524getItemsInCone_bis(list<const CalItem*> &tlist, 
float etaJet, 
float phiJet, 
 
  525               float cone_radius, 
float zvertex_in)
 const {
 
  532  float ZVERTEX_MAX=200.;
 
  535  float THETA_margin=0.022;
 
  537  float zvertex=zvertex_in;
 
  539  float phi_d1, phi_d2;
 
  540  float theta_E1, r1, r2, z1, z2;
 
  541  float theta_d1, theta_d2, eta_d1, eta_d2;
 
  544  if (fabs(zvertex) > ZVERTEX_MAX ) zvertex=0.0;
 
  547    d1=fabs(DMIN-zvertex);
 
  548    d2=fabs(DMAX+zvertex);
 
  550    d1=fabs(DMAX-zvertex);
 
  551    d2=fabs(DMIN+zvertex);
 
  557  phi_d1 = phiJet+cone_radius;
 
  559  theta_E1 = inline_maths::theta(etaJet+cone_radius);
 
  560  z1 = zvertex+d1*cos(theta_E1);
 
  561  r1 = d1*sin(theta_E1);
 
  563  phi_d2 = phiJet-cone_radius;
 
  565  theta_E1 = inline_maths::theta(etaJet-cone_radius);
 
  566  z2 = zvertex+d2*cos(theta_E1);
 
  567  r2 = d2*sin(theta_E1);
 
  571  theta_d1 = atan2(r1, z1);
 
  572  theta_d2 = atan2(r2, z2);
 
  576  theta_d1=max(theta_d1, THETA_margin);
 
  577  theta_d2=max(theta_d2, THETA_margin);
 
  579  theta_d1=min(inline_maths::PI-(
double)THETA_margin, (
double)theta_d1);
 
  581  theta_d2=min(inline_maths::PI-(
double)THETA_margin, (
double)theta_d2);
 
  585  eta_d1 = inline_maths::eta(theta_d1);
 
  587  eta_d2 = inline_maths::eta(theta_d2);
 
  591  if( eta_d1>=0.0 ) signe= 1.0;
 
  593  int ietaMAX= eta_d1/0.1+signe;
 
  594  if(fabs(eta_d1)>=4.45) ietaMAX= 37*signe; 
 
  595  else if(fabs(eta_d1)>=4.1) ietaMAX= 36*signe; 
 
  596  else if(fabs(eta_d1)>=3.7) ietaMAX= 35*signe; 
 
  597  else if(fabs(eta_d1)>=3.42) ietaMAX= 34*signe; 
 
  598  else if(fabs(eta_d1)>=3.2) ietaMAX= 33*signe; 
 
  600  if( eta_d2>=0.0 ) signe= 1.0;
 
  602  int ietaMIN= eta_d2/0.1+signe;
 
  603  if(fabs(eta_d2)>=4.45) ietaMIN= 37*signe; 
 
  604  else if(fabs(eta_d2)>=4.1) ietaMIN= 36*signe; 
 
  605  else if(fabs(eta_d2)>=3.7) ietaMIN= 35*signe; 
 
  606  else if(fabs(eta_d2)>=3.42) ietaMIN= 34*signe; 
 
  607  else if(fabs(eta_d2)>=3.2) ietaMIN= 33*signe; 
 
  610  int iphiMAX= 64*phi_d1/(2.*inline_maths::PI)+1;
 
  612  int iphiMIN= 64*phi_d2/(2.*inline_maths::PI)+1;
 
  614  typename list<const CalItem*>::iterator it;
 
  615  for (it=tlist.begin() ; it != tlist.end() ; ) {
 
  618    int ieta= (*it)->address().ieta();
 
  619    int iphi= (*it)->address().iphi();
 
  621    bool accepted = ieta<ietaMAX && ieta>ietaMIN;
 
  622    if ( iphiMIN>0 && iphiMAX<=64 ) {
 
  623      accepted = accepted && iphi<iphiMAX && iphi>iphiMIN;
 
  627        accepted = accepted && 
 
  628          ((iphi>iphiMIN && iphi<=64) || iphi<iphiMAX-64);
 
  631        accepted = accepted && 
 
  632          ((iphi<iphiMAX && iphi>0) || iphi>iphiMIN+64);
 
  635    if ( ! accepted ) it = tlist.erase(it);
 
  642template < 
class CalItem >
 
  644inline void ConeClusterAlgo <CalItem >:: 
 
  645print(ostream &os)
 const {
 
  646    os<<endl<<
" CONE ALGORITHM, cone radius= "<<_CONErad<<endl<<
 
  647    " min E_T fraction= "<<_JETmne<<endl<<
 
  648    " minimum Delta_R separation between cones= "<<_TWOrad<<endl<<
 
  649    " shared E_T fraction threshold for combining jets= "<<_SPLifr<<endl;
 
  654template < 
class CalItem >
 
  656void ConeClusterAlgo <CalItem >:: 
 
  658             std::list<CalItem> &jets,
 
  659             list<const CalItem*> &itemlist, 
float Zvertex 
 
  668  std::vector<const CalItem*> ecv;
 
  669  for ( 
typename std::list<const CalItem*>::iterator it = itemlist.begin(); 
 
  670        it != itemlist.end(); it++) {
 
  677  if(_Increase_Delta_R) Rcut= 1.E-04;
 
  681  list< pair<float,float> > LTrack;
 
  689  typename std::vector<const CalItem*>::iterator jclu;
 
  690  for( jclu=ecv.begin(); jclu!=ecv.end(); jclu++ ) {
 
  692    const CalItem* ptr= *jclu;
 
  697    float ETAst= E2eta(pz);
 
  698    float PHIst= E2phi(pz);
 
  706    if(_Kill_Far_Clusters) {
 
  707      list< pair<float,float> >::iterator kj;
 
  708      for(kj=LTrack.begin(); kj!=LTrack.end(); kj++) {
 
  709        if(DELTA_r((*kj).first,ETAst,(*kj).second,PHIst)<_Far_Ratio*_CONErad) {
 
  716    if( nojets==
false ) {
 
  717      TemporaryJet TJet(ETAst,PHIst);
 
  718      list< pair<int,float> > JETshare;
 
  731        if(PHIst > inline_maths::TWOPI) PHIst= PHIst-inline_maths::TWOPI;
 
  733        if(PHIst < 0.0  ) PHIst= PHIst+inline_maths::TWOPI;
 
  735        if( PHIst>inline_maths::TWOPI || PHIst<0.0 ) {
 
  736          TJet.setEtaPhiEt(0.0,0.0,0.0);
 
  739        TJet.setEtaPhiEt(ETAst,PHIst,0.0);
 
  742        list<const CalItem*> Twlist(itemlist);
 
  744        getItemsInCone(Twlist,ETAst,PHIst,_CONErad,Zvertex); 
 
  748        typename list<const CalItem*>::iterator tk;
 
  749        for( tk= Twlist.begin(); tk!=Twlist.end(); tk++ ) {
 
  750          float ETk =(*tk)->pT();
 
  753          if( ETk > _Eitem_Negdrop ) { 
 
  758            float ETAk= E2eta(pz);
 
  759            float PHIk= E2phi(pz);
 
  761            float dphi= fabs(PHIk-PHIst);
 
  763            if(dphi > inline_maths::TWOPI-dphi) {
 
  765              if(PHIst < PHIk) PHIk= PHIk-inline_maths::TWOPI;
 
  767              else PHIk= PHIk+inline_maths::TWOPI; 
 
  770            if( R2_bis(ETAk,PHIk,ETAst,PHIst) <= _CONErad*_CONErad ) { 
 
  776        if(TJet.updateEtaPhiEt()==
false) {
 
  782        if(_Jet_Et_Min_On_Iter) {
 
  783          if( TJet.Et() < _JETmne*_Et_Min_Ratio ) {
 
  791      }
while(R2_bis(TJet.Eta(),TJet.Phi(),ETAst,PHIst)>=Rcut && trial<=50);
 
  793      if( TJet.Et() >= _JETmne ) {
 
  795        if(_D0_Angle) TJet.D0_Angle_updateEtaPhi();
 
  799        list<const CalItem*> Lst;
 
  801        typename list<const CalItem*>::iterator tk;
 
  802        for(tk=Lst.begin(); tk!=Lst.end(); tk++) {
 
  803          float ETk=(*tk)->pT();
 
  805          for(
unsigned int kj=0; kj<TempColl.size(); kj++) {
 
  806            if(TempColl[kj].ItemInJet(*tk)==
true) {
 
  807              list< pair<int,float> >::iterator pit;
 
  809              for(pit=JETshare.begin(); pit!=JETshare.end();pit++) {
 
  810                if((*pit).first == (
int) kj) {
 
  816              if(jetok==
false) JETshare.push_back(make_pair(kj,ETk));
 
  821        if(JETshare.size() >0) {
 
  822          list< pair<int,float> >::iterator pit;
 
  824          list< pair<int,float> >::iterator pitMAX=JETshare.begin();
 
  825          for(pit=JETshare.begin(); pit!=JETshare.end(); pit++) {
 
  826            Ssum+= (*pit).second;
 
  827            if((*pit).second > (*pitMAX).second) pitMAX= pit;
 
  832          float Eleft= fabs(TJet.Et()-Ssum);
 
  833          float Djets= TempColl[(*pitMAX).first].dist_R2(TJet);
 
  834          if(Djets <= _TWOrad || Eleft <= _Thresh_Diff_Et) { 
 
  839            float SharedFr=Ssum/min(TempColl[(*pitMAX).first].Et(),TJet.Et());
 
  840            if(JETshare.size() >1) {
 
  841              typename list<const CalItem*>::iterator tk;
 
  842              for(tk=TJet.LItems().begin(); tk!=TJet.LItems().end(); ) {
 
  844                list< pair<int,float> >::iterator pit;
 
  845                for(pit=JETshare.begin(); pit!=JETshare.end();pit++) {
 
  846                  if((*pit).first!=(*pitMAX).first) { 
 
  847                    if(TempColl[(*pit).first].ItemInJet(*tk)==
true) {
 
  848                      tk = TJet.LItems().erase(tk);
 
  858            splshr= TempColl[(*pitMAX).first].share_jets(TJet,SharedFr,_SPLifr);
 
  862              TempColl[(*pitMAX).first].updateEtaPhiEt();
 
  863              TJet.updateEtaPhiEt();
 
  864              if(_D0_Angle) TJet.D0_Angle_updateEtaPhi();
 
  865              if(_D0_Angle) TempColl[(*pitMAX).first].D0_Angle_updateEtaPhi();
 
  866              TempColl.push_back(TJet);  
 
  867              LTrack.push_back(make_pair(TJet.Eta(),TJet.Phi()));
 
  871              TempColl[(*pitMAX).first].updateEtaPhiEt();
 
  872              if(_D0_Angle) TempColl[(*pitMAX).first].D0_Angle_updateEtaPhi();
 
  877          TJet.updateEtaPhiEt();
 
  878          if(_D0_Angle) TJet.D0_Angle_updateEtaPhi();
 
  879          TempColl.push_back(TJet);  
 
  880          LTrack.push_back(make_pair(TJet.Eta(),TJet.Phi()));
 
  886  for(
unsigned int i=0; i<TempColl.size(); i++) {
 
  890    list<const CalItem*> Vi;
 
  891    TempColl[i].getItems(Vi);
 
  892    typename list<const CalItem*>::iterator it;
 
  893    for(it=Vi.begin(); it!=Vi.end(); it++) {
 
  894      const CalItem* ptr= *it;
 
  902    jets.push_back(ptrclu);