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.momentum().vector3().mod() +
00044                                    beams.second.momentum().vector3().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 = abs( iqf.particles().front().pdgId() );
00054         quarks = iqf.particles();
00055       }
00056       else {
00057         map<int, Particle > quarkmap;
00058         foreach (const Particle& p, iqf.particles()) {
00059           if (quarkmap.find(p.pdgId())==quarkmap.end())
00060             quarkmap[p.pdgId()] = p;
00061           else if (quarkmap[p.pdgId()].momentum().E() < p.momentum().E())
00062             quarkmap[p.pdgId()] = 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].momentum().E();
00069           if(quarkmap.find(-i)!=quarkmap.end())
00070             energy += quarkmap[-i].momentum().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       // total multiplicities
00079       switch (flavour) {
00080       case PID::DQUARK:
00081       case PID::UQUARK:
00082       case PID::SQUARK:
00083         _weightLight  += weight;
00084         _weightedTotalChargedPartNumLight  += numParticles * weight;
00085         break;
00086       case PID::CQUARK:
00087         _weightCharm  += weight;
00088         _weightedTotalChargedPartNumCharm  += numParticles * weight;
00089         break;
00090       case PID::BQUARK:
00091         _weightBottom += weight;
00092         _weightedTotalChargedPartNumBottom += numParticles * weight;
00093         break;
00094       }
00095       // thrust axis for projections
00096       Vector3 axis = applyProjection<Thrust>(e, "Thrust").thrustAxis();
00097       double dot(0.);
00098       if(!quarks.empty()) {
00099         dot = quarks[0].momentum().vector3().dot(axis);
00100         if(quarks[0].pdgId()<0) dot *= -1.;
00101       }
00102       // spectra and individual multiplicities
00103       foreach (const Particle& p, fs.particles()) {
00104         double pcm = p.momentum().vector3().mod();
00105         const double xp = pcm/meanBeamMom;
00106 
00107         // if in quark or antiquark hemisphere
00108         bool quark = p.momentum().vector3().dot(axis)*dot>0.;
00109 
00110         _h_PCharged ->fill(pcm     , weight);
00111         // all charged
00112         switch (flavour) {
00113         case PID::DQUARK:
00114         case PID::UQUARK:
00115         case PID::SQUARK:
00116           _h_XpChargedL->fill(xp, weight);
00117           break;
00118         case PID::CQUARK:
00119           _h_XpChargedC->fill(xp, weight);
00120           break;
00121         case PID::BQUARK:
00122           _h_XpChargedB->fill(xp, weight);
00123           break;
00124         }
00125 
00126         int id = abs(p.pdgId());
00127         // charged pions
00128         if (id == PID::PIPLUS) {
00129           _h_XpPiPlus->fill(xp, weight);
00130           _h_XpPiPlusTotal->fill(xp, weight);
00131           switch (flavour) {
00132           case PID::DQUARK:
00133           case PID::UQUARK:
00134           case PID::SQUARK:
00135             _h_XpPiPlusL->fill(xp, weight);
00136             _h_NPiPlusL->fill(sqrtS(), weight);
00137             if( ( quark && p.pdgId()>0 ) || ( !quark && p.pdgId()<0 ))
00138               _h_RPiPlus->fill(xp, weight);
00139             else
00140               _h_RPiMinus->fill(xp, weight);
00141             break;
00142           case PID::CQUARK:
00143             _h_XpPiPlusC->fill(xp, weight);
00144             _h_NPiPlusC->fill(sqrtS(), weight);
00145             break;
00146           case PID::BQUARK:
00147             _h_XpPiPlusB->fill(xp, weight);
00148             _h_NPiPlusB->fill(sqrtS(), weight);
00149             break;
00150           }
00151         }
00152         else if (id == PID::KPLUS) {
00153           _h_XpKPlus->fill(xp, weight);
00154           _h_XpKPlusTotal->fill(xp, weight);
00155           switch (flavour) {
00156           case PID::DQUARK:
00157           case PID::UQUARK:
00158           case PID::SQUARK:
00159             _h_XpKPlusL->fill(xp, weight);
00160             _h_NKPlusL->fill(sqrtS(), weight);
00161             if( ( quark && p.pdgId()>0 ) || ( !quark && p.pdgId()<0 ))
00162               _h_RKPlus->fill(xp, weight);
00163             else
00164               _h_RKMinus->fill(xp, weight);
00165             break;
00166           case PID::CQUARK:
00167             _h_XpKPlusC->fill(xp, weight);
00168             _h_NKPlusC->fill(sqrtS(), weight);
00169             break;
00170           case PID::BQUARK:
00171             _h_XpKPlusB->fill(xp, weight);
00172             _h_NKPlusB->fill(sqrtS(), weight);
00173             break;
00174           }
00175         }
00176         else if (id == PID::PROTON) {
00177           _h_XpProton->fill(xp, weight);
00178           _h_XpProtonTotal->fill(xp, weight);
00179           switch (flavour) {
00180           case PID::DQUARK:
00181           case PID::UQUARK:
00182           case PID::SQUARK:
00183             _h_XpProtonL->fill(xp, weight);
00184             _h_NProtonL->fill(sqrtS(), weight);
00185             if( ( quark && p.pdgId()>0 ) || ( !quark && p.pdgId()<0 ))
00186               _h_RProton->fill(xp, weight);
00187             else
00188               _h_RPBar  ->fill(xp, weight);
00189             break;
00190           case PID::CQUARK:
00191             _h_XpProtonC->fill(xp, weight);
00192             _h_NProtonC->fill(sqrtS(), weight);
00193             break;
00194           case PID::BQUARK:
00195             _h_XpProtonB->fill(xp, weight);
00196             _h_NProtonB->fill(sqrtS(), weight);
00197             break;
00198           }
00199         }
00200       }
00201     }
00202 
00203 
00204     void init() {
00205       // Projections
00206       addProjection(Beam(), "Beams");
00207       addProjection(ChargedFinalState(), "FS");
00208       addProjection(InitialQuarks(), "IQF");
00209       addProjection(Thrust(FinalState()), "Thrust");
00210 
00211       // Book histograms
00212       _h_PCharged   = bookHisto1D( 1, 1, 1);
00213       _h_XpPiPlus   = bookHisto1D( 2, 1, 2);
00214       _h_XpKPlus    = bookHisto1D( 3, 1, 2);
00215       _h_XpProton   = bookHisto1D( 4, 1, 2);
00216       _h_XpPiPlusTotal = bookHisto1D( 2, 2, 2);
00217       _h_XpKPlusTotal  = bookHisto1D( 3, 2, 2);
00218       _h_XpProtonTotal = bookHisto1D( 4, 2, 2);
00219       _h_XpPiPlusL  = bookHisto1D( 5, 1, 1);
00220       _h_XpPiPlusC  = bookHisto1D( 5, 1, 2);
00221       _h_XpPiPlusB  = bookHisto1D( 5, 1, 3);
00222       _h_XpKPlusL   = bookHisto1D( 6, 1, 1);
00223       _h_XpKPlusC   = bookHisto1D( 6, 1, 2);
00224       _h_XpKPlusB   = bookHisto1D( 6, 1, 3);
00225       _h_XpProtonL  = bookHisto1D( 7, 1, 1);
00226       _h_XpProtonC  = bookHisto1D( 7, 1, 2);
00227       _h_XpProtonB  = bookHisto1D( 7, 1, 3);
00228       _h_XpChargedL = bookHisto1D( 8, 1, 1);
00229       _h_XpChargedC = bookHisto1D( 8, 1, 2);
00230       _h_XpChargedB = bookHisto1D( 8, 1, 3);
00231 
00232       _h_NPiPlusL  = bookHisto1D( 5, 2, 1);
00233       _h_NPiPlusC  = bookHisto1D( 5, 2, 2);
00234       _h_NPiPlusB  = bookHisto1D( 5, 2, 3);
00235       _h_NKPlusL   = bookHisto1D( 6, 2, 1);
00236       _h_NKPlusC   = bookHisto1D( 6, 2, 2);
00237       _h_NKPlusB   = bookHisto1D( 6, 2, 3);
00238       _h_NProtonL  = bookHisto1D( 7, 2, 1);
00239       _h_NProtonC  = bookHisto1D( 7, 2, 2);
00240       _h_NProtonB  = bookHisto1D( 7, 2, 3);
00241 
00242       _h_RPiPlus  = bookHisto1D( 9, 1, 1);
00243       _h_RPiMinus = bookHisto1D( 9, 1, 2);
00244       _h_RKPlus   = bookHisto1D(10, 1, 1);
00245       _h_RKMinus  = bookHisto1D(10, 1, 2);
00246       _h_RProton  = bookHisto1D(11, 1, 1);
00247       _h_RPBar    = bookHisto1D(11, 1, 2);
00248 
00249       // Ratios: used as target of divide() later
00250       _s_PiM_PiP  = bookScatter2D(9, 1, 3);
00251       _s_KM_KP    = bookScatter2D(10, 1, 3);
00252       _s_Pr_PBar  = bookScatter2D(11, 1, 3);
00253 
00254     }
00255 
00256 
00257     /// Finalize
00258     void finalize() {
00259 
00260       // Multiplicities
00261       /// @todo Include errors
00262       const double avgNumPartsLight = _weightedTotalChargedPartNumLight / _weightLight;
00263       const double avgNumPartsCharm = _weightedTotalChargedPartNumCharm / _weightCharm;
00264       const double avgNumPartsBottom = _weightedTotalChargedPartNumBottom / _weightBottom;
00265       bookScatter2D(8, 2, 1, true)->point(0).setY(avgNumPartsLight);
00266       bookScatter2D(8, 2, 2, true)->point(0).setY(avgNumPartsCharm);
00267       bookScatter2D(8, 2, 3, true)->point(0).setY(avgNumPartsBottom);
00268       bookScatter2D(8, 3, 2, true)->point(0).setY(avgNumPartsCharm - avgNumPartsLight);
00269       bookScatter2D(8, 3, 3, true)->point(0).setY(avgNumPartsBottom - avgNumPartsLight);
00270 
00271       // Do divisions
00272       divide(*_h_RPiMinus - *_h_RPiPlus, *_h_RPiMinus + *_h_RPiPlus, _s_PiM_PiP);
00273       divide(*_h_RKMinus - *_h_RKPlus, *_h_RKMinus + *_h_RKPlus, _s_KM_KP);
00274       divide(*_h_RProton - *_h_RPBar, *_h_RProton + *_h_RPBar, _s_Pr_PBar);
00275 
00276       // Scale histograms
00277       scale(_h_PCharged,      1./sumOfWeights());
00278       scale(_h_XpPiPlus,      1./sumOfWeights());
00279       scale(_h_XpKPlus,       1./sumOfWeights());
00280       scale(_h_XpProton,      1./sumOfWeights());
00281       scale(_h_XpPiPlusTotal, 1./sumOfWeights());
00282       scale(_h_XpKPlusTotal,  1./sumOfWeights());
00283       scale(_h_XpProtonTotal, 1./sumOfWeights());
00284       scale(_h_XpPiPlusL,     1./_weightLight);
00285       scale(_h_XpPiPlusC,     1./_weightCharm);
00286       scale(_h_XpPiPlusB,     1./_weightBottom);
00287       scale(_h_XpKPlusL,      1./_weightLight);
00288       scale(_h_XpKPlusC,      1./_weightCharm);
00289       scale(_h_XpKPlusB,      1./_weightBottom);
00290       scale(_h_XpProtonL,     1./_weightLight);
00291       scale(_h_XpProtonC,     1./_weightCharm);
00292       scale(_h_XpProtonB,     1./_weightBottom);
00293 
00294       scale(_h_XpChargedL, 1./_weightLight);
00295       scale(_h_XpChargedC, 1./_weightCharm);
00296       scale(_h_XpChargedB, 1./_weightBottom);
00297 
00298       scale(_h_NPiPlusL, 1./_weightLight);
00299       scale(_h_NPiPlusC, 1./_weightCharm);
00300       scale(_h_NPiPlusB, 1./_weightBottom);
00301       scale(_h_NKPlusL,  1./_weightLight);
00302       scale(_h_NKPlusC,  1./_weightCharm);
00303       scale(_h_NKPlusB,  1./_weightBottom);
00304       scale(_h_NProtonL, 1./_weightLight);
00305       scale(_h_NProtonC, 1./_weightCharm);
00306       scale(_h_NProtonB, 1./_weightBottom);
00307 
00308       // Paper suggests this should be 0.5/weight but it has to be 1.0 to get normalisations right...
00309       scale(_h_RPiPlus,  1./_weightLight);
00310       scale(_h_RPiMinus, 1./_weightLight);
00311       scale(_h_RKPlus,   1./_weightLight);
00312       scale(_h_RKMinus,  1./_weightLight);
00313       scale(_h_RProton,  1./_weightLight);
00314       scale(_h_RPBar,    1./_weightLight);
00315     }
00316 
00317     //@}
00318 
00319 
00320   private:
00321 
00322     /// @name Multiplicities
00323     //@{
00324     double _weightedTotalChargedPartNumLight;
00325     double _weightedTotalChargedPartNumCharm;
00326     double _weightedTotalChargedPartNumBottom;
00327     //@}
00328 
00329     /// @name Weights
00330     //@{
00331     double _weightLight, _weightCharm, _weightBottom;
00332     //@}
00333 
00334     // Histograms
00335     //@{
00336     Histo1DPtr _h_PCharged;
00337     Histo1DPtr _h_XpPiPlus, _h_XpKPlus, _h_XpProton;
00338     Histo1DPtr _h_XpPiPlusTotal, _h_XpKPlusTotal, _h_XpProtonTotal;
00339     Histo1DPtr _h_XpPiPlusL, _h_XpPiPlusC, _h_XpPiPlusB;
00340     Histo1DPtr _h_XpKPlusL, _h_XpKPlusC, _h_XpKPlusB;
00341     Histo1DPtr _h_XpProtonL, _h_XpProtonC, _h_XpProtonB;
00342     Histo1DPtr _h_XpChargedL, _h_XpChargedC, _h_XpChargedB;
00343     Histo1DPtr _h_NPiPlusL, _h_NPiPlusC, _h_NPiPlusB;
00344     Histo1DPtr _h_NKPlusL, _h_NKPlusC, _h_NKPlusB;
00345     Histo1DPtr _h_NProtonL, _h_NProtonC, _h_NProtonB;
00346     Histo1DPtr _h_RPiPlus, _h_RPiMinus, _h_RKPlus;
00347     Histo1DPtr _h_RKMinus, _h_RProton, _h_RPBar;
00348     Scatter2DPtr _s_PiM_PiP, _s_KM_KP, _s_Pr_PBar;
00349     //@}
00350 
00351   };
00352 
00353 
00354   // Hook for the plugin system
00355   DECLARE_RIVET_PLUGIN(SLD_2004_S5693039);
00356 
00357 }