Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-22 10:55:45

0001 // -*- C++ -*-
0002 ///////////////////////////////////////////////////////////////////////////////
0003 // File: split_merge.h                                                       //
0004 // Description: header file for splitting/merging (contains the CJet class)  //
0005 // This file is part of the SISCone project.                                 //
0006 // WARNING: this is not the main SISCone trunk but                           //
0007 //          an adaptation to spherical coordinates                           //
0008 // For more details, see http://projects.hepforge.org/siscone                //
0009 //                                                                           //
0010 // Copyright (c) 2006-2008 Gavin Salam and Gregory Soyez                          //
0011 //                                                                           //
0012 // This program is free software; you can redistribute it and/or modify      //
0013 // it under the terms of the GNU General Public License as published by      //
0014 // the Free Software Foundation; either version 2 of the License, or         //
0015 // (at your option) any later version.                                       //
0016 //                                                                           //
0017 // This program is distributed in the hope that it will be useful,           //
0018 // but WITHOUT ANY WARRANTY; without even the implied warranty of            //
0019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
0020 // GNU General Public License for more details.                              //
0021 //                                                                           //
0022 // You should have received a copy of the GNU General Public License         //
0023 // along with this program; if not, write to the Free Software               //
0024 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
0025 //                                                                           //
0026 // $Revision::                                                              $//
0027 // $Date::                                                                  $//
0028 ///////////////////////////////////////////////////////////////////////////////
0029 
0030 #ifndef __SPH_SPLIT_MERGE_H__
0031 #define __SPH_SPLIT_MERGE_H__
0032 
0033 #include <siscone/defines.h>
0034 #include <siscone/config.h>
0035 #include "geom_2d.h"
0036 #include "momentum.h"
0037 #include <stdio.h>
0038 #include <vector>
0039 #include <set>
0040 #include <memory>
0041 #include <string>
0042 
0043 namespace siscone_spherical{
0044 
0045 const int CJET_INEXISTENT_PASS = -2;
0046 
0047 /**
0048  * \class CSphjet
0049  * real Jet information.
0050  *
0051  * This class contains information for one single jet. 
0052  * That is, first, its momentum carrying information
0053  * about its centre and pT, and second, its particle
0054  * contents
0055  */
0056 class CSphjet{
0057  public:
0058   /// default ctor
0059   CSphjet();
0060 
0061   /// default dtor
0062   ~CSphjet();
0063 
0064   CSphmomentum v;            ///< jet momentum
0065   double E_tilde;            ///< sum of E_i [ 1 +|p_i x p_J|^2/(|p_i|^2 E_J^2)]
0066   int n;                     ///< number of particles inside
0067   std::vector<int> contents; ///< particle contents (list of indices)
0068 
0069   /// ordering variable used for ordering and overlap in the
0070   /// split--merge. This variable is automatically set either to
0071   /// E_tilde or E depending on the siscone parameter.
0072   ///
0073   /// Note that the default behaviour is E_tilde and that other
0074   /// choices may lead to infrared unsafe situations.
0075   ///
0076   ///  Note: we use the square of the varible rather than the variable
0077   /// itself
0078   ///
0079   ///  Note 2: for the overlap computation, we shall use the jet energy!
0080   double sm_var2;
0081 
0082   /// covered range in eta-phi
0083   CSphtheta_phi_range range;
0084 
0085   /// pass at which the jet has been found
0086   /// It starts at 0 (first pass), -1 means infinite rapidity
0087   /// (it will be initialised to "CJET_INEXISTENT_PASS" which should
0088   /// never appear after clustering)
0089   int pass;
0090 };
0091 
0092 /// ordering of jets in pt
0093 ///bool jets_pt_less(const CSphjet &j1, const CSphjet &j2);
0094   
0095 /// ordering of jets in energy (e.g. used in final jets ordering)
0096 bool jets_E_less(const CSphjet &j1, const CSphjet &j2);
0097   
0098 
0099 /// the choices of scale variable that can be used in the split-merge
0100 /// step, both for ordering the protojets and for measuing their
0101 /// overlap; E is defined in E-scheme (4-momentum) recombination;
0102 /// Etilde = \sum_{i\in jet} E_i [1+sin^2(theta_{i,jet})]
0103 ///
0104 /// NB: if one changes the order here, one _MUST_ also change the order
0105 ///     in the SISCone plugin
0106 enum Esplit_merge_scale {
0107   SM_E,        ///< Energy (IR unsafe with momentum conservation)
0108   SM_Etilde    ///< sum_{i \in jet} E_i [1+sin^2(theta_iJ)]
0109 };
0110 
0111 /// return the name of the split-merge scale choice
0112 std::string split_merge_scale_name(Esplit_merge_scale sms);
0113 
0114 /**
0115  * \class CSphsplit_merge_ptcomparison
0116  * a class that allows us to carry out comparisons of pt of jets, using
0117  * information from exact particle contents where necessary.
0118  */
0119 class CSphsplit_merge_ptcomparison{
0120 public:
0121   /// default ctor
0122   CSphsplit_merge_ptcomparison() : 
0123     particles(0), split_merge_scale(SM_Etilde){};
0124 
0125   /// return the name corresponding to the SM scale variable
0126   std::string SM_scale_name() const {
0127     return split_merge_scale_name(split_merge_scale);}
0128 
0129   std::vector<CSphmomentum> * particles;  ///< pointer to the list of particles
0130   std::vector<double> * particles_norm2;  ///< pointer to the particles's norm^2
0131 
0132   /// comparison of 2 CSphjet
0133   bool operator()(const CSphjet &jet1, const CSphjet &jet2) const;
0134 
0135   /**
0136    * get the difference between 2 jets, calculated such that rounding
0137    * errors will not affect the result even if the two jets have
0138    * almost the same content (so that the difference is below the
0139    * rounding errors)
0140    *
0141    * \param j1        first jet
0142    * \param j2        second jet
0143    * \param v         jet1-jet2
0144    * \param E_tilde   jet1-jet2 E_tilde
0145    */
0146   void get_difference(const CSphjet &j1, const CSphjet &j2, CSphmomentum *v, double *E_tilde) const;
0147 
0148   /// the following parameter controls the variable we're using for 
0149   /// the split-merge process i.e. the variable we use for 
0150   ///  1. ordering jet candidates;
0151   ///  2. computing the overlap fraction of two candidates.
0152   /// The default value uses Etilde. The other alternative is E
0153   /// NOTE: Modifying the default choice can have nasty effects:
0154   /// - using E is IR-safe for QCD jets but the IR unsafety remains
0155   ///   for back-to-back jets of unstable narrow-width particles
0156   ///   (e.g. Higgs).
0157   /// Therefore, keeping the default value is strongly advised.
0158   Esplit_merge_scale split_merge_scale;
0159 };
0160 
0161 
0162 // iterator types
0163 /// iterator definition for the jet candidates structure
0164 typedef std::multiset<siscone_spherical::CSphjet,CSphsplit_merge_ptcomparison>::iterator cjet_iterator;
0165 
0166 /// iterator definition for the jet structure
0167 typedef std::vector<siscone_spherical::CSphjet>::iterator jet_iterator;
0168 
0169 
0170 
0171 /**
0172  * \class CSphsplit_merge
0173  * Class used to split and merge jets.
0174  */
0175 class CSphsplit_merge{
0176  public:
0177   /// default ctor
0178   CSphsplit_merge();
0179 
0180   /// default dtor
0181   ~CSphsplit_merge();
0182 
0183 
0184   //////////////////////////////
0185   // initialisation functions //
0186   //////////////////////////////
0187 
0188   /**
0189    * initialisation function
0190    * \param _particles  list of particles
0191    * \param protocones  list of protocones (initial jet candidates)
0192    * \param R2          cone radius (squared)
0193    * \param Emin        minimal energy allowed for jets
0194    * \return 0 on success, 1 on error
0195    */
0196   int init(std::vector<CSphmomentum> &_particles, std::vector<CSphmomentum> *protocones, double R2, double Emin=0.0);
0197 
0198   /**
0199    * initialisation function for particle list
0200    * \param _particles  list of particles
0201    * \return 0 on success, 1 on error
0202    */
0203   int init_particles(std::vector<CSphmomentum> &_particles);
0204 
0205   /**
0206    * build initial list of left particles
0207    */
0208   int init_pleft();
0209 
0210   /**
0211    * use an energy-dependent boundary for splitting
0212    * When called with true, the criterium for splitting two protojets 
0213    * will be to compare D1^2/kt1^2 vs. D2^2/kt2^2, the (anti-)kt-weighted 
0214    * distance instead of the plain distance D1^2 vs. D2^2.
0215    * This can be set in order to produce more circular hard jets, 
0216    * with the same underlying philosophy as for the anti-kt algorithm.
0217    * We thus expect a behaviour closer to the IterativeCone one. 
0218    * By default, we use the standard D1^2 vs. D2^2 comparison and this 
0219    * function is not called.
0220    */
0221   inline int set_E_weighted_splitting(bool _use_E_weighted_splitting){
0222     use_E_weighted_splitting = _use_E_weighted_splitting;
0223     return 0;
0224   }
0225 
0226   ////////////////////////
0227   // cleaning functions //
0228   ////////////////////////
0229 
0230   /// partial clearance
0231   int partial_clear();
0232 
0233   /// full clearance
0234   int full_clear();
0235 
0236   ///////////////////////////////////////
0237   // user-defined stable-cone ordering //
0238   ///////////////////////////////////////
0239 
0240   /// \class Cuser_scale_base
0241   /// base class for user-defined ordering of stable cones
0242   ///
0243   /// derived classes have to implement the () operator that returns
0244   /// the scale associated with a given jet.
0245   class Cuser_scale_base{
0246   public:
0247     /// empty virtual dtor
0248     virtual ~Cuser_scale_base(){}
0249 
0250     /// the scale associated with a given jet
0251     ///
0252     /// "progressive removal" iteratively removes the stable cone with
0253     /// the largest scale
0254     virtual double operator()(const CSphjet & jet) const = 0;
0255 
0256     /// returns true when the scale associated with jet a is larger than
0257     /// the scale associated with jet b
0258     ///
0259     /// By default this does a simple direct comparison but it can be
0260     /// overloaded for higher precision [recommended if possible]
0261     ///
0262     /// This function assumes that a.sm_var2 and b.sm_var2 have been
0263     /// correctly initialised with the signed squared output of
0264     /// operator(), as is by default the case when is_larger is called
0265     /// from within siscone.
0266     virtual bool is_larger(const CSphjet & a, const CSphjet & b) const{
0267       return (a.sm_var2 > b.sm_var2);
0268     }
0269   };
0270 
0271   /// associate a user-defined scale to order the stable cones
0272   ///
0273   /// Note that this is only used in "progressive-removal mode",
0274   /// e.g. in add_hardest_protocone_to_jets().
0275   void set_user_scale(const Cuser_scale_base * user_scale_in){
0276     _user_scale = user_scale_in;
0277   }
0278 
0279   /// return the user-defined scale (NULL if none)
0280   const Cuser_scale_base * user_scale() const { return _user_scale; }
0281 
0282 
0283   /////////////////////////////////
0284   // main parts of the algorithm //
0285   /////////////////////////////////
0286  
0287   /**
0288    * build the list 'p_uncol_hard' from p_remain by clustering
0289    * collinear particles 
0290    * note that thins in only used for stable-cone detection 
0291    * so the parent_index field is unnecessary
0292    *
0293    * Note that soft particles are not removed here
0294    * This is just a remnant from the trunk version
0295    */
0296   int merge_collinear_and_remove_soft();
0297 
0298   /**
0299    * add a list of protocones
0300    * \param protocones  list of protocones (initial jet candidates)
0301    * \param R2          cone radius (squared)
0302    * \param Emin        minimal emergy allowed for jets
0303    * \return 0 on success, 1 on error
0304    */
0305   int add_protocones(std::vector<CSphmomentum> *protocones, double R2, double Emin=0.0);
0306 
0307   /**
0308    * remove the hardest protocone and declare it a a jet 
0309    * \param protocones  list of protocones (initial jet candidates)
0310    * \param R2          cone radius (squared)
0311    * \param Emin        minimal emergy allowed for jets
0312    * \return 0 on success, 1 on error
0313    *
0314    * The list of remaining particles (and the uncollinear-hard ones)
0315    * is updated.
0316    */
0317   int add_hardest_protocone_to_jets(std::vector<CSphmomentum> *protocones, double R2, double Emin=0.0);
0318 
0319   /**
0320    * really do the splitting and merging
0321    * At the end, the vector jets is filled with the jets found.
0322    * the 'contents' field of each jets contains the indices
0323    * of the particles included in that jet. 
0324    * \param overlap_tshold  threshold for splitting/merging transition
0325    * \param Emin            minimal energy allowed for jets
0326    * \return the number of jets is returned
0327    */
0328   int perform(double overlap_tshold, double Emin=0.0);
0329 
0330 
0331   //////////////////////////////
0332   // save and debug functions //
0333   //////////////////////////////
0334 
0335   /// save final jets
0336   /// \param flux   stream to save the jet contentss
0337   int save_contents(FILE *flux);
0338 
0339   /// show jets/candidates status
0340   int show();
0341 
0342   // particle information
0343   int n;                                  ///< number of particles
0344   std::vector<CSphmomentum> particles;    ///< list of particles
0345   std::vector<double> particles_norm2;    ///< norm^2 of the particle (3-vect part)
0346   int n_left;                             ///< numer of particles that does not belong to any jet
0347   std::vector<CSphmomentum> p_remain;     ///< list of particles remaining to deal with
0348   std::vector<CSphmomentum> p_uncol_hard; ///< list of particles remaining with collinear clustering
0349   int n_pass;                             ///< index of the run
0350 
0351   /// minimal difference in squared distance between a particle and
0352   /// two overlapping protojets when doing a split (useful when
0353   /// testing approx. collinear safety)
0354   double most_ambiguous_split; 
0355 
0356   // jets information
0357   std::vector<CSphjet> jets;            ///< list of jets
0358 
0359   // working entries
0360   int *indices;                      ///< maximal size array for indices works
0361   int idx_size;                      ///< number of elements in indices1
0362 
0363   /// The following flag indicates that identical protocones
0364   /// are to be merged automatically each time around the split-merge
0365   /// loop and before anything else happens.
0366   ///
0367   /// This flag is only effective if ALLOW_MERGE_IDENTICAL_PROTOCONES
0368   /// is set in 'defines.h'
0369   /// Note that this lead to infrared-unsafety so it is disabled
0370   /// by default
0371   bool merge_identical_protocones;
0372 
0373   /// member used for detailed comparisons of pt's
0374   CSphsplit_merge_ptcomparison ptcomparison;
0375 
0376   /// stop split--merge or progressive-removal when the squared SM_var
0377   /// of the hardest protojet is below this cut-off. Note that this is
0378   /// a signed square (ie SM_var*|SM_var|) to be able to handle
0379   /// negative values.
0380   ///
0381   /// Note that the cut-off is set on the variable squared.
0382   double SM_var2_hardest_cut_off;
0383 
0384   /// Energy cutoff for the particles to put in p_uncol_hard 
0385   /// this is meant to allow removing soft particles in the
0386   /// stable-cone search.
0387   ///
0388   /// This is not collinear-safe so you should not use this
0389   /// variable unless you really know what you are doing
0390   /// Note that the cut-off is set on the variable squared.
0391   double stable_cone_soft_E2_cutoff;
0392 
0393  private:
0394   /**
0395    * get the overlap between 2 jets
0396    * \param j1   first jet
0397    * \param j2   second jet
0398    * \param v    returned overlap^2 (determined by the choice of SM variable)
0399    * \return true if overlapping, false if disjoint
0400    */
0401   bool get_overlap(const CSphjet &j1, const CSphjet &j2, double *v);
0402 
0403 
0404   /**
0405    * split the two given jets.
0406    * during this procedure, the jets j1 & j2 are replaced
0407    * by 2 new jets. Common particles are associted to the 
0408    * closest initial jet.
0409    * \param it_j1  iterator of the first jet in 'candidates'
0410    * \param it_j2  iterator of the second jet in 'candidates'
0411    * \param j1     first jet (CSphjet instance)
0412    * \param j2     second jet (CSphjet instance)
0413    * \return true on success, false on error
0414    */
0415   bool split(cjet_iterator &it_j1, cjet_iterator &it_j2);
0416 
0417   /**
0418    * merge the two given jet.
0419    * during this procedure, the jets j1 & j2 are replaced
0420    * by 1 single jets containing both of them.
0421    * \param it_j1  iterator of the first jet in 'candidates'
0422    * \param it_j2  iterator of the second jet in 'candidates'
0423    * \return true on success, false on error
0424    */
0425   bool merge(cjet_iterator &it_j1, cjet_iterator &it_j2);
0426 
0427   /**
0428    * Check whether or not a jet has to be inserted in the 
0429    * list of protojets. If it has, set its sm_variable and
0430    * insert it to the list of protojets.
0431    * \param jet    jet to insert
0432    */
0433   bool insert(CSphjet &jet);
0434 
0435   /**
0436    * given a 4-momentum and its associated pT, return the 
0437    * variable tht has to be used for SM
0438    * \param v          4 momentum of the protojet
0439    * \param E_tilde    E_tilde of the protojet
0440    */
0441   double get_sm_var2(CSphmomentum &v, double &E_tilde);
0442 
0443   /// compute Etilde for a given jet
0444   void compute_Etilde(CSphjet &j);
0445 
0446   // jet information
0447   /// list of jet candidates
0448 #ifdef SISCONE_USES_UNIQUE_PTR_AS_AUTO_PTR
0449   std::unique_ptr<std::multiset<CSphjet,CSphsplit_merge_ptcomparison> > candidates;
0450 #else
0451   std::auto_ptr<std::multiset<CSphjet,CSphsplit_merge_ptcomparison> > candidates;
0452 #endif
0453 
0454   /// minimal E
0455   double E_min;
0456 
0457   /**
0458    * do we have or not to use the energy-weighted splitting
0459    * (see description for set_E_weighted_splitting)
0460    * This will be false by default
0461    */
0462   bool use_E_weighted_splitting;
0463 
0464   /// use a user-defined scale to order the stable cones and jet
0465   /// candidates
0466   const Cuser_scale_base *_user_scale;
0467 
0468 #ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
0469   /// checkxor for the candidates (to avoid having twice the same contents)
0470   std::set<siscone::Creference> cand_refs;
0471 #endif
0472 };
0473 
0474 }
0475 
0476 
0477 #endif