FastJet 3.0.1
ConeSplitMerge.hpp
00001 #ifndef  D0RunIIconeJets_CONESPLITMERGE
00002 #define  D0RunIIconeJets_CONESPLITMERGE
00003 // ---------------------------------------------------------------------------
00004 // ConeSplitMerge.hpp
00005 //
00006 // Created: 28-JUL-2000 Francois Touze
00007 //
00008 // Purpose: Implements the pT ordered jet split/merge algorithm for the 
00009 //   Improved Legacy Cone Algorithm split/merge algo.
00010 //
00011 // Modified:
00012 //   31-JUL-2000  Laurent Duflot
00013 //     + introduce support for additional informations (ConeJetInfo)
00014 //    1-AUG-2000  Laurent Duflot
00015 //     + jet merge criteria was wrong, now calculate shared_ET and compare to 
00016 //       neighbour jet pT.
00017 //     + split was incomplete: shared items not really removed from jets.
00018 //    4-Aug-2000  Laurent Duflot
00019 //     + use item methods y() and phi() rather than p4vec() and then P2y and 
00020 //       P2phi
00021 //    7-Aug-2000  Laurent Duflot 
00022 //     + force the list to be organized by decreasing ET and, for identical ET,
00023 //       by decreasing seedET. Identical protojets can be found by eg nearby
00024 //       seeds. The seedET ordering is such that for identical jets, the one
00025 //       with the highest seedET is kept, which is what we want for efficiency
00026 //       calculations.
00027 //     + avoid unecessary copies of lists by using reference when possible
00028 //    9-Aug-2000  Laurent Duflot
00029 //     + save initial jet ET before split/merge
00030 //    1-May-2007 Lars Sonnenschein
00031 //    extracted from D0 software framework and modified to remove subsequent dependencies
00032 // ---------------------------------------------------------------------------
00033 //
00034 
00035 // History of changes in FastJet compared tothe original version of
00036 // ConeSplitMerge.hpp
00037 //
00038 // 2009-01-17  Gregory Soyez  <soyez@fastjet.fr>
00039 //
00040 //        * put the code in the fastjet::d0 namespace
00041 //
00042 // 2007-12-14  Gavin Salam  <salam@lpthe.jussieu.fr>
00043 // 
00044 //        * replaced make_pair by std::make_pair
00045 
00046 #include <iostream>
00047 #include <map>
00048 #include <utility>
00049 #include <vector>
00050 #include "ProtoJet.hpp"
00051 
00052 //using namespace D0RunIIconeJets_CONEJETINFO;
00053 
00054 #include <fastjet/internal/base.hh>
00055 
00056 FASTJET_BEGIN_NAMESPACE
00057 
00058 namespace d0{
00059 
00060 //
00061 // this class is used to order ProtoJets by decreasing ET and seed ET
00062 template <class Item>
00063 class ProtoJet_ET_seedET_order
00064 {
00065 public:
00066   bool operator()(const ProtoJet<Item> & first, const ProtoJet<Item> & second)
00067   {
00068     if ( first.pT() > second.pT() ) return true;
00069     else
00070       if ( first.pT() < second.pT() ) return false;
00071       else return ( first.info().seedET() > second.info().seedET() );
00072   }
00073 };
00074 
00075 
00076 template <class Item>
00077 class ConeSplitMerge {
00078 
00079 public :
00080 
00081   typedef std::multimap<ProtoJet<Item>,float,ProtoJet_ET_seedET_order<Item> > PJMMAP;
00082   
00083   ConeSplitMerge();
00084   ConeSplitMerge(const std::vector<ProtoJet<Item> >& jvector);
00085   ConeSplitMerge(const std::list<ProtoJet<Item> >& jlist);
00086   ~ConeSplitMerge() {;}
00087   void split_merge(std::vector<ProtoJet<Item> >& ecv,float s, float pT_min_leading_protojet, float pT_min_second_protojet, int MergeMax, float pT_min_noMergeMax);
00088 
00089 private :
00090   PJMMAP _members;
00091 };
00092 ///////////////////////////////////////////////////////////////////////////////
00093 template<class Item>
00094 ConeSplitMerge<Item>::ConeSplitMerge():_members() {;}
00095 
00096 template<class Item>
00097 ConeSplitMerge<Item>::ConeSplitMerge(const std::vector<ProtoJet<Item> >& jvector) 
00098 {
00099   // sort proto_jets in Et descending order
00100   typename std::vector<ProtoJet<Item> >::const_iterator jt;
00101   for(jt = jvector.begin(); jt != jvector.end(); ++jt) 
00102   {
00103     // this is supposed to be a stable cone, declare so
00104     ProtoJet<Item> jet(*jt);
00105     jet.NowStable();
00106     _members.insert(std::make_pair(jet,jet.pT()));
00107   }
00108 }
00109 
00110 template<class Item>
00111 ConeSplitMerge<Item>::ConeSplitMerge(const std::list<ProtoJet<Item> >& jlist) 
00112 {
00113   //_max_nb_items =-1;
00114   // sort proto_jets in Et descending order
00115   typename std::list<ProtoJet<Item> >::const_iterator jt;
00116   for(jt = jlist.begin(); jt != jlist.end(); ++jt) 
00117   {
00118     // this is supposed to be a stable cone, declare so
00119     ProtoJet<Item> jet(*jt);
00120     jet.NowStable();
00121     _members.insert(std::make_pair(jet,jet.pT()));
00122   }
00123 }
00124 
00125 template<class Item>
00126 void ConeSplitMerge<Item>::split_merge(std::vector<ProtoJet<Item> >& jcv,
00127                                        float shared_ET_fraction,
00128                                        float pT_min_leading_protojet, float pT_min_second_protojet,
00129                                        int MergeMax, float pT_min_noMergeMax) 
00130 {
00131   while(!_members.empty()) 
00132   {
00133     /*
00134     {
00135       std::cout << std::endl;
00136       std::cout << " ---------------  list of protojets ------------------ " <<std::endl;
00137       for ( PJMMAP::iterator it = _members.begin();
00138             it != _members.end(); ++it)
00139       {
00140         std::cout << " pT y phi " << (*it).pT() << " " << (*it).y() << " " << (*it).phi() << " " << (*it).info().seedET() <<  " " << (*it).info().nbMerge() << " " << (*it).info().nbSplit() << std::endl;
00141       }
00142       std::cout << " ----------------------------------------------------- " <<std::endl;
00143     }
00144     */
00145 
00146 
00147     // select highest Et jet
00148     typename PJMMAP::iterator itmax= _members.begin();
00149     ProtoJet<Item> imax((*itmax).first);
00150     const std::list<const Item*>& ilist(imax.LItems());
00151 
00152     _members.erase(itmax);
00153  
00154     // does jet share items?
00155     bool share= false;
00156     float shared_ET = 0.;
00157     typename PJMMAP::iterator jtmax;
00158     typename PJMMAP::iterator jt;
00159     for(jt = _members.begin(); jt != _members.end(); ++jt) 
00160     {
00161       const std::list<const Item*>& jlist((*jt).first.LItems());
00162       typename std::list<const Item*>::const_iterator tk;
00163       int count;
00164       for(tk = ilist.begin(), count = 0; tk != ilist.end(); 
00165           ++tk, ++count) 
00166       {
00167         typename std::list<const Item*>::const_iterator where= 
00168           find(jlist.begin(),jlist.end(),*tk);   
00169         if(where != jlist.end()) 
00170         {
00171           share= true;
00172           shared_ET += (*tk)->pT();
00173         }
00174       }
00175       if(share) 
00176       {
00177         jtmax = jt;
00178         break;
00179       }
00180     }
00181     
00182     if(!share) {
00183       // add jet to the final jet list
00184       jcv.push_back(imax);
00185       //std::cout << " final jet " << imax.pT() << " "<< imax.info().nbMerge() << " " << imax.info().nbSplit() << std::endl; 
00186     }
00187     else 
00188     {
00189       // find highest Et neighbor
00190       ProtoJet<Item> jmax((*jtmax).first);
00191 
00192       // drop neighbor
00193       _members.erase(jtmax);
00194 
00195 
00196       //std::cout << " split or merge ? " << imax.pT() << " " << shared_ET << " " << jmax.pT() << " " << s << " " << (jmax.pT())*s << std::endl;
00197 
00198       // merge
00199       if( shared_ET > (jmax.pT())*shared_ET_fraction 
00200           && (imax.pT() > pT_min_leading_protojet || jmax.pT() > pT_min_second_protojet)
00201           && (imax.info().nbMerge() < MergeMax || imax.pT() > pT_min_noMergeMax))
00202         {
00203           // add neighbor's items to imax
00204           const std::list<const Item*>& jlist(jmax.LItems());
00205           typename std::list<const Item*>::const_iterator tk;
00206           typename std::list<const Item*>::const_iterator iend= ilist.end();
00207           bool same = true; // is jmax just the same as imax ? 
00208           for(tk = jlist.begin(); tk != jlist.end(); ++tk) 
00209             {
00210               typename std::list<const Item*>::const_iterator where= 
00211                 find(ilist.begin(),iend,*tk);   
00212               if(where == iend) 
00213                 {
00214                   imax.addItem(*tk);
00215                   same = false;
00216                 }
00217             }
00218           if ( ! same ) 
00219             {
00220               // recalculate
00221               //float old_pT = imax.pT();
00222               
00223               imax.updateJet();
00224               imax.merged();
00225               //std::cout << " jet merge :: " << old_pT << " " << jmax.pT() << " " << imax.pT() << " "<< imax.info().nbMerge() << " " << imax.info().nbSplit() << std::endl; 
00226             }
00227         }
00228       
00229       //split and assign removed shared cells from lowest pT protojet
00230       else if(shared_ET > (jmax.pT())*shared_ET_fraction)
00231       {
00232         // here we need to pull the lists, because there are items to remove                                                                           
00233         std::list<const Item*> ilist(imax.LItems());
00234         std::list<const Item*> jlist(jmax.LItems());
00235 
00236         typename std::list<const Item*>::iterator tk;
00237         for(tk = jlist.begin(); tk != jlist.end(); )
00238           {
00239             typename std::list<const Item*>::iterator where=
00240               find(ilist.begin(),ilist.end(),*tk);
00241             if(where != ilist.end()) {
00242               tk = jlist.erase(tk);
00243             }
00244             else ++tk;
00245           }
00246         
00247         jmax.erase();
00248 
00249         for ( typename std::list<const Item*>::const_iterator it = jlist.begin();
00250               it != jlist.end(); ++it) jmax.addItem(*it);
00251 
00252         // recalculated jet quantities 
00253         jmax.updateJet();
00254         jmax.splitted();
00255         //std::cout << " jet split 1 :: " << jmax.pT() << " "<< jmax.info().nbMerge() << " " << jmax.info().nbSplit() << std::endl;                         
00256         _members.insert(std::make_pair(jmax,jmax.pT()));
00257       }
00258 
00259       // split and assign shared cells to nearest protojet
00260       else 
00261       {
00262         // here we need to pull the lists, because there are items to remove
00263         std::list<const Item*> ilist(imax.LItems());
00264         std::list<const Item*> jlist(jmax.LItems());
00265         
00266         typename std::list<const Item*>::iterator tk;
00267         for(tk = jlist.begin(); tk != jlist.end(); ) 
00268         {
00269           typename std::list<const Item*>::iterator where= 
00270             find(ilist.begin(),ilist.end(),*tk);
00271           if(where != ilist.end()) {
00272             float yk   = (*tk)->y();
00273             float phik = (*tk)->phi();
00274             float di= RD2(imax.y(),imax.phi(),yk,phik);
00275             float dj= RD2(jmax.y(),jmax.phi(),yk,phik);
00276             if(dj > di) 
00277             {
00278               tk = jlist.erase(tk);
00279               //std::cout << " shared item " << (*tk)->pT() << " removed from neighbour jet " << std::endl;
00280             }
00281             else
00282             {
00283               ilist.erase(where);
00284               ++tk;
00285               //std::cout << " shared item " << (*tk)->pT() << " removed from leading jet " << std::endl;
00286             }
00287           }
00288           else ++tk;
00289         }
00290         // recalculate jets imax and jmax
00291         
00292         // first erase all items
00293         imax.erase();
00294         // put items that are left
00295         for ( typename std::list<const Item*>::const_iterator it = ilist.begin();
00296               it != ilist.end(); ++it) imax.addItem(*it);
00297         // recalculated jet quantities
00298         imax.updateJet();
00299         imax.splitted();
00300         //std::cout << " jet split 2 :: " << imax.pT() << " "<< imax.info().nbMerge() << " " << imax.info().nbSplit() << std::endl; 
00301 
00302 
00303         // first erase all items
00304         jmax.erase();
00305         // put items that are left
00306         for ( typename std::list<const Item*>::const_iterator it = jlist.begin();
00307               it != jlist.end(); ++it) jmax.addItem(*it);
00308         // recalculated jet quantities
00309         jmax.updateJet();
00310         jmax.splitted();
00311         //std::cout << " jet split " << jmax.pT() << " "<< jmax.info().nbMerge() << " " << jmax.info().nbSplit() << std::endl; 
00312 
00313         _members.insert(std::make_pair(jmax,jmax.pT()));
00314       }
00315       _members.insert(std::make_pair(imax,imax.pT()));
00316     }
00317   } // while
00318 }
00319 ///////////////////////////////////////////////////////////////////////////////
00320 
00321 }  // namespace d0
00322 
00323 FASTJET_END_NAMESPACE
00324 
00325 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends