rivet is hosted by Hepforge, IPPP Durham
SLD_2004_S5693039.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analysis.hh"
00003 #include "Rivet/Projections/Beam.hh"
00004 #include "Rivet/Projections/FinalState.hh"
00005 #include "Rivet/Projections/ChargedFinalState.hh"
00006 #include "Rivet/Projections/InitialQuarks.hh"
00007 #include "Rivet/Projections/Thrust.hh"
00008 
00009 namespace Rivet {
00010 
00011 
00012   /// @brief SLD flavour-dependent fragmentation paper
00013   /// @author Peter Richardson
00014   class SLD_2004_S5693039 : public Analysis {
00015   public:
00016 
00017     /// Constructor
00018     SLD_2004_S5693039() : Analysis("SLD_2004_S5693039"),
00019         _weightedTotalChargedPartNumLight(0.),
00020         _weightedTotalChargedPartNumCharm(0.),
00021         _weightedTotalChargedPartNumBottom(0.),
00022         _weightLight(0.),_weightCharm(0.),_weightBottom(0.)
00023     {}
00024 
00025     /// @name Analysis methods
00026     //@{
00027 
00028     void analyze(const Event& e) {
00029       // First, veto on leptonic events by requiring at least 2 charged FS particles
00030       const FinalState& fs = applyProjection<FinalState>(e, "FS");
00031       const size_t numParticles = fs.particles().size();
00032 
00033       // Even if we only generate hadronic events, we still need a cut on numCharged >= 2.
00034       if (numParticles < 2) {
00035         MSG_DEBUG("Failed ncharged cut");
00036         vetoEvent;
00037       }
00038       MSG_DEBUG("Passed ncharged cut");
00039       // Get event weight for histo filling
00040       const double weight = e.weight();
00041       // Get beams and average beam momentum
00042       const ParticlePair& beams = applyProjection<Beam>(e, "Beams").beams();
00043       const double meanBeamMom = ( beams.first.p3().mod() +
00044                                    beams.second.p3().mod() ) / 2.0;
00045       MSG_DEBUG("Avg beam momentum = " << meanBeamMom);
00046       int flavour = 0;
00047       const InitialQuarks& iqf = applyProjection<InitialQuarks>(e, "IQF");
00048 
00049       // If we only have two quarks (qqbar), just take the flavour.
00050       // If we have more than two quarks, look for the highest energetic q-qbar pair.
00051       Particles quarks;
00052       if (iqf.particles().size() == 2) {
00053         flavour = iqf.particles().front().abspid();
00054         quarks = iqf.particles();
00055       }
00056       else {
00057         map<int, Particle > quarkmap;
00058         foreach (const Particle& p, iqf.particles()) {
00059           if (quarkmap.find(p.pid())==quarkmap.end())
00060             quarkmap[p.pid()] = p;
00061           else if (quarkmap[p.pid()].E() < p.E())
00062             quarkmap[p.pid()] = p;
00063         }
00064         double maxenergy = 0.;
00065         for (int i = 1; i <= 5; ++i) {
00066           double energy(0.);
00067           if(quarkmap.find( i)!=quarkmap.end())
00068             energy += quarkmap[ i].E();
00069           if(quarkmap.find(-i)!=quarkmap.end())
00070             energy += quarkmap[-i].E();
00071           if (energy > maxenergy) flavour = i;
00072         }
00073         if(quarkmap.find( flavour)!=quarkmap.end())
00074           quarks.push_back(quarkmap[ flavour]);
00075         if(quarkmap.find(-flavour)!=quarkmap.end())
00076           quarks.push_back(quarkmap[-flavour]);
00077       }
00078 
00079       // total multiplicities
00080       switch (flavour) {
00081       case PID::DQUARK:
00082       case PID::UQUARK:
00083       case PID::SQUARK:
00084         _weightLight  += weight;
00085         _weightedTotalChargedPartNumLight  += numParticles * weight;
00086         break;
00087       case PID::CQUARK:
00088         _weightCharm  += weight;
00089         _weightedTotalChargedPartNumCharm  += numParticles * weight;
00090         break;
00091       case PID::BQUARK:
00092         _weightBottom += weight;
00093         _weightedTotalChargedPartNumBottom += numParticles * weight;
00094         break;
00095       }
00096       // thrust axis for projections
00097       Vector3 axis = applyProjection<Thrust>(e, "Thrust").thrustAxis();
00098       double dot(0.);
00099       if(!quarks.empty()) {
00100         dot = quarks[0].p3().dot(axis);
00101         if(quarks[0].pid()<0) dot *= -1.;
00102       }
00103       // spectra and individual multiplicities
00104       foreach (const Particle& p, fs.particles()) {
00105         double pcm = p.p3().mod();
00106         const double xp = pcm/meanBeamMom;
00107 
00108         // if in quark or antiquark hemisphere
00109         bool quark = p.p3().dot(axis)*dot>0.;
00110 
00111         _h_PCharged ->fill(pcm     , weight);
00112         // all charged
00113         switch (flavour) {
00114         case PID::DQUARK:
00115         case PID::UQUARK:
00116         case PID::SQUARK:
00117           _h_XpChargedL->fill(xp, weight);
00118           break;
00119         case PID::CQUARK:
00120           _h_XpChargedC->fill(xp, weight);
00121           break;
00122         case PID::BQUARK:
00123           _h_XpChargedB->fill(xp, weight);
00124           break;
00125         }
00126 
00127         int id = p.abspid();
00128         // charged pions
00129         if (id == PID::PIPLUS) {
00130           _h_XpPiPlus->fill(xp, weight);
00131           _h_XpPiPlusTotal->fill(xp, weight);
00132           switch (flavour) {
00133           case PID::DQUARK:
00134           case PID::UQUARK:
00135           case PID::SQUARK:
00136             _h_XpPiPlusL->fill(xp, weight);
00137             _h_NPiPlusL->fill(sqrtS(), weight);
00138             if( ( quark && p.pid()>0 ) || ( !quark && p.pid()<0 ))
00139               _h_RPiPlus->fill(xp, weight);
00140             else
00141               _h_RPiMinus->fill(xp, weight);
00142             break;
00143           case PID::CQUARK:
00144             _h_XpPiPlusC->fill(xp, weight);
00145             _h_NPiPlusC->fill(sqrtS(), weight);
00146             break;
00147           case PID::BQUARK:
00148             _h_XpPiPlusB->fill(xp, weight);
00149             _h_NPiPlusB->fill(sqrtS(), weight);
00150             break;
00151           }
00152         }
00153         else if (id == PID::KPLUS) {
00154           _h_XpKPlus->fill(xp, weight);
00155           _h_XpKPlusTotal->fill(xp, weight);
00156           switch (flavour) {
00157           case PID::DQUARK:
00158           case PID::UQUARK:
00159           case PID::SQUARK:
00160             _h_XpKPlusL->fill(xp, weight);
00161             _h_NKPlusL->fill(sqrtS(), weight);
00162             if( ( quark && p.pid()>0 ) || ( !quark && p.pid()<0 ))
00163               _h_RKPlus->fill(xp, weight);
00164             else
00165               _h_RKMinus->fill(xp, weight);
00166             break;
00167           case PID::CQUARK:
00168             _h_XpKPlusC->fill(xp, weight);
00169             _h_NKPlusC->fill(sqrtS(), weight);
00170             break;
00171           case PID::BQUARK:
00172             _h_XpKPlusB->fill(xp, weight);
00173             _h_NKPlusB->fill(sqrtS(), weight);
00174             break;
00175           }
00176         }
00177         else if (id == PID::PROTON) {
00178           _h_XpProton->fill(xp, weight);
00179           _h_XpProtonTotal->fill(xp, weight);
00180           switch (flavour) {
00181           case PID::DQUARK:
00182           case PID::UQUARK:
00183           case PID::SQUARK:
00184             _h_XpProtonL->fill(xp, weight);
00185             _h_NProtonL->fill(sqrtS(), weight);
00186             if( ( quark && p.pid()>0 ) || ( !quark && p.pid()<0 ))
00187               _h_RProton->fill(xp, weight);
00188             else
00189               _h_RPBar  ->fill(xp, weight);
00190             break;
00191           case PID::CQUARK:
00192             _h_XpProtonC->fill(xp, weight);
00193             _h_NProtonC->fill(sqrtS(), weight);
00194             break;
00195           case PID::BQUARK:
00196             _h_XpProtonB->fill(xp, weight);
00197             _h_NProtonB->fill(sqrtS(), weight);
00198             break;
00199           }
00200         }
00201       }
00202     }
00203 
00204 
00205     void init() {
00206       // Projections
00207       addProjection(Beam(), "Beams");
00208       addProjection(ChargedFinalState(), "FS");
00209       addProjection(InitialQuarks(), "IQF");
00210       addProjection(Thrust(FinalState()), "Thrust");
00211 
00212       // Book histograms
00213       _h_PCharged   = bookHisto1D( 1, 1, 1);
00214       _h_XpPiPlus   = bookHisto1D( 2, 1, 2);
00215       _h_XpKPlus    = bookHisto1D( 3, 1, 2);
00216       _h_XpProton   = bookHisto1D( 4, 1, 2);
00217       _h_XpPiPlusTotal = bookHisto1D( 2, 2, 2);
00218       _h_XpKPlusTotal  = bookHisto1D( 3, 2, 2);
00219       _h_XpProtonTotal = bookHisto1D( 4, 2, 2);
00220       _h_XpPiPlusL  = bookHisto1D( 5, 1, 1);
00221       _h_XpPiPlusC  = bookHisto1D( 5, 1, 2);
00222       _h_XpPiPlusB  = bookHisto1D( 5, 1, 3);
00223       _h_XpKPlusL   = bookHisto1D( 6, 1, 1);
00224       _h_XpKPlusC   = bookHisto1D( 6, 1, 2);
00225       _h_XpKPlusB   = bookHisto1D( 6, 1, 3);
00226       _h_XpProtonL  = bookHisto1D( 7, 1, 1);
00227       _h_XpProtonC  = bookHisto1D( 7, 1, 2);
00228       _h_XpProtonB  = bookHisto1D( 7, 1, 3);
00229       _h_XpChargedL = bookHisto1D( 8, 1, 1);
00230       _h_XpChargedC = bookHisto1D( 8, 1, 2);
00231       _h_XpChargedB = bookHisto1D( 8, 1, 3);
00232 
00233       _h_NPiPlusL  = bookHisto1D( 5, 2, 1);
00234       _h_NPiPlusC  = bookHisto1D( 5, 2, 2);
00235       _h_NPiPlusB  = bookHisto1D( 5, 2, 3);
00236       _h_NKPlusL   = bookHisto1D( 6, 2, 1);
00237       _h_NKPlusC   = bookHisto1D( 6, 2, 2);
00238       _h_NKPlusB   = bookHisto1D( 6, 2, 3);
00239       _h_NProtonL  = bookHisto1D( 7, 2, 1);
00240       _h_NProtonC  = bookHisto1D( 7, 2, 2);
00241       _h_NProtonB  = bookHisto1D( 7, 2, 3);
00242 
00243       _h_RPiPlus  = bookHisto1D( 9, 1, 1);
00244       _h_RPiMinus = bookHisto1D( 9, 1, 2);
00245       _h_RKPlus   = bookHisto1D(10, 1, 1);
00246       _h_RKMinus  = bookHisto1D(10, 1, 2);
00247       _h_RProton  = bookHisto1D(11, 1, 1);
00248       _h_RPBar    = bookHisto1D(11, 1, 2);
00249 
00250       // Ratios: used as target of divide() later
00251       _s_PiM_PiP  = bookScatter2D(9, 1, 3);
00252       _s_KM_KP    = bookScatter2D(10, 1, 3);
00253       _s_Pr_PBar  = bookScatter2D(11, 1, 3);
00254 
00255     }
00256 
00257 
00258     /// Finalize
00259     void finalize() {
00260 
00261       // Multiplicities
00262       /// @todo Include errors
00263       const double avgNumPartsLight = _weightedTotalChargedPartNumLight / _weightLight;
00264       const double avgNumPartsCharm = _weightedTotalChargedPartNumCharm / _weightCharm;
00265       const double avgNumPartsBottom = _weightedTotalChargedPartNumBottom / _weightBottom;
00266       bookScatter2D(8, 2, 1, true)->point(0).setY(avgNumPartsLight);
00267       bookScatter2D(8, 2, 2, true)->point(0).setY(avgNumPartsCharm);
00268       bookScatter2D(8, 2, 3, true)->point(0).setY(avgNumPartsBottom);
00269       bookScatter2D(8, 3, 2, true)->point(0).setY(avgNumPartsCharm - avgNumPartsLight);
00270       bookScatter2D(8, 3, 3, true)->point(0).setY(avgNumPartsBottom - avgNumPartsLight);
00271 
00272       // Do divisions
00273       divide(*_h_RPiMinus - *_h_RPiPlus, *_h_RPiMinus + *_h_RPiPlus, _s_PiM_PiP);
00274       divide(*_h_RKMinus - *_h_RKPlus, *_h_RKMinus + *_h_RKPlus, _s_KM_KP);
00275       divide(*_h_RProton - *_h_RPBar, *_h_RProton + *_h_RPBar, _s_Pr_PBar);
00276 
00277       // Scale histograms
00278       scale(_h_PCharged,      1./sumOfWeights());
00279       scale(_h_XpPiPlus,      1./sumOfWeights());
00280       scale(_h_XpKPlus,       1./sumOfWeights());
00281       scale(_h_XpProton,      1./sumOfWeights());
00282       scale(_h_XpPiPlusTotal, 1./sumOfWeights());
00283       scale(_h_XpKPlusTotal,  1./sumOfWeights());
00284       scale(_h_XpProtonTotal, 1./sumOfWeights());
00285       scale(_h_XpPiPlusL,     1./_weightLight);
00286       scale(_h_XpPiPlusC,     1./_weightCharm);
00287       scale(_h_XpPiPlusB,     1./_weightBottom);
00288       scale(_h_XpKPlusL,      1./_weightLight);
00289       scale(_h_XpKPlusC,      1./_weightCharm);
00290       scale(_h_XpKPlusB,      1./_weightBottom);
00291       scale(_h_XpProtonL,     1./_weightLight);
00292       scale(_h_XpProtonC,     1./_weightCharm);
00293       scale(_h_XpProtonB,     1./_weightBottom);
00294 
00295       scale(_h_XpChargedL, 1./_weightLight);
00296       scale(_h_XpChargedC, 1./_weightCharm);
00297       scale(_h_XpChargedB, 1./_weightBottom);
00298 
00299       scale(_h_NPiPlusL, 1./_weightLight);
00300       scale(_h_NPiPlusC, 1./_weightCharm);
00301       scale(_h_NPiPlusB, 1./_weightBottom);
00302       scale(_h_NKPlusL,  1./_weightLight);
00303       scale(_h_NKPlusC,  1./_weightCharm);
00304       scale(_h_NKPlusB,  1./_weightBottom);
00305       scale(_h_NProtonL, 1./_weightLight);
00306       scale(_h_NProtonC, 1./_weightCharm);
00307       scale(_h_NProtonB, 1./_weightBottom);
00308 
00309       // Paper suggests this should be 0.5/weight but it has to be 1.0 to get normalisations right...
00310       scale(_h_RPiPlus,  1./_weightLight);
00311       scale(_h_RPiMinus, 1./_weightLight);
00312       scale(_h_RKPlus,   1./_weightLight);
00313       scale(_h_RKMinus,  1./_weightLight);
00314       scale(_h_RProton,  1./_weightLight);
00315       scale(_h_RPBar,    1./_weightLight);
00316 
00317       // convert ratio to %
00318       _s_PiM_PiP->scale(1.,100.);
00319       _s_KM_KP  ->scale(1.,100.);
00320       _s_Pr_PBar->scale(1.,100.);
00321     }
00322 
00323     //@}
00324 
00325 
00326   private:
00327 
00328     /// @name Multiplicities
00329     //@{
00330     double _weightedTotalChargedPartNumLight;
00331     double _weightedTotalChargedPartNumCharm;
00332     double _weightedTotalChargedPartNumBottom;
00333     //@}
00334 
00335     /// @name Weights
00336     //@{
00337     double _weightLight, _weightCharm, _weightBottom;
00338     //@}
00339 
00340     // Histograms
00341     //@{
00342     Histo1DPtr _h_PCharged;
00343     Histo1DPtr _h_XpPiPlus, _h_XpKPlus, _h_XpProton;
00344     Histo1DPtr _h_XpPiPlusTotal, _h_XpKPlusTotal, _h_XpProtonTotal;
00345     Histo1DPtr _h_XpPiPlusL, _h_XpPiPlusC, _h_XpPiPlusB;
00346     Histo1DPtr _h_XpKPlusL, _h_XpKPlusC, _h_XpKPlusB;
00347     Histo1DPtr _h_XpProtonL, _h_XpProtonC, _h_XpProtonB;
00348     Histo1DPtr _h_XpChargedL, _h_XpChargedC, _h_XpChargedB;
00349     Histo1DPtr _h_NPiPlusL, _h_NPiPlusC, _h_NPiPlusB;
00350     Histo1DPtr _h_NKPlusL, _h_NKPlusC, _h_NKPlusB;
00351     Histo1DPtr _h_NProtonL, _h_NProtonC, _h_NProtonB;
00352     Histo1DPtr _h_RPiPlus, _h_RPiMinus, _h_RKPlus;
00353     Histo1DPtr _h_RKMinus, _h_RProton, _h_RPBar;
00354     Scatter2DPtr _s_PiM_PiP, _s_KM_KP, _s_Pr_PBar;
00355     //@}
00356 
00357   };
00358 
00359 
00360   // Hook for the plugin system
00361   DECLARE_RIVET_PLUGIN(SLD_2004_S5693039);
00362 
00363 }