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);