Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:57:15

0001 // $Id: RecursiveSymmetryCutBase.hh 1074 2017-09-18 15:15:20Z gsoyez $
0002 //
0003 // Copyright (c) 2014-, Gavin P. Salam, Gregory Soyez, Jesse Thaler
0004 //
0005 //----------------------------------------------------------------------
0006 // This file is part of FastJet contrib.
0007 //
0008 // It is free software; you can redistribute it and/or modify it under
0009 // the terms of the GNU General Public License as published by the
0010 // Free Software Foundation; either version 2 of the License, or (at
0011 // your option) any later version.
0012 //
0013 // It is distributed in the hope that it will be useful, but WITHOUT
0014 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
0015 // or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
0016 // License for more details.
0017 //
0018 // You should have received a copy of the GNU General Public License
0019 // along with this code. If not, see <http://www.gnu.org/licenses/>.
0020 //----------------------------------------------------------------------
0021 
0022 #ifndef __FASTJET_CONTRIB_RECURSIVESYMMETRYCUTBASE_HH__
0023 #define __FASTJET_CONTRIB_RECURSIVESYMMETRYCUTBASE_HH__
0024 
0025 #include <limits>
0026 #include <cassert>
0027 #include <fastjet/internal/base.hh>
0028 #include "fastjet/tools/Transformer.hh"
0029 #include "fastjet/WrappedStructure.hh"
0030 #include "fastjet/CompositeJetStructure.hh"
0031 
0032 #include "fastjet/config.h"
0033 
0034 // we'll use the native FJ class for reculstering if available
0035 #if FASTJET_VERSION_NUMBER >= 30100
0036 #include "fastjet/tools/Recluster.hh"
0037 #else
0038 #include "Recluster.hh"
0039 #endif
0040 
0041 /** \mainpage RecursiveTools contrib 
0042 
0043     The RecursiveTools contrib provides a set of tools for
0044     recursive investigation jet substructure. Currently it includes:
0045     - fastjet::contrib::ModifiedMassDropTagger
0046     - fastjet::contrib::SoftDrop
0047     - fastjet::contrib::RecursiveSymmetryCutBase (from which the above two classes derive)
0048     - fastjet::contrib::IteratedSoftDropSymmetryFactors (defines ISD procedure)
0049     - fastjet::contrib::IteratedSoftDropMultiplicity (defines a useful observable using ISD)  
0050     - example*.cc provides usage examples
0051  */
0052 
0053 
0054 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
0055 
0056 namespace contrib{
0057 
0058 //------------------------------------------------------------------------
0059 /// \class RecursiveSymmetryCutBase
0060 /// A base class for all the tools that de-cluster a jet until a
0061 /// sufficiently symmetric configuration if found.
0062 ///
0063 /// Derived classes (so far, ModifiedMassDropTagger and SoftDrop) have to
0064 /// implement the symmetry cut and its description
0065 ///
0066 /// Note that by default, the jet will be reculstered with
0067 /// Cambridge/Aachen before applying the de-clustering procedure. This
0068 /// behaviour can be changed using set_clustering (see below).
0069 ///
0070 /// By default, this class behaves as a tagger, i.e. returns an empty
0071 /// PseudoJet if no substructure is found.  While the derived
0072 /// ModifiedMassDropTagger is a tagger, the derived SoftDrop is a groomer
0073 /// (i.e. it returns a non-zero jet even if no substructure is found).
0074 ///
0075 /// This class provides support for
0076 ///  - an optional mass-drop cut (see ctor)
0077 ///  - options to select which symmetry measure should be used (see ctor)
0078 ///  - options to select how the recursion proceeds (see ctor)
0079 ///  - options for reclustering the jet before running the de-clustering
0080 ///    (see set_reclustering)
0081 ///  - an optional subtractor (see ctor and other methods below)
0082 class RecursiveSymmetryCutBase : public Transformer {
0083 public:
0084   // ctors and dtors
0085   //----------------------------------------------------------------------
0086 
0087   /// an enum of the different (a)symmetry measures that can be used
0088   enum SymmetryMeasure{scalar_z,   ///< \f$ \min(p_{ti}, p_{tj})/(p_{ti} + p_{tj}) \f$
0089                        vector_z,   ///< \f$ \min(p_{ti}, p_{tj})/p_{t(i+j)} \f$
0090                        y,          ///< \f$ \min(p_{ti}^2,p_{tj}^2) \Delta R_{ij}^2 / m_{ij}^2 \f$
0091                        theta_E,    ///< \f$ \min(E_i,E_j)/(E_i+E_j) \f$ with 3d angle (ee collisions)
0092                        cos_theta_E ///< \f$ \min(E_i,E_j)/(E_i+E_j) \f$ with
0093                                    ///  \f$ \sqrt{2[1-cos(theta)]}\f$ for angles (ee collisions)
0094   };
0095 
0096   /// an enum for the options of how to choose which of two subjets to recurse into
0097   enum RecursionChoice{larger_pt, ///< choose the subjet with larger \f$ p_t \f$
0098                        larger_mt, ///< choose the subjet with larger \f$ m_t \equiv (m^2+p_t^2)^{\frac12}] \f$
0099                        larger_m,  ///< choose the subjet with larger mass (deprecated)
0100                        larger_E   ///< choose the subjet with larger energy (meant for ee collisions)
0101   }; 
0102 
0103   /// Full constructor, which takes the following parameters:
0104   ///
0105   /// \param symmetry_measure   the choice of measure to use to estimate the symmetry
0106   /// \param mu_cut             the maximal allowed value of mass drop variable mu = m_heavy/m_parent 
0107   /// \param recursion_choice   the strategy used to decide which subjet to recurse into
0108   /// \param subtractor         an optional pointer to a pileup subtractor (ignored if zero)
0109   ///
0110   /// If the (optional) pileup subtractor is supplied, then, by
0111   /// default, the input jet is assumed unsubtracted and the
0112   /// RecursiveSymmetryCutBase returns a subtracted 4-vector. [see
0113   /// also the set_input_jet_is_subtracted() member function].
0114   ///
0115   RecursiveSymmetryCutBase(SymmetryMeasure  symmetry_measure = scalar_z,
0116                double           mu_cut = std::numeric_limits<double>::infinity(), 
0117                RecursionChoice  recursion_choice = larger_pt,
0118                const FunctionOfPseudoJet<PseudoJet> * subtractor = 0
0119                ) : 
0120     _symmetry_measure(symmetry_measure),
0121     _mu_cut(mu_cut),
0122     _recursion_choice(recursion_choice),
0123     _subtractor(subtractor), _input_jet_is_subtracted(false),
0124     _do_reclustering(true), _recluster(0),
0125     _grooming_mode(false),
0126     _verbose_structure(false) // by default, don't story verbose information
0127   {}
0128     
0129   /// default destructor
0130   virtual ~RecursiveSymmetryCutBase(){}
0131 
0132   // access to class info
0133   //----------------------------------------------------------------------
0134   SymmetryMeasure symmetry_measure() const { return _symmetry_measure; }
0135   double mu_cut() const { return _mu_cut; }
0136   RecursionChoice recursion_choice() const { return _recursion_choice; }
0137 
0138   // internal subtraction configuration
0139   //----------------------------------------------------------------------
0140 
0141   /// This tells the tagger whether to assume that the input jet has
0142   /// already been subtracted. This is relevant only if a non-null
0143   /// subtractor pointer has been supplied, and the default assymption
0144   /// is that the input jet is passed unsubtracted.
0145   /// 
0146   /// Note: given that subtractors usually change the momentum of the
0147   /// main jet, but not that of the subjets, subjets will continue to
0148   /// have subtraction applied to them.
0149   void set_input_jet_is_subtracted(bool is_subtracted) {_input_jet_is_subtracted = is_subtracted;}
0150 
0151   /// returns a bool to indicate if the input jet is assumed already subtracted
0152   bool input_jet_is_subtracted() const {return _input_jet_is_subtracted;}
0153 
0154   /// an alternative way to set the subtractor
0155   ///
0156   /// Note that when a subtractor is provided, the result of the
0157   /// RecursiveSymmetryCutBase will be a subtracted jet.
0158   void set_subtractor(const FunctionOfPseudoJet<PseudoJet> * subtractor_) {_subtractor = subtractor_;}
0159 
0160   /// returns a pointer to the subtractor
0161   const FunctionOfPseudoJet<PseudoJet> * subtractor() const {return _subtractor;}
0162 
0163   // reclustering behaviour
0164   //----------------------------------------------------------------------
0165 
0166   /// configure the reclustering prior to the recursive de-clustering
0167   ///  \param do_reclustering   recluster the jet or not?
0168   ///  \param recluster         how to recluster the jet 
0169   ///                           (only if do_recluster is true; 
0170   ///                           Cambridge/Aachen used if NULL)
0171   ///
0172   /// Note that the ModifiedMassDropTagger and SoftDrop are designed
0173   /// to work with a Cambridge/Aachen clustering. Use any other option
0174   /// at your own risk!
0175   void set_reclustering(bool do_reclustering=true, const Recluster *recluster=0){
0176     _do_reclustering = do_reclustering;
0177     _recluster = recluster;
0178   }
0179 
0180   // what to do when no substructure is found
0181   //----------------------------------------------------------------------
0182   /// specify the behaviour adopted when no substructure is found
0183   ///  - in tagging  mode, an empty PseudoJet will be returned
0184   ///  - in grooming mode, a single particle is returned
0185   /// for clarity, we provide both function although they are redundant
0186   void set_grooming_mode(bool enable=true){ _grooming_mode = enable;}
0187   void set_tagging_mode(bool enable=true){ _grooming_mode = !enable;}
0188 
0189   
0190   /// Allows access to verbose information about recursive declustering,
0191   /// in particular values of symmetry, delta_R, and mu of dropped branches
0192   void set_verbose_structure(bool enable=true) { _verbose_structure = enable; }
0193   bool has_verbose_structure() const { return _verbose_structure; }
0194   
0195   
0196   // inherited from the Transformer base
0197   //----------------------------------------------------------------------
0198 
0199   /// the function that carries out the tagging; if a subtractor is
0200   /// being used, then this function assumes that input jet is
0201   /// unsubtracted (unless set_input_jet_is_subtracted(true) has been
0202   /// explicitly called before) and the result of the MMDT will be a
0203   /// subtracted jet.
0204   virtual PseudoJet result(const PseudoJet & j) const;
0205   
0206   /// description of the tool
0207   virtual std::string description() const;
0208 
0209   /// returns the gepometrical distance between the two particles
0210   /// depending on the symmetry measure used
0211   double squared_geometric_distance(const PseudoJet &j1,
0212                                     const PseudoJet &j2) const;
0213   
0214 
0215   class StructureType;
0216 
0217   /// for testing 
0218   static bool _verbose;
0219 
0220 protected:
0221   // the methods below have to be defined by deerived classes
0222   //----------------------------------------------------------------------
0223   /// the cut on the symmetry measure (typically z) that one need to
0224   /// apply for a given pair of subjets p1 and p2
0225   virtual double symmetry_cut_fn(const PseudoJet & /* p1 */, 
0226                                  const PseudoJet & /* p2 */,
0227                                  void *extra_parameters = 0) const = 0;
0228   /// the associated dwescription
0229   virtual std::string symmetry_cut_description() const = 0;
0230 
0231   //----------------------------------------------------------------------
0232   /// this defines status codes when checking for substructure
0233   enum RecursionStatus{
0234     recursion_success=0,   //< found some substructure
0235     recursion_dropped,     //< dropped softest prong; recursion continues
0236     recursion_no_parents,  //< down to constituents; bottom of recursion
0237     recursion_issue        //< something went wrong; recursion stops
0238   };
0239   
0240   //----------------------------------------------------------------------
0241   /// the method below is the one actually performing one step of the
0242   /// recursion.
0243   ///
0244   /// It returns a status code (defined above)
0245   ///
0246   /// In case of success, all the information is filled
0247   /// In case of "no parents", piee1 is the same subjet
0248   /// In case of trouble, piece2 will be a 0 PJ and piece1 is the PJ we
0249   ///   should return (either 0 itself if the issue was critical, or
0250   ///   non-wero in case of a minor issue just causing the recursion to
0251   ///   stop)
0252   ///
0253   /// The extra_parameter argument allows one to pass extra agruments
0254   /// to the symmetry condition
0255   RecursionStatus recurse_one_step(const PseudoJet & subjet,
0256                                    PseudoJet &piece1, PseudoJet &piece2,
0257                                    double &sym, double &mu2,
0258                                    void *extra_parameters = 0) const;
0259 
0260   //----------------------------------------------------------------------
0261   /// helper for handling the reclustering
0262   PseudoJet _recluster_if_needed(const PseudoJet &jet) const;
0263   
0264   //----------------------------------------------------------------------
0265   // helpers for selecting between ee and pp cases
0266   bool is_ee() const{
0267     return ((_symmetry_measure==theta_E) || (_symmetry_measure==cos_theta_E));
0268   }
0269 
0270 private:
0271   SymmetryMeasure  _symmetry_measure;
0272   double           _mu_cut;
0273   RecursionChoice  _recursion_choice;
0274   const FunctionOfPseudoJet<PseudoJet> * _subtractor;
0275   bool             _input_jet_is_subtracted;
0276 
0277   bool _do_reclustering;       ///< start with a reclustering
0278   const Recluster *_recluster; ///< how to recluster the jet
0279 
0280   bool _grooming_mode;  ///< grooming or tagging mode
0281 
0282   static LimitedWarning   _negative_mass_warning;
0283   static LimitedWarning   _mu2_gt1_warning;
0284   //static LimitedWarning   _nonca_warning;
0285   static LimitedWarning   _explicit_ghost_warning;
0286 
0287   // additional verbose structure information
0288   bool _verbose_structure;
0289   
0290   /// decide what to return when no substructure has been found
0291   PseudoJet _result_no_substructure(const PseudoJet &last_parent) const;
0292 };
0293 
0294   
0295   
0296 //----------------------------------------------------------------------
0297 /// class to hold the structure of a jet tagged by RecursiveSymmetryCutBase.
0298 class RecursiveSymmetryCutBase::StructureType : public WrappedStructure {
0299 public:
0300   StructureType(const PseudoJet & j) :
0301     WrappedStructure(j.structure_shared_ptr()), _delta_R(-1.0), _symmetry(-1.0), _mu(-1.0),
0302     _is_composite(false), _has_verbose(false) // by default, do not store verbose structure
0303   {}
0304 
0305   /// construct a structure with
0306   ///  - basic info inherited from the reference jet "j"
0307   ///  - a given deltaR       for substructure
0308   ///  - a given symmetry     for substructure
0309   ///  - a given mu parameter for substructure
0310   /// If j is a "copmposite jet", it means that it has further
0311   /// substructure to potentially recurse  into
0312   StructureType(const PseudoJet & j, double delta_R_in, double symmetry_in, double mu_in=-1.0) :
0313     WrappedStructure(j.structure_shared_ptr()), _delta_R(delta_R_in), _symmetry(symmetry_in), _mu(mu_in),
0314     _is_composite(dynamic_cast<const CompositeJetStructure*>(j.structure_ptr()) != NULL),
0315     _has_verbose(false) // by default, do not store verbose structure
0316   {}
0317   
0318   // information about kept branch
0319   double delta_R()  const {return _delta_R;}
0320   double thetag()   const {return _delta_R;}  // alternative name
0321   double symmetry() const {return _symmetry;}
0322   double zg()       const {return _symmetry;} // alternative name
0323   double mu()       const {return _mu;}
0324   
0325   // additional verbose information about dropped branches
0326   bool has_verbose() const { return _has_verbose;}
0327   void set_verbose(bool value) { _has_verbose = value;}
0328 
0329   /// returns true if the current jet has some substructure (i.e. has
0330   /// been tagged by the resursion) or not
0331   ///
0332   /// Note that this should include deltaR==0 (e.g. a perfectly
0333   /// collinear branching with SoftDrop)
0334   bool has_substructure() const { return _delta_R>=0; }
0335   
0336   /// number of dropped branches
0337   int dropped_count(bool global=true) const;
0338   
0339   /// delta_R of dropped branches
0340   /// when "global" is set, recurse into possile further substructure
0341   std::vector<double> dropped_delta_R(bool global=true) const;
0342   void set_dropped_delta_R(const std::vector<double> &v) { _dropped_delta_R = v; }
0343 
0344   /// symmetry values of dropped branches
0345   std::vector<double> dropped_symmetry(bool global=true) const;
0346   void set_dropped_symmetry(const std::vector<double> &v) { _dropped_symmetry = v; }
0347 
0348   /// mass drop values of dropped branches
0349   std::vector<double> dropped_mu(bool global=true) const;
0350   void set_dropped_mu(const std::vector<double> &v) { _dropped_mu = v; }
0351   
0352   /// maximum symmetry value dropped
0353   double max_dropped_symmetry(bool global=true) const;
0354 
0355   /// (global) list of groomed away elements as zg and thetag
0356   /// sorted from largest to smallest anlge
0357   std::vector<std::pair<double,double> > sorted_zg_and_thetag() const;
0358 
0359 private:
0360   double _delta_R, _symmetry, _mu;
0361   friend class RecursiveSymmetryCutBase;
0362 
0363   bool _is_composite;
0364   
0365   // additional verbose information
0366   bool _has_verbose;
0367   // information about dropped values
0368   std::vector<double> _dropped_delta_R;
0369   std::vector<double> _dropped_symmetry;
0370   std::vector<double> _dropped_mu;
0371 
0372   bool check_verbose(const std::string &what) const{
0373     if (!_has_verbose){
0374       throw Error("RecursiveSymmetryCutBase::StructureType: Verbose structure must be turned on to get "+what+".");
0375       return false;
0376     }
0377     return true;
0378   }
0379     
0380   
0381 };
0382 
0383 } // namespace contrib
0384 
0385 FASTJET_END_NAMESPACE
0386 
0387 #endif  // __FASTJET_CONTRIB_RECURSIVESYMMETRYCUTBASE_HH__