Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:15:01

0001 /** @file JetAnalyzer.hh
0002     @author Kauder:Kolja
0003     @version Revision 0.1
0004     @brief Light FastJet wrapper for Heavy Ion analysis
0005     program file and the functions in that file.
0006     @details Light FastJet wrapper for Heavy Ion analysis
0007     program file and the functions in that file.
0008     @date Mar 03, 2015
0009 */
0010 
0011 /**
0012    @mainpage
0013    Light, unified wrapper for Fastjet 3.x to simplify common Heavy Ion tasks. 
0014 
0015    Design decisions:
0016    - KISS. Please do event selection and track cleanup in the calling macro. 
0017    Provide this class with PseudoJets and try to stick to the FastJet way and c++ stl functionality as much as possible.
0018    - Derived from fastjet::ClusterSequenceArea.
0019    - Typical heavy ion workflow: 
0020      - Fill with an event
0021      - Cluster
0022      - Do analysis. This may require minimal extra data (e.g. A_J) or more information (e.g. jet-h)
0023      - Tweak the jets (using selectors, transformers, filters, etc.), or the underlying data a bit and repeat.
0024    - FastJet Selectors are really meant to operate on the _result_ of a clustering, but can be used 
0025    on the original constituents as well.
0026    - Therefore, we will keep a version of the original event, and request a constituent selector to choose on which particles 
0027    to actually perform the analysis. A result selector can be used via default fastjet machinery.
0028 
0029    Style:
0030    - Doxygen comments should go in the header files.
0031    - Please name your variables properly. 
0032    - Comment a lot.
0033    - Please try to keep track of changes. Use version control.
0034    - Please keep indentation clean. I'm using some combination of [K&R and GNU style](http://en.wikipedia.org/wiki/Indent_style#Styles), 
0035    but anything clean works. If it gets messed up, open it in emacs, mark everything, and hit tab once.
0036 */
0037 
0038 
0039 /*
0040   Author self-assessment statement: It gets the job done for A_J.
0041 */
0042 
0043 #ifndef JETANALYZER_H
0044 #define  JETANALYZER_H
0045 
0046 // Includes and namespaces
0047 //#include "FastJet3.h"
0048 #include "fastjet/ClusterSequence.hh"
0049 #include "fastjet/ClusterSequenceArea.hh"
0050 #include "fastjet/ClusterSequencePassiveArea.hh"
0051 #include "fastjet/ClusterSequenceActiveArea.hh"
0052 #include "fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh"
0053 #include "fastjet/Selector.hh"
0054 
0055 #include <TLorentzVector.h>
0056 #include <TClonesArray.h>
0057 
0058 #include "fastjet/tools/JetMedianBackgroundEstimator.hh"
0059 #include "fastjet/tools/Subtractor.hh"
0060 #include "fastjet/tools/Filter.hh"
0061 #include "fastjet/FunctionOfPseudoJet.hh"
0062 
0063 #include <iostream>
0064 #include <string>
0065 #include <sstream>
0066 
0067 // For pairs and sorting in the dijet finding
0068 #include <utility>
0069 #include <algorithm>
0070 
0071 
0072 /** The main class.
0073  */
0074 class JetAnalyzer : public fastjet::ClusterSequenceArea {
0075 
0076 private :  
0077   /** Keep a copy of the original constituents.
0078       In principle, they should be accessible via this->jets(),
0079       but there is extra space allocated in that vector and I'd rather not muck around with it.      
0080    */
0081   std::vector<fastjet::PseudoJet>& OrigParticles;
0082 
0083   /** Determined by whether we have an area definition */
0084   bool CanDoBackground;
0085   
0086   /**  For background subtraction.
0087        Pointer for now, so that it can be 0 if unused.
0088        Default specs and areas will be supplied.       
0089   */
0090   fastjet::JetMedianBackgroundEstimator* bkgd_estimator;
0091   /** Subtractor */
0092   fastjet::Subtractor* bkgd_subtractor;
0093 
0094   /** Background jet cut */
0095   fastjet::Selector selector_bkgd;
0096   /**  Background jet definiton */
0097   fastjet::JetDefinition* jet_def_bkgd;  
0098   /**  Background area definiton */
0099   fastjet::AreaDefinition* area_def_bkgd;
0100 
0101 public :
0102   // ------------
0103   // Constructors
0104   // ------------
0105   /** Standard constructor. 
0106       Pass through to Fastjet and set up internal background estimator with default values.
0107       Note that initialization as ClusterSequenceArea( pHi, jet_def, 0 ) works fine and skips the 
0108       area computation. Instead, we provide a second ctor and use this information to 
0109       determine whether to provide background capability.
0110       \param InOrigParticles is the full set of constituent candidates. Passed by reference!
0111       \param JetDef is a fastjet::JetDefinition for the clustering. Passed by reference!
0112       \param AreaDef is a fastjet::AreaDefinition for the clustering
0113       \param selector_bkgd is a fastjet::Selector for background subtraction
0114    */
0115   JetAnalyzer ( std::vector<fastjet::PseudoJet>& InOrigParticles, fastjet::JetDefinition& JetDef, fastjet::AreaDefinition& AreaDef,
0116         fastjet::Selector selector_bkgd=fastjet::SelectorAbsRapMax( 0.6 ) * (!fastjet::SelectorNHardest(2)) );
0117 
0118   /** Use as ClusterSequence, without area computation and without BG options
0119       \param InOrigParticles is the full set of constituent candidates. handed by reference!
0120       \param JetDef is a fastjet::JetDefinition for the clustering
0121    */
0122   JetAnalyzer ( std::vector<fastjet::PseudoJet>& InOrigParticles, fastjet::JetDefinition& JetDef );
0123   
0124   /** Destructor. Take care of all the objects created with new.
0125    */
0126   ~JetAnalyzer (){
0127     if ( area_def_bkgd )  {
0128       delete area_def_bkgd;
0129       area_def_bkgd = 0 ;
0130     }
0131     if ( jet_def_bkgd )  {
0132       delete jet_def_bkgd;
0133       jet_def_bkgd = 0 ;
0134     }
0135     if ( bkgd_estimator ) {
0136       delete bkgd_estimator;
0137       bkgd_estimator = 0 ;
0138     }
0139     if ( bkgd_subtractor ) {
0140       delete bkgd_subtractor;
0141       bkgd_subtractor = 0 ;
0142     }
0143     
0144   };
0145   
0146 
0147   // ----------------
0148   // Analysis methods
0149   // ----------------
0150 
0151   // -------------
0152   // Other Methods
0153   // -------------
0154   /** Background functionality.
0155       Currently, the jet definition is hard-coded to fastjet::kt_algorithm, jet_def().R(),
0156       and the area definition is computed internally. Expand and modify as needed.
0157    */
0158   fastjet::Subtractor* GetBackgroundSubtractor();
0159   /**
0160      Handle to BackgroundEstimator()
0161    */
0162   fastjet::JetMedianBackgroundEstimator* GetBackgroundEstimator() { return bkgd_estimator; };
0163   // ---------
0164   // Operators 
0165   // ---------
0166   // May eventually be added.
0167   // bool operator==(JetAnalyzer& rhs);
0168 
0169   // -------
0170   // Helpers
0171   // -------
0172   /** The nth version of this important constant.
0173    */
0174   static const double pi;
0175 
0176   /** Returns an angle between -pi and pi
0177    */
0178   static double phimod2pi ( double phi );  
0179   
0180 };
0181 
0182 // NOT part of the class!
0183 // =============================================================================
0184 /** Dijet finding as a Selector. Fashioned after fastjet::SW_NHardest.
0185     Searches for and returns dijet pairs within |&phi;1 - &phi;2 - &pi;| < &Delta;&phi;.
0186     returns 0 if no pair is found.
0187     In the current implementation, only the top two jets are compared.
0188 
0189     NOTE: Could also use something like
0190     \code
0191     Selector sel = SelectorCircle( dPhi );
0192     sel.set_reference( -jet1 ); // Pseudocode
0193     vector<PseudoJet> jets_near_MinusJet1 = sel(jets);
0194     \endcode
0195  */
0196 class SelectorDijetWorker : public fastjet::SelectorWorker{
0197 public:
0198   /** Standard constructor
0199       \param dPhi: Opening angle, searching for |&phi;1 - &phi;2 - &pi;| < &Delta;&phi;
0200   */
0201   SelectorDijetWorker( double dPhi )
0202     : dPhi(dPhi){};
0203   
0204   /// the selector's description
0205   std::string description() const{
0206     std::ostringstream oss;
0207     oss << "Searches for and returns dijet pairs within |phi1 - phi2 - pi| < " << dPhi;    
0208     return oss.str() ; 
0209   };
0210 
0211   /// Returns false, we need a jet ensemble.
0212   bool applies_jet_by_jet() const { return false;};
0213 
0214   /// Returns false, we need a jet ensemble.
0215   bool pass(const fastjet::PseudoJet& pj) const{
0216     if (!applies_jet_by_jet())
0217       throw ( std::string("Cannot apply this selector worker to an individual jet") );
0218     return false;
0219   };
0220 
0221   /// The relevant method
0222   void terminator(std::vector<const fastjet::PseudoJet *> & jets) const;
0223  
0224 private:
0225   const double dPhi;                   ///< Opening angle, searching for |&phi;1 - &phi;2 - &pi;| < &Delta;&phi;  
0226 };
0227 
0228 /** Helper for sorting pairs by second argument
0229  */
0230 struct sort_IntDoubleByDouble {
0231   /// returns left.second < right.second
0232   bool operator()(const std::pair<int,double> &left, const std::pair<int,double> &right) {
0233     return left.second < right.second;
0234   }
0235 };
0236 /** Determines whether two vector sets are matched 1 to 1.
0237     Actual Dijet selector
0238     \param dPhi: Dijet acceptance angle &Delta;&phi;
0239  */
0240 fastjet::Selector SelectorDijets( const double dPhi=0.4);
0241 
0242 
0243 
0244 // =============================================================================
0245 /** Determines whether two vector sets are matched 1 to 1.
0246     Could return something like lists of matches, but 
0247     for now it's using a primitive 1-to-1 matching.
0248     Enforcing 1-to-1 to avoid pathologies.
0249     For dijet A_J, the implementation is already overkill, but I want to
0250     lay the groundwork for more complex tasks
0251  */
0252 bool IsMatched ( const std::vector<fastjet::PseudoJet>& jetset1, const std::vector<fastjet::PseudoJet>& jetset2, const double Rmax );
0253 
0254 /** Check if one of the jets in jetset1 matches the reference. 
0255     TODO: Could use this in the vector-vector version
0256  */
0257 bool IsMatched ( const std::vector<fastjet::PseudoJet>& jetset1, const fastjet::PseudoJet& reference, const double Rmax );
0258 
0259 /** Check if jet and jet2 are matched 
0260     TODO: Could use this in the vector versions
0261  */
0262 bool IsMatched ( const fastjet::PseudoJet& jet1, const fastjet::PseudoJet& jet2, const double Rmax );
0263 
0264 
0265 
0266 // =============================================================================
0267 /** The best way to interface vector<PseudoJet> with ROOT seems to be via 
0268     TClonesArray<TLorentzVector>, so we'll provide some ways to go back and forth between them.
0269 */
0270 // ------------------------------------------------------------------------
0271 TLorentzVector MakeTLorentzVector ( const fastjet::PseudoJet& pj );
0272 // ------------------------------------------------------------------------
0273 
0274 // // =============================================================================
0275 // Experimental, not working.
0276 // Should work if this class is _instantiated_ and then the instance is used.
0277 // That's not really the usage scenario.
0278 // class MakeTLorentzVector : public fastjet::FunctionOfPseudoJet<TLorentzVector>{
0279 //   TLorentzVector result(const fastjet::PseudoJet &pj) const{
0280 //     return TLorentzVector( pj.px(), pj.py(), pj.pz(), pj.E() );
0281 //   };
0282 //   std::string description() const {return "Translates Pseudojet into ROOT TLorentzVector";}
0283 //   TLorentzVector operator()(const fastjet::PseudoJet & pj) const {return result(pj);};
0284 // };
0285 
0286 
0287 // =============================================================================
0288 /** The best way to interface vector<PseudoJet> with ROOT seems to be via 
0289     TClonesArray<TLorentzVector>, so we'll provide some ways to go back and forth between them.
0290     Pretty redundant, PseudoJet is a smart class and does all the work.
0291 */
0292 fastjet::PseudoJet MakePseudoJet ( const TLorentzVector* const lv );
0293 // =============================================================================
0294 // =============================================================================
0295 
0296 /** Simple UserInfo. Derived from PseudoJet::UserInfoBase. 
0297     Currently just providing charge, please add as appropriate.
0298     Based on 09-user__info_8cc_source.cc
0299  */
0300 class JetAnalysisUserInfo: public fastjet::PseudoJet::UserInfoBase {
0301 public:
0302   /// Standard Constructor
0303   JetAnalysisUserInfo(int quarkcharge=-999) :  quarkcharge( quarkcharge )  {};
0304   
0305   /// Charge in units of e/3
0306   int GetQuarkCharge() const { return quarkcharge; };
0307 
0308 private:
0309   const int quarkcharge;   ///< Charge in units of e/3
0310 };
0311 
0312 // =============================================================================
0313 /** This shows how we can build a Selector that uses the user-defined
0314     information to select particles by charge.
0315     Charge is in units of e/3!
0316     
0317     To create a user-defined Selector, the first step is to
0318     create its associated "worker" class, i.e. to derive a class from
0319     SelectorWorker. Then (see below), we just write a function
0320     that creates a Selector with the appropriate worker class.
0321 */
0322 class SelectorChargeWorker : public fastjet::SelectorWorker{
0323 public:
0324   /** Standard constructor
0325       \param cmin: inclusive lower bound
0326       \param cmax: inclusive upper bound
0327   */
0328   SelectorChargeWorker( const int cmin, const int cmax)  : cmin(cmin), cmax(cmax) {};
0329   
0330   /// the selector's description
0331   std::string description() const{
0332     std::ostringstream oss;
0333     oss.str("");
0334     oss << cmin << " <= quark charge <= " << cmax;    
0335     return oss.str() ; 
0336   };
0337   
0338   /// keeps the ones that have cmin <= quarkcharge <= cmax
0339   bool pass(const fastjet::PseudoJet &p) const{
0340     const int & quarkcharge = p.user_info<JetAnalysisUserInfo>().GetQuarkCharge();
0341     return (quarkcharge >= cmin) &&  (quarkcharge<= cmax);
0342   };
0343 
0344 private: 
0345   const int cmin; ///< inclusive lower bound
0346   const int cmax; ///< inclusive upper bound
0347   
0348 };
0349 // =============================================================================
0350 /** the function that allows to write simply
0351     
0352     Selector sel = SelectorChargeRange( cmin, cmax );
0353 */
0354 fastjet::Selector SelectorChargeRange( const int cmin=-999, const int cmax=999);
0355 
0356 // =============================================================================
0357 // =============================================================================
0358 // =============================================================================
0359 /** Helper to get an enum from a string
0360     we'll allow some more generous spellings and abbreviations
0361 */
0362 fastjet::JetAlgorithm AlgoFromString( std::string s);
0363 
0364 
0365 #endif // JETANALYZER_H