rivet is hosted by Hepforge, IPPP Durham
ARGUS_1993_S2669951.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analysis.hh"
00003 #include "Rivet/Projections/UnstableFinalState.hh"
00004 
00005 namespace Rivet {
00006 
00007 
00008   /// @brief Production of the $\eta'(958)$ and $f_0(980)$ in $e^+e^-$ annihilation in the Upsilon region
00009   /// @author Peter Richardson
00010   class ARGUS_1993_S2669951 : public Analysis {
00011   public:
00012 
00013     ARGUS_1993_S2669951()
00014       : Analysis("ARGUS_1993_S2669951"),
00015         _count_etaPrime_highZ(2, 0.),
00016         _count_etaPrime_allZ(3, 0.),
00017         _count_f0(3, 0.),
00018         _weightSum_cont(0.),
00019         _weightSum_Ups1(0.),
00020         _weightSum_Ups2(0.)
00021     {   }
00022 
00023 
00024     void init() {
00025       declare(UnstableFinalState(), "UFS");
00026 
00027       _hist_cont_f0 = bookHisto1D(2, 1, 1);
00028       _hist_Ups1_f0 = bookHisto1D(3, 1, 1);
00029       _hist_Ups2_f0 = bookHisto1D(4, 1, 1);
00030     }
00031 
00032 
00033     void analyze(const Event& e) {
00034 
00035       // Find the Upsilons among the unstables
00036       const UnstableFinalState& ufs = apply<UnstableFinalState>(e, "UFS");
00037       Particles upsilons;
00038 
00039       // First in unstable final state
00040       foreach (const Particle& p, ufs.particles())
00041         if (p.pid() == 553 || p.pid() == 100553)
00042           upsilons.push_back(p);
00043       // Then in whole event if fails
00044       if (upsilons.empty()) {
00045         /// @todo Replace HepMC digging with Particle::descendents etc. calls
00046         foreach (const GenParticle* p, Rivet::particles(e.genEvent())) {
00047           if ( p->pdg_id() != 553 && p->pdg_id() != 100553 ) continue;
00048           // Discard it if its parent has the same PDG ID code (avoid duplicates)
00049           const GenVertex* pv = p->production_vertex();
00050           bool passed = true;
00051           if (pv) {
00052             foreach (const GenParticle* pp, particles_in(pv)) {
00053               if ( p->pdg_id() == pp->pdg_id() ) {
00054                 passed = false;
00055                 break;
00056               }
00057             }
00058           }
00059           if (passed) upsilons.push_back(Particle(*p));
00060         }
00061       }
00062 
00063 
00064       // Finding done, now fill counters
00065       const double weight = e.weight();
00066       if (upsilons.empty()) { // Continuum
00067         MSG_DEBUG("No Upsilons found => continuum event");
00068 
00069         _weightSum_cont += weight;
00070         unsigned int nEtaA(0), nEtaB(0), nf0(0);
00071         foreach (const Particle& p, ufs.particles()) {
00072           const int id = p.abspid();
00073           const double xp = 2.*p.E()/sqrtS();
00074           const double beta = p.p3().mod() / p.E();
00075           if (id == 9010221) {
00076             _hist_cont_f0->fill(xp, weight/beta);
00077             nf0 += 1;
00078           } else if (id == 331) {
00079             if (xp > 0.35) nEtaA += 1;
00080             nEtaB += 1;
00081           }
00082         }
00083         _count_f0[2]             += nf0*weight;
00084         _count_etaPrime_highZ[1] += nEtaA*weight;
00085         _count_etaPrime_allZ[2]  += nEtaB*weight;
00086 
00087       } else { // Upsilon(s) found
00088         MSG_DEBUG("Upsilons found => resonance event");
00089 
00090         foreach (const Particle& ups, upsilons) {
00091           const int parentId = ups.pid();
00092           ((parentId == 553) ? _weightSum_Ups1 : _weightSum_Ups2) += weight;
00093           Particles unstable;
00094           // Find the decay products we want
00095           findDecayProducts(ups.genParticle(), unstable);
00096           LorentzTransform cms_boost;
00097           if (ups.p3().mod() > 1*MeV)
00098             cms_boost = LorentzTransform::mkFrameTransformFromBeta(ups.momentum().betaVec());
00099           const double mass = ups.mass();
00100           unsigned int nEtaA(0), nEtaB(0), nf0(0);
00101           foreach(const Particle& p, unstable) {
00102             const int id = p.abspid();
00103             const FourMomentum p2 = cms_boost.transform(p.momentum());
00104             const double xp = 2.*p2.E()/mass;
00105             const double beta = p2.p3().mod()/p2.E();
00106             if (id == 9010221) { //< ?
00107               ((parentId == 553) ? _hist_Ups1_f0 : _hist_Ups2_f0)->fill(xp, weight/beta);
00108               nf0 += 1;
00109             } else if (id == 331) { //< ?
00110               if (xp > 0.35) nEtaA += 1;
00111               nEtaB += 1;
00112             }
00113           }
00114           if (parentId == 553) {
00115             _count_f0[0]             +=   nf0*weight;
00116             _count_etaPrime_highZ[0] += nEtaA*weight;
00117             _count_etaPrime_allZ[0]  += nEtaB*weight;
00118           } else {
00119             _count_f0[1] += nf0*weight;
00120             _count_etaPrime_allZ[1]  += nEtaB*weight;
00121           }
00122         }
00123       }
00124     }
00125 
00126 
00127     void finalize() {
00128 
00129       // High-Z eta' multiplicity
00130       Scatter2DPtr s111 = bookScatter2D(1, 1, 1, true);
00131       if (_weightSum_Ups1 > 0) // Point at 9.460
00132         s111->point(0).setY(_count_etaPrime_highZ[0] / _weightSum_Ups1, 0);
00133       if (_weightSum_cont > 0) // Point at 9.905
00134         s111->point(1).setY(_count_etaPrime_highZ[1] / _weightSum_cont, 0);
00135 
00136       // All-Z eta' multiplicity
00137       Scatter2DPtr s112 = bookScatter2D(1, 1, 2, true);
00138       if (_weightSum_Ups1 > 0) // Point at 9.460
00139         s112->point(0).setY(_count_etaPrime_allZ[0] / _weightSum_Ups1, 0);
00140       if (_weightSum_cont > 0) // Point at 9.905
00141         s112->point(1).setY(_count_etaPrime_allZ[2] / _weightSum_cont, 0);
00142       if (_weightSum_Ups2 > 0) // Point at 10.02
00143         s112->point(2).setY(_count_etaPrime_allZ[1] / _weightSum_Ups2, 0);
00144 
00145       // f0 multiplicity
00146       Scatter2DPtr s511 = bookScatter2D(5, 1, 1, true);
00147       if (_weightSum_Ups1 > 0) // Point at 9.46
00148         s511->point(0).setY(_count_f0[0] / _weightSum_Ups1, 0);
00149       if (_weightSum_Ups2 > 0) // Point at 10.02
00150         s511->point(1).setY(_count_f0[1] / _weightSum_Ups2, 0);
00151       if (_weightSum_cont > 0) // Point at 10.45
00152         s511->point(2).setY(_count_f0[2] / _weightSum_cont, 0);
00153 
00154       // Scale histos
00155       if (_weightSum_cont > 0.) scale(_hist_cont_f0, 1./_weightSum_cont);
00156       if (_weightSum_Ups1 > 0.) scale(_hist_Ups1_f0, 1./_weightSum_Ups1);
00157       if (_weightSum_Ups2 > 0.) scale(_hist_Ups2_f0, 1./_weightSum_Ups2);
00158     }
00159 
00160 
00161   private:
00162 
00163     /// @name Counters
00164     //@{
00165     vector<double> _count_etaPrime_highZ, _count_etaPrime_allZ, _count_f0;
00166     double _weightSum_cont,_weightSum_Ups1,_weightSum_Ups2;
00167     //@}
00168 
00169 
00170     /// Histos
00171     Histo1DPtr _hist_cont_f0, _hist_Ups1_f0, _hist_Ups2_f0;
00172 
00173 
00174     /// Recursively walk the HepMC tree to find decay products of @a p
00175     void findDecayProducts(const GenParticle* p, Particles& unstable) {
00176       const GenVertex* dv = p->end_vertex();
00177       /// @todo Use better looping
00178       for (GenVertex::particles_out_const_iterator pp = dv->particles_out_const_begin(); pp != dv->particles_out_const_end(); ++pp) {
00179         const int id = abs((*pp)->pdg_id());
00180         if (id == 331 || id == 9010221) unstable.push_back(Particle(*pp));
00181         else if ((*pp)->end_vertex()) findDecayProducts(*pp, unstable);
00182       }
00183     }
00184 
00185 
00186   };
00187 
00188 
00189   // The hook for the plugin system
00190   DECLARE_RIVET_PLUGIN(ARGUS_1993_S2669951);
00191 
00192 }