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/RivetYODA.hh"
00004 #include "Rivet/Tools/ParticleIdUtils.hh"
00005 #include "Rivet/Projections/Beam.hh"
00006 #include "Rivet/Projections/FinalState.hh"
00007 #include "Rivet/Projections/ChargedFinalState.hh"
00008 #include "Rivet/Projections/InitialQuarks.hh"
00009 #include "Rivet/Projections/Thrust.hh"
00010 
00011 namespace Rivet {
00012 
00013 
00014   /// @brief SLD flavour-dependent fragmentation paper
00015   /// @author Peter Richardson
00016   class SLD_2004_S5693039 : public Analysis {
00017   public:
00018 
00019     /// Constructor
00020     SLD_2004_S5693039() : Analysis("SLD_2004_S5693039"),
00021         _weightedTotalChargedPartNumLight(0.),
00022         _weightedTotalChargedPartNumCharm(0.),
00023         _weightedTotalChargedPartNumBottom(0.),
00024         _weightLight(0.),_weightCharm(0.),_weightBottom(0.)
00025     {}
00026 
00027     /// @name Analysis methods
00028     //@{
00029 
00030     void analyze(const Event& e) {
00031       // First, veto on leptonic events by requiring at least 2 charged FS particles
00032       const FinalState& fs = applyProjection<FinalState>(e, "FS");
00033       const size_t numParticles = fs.particles().size();
00034 
00035       // Even if we only generate hadronic events, we still need a cut on numCharged >= 2.
00036       if (numParticles < 2) {
00037         MSG_DEBUG("Failed ncharged cut");
00038         vetoEvent;
00039       }
00040       MSG_DEBUG("Passed ncharged cut");
00041       // Get event weight for histo filling
00042       const double weight = e.weight();
00043       // Get beams and average beam momentum
00044       const ParticlePair& beams = applyProjection<Beam>(e, "Beams").beams();
00045       const double meanBeamMom = ( beams.first.momentum().vector3().mod() +
00046                                    beams.second.momentum().vector3().mod() ) / 2.0;
00047       MSG_DEBUG("Avg beam momentum = " << meanBeamMom);
00048       int flavour = 0;
00049       const InitialQuarks& iqf = applyProjection<InitialQuarks>(e, "IQF");
00050 
00051       // If we only have two quarks (qqbar), just take the flavour.
00052       // If we have more than two quarks, look for the highest energetic q-qbar pair.
00053       ParticleVector quarks;
00054       if (iqf.particles().size() == 2) {
00055         flavour = abs( iqf.particles().front().pdgId() );
00056         quarks = iqf.particles();
00057       }
00058       else {
00059         map<int, Particle > quarkmap;
00060         foreach (const Particle& p, iqf.particles()) {
00061           if (quarkmap.find(p.pdgId())==quarkmap.end())
00062             quarkmap[p.pdgId()] = p;
00063           else if (quarkmap[p.pdgId()].momentum().E() < p.momentum().E())
00064             quarkmap[p.pdgId()] = p;
00065         }
00066         double maxenergy = 0.;
00067         for (int i = 1; i <= 5; ++i) {
00068           double energy(0.);
00069           if(quarkmap.find( i)!=quarkmap.end())
00070             energy += quarkmap[ i].momentum().E();
00071           if(quarkmap.find(-i)!=quarkmap.end())
00072             energy += quarkmap[-i].momentum().E();
00073           if (energy > maxenergy) flavour = i;
00074         }
00075         if(quarkmap.find( flavour)!=quarkmap.end())
00076           quarks.push_back(quarkmap[ flavour]);
00077         if(quarkmap.find(-flavour)!=quarkmap.end())
00078           quarks.push_back(quarkmap[-flavour]);
00079       }
00080       // total multiplicities
00081       switch (flavour) {
00082       case 1: case 2: case 3:
00083         _weightLight  += weight;
00084         _weightedTotalChargedPartNumLight  += numParticles * weight;
00085         break;
00086       case 4:
00087         _weightCharm  += weight;
00088         _weightedTotalChargedPartNumCharm  += numParticles * weight;
00089         break;
00090       case 5:
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         _histPCharged ->fill(pcm     , weight);
00111         // all charged
00112         switch (flavour) {
00113         case DQUARK: case UQUARK: case SQUARK:
00114           _histXpChargedL->fill(xp, weight);
00115           break;
00116         case CQUARK:
00117           _histXpChargedC->fill(xp, weight);
00118           break;
00119         case BQUARK:
00120           _histXpChargedB->fill(xp, weight);
00121           break;
00122         }
00123 
00124         int id = abs(p.pdgId());
00125         // charged pions
00126         if(id==PIPLUS) {
00127           _histXpPiPlus->fill(xp, weight);
00128           _histXpPiPlusTotal->fill(xp, weight);
00129           switch (flavour) {
00130           case DQUARK: case UQUARK: case SQUARK:
00131             _histXpPiPlusL->fill(xp, weight);
00132             _multPiPlusL->fill(sqrtS(), weight);
00133             if( ( quark && p.pdgId()>0 ) || ( !quark && p.pdgId()<0 ))
00134               _histRPiPlus->fill(xp, weight);
00135             else
00136               _histRPiMinus->fill(xp, weight);
00137             break;
00138           case CQUARK:
00139             _histXpPiPlusC->fill(xp, weight);
00140             _multPiPlusC->fill(sqrtS(), weight);
00141             break;
00142           case BQUARK:
00143             _histXpPiPlusB->fill(xp, weight);
00144             _multPiPlusB->fill(sqrtS(), weight);
00145             break;
00146           }
00147         }
00148         else if(id==KPLUS) {
00149           _histXpKPlus->fill(xp, weight);
00150           _histXpKPlusTotal->fill(xp, weight);
00151           switch (flavour) {
00152           case DQUARK: case UQUARK: case SQUARK:
00153             _histXpKPlusL->fill(xp, weight);
00154             _multKPlusL->fill(sqrtS(), weight);
00155             if( ( quark && p.pdgId()>0 ) || ( !quark && p.pdgId()<0 ))
00156               _histRKPlus->fill(xp, weight);
00157             else
00158               _histRKMinus->fill(xp, weight);
00159             break;
00160           case CQUARK:
00161             _histXpKPlusC->fill(xp, weight);
00162             _multKPlusC->fill(sqrtS(), weight);
00163             break;
00164           case BQUARK:
00165             _histXpKPlusB->fill(xp, weight);
00166             _multKPlusB->fill(sqrtS(), weight);
00167             break;
00168           }
00169         }
00170         else if(id==PROTON) {
00171           _histXpProton->fill(xp, weight);
00172           _histXpProtonTotal->fill(xp, weight);
00173           switch (flavour) {
00174           case DQUARK: case UQUARK: case SQUARK:
00175             _histXpProtonL->fill(xp, weight);
00176             _multProtonL->fill(sqrtS(), weight);
00177             if( ( quark && p.pdgId()>0 ) || ( !quark && p.pdgId()<0 ))
00178               _histRProton->fill(xp, weight);
00179             else
00180               _histRPBar  ->fill(xp, weight);
00181             break;
00182           case CQUARK:
00183             _histXpProtonC->fill(xp, weight);
00184             _multProtonC->fill(sqrtS(), weight);
00185             break;
00186           case BQUARK:
00187             _histXpProtonB->fill(xp, weight);
00188             _multProtonB->fill(sqrtS(), weight);
00189             break;
00190           }
00191         }
00192       }
00193     }
00194 
00195     void init() {
00196       // Projections
00197       addProjection(Beam(), "Beams");
00198       addProjection(ChargedFinalState(), "FS");
00199       addProjection(InitialQuarks(), "IQF");
00200       addProjection(Thrust(FinalState()), "Thrust");
00201       // histograms
00202       _histPCharged   = bookHisto1D( 1, 1, 1);
00203       _histXpPiPlus   = bookHisto1D( 2, 1, 2);
00204       _histXpKPlus    = bookHisto1D( 3, 1, 2);
00205       _histXpProton   = bookHisto1D( 4, 1, 2);
00206       _histXpPiPlusTotal = bookHisto1D( 2, 2, 2);
00207       _histXpKPlusTotal  = bookHisto1D( 3, 2, 2);
00208       _histXpProtonTotal = bookHisto1D( 4, 2, 2);
00209       _histXpPiPlusL  = bookHisto1D( 5, 1, 1);
00210       _histXpPiPlusC  = bookHisto1D( 5, 1, 2);
00211       _histXpPiPlusB  = bookHisto1D( 5, 1, 3);
00212       _histXpKPlusL   = bookHisto1D( 6, 1, 1);
00213       _histXpKPlusC   = bookHisto1D( 6, 1, 2);
00214       _histXpKPlusB   = bookHisto1D( 6, 1, 3);
00215       _histXpProtonL  = bookHisto1D( 7, 1, 1);
00216       _histXpProtonC  = bookHisto1D( 7, 1, 2);
00217       _histXpProtonB  = bookHisto1D( 7, 1, 3);
00218       _histXpChargedL = bookHisto1D( 8, 1, 1);
00219       _histXpChargedC = bookHisto1D( 8, 1, 2);
00220       _histXpChargedB = bookHisto1D( 8, 1, 3);
00221 
00222       _multPiPlusL  = bookHisto1D( 5, 2, 1);
00223       _multPiPlusC  = bookHisto1D( 5, 2, 2);
00224       _multPiPlusB  = bookHisto1D( 5, 2, 3);
00225       _multKPlusL   = bookHisto1D( 6, 2, 1);
00226       _multKPlusC   = bookHisto1D( 6, 2, 2);
00227       _multKPlusB   = bookHisto1D( 6, 2, 3);
00228       _multProtonL  = bookHisto1D( 7, 2, 1);
00229       _multProtonC  = bookHisto1D( 7, 2, 2);
00230       _multProtonB  = bookHisto1D( 7, 2, 3);
00231 
00232       _histRPiPlus  = bookHisto1D( 9, 1, 1);
00233       _histRPiMinus = bookHisto1D( 9, 1, 2);
00234       _histRKPlus   = bookHisto1D(10, 1, 1);
00235       _histRKMinus  = bookHisto1D(10, 1, 2);
00236       _histRProton  = bookHisto1D(11, 1, 1);
00237       _histRPBar    = bookHisto1D(11, 1, 2);
00238 
00239       _h_PiM_PiP    = bookScatter2D(9, 1, 3);
00240       _h_KM_KP      = bookScatter2D(10, 1, 3);
00241       _h_Pr_PBar    = bookScatter2D(11, 1, 3);
00242 
00243     }
00244 
00245 
00246     /// Finalize
00247     void finalize() {
00248       // @todo YODA
00249       //// multiplicities
00250       //// bottom
00251       //const double avgNumPartsBottom = _weightedTotalChargedPartNumBottom / _weightBottom;
00252       //AIDA::IDataPointSet * multB = bookDataPointSet(8, 2, 3);
00253       //multB->point(0)->coordinate(1)->setValue(avgNumPartsBottom);
00254       //// charm
00255       //const double avgNumPartsCharm = _weightedTotalChargedPartNumCharm / _weightCharm;
00256       //AIDA::IDataPointSet * multC = bookDataPointSet(8, 2, 2);
00257       //multC->point(0)->coordinate(1)->setValue(avgNumPartsCharm);
00258       //// light
00259       //const double avgNumPartsLight = _weightedTotalChargedPartNumLight / _weightLight;
00260       //AIDA::IDataPointSet * multL = bookDataPointSet(8, 2, 1);
00261       //multL->point(0)->coordinate(1)->setValue(avgNumPartsLight);
00262       //// charm-light
00263       //AIDA::IDataPointSet * multD1 = bookDataPointSet(8, 3, 2);
00264       //multD1->point(0)->coordinate(1)->setValue(avgNumPartsCharm -avgNumPartsLight);
00265       //// bottom-light
00266       //AIDA::IDataPointSet * multD2 = bookDataPointSet(8, 3, 3);
00267       //multD2->point(0)->coordinate(1)->setValue(avgNumPartsBottom-avgNumPartsLight);
00268 
00269 
00270       divide(*_histRPiMinus - *_histRPiPlus,*_histRPiMinus + *_histRPiPlus,
00271          _h_PiM_PiP);
00272 
00273       divide(*_histRKMinus - *_histRKPlus,*_histRKMinus + *_histRKPlus,
00274          _h_KM_KP);
00275 
00276       divide(*_histRProton - *_histRPBar,*_histRProton + *_histRPBar,
00277          _h_Pr_PBar);
00278 
00279       // histograms
00280       Analysis::scale(_histPCharged   ,1./sumOfWeights());
00281       Analysis::scale(_histXpPiPlus   ,1./sumOfWeights());
00282       Analysis::scale(_histXpKPlus    ,1./sumOfWeights());
00283       Analysis::scale(_histXpProton   ,1./sumOfWeights());
00284       Analysis::scale(_histXpPiPlusTotal ,1./sumOfWeights());
00285       Analysis::scale(_histXpKPlusTotal  ,1./sumOfWeights());
00286       Analysis::scale(_histXpProtonTotal ,1./sumOfWeights());
00287       Analysis::scale(_histXpPiPlusL  ,1./_weightLight);
00288       Analysis::scale(_histXpPiPlusC  ,1./_weightCharm);
00289       Analysis::scale(_histXpPiPlusB  ,1./_weightBottom);
00290       Analysis::scale(_histXpKPlusL   ,1./_weightLight);
00291       Analysis::scale(_histXpKPlusC   ,1./_weightCharm);
00292       Analysis::scale(_histXpKPlusB   ,1./_weightBottom);
00293       Analysis::scale(_histXpProtonL  ,1./_weightLight);
00294       Analysis::scale(_histXpProtonC  ,1./_weightCharm);
00295       Analysis::scale(_histXpProtonB  ,1./_weightBottom);
00296 
00297       Analysis::scale(_histXpChargedL ,1./_weightLight);
00298       Analysis::scale(_histXpChargedC ,1./_weightCharm);
00299       Analysis::scale(_histXpChargedB ,1./_weightBottom);
00300 
00301       Analysis::scale(_multPiPlusL   ,1./_weightLight);
00302       Analysis::scale(_multPiPlusC   ,1./_weightCharm);
00303       Analysis::scale(_multPiPlusB   ,1./_weightBottom);
00304       Analysis::scale(_multKPlusL    ,1./_weightLight);
00305       Analysis::scale(_multKPlusC    ,1./_weightCharm);
00306       Analysis::scale(_multKPlusB    ,1./_weightBottom);
00307       Analysis::scale(_multProtonL   ,1./_weightLight);
00308       Analysis::scale(_multProtonC   ,1./_weightCharm);
00309       Analysis::scale(_multProtonB   ,1./_weightBottom);
00310 
00311       // paper suggests this should be 0.5/weight but has to be 1.
00312       // to get normalisations right
00313       Analysis::scale(_histRPiPlus ,1./_weightLight);
00314       Analysis::scale(_histRPiMinus,1./_weightLight);
00315       Analysis::scale(_histRKPlus  ,1./_weightLight);
00316       Analysis::scale(_histRKMinus ,1./_weightLight);
00317       Analysis::scale(_histRProton ,1./_weightLight);
00318       Analysis::scale(_histRPBar   ,1./_weightLight);
00319 
00320     }
00321     //@}
00322 
00323   private:
00324 
00325 
00326     /// @name Multiplicities
00327     //@{
00328     double _weightedTotalChargedPartNumLight;
00329     double _weightedTotalChargedPartNumCharm;
00330     double _weightedTotalChargedPartNumBottom;
00331     //@}
00332 
00333     /// @name Weights
00334     //@{
00335     double _weightLight;
00336     double _weightCharm;
00337     double _weightBottom;
00338     //@}
00339 
00340     // Histograms
00341     //@{
00342     Histo1DPtr _histPCharged  ;
00343     Histo1DPtr _histXpPiPlus  ;
00344     Histo1DPtr _histXpKPlus   ;
00345     Histo1DPtr _histXpProton  ;
00346     Histo1DPtr _histXpPiPlusTotal;
00347     Histo1DPtr _histXpKPlusTotal ;
00348     Histo1DPtr _histXpProtonTotal;
00349     Histo1DPtr _histXpPiPlusL ;
00350     Histo1DPtr _histXpPiPlusC ;
00351     Histo1DPtr _histXpPiPlusB ;
00352     Histo1DPtr _histXpKPlusL  ;
00353     Histo1DPtr _histXpKPlusC  ;
00354     Histo1DPtr _histXpKPlusB  ;
00355     Histo1DPtr _histXpProtonL ;
00356     Histo1DPtr _histXpProtonC ;
00357     Histo1DPtr _histXpProtonB ;
00358     Histo1DPtr _histXpChargedL;
00359     Histo1DPtr _histXpChargedC;
00360     Histo1DPtr _histXpChargedB;
00361     Histo1DPtr _multPiPlusL ;
00362     Histo1DPtr _multPiPlusC ;
00363     Histo1DPtr _multPiPlusB ;
00364     Histo1DPtr _multKPlusL  ;
00365     Histo1DPtr _multKPlusC  ;
00366     Histo1DPtr _multKPlusB  ;
00367     Histo1DPtr _multProtonL ;
00368     Histo1DPtr _multProtonC ;
00369     Histo1DPtr _multProtonB ;
00370     Histo1DPtr _histRPiPlus ;
00371     Histo1DPtr _histRPiMinus;
00372     Histo1DPtr _histRKPlus  ;
00373     Histo1DPtr _histRKMinus ;
00374     Histo1DPtr _histRProton ;
00375     Histo1DPtr _histRPBar   ;
00376 
00377     Scatter2DPtr _h_PiM_PiP;
00378     Scatter2DPtr _h_KM_KP;
00379     Scatter2DPtr _h_Pr_PBar;
00380 
00381     //@}
00382 
00383     // @todo YODA
00384     //void scale(AIDA::IDataPointSet*& histo, double scale) {
00385     //  if (!histo) {
00386     //    MSG_ERROR("Failed to scale histo=NULL in analysis "
00387     //              << name() << " (scale=" << scale << ")");
00388     //    return;
00389     //  }
00390     //  const string hpath = tree().findPath(dynamic_cast<const AIDA::IManagedObject&>(*histo));
00391     //  MSG_TRACE("Scaling histo " << hpath);
00392 
00393     //  vector<double> x, y, ex, ey;
00394     //  for (size_t i = 0, N = histo->size(); i < N; ++i) {
00395 
00396     //    IDataPoint * point = histo->point(i);
00397     //    assert(point->dimension()==2);
00398     //    x .push_back(point->coordinate(0)->value());
00399     //    ex.push_back(0.5*(point->coordinate(0)->errorPlus()+
00400     //                      point->coordinate(0)->errorMinus()));
00401     //    y .push_back(point->coordinate(1)->value()*scale);
00402     //    ey.push_back(0.5*scale*(point->coordinate(1)->errorPlus()+
00403     //                            point->coordinate(1)->errorMinus()));
00404     //  }
00405     //  string title = histo->title();
00406     //  string xtitle = histo->xtitle();
00407     //  string ytitle = histo->ytitle();
00408 
00409     //  tree().mkdir("/tmpnormalize");
00410     //  tree().mv(hpath, "/tmpnormalize");
00411 
00412     //  if (hpath.find(" ") != string::npos) {
00413     //    throw Error("Histogram path '" + hpath + "' is invalid: spaces are not permitted in paths");
00414     //  }
00415     //  AIDA::IDataPointSet* dps = datapointsetFactory().createXY(hpath, title, x, y, ex, ey);
00416     //  dps->setXTitle(xtitle);
00417     //  dps->setYTitle(ytitle);
00418 
00419     //  tree().rm(tree().findPath(dynamic_cast<AIDA::IManagedObject&>(*histo)));
00420     //  tree().rmdir("/tmpnormalize");
00421 
00422     //  // Set histo pointer to null - it can no longer be used.
00423     //  histo = 0;
00424     //}
00425   };
00426 
00427   // The hook for the plugin system
00428   DECLARE_RIVET_PLUGIN(SLD_2004_S5693039);
00429 
00430 }