Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // JetsWithoutJets Package
0002 // Questions/Comments? danbert@mit.edu jthaler@mit.edu
0003 //
0004 // Copyright (c) 2013
0005 // Daniele Bertolini and Jesse Thaler
0006 //
0007 // $Id: JetsWithoutJets.hh 554 2014-02-21 19:02:08Z danbert $
0008 //----------------------------------------------------------------------
0009 // This file is part of FastJet contrib.
0010 //
0011 // It is free software; you can redistribute it and/or modify it under
0012 // the terms of the GNU General Public License as published by the
0013 // Free Software Foundation; either version 2 of the License, or (at
0014 // your option) any later version.
0015 //
0016 // It is distributed in the hope that it will be useful, but WITHOUT
0017 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
0018 // or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
0019 // License for more details.
0020 //
0021 // You should have received a copy of the GNU General Public License
0022 // along with this code. If not, see <http://www.gnu.org/licenses/>.
0023 //----------------------------------------------------------------------
0024 
0025 #ifndef __FASTJET_CONTRIB_JETSWITHOUTJETS_HH__
0026 #define __FASTJET_CONTRIB_JETSWITHOUTJETS_HH__
0027 
0028 #include <fastjet/internal/base.hh>
0029 #include "fastjet/FunctionOfPseudoJet.hh"
0030 #include "fastjet/tools/Transformer.hh"
0031 #include "fastjet/JetDefinition.hh"
0032 #include "fastjet/PseudoJet.hh"
0033 #include "fastjet/ClusterSequence.hh"
0034 #include "fastjet/SharedPtr.hh"
0035 #include <string>
0036 #include <algorithm> 
0037 
0038 #include "EventStorage.hh"
0039 
0040 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
0041 
0042 namespace jwj {
0043 
0044 //////
0045 //
0046 // Defining a function of a vector of PseudoJets
0047 //
0048 //////
0049 
0050 //----------------------------------------------------------------------
0051 // MyFunctionOfVectorOfPseudoJets
0052 // In current version of FastJet there is no standard interface for a function
0053 // that takes a vector of PseudoJets as argument. This class serves as a base class
0054 // and it is the analog of FunctionOfPseudoJet, it only differs in taking a vector
0055 // of PseudoJets as argument. Should a standard interface become available, this
0056 // class could be removed and the classes below (like JetLikeEventShape,
0057 // FunctionUnity, etc.) could derive from the standard base class.
0058 
0059 template<typename TOut>
0060 class MyFunctionOfVectorOfPseudoJets {
0061    
0062 public:
0063    
0064    MyFunctionOfVectorOfPseudoJets(){}
0065    
0066    MyFunctionOfVectorOfPseudoJets(const TOut &constant_value);
0067    
0068    virtual ~MyFunctionOfVectorOfPseudoJets(){}
0069    
0070    virtual std::string description() const{ return "";}
0071    
0072    virtual TOut result(const std::vector<PseudoJet> &pjs) const = 0;
0073    
0074    TOut operator()(const std::vector<PseudoJet> &pjs) const { return result(pjs);}
0075 };
0076 
0077 
0078 //////
0079 //
0080 // Extendable Jet-like Event Shapes
0081 // (works on any function of vector<PseudoJet> that returns double)
0082 //
0083 //////
0084 
0085 
0086 //----------------------------------------------------------------------
0087 // JetLikeEventShape
0088 // Event shape that corresponds to a jet-based observable (summed over all jets).
0089 // It takes a Function (derived from MyFunctionOfVectorOfPseudoJets) that would 
0090 // correspond to a measurement done on each jet as an argument and it applies it to cones or radius R around each particle, 
0091 // then sums over all such "jets" which are above pTcut threshold. 
0092 // Optional trimming built in.  Note that in general trimming first,
0093 // then applying the event shape gives a different answer.
0094 // Only works with quantities that are doubles for each jet
0095 // (could templatize, but easier to deal with case by case)
0096 // If one wants to derive one's own JetLikeEventShape that is not based on a measurement,
0097 // then one has to overload the virtual result(EventStorage & myStorage) function.
0098 
0099 class JetLikeEventShape: public MyFunctionOfVectorOfPseudoJets<double>{
0100    
0101 public:
0102    
0103    JetLikeEventShape(): _measurement(NULL),_useLocalStorage(true) {}
0104    
0105    // Constructor without trimming. By default it uses LocalStorage, it stores neighbors and and it does not store mass of neighbors. 
0106    // Measurement is automatically deleted when destructor is called.
0107    JetLikeEventShape(MyFunctionOfVectorOfPseudoJets<double> * measurement, double Rjet, double ptcut)
0108    : _measurement(measurement), _Rjet(Rjet), _ptcut(ptcut), _Rsub(Rjet), _fcut(1.0), _trim(false),_useLocalStorage(true),_storeNeighbors(true),_storeMass(false) {}
0109    
0110    // Constructor with trimming. By default it uses LocalStorage, it stores neighbors and it does not store mass of neighbors. 
0111    // Measurement is automatically deleted when destructor is called.
0112    JetLikeEventShape(MyFunctionOfVectorOfPseudoJets<double> * measurement, double Rjet, double ptcut, double Rsub, double fcut)
0113    : _measurement(measurement), _Rjet(Rjet), _ptcut(ptcut), _Rsub(Rsub), _fcut(fcut), _trim(true),_useLocalStorage(true),_storeNeighbors(true),_storeMass(false) {}
0114    
0115    virtual ~JetLikeEventShape(){ if(_measurement) delete _measurement;}
0116    
0117    // This result function takes an EventStorage as input and returns the event shape value.
0118    // Call directly this function if you want to use a pre-built EventStorage 
0119    // This function is overloaded for built-in JetLikeEventShapes
0120    virtual double result(EventStorage & myStorage) const {
0121       
0122       double myMeasurement = 0.0;
0123       
0124       // check if storage can be used for this shape
0125       if (!_check_storage_parameters(myStorage) || !myStorage.storeNeighbors() ) {
0126          throw Error("Storage cannot be used for this shape"); 
0127       } else {
0128          // loop through all particles
0129          for (unsigned int i = 0; i<myStorage.size(); i++) {
0130             // for particles above the cut add the measurement weighted by
0131             // the fraction of pT carried by particle i in a neightborhood of radius R
0132             if (myStorage[i].includeParticle()) myMeasurement += myStorage[i].weight()*_measurement->result(myStorage.particles_near_to(i));
0133          }
0134       }
0135       return myMeasurement;
0136    }
0137    
0138    // Standard result function. It takes a vector<PseudoJet> as input and returns the event shape.
0139    // It creates the appropriate EventStorage and calls result(EventStorage & myStorage)
0140    double result(const std::vector<PseudoJet> & particles) const {
0141       EventStorage myStorage(_Rjet,_ptcut,_Rsub,_fcut,_useLocalStorage,_storeNeighbors,_storeMass);
0142       myStorage.establishStorage(particles);        
0143       
0144       return (result(myStorage));
0145    }
0146    
0147    // Choose whether to use LocalStorage or not (on by default).
0148    // In general, no reason not turn it off except for debugging.
0149    void setUseLocalStorage(bool useLocalStorage) {_useLocalStorage = useLocalStorage;}      
0150    
0151    // Description
0152    std::string jetParameterString() const {
0153       std::stringstream stream;
0154       stream << "R_jet=" << _Rjet << ", pT_cut=" << _ptcut;
0155       if (_trim) stream << ", trimming with R_sub=" << _Rsub <<", fcut=" << _fcut;
0156       return stream.str();
0157    }
0158    
0159    virtual std::string description() const {
0160       return "Summed " + _measurement->description() + " as event shape, " + jetParameterString();
0161    }
0162    
0163    
0164 protected:
0165    
0166    MyFunctionOfVectorOfPseudoJets<double> * _measurement;
0167    
0168    double _Rjet, _ptcut, _Rsub, _fcut;
0169    bool _trim;
0170    
0171    // optional storage array to cache the 2R x 2R partitions.
0172    bool _useLocalStorage;
0173    
0174    // Choose whether to store neighbors or not, and wheter to store mass of neighbors or not.
0175    // By default it stores neighbors, but not needed for the built-in JetLikeEventShapes
0176    // Also, by default it does not store mass of neighbors, but needed for built-in jet mass or mass squared shapes.
0177    bool _storeNeighbors,_storeMass;
0178    void _setStoreNeighbors(bool storeNeighbors) {_storeNeighbors=storeNeighbors;}
0179    void _setStoreMass(bool storeMass) {_storeMass=storeMass;}
0180    
0181    // helper to check if an external EventStorage can be used for this JetLikeEventShape (i.e. whether it has been built using the same parameters)
0182    bool _check_storage_parameters(EventStorage & myStorage) const {
0183       bool answer = false;
0184       if(!_trim) answer = myStorage.Rjet()==_Rjet && myStorage.ptcut()==_ptcut;
0185       else answer = myStorage.Rjet()==_Rjet && myStorage.ptcut()==_ptcut && myStorage.Rsub()==_Rsub && myStorage.fcut()==_fcut;
0186       
0187       return answer;
0188    }
0189    
0190 };
0191 
0192 
0193 
0194 //////
0195 //
0196 // Example Functions to Use
0197 //
0198 //////
0199 
0200 //----------------------------------------------------------------------
0201 // Below are examples of function to use as measurement in JetLikeEventShape.
0202 // Most of these are irrevant since there are built-in JetLikeEventShapes,
0203 // but we have maintained them for debugging purposes.
0204 
0205 //----------------------------------------------------------------------
0206 // FunctionUnity
0207 // Returns 1 for each jet
0208 
0209 class FunctionUnity : public MyFunctionOfVectorOfPseudoJets<double> {
0210    
0211    double result(const std::vector<PseudoJet> & particles) const { return 1.0; }
0212    
0213    std::string description() const { return "Jet unit weight";}
0214 };
0215 
0216 //----------------------------------------------------------------------
0217 // FunctionScalarPtSum
0218 // Finds the summed pt of the jet constituents (NOT the pT of the jet)
0219 
0220 class FunctionScalarPtSum : public MyFunctionOfVectorOfPseudoJets<double> {
0221    
0222    double result(const std::vector<PseudoJet> & particles) const {
0223       double myPt = 0.0;
0224       for (unsigned int i = 0; i<particles.size(); i++) {
0225          myPt += particles[i].pt();
0226       }
0227       return myPt;
0228    }
0229    
0230    std::string description() const { return "Jet Scalar Pt";}
0231 };
0232 
0233 //----------------------------------------------------------------------
0234 // FunctionScalarPtSumToN
0235 // Raises FunctionScalarPtSum to an arbitrary Power
0236 
0237 class FunctionScalarPtSumToN : public MyFunctionOfVectorOfPseudoJets<double> {
0238    
0239 private:
0240    int _n;
0241    
0242 public:
0243    
0244    FunctionScalarPtSumToN(int n) : _n(n) {}
0245    double result(const std::vector<PseudoJet> & particles) const {
0246       FunctionScalarPtSum sumPt = FunctionScalarPtSum();
0247       return pow(sumPt(particles),_n);
0248    }
0249    
0250    std::string description() const {
0251       std::stringstream myStream;
0252       myStream << "Jet Scalar Pt^" << _n;
0253       return myStream.str();
0254    }
0255 };
0256 
0257 
0258 //----------------------------------------------------------------------
0259 // FunctionInvariantMass
0260 // Finds the mass of the jet
0261 
0262 class FunctionInvariantMass : public MyFunctionOfVectorOfPseudoJets<double> {
0263    
0264    double result(const std::vector<PseudoJet> & particles) const {
0265       PseudoJet myJet(0,0,0,0);
0266       for (unsigned int i = 0; i<particles.size(); i++) {
0267          myJet += particles[i];
0268       }
0269       return myJet.m();
0270    }
0271    
0272    std::string description() const { return "Jet Mass";}
0273 };
0274 
0275 //----------------------------------------------------------------------
0276 // FunctionInvariantMassSquared
0277 // Finds the squared mass of the jet
0278 
0279 class FunctionInvariantMassSquared : public MyFunctionOfVectorOfPseudoJets<double> {
0280    
0281    double result(const std::vector<PseudoJet> & particles) const {
0282       PseudoJet myJet(0,0,0,0);
0283       for (unsigned int i = 0; i<particles.size(); i++) {
0284          myJet += particles[i];
0285       }
0286       return myJet.m2();
0287    }
0288    
0289    std::string description() const { return "Jet Mass^2";}
0290 };
0291 
0292 
0293 
0294 //////
0295 //
0296 // Built-In Jet-like Event Shapes
0297 //
0298 //////
0299 
0300 //----------------------------------------------------------------------
0301 // The following JetLikeEventShapes are hard coded.
0302 // They don't use an external measurement function,
0303 // but use information stored in EventStorage to reduce computation time
0304 
0305 
0306 //----------------------------------------------------------------------
0307 // ShapeJetMultiplicity
0308 // Defines event shape jet counting
0309 
0310 class ShapeJetMultiplicity: public JetLikeEventShape {
0311    
0312 public:
0313    
0314    ShapeJetMultiplicity(double Rjet, double ptcut): JetLikeEventShape(NULL,Rjet,ptcut) {_setStoreNeighbors(false);} //Don't need to store neighbors
0315    ShapeJetMultiplicity(double Rjet, double ptcut, double Rsub, double fcut) : 
0316    JetLikeEventShape(NULL,Rjet,ptcut,Rsub,fcut) {_setStoreNeighbors(false);}
0317    ~ShapeJetMultiplicity(){}
0318    
0319    // Call directly this function if you want to use a pre-built EventStorage 
0320    double result(EventStorage & myStorage) const {
0321       
0322       double myMeasurement = 0.0;
0323       
0324       // if this result function is called with a pre-built storage need to check if storage can be used for this shape
0325       if(!_check_storage_parameters(myStorage)) throw Error("Storage parameters are not consistent with shape parameters"); 
0326       else {
0327          for (unsigned int i = 0; i<myStorage.size(); i++){
0328             if(myStorage[i].includeParticle()) myMeasurement += myStorage[i].weight(); //counting is just summing the weights.
0329          }
0330       }
0331       return myMeasurement;
0332    }
0333    
0334    std::string description() const {
0335       return "Jet multiplicity as event shape, " + jetParameterString();
0336    }
0337    
0338 };
0339 
0340 //----------------------------------------------------------------------
0341 // ShapeScalarPt
0342 // Defines event shape scalar pT sum
0343 
0344 class ShapeScalarPt: public JetLikeEventShape{
0345    
0346 public:
0347    
0348    ShapeScalarPt(double Rjet, double ptcut): JetLikeEventShape(NULL,Rjet,ptcut) {_setStoreNeighbors(false);} //Don't need to store neighbors
0349    ShapeScalarPt(double Rjet, double ptcut, double Rsub, double fcut) : JetLikeEventShape(NULL,Rjet,ptcut,Rsub,fcut) {_setStoreNeighbors(false);}
0350    ~ShapeScalarPt(){}
0351    
0352    // Call directly this function if you want to use a pre-built EventStorage 
0353    double result(EventStorage & myStorage) const {
0354       
0355       double myMeasurement = 0.0;
0356       
0357       // if this result function is called with a pre-built storage need to check if storage can be used for this shape
0358       if(!_check_storage_parameters(myStorage)) throw Error("Storage parameters are not consistent with shape parameters"); 
0359       else{
0360          for (unsigned int i = 0; i<myStorage.size(); i++){
0361             if(myStorage[i].includeParticle()) myMeasurement += myStorage[i].pt();
0362          }
0363       }
0364       return myMeasurement;
0365    }
0366    
0367    std::string description() const {
0368       return "Summed scalar pt as event shape, " + jetParameterString();
0369    }
0370 };
0371 
0372 
0373 //----------------------------------------------------------------------
0374 // ShapeScalarPtToN
0375 // Sum of pT^n of jets 
0376 
0377 class ShapeScalarPtToN: public JetLikeEventShape {
0378    
0379 public:
0380    
0381    ShapeScalarPtToN(double n, double Rjet, double ptcut): JetLikeEventShape(NULL,Rjet,ptcut), _n(n) {_setStoreNeighbors(false);} //Don't need to store neighbors
0382    ShapeScalarPtToN(double n, double Rjet, double ptcut, double Rsub, double fcut) : 
0383    JetLikeEventShape(NULL,Rjet,ptcut,Rsub,fcut), _n(n) {_setStoreNeighbors(false);}
0384    ~ShapeScalarPtToN(){}
0385    
0386    
0387    // Call directly this function if you want to use a pre-built EventStorage 
0388    double result(EventStorage & myStorage) const {
0389       
0390       double myMeasurement = 0.0;
0391       
0392       // if this result function is called with a pre-built storage need to check if storage can be used for this shape
0393       if(!_check_storage_parameters(myStorage)) throw Error("Storage parameters are not consistent with shape parameters"); 
0394       else{
0395          for (unsigned int i = 0; i<myStorage.size(); i++){
0396             if(myStorage[i].includeParticle()) myMeasurement += myStorage[i].pt()*pow(myStorage[i].pt_in_Rjet(),_n-1);
0397          }
0398       }
0399       return myMeasurement;
0400    }        
0401    
0402    
0403    std::string description() const {
0404       std::stringstream myStream;
0405       myStream << "Jet Scalar Pt^" << _n <<"as event shape, ";
0406       return myStream.str()+jetParameterString();
0407    }
0408    
0409 protected:
0410    
0411    int _n;
0412 };
0413 
0414 //----------------------------------------------------------------------
0415 // ShapeSummedMass
0416 // Sum over jet masses 
0417 
0418 class ShapeSummedMass: public JetLikeEventShape {
0419    
0420 public:
0421    
0422    ShapeSummedMass(double Rjet, double ptcut): JetLikeEventShape(NULL,Rjet,ptcut) {
0423       _setStoreNeighbors(false); 
0424       _setStoreMass(true);} //Don't need to store neighbors, but need to store mass of neighbors
0425    
0426    ShapeSummedMass(double Rjet, double ptcut, double Rsub, double fcut) : JetLikeEventShape(NULL,Rjet,ptcut,Rsub,fcut) {
0427       _setStoreNeighbors(false);
0428       _setStoreMass(true);}
0429    ~ShapeSummedMass(){}
0430    
0431    
0432    // Call directly this function if you want to use a pre-built EventStorage 
0433    double result(EventStorage & myStorage) const {
0434       
0435       double myMeasurement = 0.0;
0436       
0437       // if this result function is called with a pre-built storage need to check if storage can be used for this shape
0438       if(!_check_storage_parameters(myStorage)) throw Error("Storage parameters are not consistent with shape parameters"); 
0439       else if(!myStorage.storeMass()) throw Error("Mass is not stored, can't use this EventStorage"); 
0440       else{
0441          for (unsigned int i = 0; i<myStorage.size(); i++){
0442             if(myStorage[i].includeParticle()) myMeasurement += myStorage[i].weight()*myStorage[i].m_in_Rjet();
0443          }
0444       }
0445       return myMeasurement;
0446    }        
0447    
0448    std::string description() const {
0449       return "Summed jet mass as event shape, " + jetParameterString();
0450    }
0451 };
0452 
0453 //----------------------------------------------------------------------
0454 // ShapeSummedMassSquared
0455 // Sum over jet mass^2
0456 
0457 class ShapeSummedMassSquared: public JetLikeEventShape {
0458    
0459 public:
0460    
0461    ShapeSummedMassSquared(double Rjet, double ptcut): JetLikeEventShape(NULL,Rjet,ptcut) {
0462       _setStoreNeighbors(false);
0463       _setStoreMass(true);} //Don't need to store neighbors, but need to store mass of neighbors.
0464    
0465    ShapeSummedMassSquared(double Rjet, double ptcut, double Rsub, double fcut) : 
0466    JetLikeEventShape(NULL,Rjet,ptcut,Rsub,fcut) {
0467       _setStoreNeighbors(false);
0468       _setStoreMass(true);}
0469    virtual ~ShapeSummedMassSquared(){}
0470    
0471    
0472    // Call directly this function if you want to use a pre-built EventStorage 
0473    double result(EventStorage & myStorage) const {
0474       
0475       double myMeasurement = 0.0;
0476       
0477       // if this result function is called with a pre-built storage need to check if storage can be used for this shape
0478       if(!_check_storage_parameters(myStorage)) throw Error("Storage parameters are not consistent with shape parameters"); 
0479       else if(!myStorage.storeMass()) throw Error("Mass is not stored, can't use this EventStorage"); 
0480       else{
0481          for (unsigned int i = 0; i<myStorage.size(); i++){
0482             if(myStorage[i].includeParticle()) myMeasurement += myStorage[i].weight()*myStorage[i].m_in_Rjet()*myStorage[i].m_in_Rjet();
0483          }
0484       }
0485       return myMeasurement;
0486    }            
0487    
0488    std::string description() const {
0489       return "Summed squared jet mass as event shape, " + jetParameterString();
0490    }
0491 };
0492 
0493 
0494 //----------------------------------------------------------------------
0495 // ShapeMissingPt is pT of the vector sum of jets momenta.
0496 
0497 class ShapeMissingPt : public JetLikeEventShape {
0498    
0499 public:
0500    
0501    ShapeMissingPt(double Rjet, double ptcut): JetLikeEventShape(NULL,Rjet,ptcut) {_setStoreNeighbors(false);} //Don't need to store neighbors
0502    ShapeMissingPt(double Rjet, double ptcut, double Rsub, double fcut) : JetLikeEventShape(NULL,Rjet,ptcut,Rsub,fcut) {_setStoreNeighbors(false);}
0503    ~ShapeMissingPt(){}
0504    
0505    
0506    // Call directly this function if you want to use a pre-built EventStorage 
0507    double result(EventStorage & myStorage) const {
0508       
0509       double tot_px = 0.0;
0510       double tot_py = 0.0;
0511       
0512       // if this result function is called with a pre-built storage need to check if storage can be used for this shape
0513       if(!_check_storage_parameters(myStorage)) throw Error("Storage parameters are not consistent with shape parameters"); 
0514       else{
0515          for (unsigned int i = 0; i<myStorage.size(); i++){
0516             if(myStorage[i].includeParticle()){
0517                tot_px += myStorage[i].px();
0518                tot_py += myStorage[i].py();
0519             }
0520          }
0521       }
0522       return sqrt(tot_px*tot_px+tot_py*tot_py);
0523    }        
0524    
0525    
0526    std::string description() const {
0527       return "Missing pt as event shape, " + jetParameterString();
0528    }
0529 };
0530 
0531 //----------------------------------------------------------------------
0532 // ShapeTrimmedSubjetMultiplicity
0533 // A counter for subjets within trimmed fat jets.  
0534 
0535 class ShapeTrimmedSubjetMultiplicity: public JetLikeEventShape {
0536    
0537 public:
0538    
0539    ShapeTrimmedSubjetMultiplicity(double Rjet, double ptcut, double Rsub, double fcut,double ptsubcut = 0.0): 
0540    JetLikeEventShape(NULL,Rjet,ptcut,Rsub,fcut), _ptsubcut(ptsubcut) {_setStoreNeighbors(false);} //Don't need to store neighbors
0541    ~ShapeTrimmedSubjetMultiplicity(){}
0542    
0543    // Call directly this function if you want to use a pre-built EventStorage 
0544    double result(EventStorage & myStorage) const {
0545       
0546       double myMeasurement = 0.0;
0547       
0548       // if this result function is called with a pre-built storage need to check if storage can be used for this shape
0549       if(!_check_storage_parameters(myStorage)) throw Error("Storage parameters are not consistent with shape parameters"); 
0550       else{
0551          for (unsigned int i = 0; i<myStorage.size(); i++){
0552             if(myStorage[i].includeParticle() && myStorage[i].pt_in_Rsub() > _ptsubcut ) myMeasurement += myStorage[i].pt()/myStorage[i].pt_in_Rsub();
0553          }
0554       }
0555       return myMeasurement;
0556    }        
0557    
0558    
0559    std::string description() const {
0560       std::stringstream myStream;
0561       myStream << "Trimmed subjet multiplicity as event shape, ptsub_cut=" << _ptsubcut <<"and, ";
0562       return myStream.str()+jetParameterString();
0563    }
0564    
0565 protected:
0566    
0567    double _ptsubcut; // additional subjet pT cut, if desired
0568 };
0569 
0570 
0571 //////
0572 //
0573 // Shape Trimming
0574 //
0575 //////
0576 
0577 
0578 //----------------------------------------------------------------------
0579 // SelectorShapeTrimming
0580 // Event-wide trimming is implemented as a selector
0581 
0582 Selector SelectorShapeTrimming(double Rjet, double ptcut, double Rsub, double fcut);
0583 
0584 //----------------------------------------------------------------------
0585 // SelectorJetShapeTrimming
0586 // Jet-based trimming, implimented as a selector.
0587 // It takes the jet pT as the sum of the given four-vectors
0588 Selector SelectorJetShapeTrimming(double Rsub, double fcut);
0589 
0590 //----------------------------------------------------------------------
0591 // JetShapeTrimmer
0592 // For convenience, a Transformer version of jet-shape trimming which 
0593 // acts on individual jets.  Simply a wrapper for SelectorJetShapeTrimming
0594 
0595 class JetShapeTrimmer : public Transformer {
0596    
0597 private:
0598    
0599    double _Rsub, _fcut;
0600    Selector _selector;
0601    
0602 public:
0603    
0604    JetShapeTrimmer(double Rsub, double fcut) : _Rsub(Rsub), _fcut(fcut){
0605       _selector = SelectorJetShapeTrimming(_Rsub,_fcut);
0606    }
0607    
0608    virtual PseudoJet result(const PseudoJet & original) const {
0609       return join(_selector(original.constituents()));
0610    }
0611    
0612    std::string jetParameterString() const {
0613       std::stringstream stream;
0614       stream << "R_sub=" << _Rsub <<", fcut=" << _fcut;
0615       return stream.str();
0616    }
0617    
0618    virtual std::string description() const {
0619       return "Jet shape trimmer, " + jetParameterString();
0620    }
0621 };
0622 
0623 
0624 //////
0625 //
0626 // Multiple pT_cut values
0627 //
0628 //////
0629 
0630 
0631 //----------------------------------------------------------------------
0632 // JetLikeEventShape_MultiplePtCutValues
0633 // Generic class to get the whole range of event shape values as ptcut 
0634 // is changed.
0635 
0636 class JetLikeEventShape_MultiplePtCutValues {
0637    
0638 public:
0639    
0640    JetLikeEventShape_MultiplePtCutValues(): _measurement(NULL), _useLocalStorage(true) {}
0641    
0642    // Constructor without trimming. By default it uses LocalStorage. Measurement is automatically deleted when destructor is called.
0643    JetLikeEventShape_MultiplePtCutValues(MyFunctionOfVectorOfPseudoJets<double> * measurement, double Rjet, double offset = 0.0): _measurement(measurement), _Rjet(Rjet), _Rsub(Rjet), _fcut(1.0), _offset(offset), _trim(false),_useLocalStorage(true) {}
0644    
0645    // Constructor with trimming. By default it uses LocalStorage. Measurement is automatically deleted when destructor is called.
0646    JetLikeEventShape_MultiplePtCutValues(MyFunctionOfVectorOfPseudoJets<double> * measurement, double Rjet, double Rsub, double fcut, double offset = 0.0): _measurement(measurement), _Rjet(Rjet), _Rsub(Rsub), _fcut(fcut), _offset(offset), _trim(true), _useLocalStorage(true) {}
0647    
0648    virtual ~JetLikeEventShape_MultiplePtCutValues() {if(_measurement) delete _measurement;}
0649    
0650    // Initialization: input particles and build step function.
0651    virtual void set_input(const std::vector<PseudoJet> & particles) {
0652       _storeLocalInfo(particles);   
0653       _buildStepFunction();
0654    }
0655    
0656    // Get the event shape for any value of ptcut.  
0657    virtual double eventShapeFor(const double ptcut_0) const;
0658    
0659    
0660    // Pseudo-inverse: get ptcut for a given event shape value. If initialized it uses an offset, default offset is zero.
0661    virtual double ptCutFor(const double eventShape_0) const;
0662    
0663    // Get the full function array. This is a vector of vector<double>. Each vector contains a ptcut/eventShape pair
0664    virtual const std::vector< std::vector<double> >& functionArray() const {return _functionArray;}
0665    
0666    void setUseLocalStorage(bool useLocalStorage) {_useLocalStorage = useLocalStorage;}
0667    
0668    std::string ParameterString() const {
0669       std::stringstream stream;
0670       stream << "R_jet=" << _Rjet;
0671       if (_trim) stream << ", trimming with R_sub=" << _Rsub <<", fcut=" << _fcut;
0672       stream << ", offset for inverse function=" << _offset;
0673       return stream.str();
0674    }
0675    
0676    virtual std::string description() const {
0677       return _measurement->description() + "as function of pT_cut, " + ParameterString();
0678    }
0679    
0680    
0681 protected:
0682    
0683    // The jet measurement of interest
0684    MyFunctionOfVectorOfPseudoJets<double> * _measurement;
0685    
0686    double _Rjet, _Rsub, _fcut, _offset;
0687    bool _trim, _useLocalStorage;   
0688    
0689    // Build up the event shape as a function of ptcut.
0690    void _storeLocalInfo(const std::vector<PseudoJet> particles);
0691    void _buildStepFunction();
0692    std::vector< std::vector<double> > _functionArray;
0693 };
0694 
0695 
0696 //----------------------------------------------------------------------
0697 // ShapeJetMultiplicity_MultiplePtCutValues
0698 // Example of an event shape with muiltiple ptcut values.  Here, we are just doing
0699 // jet multiplicity, but the same could be done for any of the other event shapes.
0700 // Again ShapeJetMultiplicity_MultiplePtCutValues does not use an external measurement but it is hard-coded
0701 // and it uses information cached in EventStorage to improve speed.
0702 
0703 class ShapeJetMultiplicity_MultiplePtCutValues: public JetLikeEventShape_MultiplePtCutValues {
0704    
0705 public:
0706    
0707    // As per the physics paper, the default offset is 0.5  
0708    ShapeJetMultiplicity_MultiplePtCutValues(double Rjet, double offset = 0.5): JetLikeEventShape_MultiplePtCutValues(NULL, Rjet, offset) {};
0709    
0710    ShapeJetMultiplicity_MultiplePtCutValues(double Rjet, double Rsub, double fcut, double offset = 0.5): JetLikeEventShape_MultiplePtCutValues(NULL, Rjet, Rsub, fcut, offset) {};
0711    
0712    ~ShapeJetMultiplicity_MultiplePtCutValues(){}
0713    
0714    
0715    void set_input(const std::vector<PseudoJet> & particles) {
0716       
0717       EventStorage myEventStorage(_Rjet,0.0,_Rsub,_fcut,_useLocalStorage,false);
0718       myEventStorage.establishStorage(particles);
0719       
0720       _functionArray.resize(myEventStorage.size());
0721       for (unsigned int i = 0; i < myEventStorage.size(); i++){ 
0722          _functionArray[i].push_back(myEventStorage[i].pt_in_Rjet());
0723          _functionArray[i].push_back(myEventStorage[i].weight());
0724       } 
0725       _buildStepFunction();
0726    }
0727    
0728    std::string description() const {
0729       return "Shape jet multiplicity as function of pT_cut, " + ParameterString();
0730    }
0731    
0732 };
0733 
0734 
0735 
0736 //////
0737 //
0738 // Njet with multiple R_jet values
0739 //
0740 //////
0741 
0742 
0743 //----------------------------------------------------------------------
0744 // ShapeJetMultiplicity_MultipleRValues
0745 // It calculates jet multiplicity for all values of R_jet.
0746 // It needs to store all particle mutual distances, 
0747 // so memory required scales as N^2 for N particles in the event.
0748 // This is the only event shape we have coded up with the ability to do
0749 // multiple R.
0750 
0751 class ShapeJetMultiplicity_MultipleRValues {
0752    
0753    
0754 public:
0755    
0756    ShapeJetMultiplicity_MultipleRValues(){}
0757    
0758    // constructor without trimming
0759    ShapeJetMultiplicity_MultipleRValues(double ptcut):_ptcut(ptcut), _Rsub(0.0), _fcut(1.0), _trim(false) {}
0760    
0761    // constructor with trimming
0762    ShapeJetMultiplicity_MultipleRValues(double ptcut, double Rsub, double fcut): _ptcut(ptcut), _Rsub(Rsub), _fcut(fcut), _trim(true) {}
0763    
0764    ~ShapeJetMultiplicity_MultipleRValues() {}
0765    
0766    // Initialization: input particles and build step function.
0767    void set_input(const std::vector<PseudoJet> & particles) {_buildStepFunction(particles);}
0768    
0769    // Get the event shape for any value of R.  
0770    virtual double eventShapeFor(const double Rjet_0) const;
0771    
0772    // Get the full function array. This is a vector of vectors. Each vector contains a Rjet/eventShape pair 
0773    const std::vector< std::vector<double> >& functionArray() const {return _functionArray;}
0774    
0775    std::string ParameterString() const {
0776       std::stringstream stream;
0777       stream << "pT_cut=" << _ptcut;
0778       if (_trim) stream << ", trimming with R_sub=" << _Rsub <<", fcut=" << _fcut;
0779       return stream.str();
0780    }
0781    
0782    std::string description() const {
0783       return "Shape jet multiplicity as function of Rjet, " + ParameterString();
0784    }
0785    
0786 protected:
0787    
0788    double _ptcut, _Rsub, _fcut;
0789    bool _trim;  
0790    
0791    // Build up the event shape as a function of Rjet
0792    void _buildStepFunction(const std::vector<PseudoJet> particles); 
0793    
0794    std::vector< std::vector<double> > _functionArray; 
0795 };
0796 
0797 
0798 //////
0799 //
0800 // Finding Jet Axes with the Event Shape Density
0801 //
0802 //////
0803 
0804 
0805 //--------------------------------------------------------
0806 // FunctionJetAxis
0807 // Function to find jet axis according to a given jet definition.
0808 // Needed for the event shape densities
0809 
0810 class FunctionJetAxis : public MyFunctionOfVectorOfPseudoJets< PseudoJet > {
0811    
0812 public:
0813    
0814    FunctionJetAxis(){}
0815    FunctionJetAxis(fastjet::JetDefinition &jetDef) : _jetDef(jetDef) {} 
0816    ~FunctionJetAxis(){}
0817    
0818    PseudoJet result(const std::vector<PseudoJet> & particles) const {
0819       fastjet::ClusterSequence clustSeq(particles,_jetDef);
0820       fastjet::PseudoJet myAxis = clustSeq.inclusive_jets(0.0)[0];  // should cluster everything
0821       return(myAxis);
0822    }
0823    
0824    std::string description() const { return "Jet axis with " + _jetDef.description();}
0825    
0826 private:
0827    
0828    fastjet::JetDefinition _jetDef;
0829 };
0830 
0831 //--------------------------------------------------------
0832 // LightLikeAxis
0833 // Takes a pseudojet and returns a light-like version with no mass,
0834 // pT is set to 1, and it maintains the input rapidity and azimuth
0835 
0836 class LightLikeAxis : public FunctionOfPseudoJet< PseudoJet > {
0837    
0838 public:
0839    
0840    LightLikeAxis() {}
0841    
0842    // Convert to light-like object
0843    PseudoJet result(const PseudoJet & jet) const {
0844       PseudoJet p = jet;
0845       p.reset_momentum_PtYPhiM(1.0, jet.rap(), jet.phi(),0.0);
0846       return p;
0847    }
0848    
0849    std::string description() const { return "Light-like version with pT=1";}
0850 };
0851 
0852 //--------------------------------------------------------
0853 // Winner-take-all recombiner.  
0854 // Returns a recombined pseudojet whose pt is the sum of the input pts,
0855 // but direction is the hardest jet direction.
0856 
0857 class WinnerTakeAllRecombiner : public  fastjet::JetDefinition::Recombiner {
0858    
0859 public:
0860    
0861    WinnerTakeAllRecombiner() {}
0862    
0863    virtual std::string description() const {return "WinnerTakeAll Recombination Scheme";}
0864    
0865    // recombine pa and pb and put result into pab
0866    virtual void recombine(const PseudoJet & pa, const PseudoJet & pb, PseudoJet & pab) const {
0867       PseudoJet harder = pa;
0868       PseudoJet softer = pb;
0869       double pTa = pa.pt();
0870       double pTb = pb.pt();
0871       
0872       if (pTa < pTb) std::swap(harder,softer);
0873       
0874       PseudoJet direction = lightLikeVersion(harder);
0875       double newpT = pTa+pTb;
0876       pab = newpT * direction;
0877    }
0878    
0879 protected:
0880    
0881    LightLikeAxis lightLikeVersion;
0882 };
0883 
0884 
0885 //--------------------------------------------------------
0886 // EventShapeDensity_JetAxes
0887 // This is the hybrid probability density shape for jet axes position
0888 // It calculates axis directions using the winner-take-all recombination,
0889 // and also returns weights
0890 
0891 class EventShapeDensity_JetAxes {
0892    
0893 public:
0894    
0895    EventShapeDensity_JetAxes(){}
0896    
0897    // using default cluster measure (anti-kT with winner-take-all recombination). By default it doesn't apply global consistency
0898    // and it uses LocalStorage 
0899    EventShapeDensity_JetAxes(double Rjet, double ptcut, bool applyGlobalConsistency = false): _Rjet(Rjet), _ptcut(ptcut), _jetDef(fastjet::JetDefinition(fastjet::antikt_algorithm, 2.0*Rjet, new WinnerTakeAllRecombiner(), fastjet::Best)), _applyGlobalConsistency(applyGlobalConsistency), _useLocalStorage(true) {_jetDef.delete_recombiner_when_unused();}
0900    
0901    // Using arbitrary jet clustering procedure
0902    EventShapeDensity_JetAxes(double Rjet, double ptcut, const fastjet::JetAlgorithm &jetAlgo, bool applyGlobalConsistency = false): _Rjet(Rjet), _ptcut(ptcut), _jetDef(fastjet::JetDefinition(jetAlgo, 2.0*Rjet, new WinnerTakeAllRecombiner(), fastjet::Best)), _applyGlobalConsistency(applyGlobalConsistency), _useLocalStorage(true) { _jetDef.delete_recombiner_when_unused();}
0903    
0904    ~EventShapeDensity_JetAxes(){}
0905    
0906    // Set input and find local axes 
0907    void set_input(const std::vector<PseudoJet> & particles) {
0908       _find_local_axes(particles);
0909       find_axes_and_weights();
0910    }   
0911    
0912    //Turn on/off global consistency requirement
0913    void setGlobalConsistencyCheck(bool applyGlobalConsistency) {_applyGlobalConsistency = applyGlobalConsistency;}
0914    
0915    //(re)find axes and weights
0916    void find_axes_and_weights();
0917    
0918    //Turn on/off global use of LocalStorage
0919    void setUseLocalStorage(bool useLocalStorage) {_useLocalStorage = useLocalStorage;}
0920    
0921    //Return a vector of PseudoJets sorted by pT. pT of each axis is its corresponding pT weight.    
0922    std::vector<PseudoJet> axes() const { return _distinctAxes; } 
0923    
0924    //Return the corresponding vector of Njet weights
0925    std::vector<double> Njet_weights() const { return _tot_Njet_weights; }
0926    
0927    //Description
0928    std::string ParameterString() const {
0929       std::stringstream stream;
0930       stream << "R_jet=" << _Rjet << ", pT_cut=" << _ptcut;
0931       stream << ". Local clustering with " << _jetDef.description()<<".";
0932       if (_applyGlobalConsistency) stream << " Global consistency condition on.";
0933       return stream.str();
0934    }
0935    
0936    
0937    std::string description() const { return "Hybrid event shape density for finding jet axes." + ParameterString();}
0938    
0939    
0940 private:
0941    
0942    double _Rjet, _ptcut;
0943    fastjet::JetDefinition _jetDef;
0944    bool _applyGlobalConsistency;
0945    
0946    void _find_local_axes(const std::vector<PseudoJet> & particles);
0947    bool _isStable(const int thisAxis) const;
0948    
0949    unsigned int _N;
0950    std::vector<double> _tot_Njet_weights,_Njet_weights, _pt_weights;
0951    std::vector<int> _axes;
0952    
0953    std::vector<PseudoJet> _myParticles, _distinctAxes;
0954    
0955    LightLikeAxis _lightLikeVersion;
0956    
0957    bool _useLocalStorage;
0958    LocalStorage _myLocalStorage;
0959 };
0960 
0961 
0962 } // namespace jwj
0963 
0964 FASTJET_END_NAMESPACE
0965 
0966 #endif  // __FASTJET_CONTRIB_JETSWITHOUTJETS_HH__