rivet is hosted by Hepforge, IPPP Durham

Rivet analyses reference

ATLAS_2011_I944826

$K_S^0$ and $\Lambda$ production at 0.9 and 7 TeV with ATLAS
Experiment: ATLAS (LHC)
Inspire ID: 944826
Status: VALIDATED
Authors:
  • Holger Schulz
References: Beams: p+ p+
Beam energies: (450.0, 450.0); (3500.0, 3500.0) GeV
Run details:
  • QCD events, 900 GeV and 7 TeV. $\Lambda$ and $K_S$ must be able to decay. Allow only charged decay modes to improve efficiency. Beam energy must be specified as analysis option "ENERGY" when rivet-merge'ing samples.

The production of $K_S$ and $\Lambda$ hadrons is studied in inelastic $pp$ collisions at $\sqrt{s} = 0.9$ and 7 TeV collected with the ATLAS detector at the LHC using a minimum-bias trigger. The observed distributions of transverse momentum, rapidity, and multiplicity are corrected to hadron level in a model-independent way within well defined phase-space regions. The distribution of the production ratio of $\bar{\Lambda}$ to $\Lambda$ baryons is also measured. The results are compared with various Monte Carlo simulation models. Although most of these models agree with data to within 15 percent in the $K_S$ distributions, substantial disagreements with data are found in the $\Lambda$ distributions of transverse momentum. Beam energy must be specified (in GeV) as analysis option "ENERGY" when rivet-merging samples.

Source code: ATLAS_2011_I944826.cc
  1// -*- C++ -*-
  2#include "Rivet/Analysis.hh"
  3#include "Rivet/Projections/ChargedFinalState.hh"
  4#include "Rivet/Projections/IdentifiedFinalState.hh"
  5#include "Rivet/Projections/UnstableParticles.hh"
  6
  7namespace Rivet {
  8
  9
 10  class ATLAS_2011_I944826 : public Analysis {
 11  public:
 12
 13    /// Constructor
 14    ATLAS_2011_I944826()
 15      : Analysis("ATLAS_2011_I944826")
 16    {}
 17
 18
 19    /// Book histograms and initialise projections before the run
 20    void init() {
 21
 22      book(_sum_w_ks    , "ks");
 23      book(_sum_w_lambda, "lambda");
 24      book(_sum_w_passed, "passed");
 25
 26      UnstableParticles ufs(Cuts::pT > 100*MeV);
 27      declare(ufs, "UFS");
 28
 29      ChargedFinalState  mbts(Cuts::absetaIn(2.09, 3.84));
 30      declare(mbts, "MBTS");
 31
 32      IdentifiedFinalState nstable(Cuts::abseta < 2.5 && Cuts::pT >= 100*MeV);
 33      nstable.acceptIdPair(PID::ELECTRON)
 34        .acceptIdPair(PID::MUON)
 35        .acceptIdPair(PID::PIPLUS)
 36        .acceptIdPair(PID::KPLUS)
 37        .acceptIdPair(PID::PROTON);
 38      declare(nstable, "nstable");
 39
 40
 41      if (isCompatibleWithSqrtS(7000*GeV)) {
 42        book(_hist_Ks_pT      ,1, 1, 1);
 43        book(_hist_Ks_y       ,2, 1, 1);
 44        book(_hist_Ks_mult    ,3, 1, 1);
 45        book(_hist_L_pT       ,7, 1, 1);
 46        book(_hist_L_y        ,8, 1, 1);
 47        book(_hist_L_mult     ,9, 1, 1);
 48        book(_hist_Ratio_v_y ,13, 1, 1);
 49        book(_hist_Ratio_v_pT,14, 1, 1);
 50        //
 51        book(_temp_lambda_v_y, "TMP/lambda_v_y", 10, 0.0, 2.5);
 52        book(_temp_lambdabar_v_y, "TMP/lambdabar_v_y", 10, 0.0, 2.5);
 53        book(_temp_lambda_v_pT, "TMP/lambda_v_pT", 18, 0.5, 4.1);
 54        book(_temp_lambdabar_v_pT, "TMP/lambdabar_v_pT", 18, 0.5, 4.1);
 55      }
 56      else if (isCompatibleWithSqrtS(900*GeV)) {
 57        book(_hist_Ks_pT   ,4, 1, 1);
 58        book(_hist_Ks_y    ,5, 1, 1);
 59        book(_hist_Ks_mult ,6, 1, 1);
 60        book(_hist_L_pT    ,10, 1, 1);
 61        book(_hist_L_y     ,11, 1, 1);
 62        book(_hist_L_mult  ,12, 1, 1);
 63        book(_hist_Ratio_v_y ,15, 1, 1);
 64        book(_hist_Ratio_v_pT,16, 1, 1);
 65        //
 66        book(_temp_lambda_v_y, "TMP/lambda_v_y", 5, 0.0, 2.5);
 67        book(_temp_lambdabar_v_y, "TMP/lambdabar_v_y", 5, 0.0, 2.5);
 68        book(_temp_lambda_v_pT, "TMP/lambda_v_pT", 8, 0.5, 3.7);
 69        book(_temp_lambdabar_v_pT, "TMP/lambdabar_v_pT", 8, 0.5, 3.7);
 70      }
 71    }
 72
 73
 74    // This function is required to impose the flight time cuts on Kaons and Lambdas
 75    double getPerpFlightDistance(const Rivet::Particle& p) {
 76      ConstGenParticlePtr genp = p.genParticle();
 77      ConstGenVertexPtr prodV = genp->production_vertex();
 78      ConstGenVertexPtr decV  = genp->end_vertex();
 79      RivetHepMC::FourVector prodPos = prodV->position();
 80      if (decV) {
 81        const RivetHepMC::FourVector decPos = decV->position();
 82        double dy = prodPos.y() - decPos.y();
 83        double dx = prodPos.x() - decPos.x();
 84        return add_quad(dx, dy);
 85      }
 86      return numeric_limits<double>::max();
 87    }
 88
 89
 90    bool daughtersSurviveCuts(const Rivet::Particle& p) {
 91      // We require the Kshort or Lambda to decay into two charged
 92      // particles with at least pT = 100 MeV inside acceptance region
 93      ConstGenParticlePtr genp = p.genParticle();
 94      ConstGenVertexPtr decV  = genp->end_vertex();
 95      bool decision = true;
 96
 97      if (!decV) return false;
 98      if (HepMCUtils::particles(decV, Relatives::CHILDREN).size() == 2) {
 99        std::vector<double> pTs;
100        std::vector<int> charges;
101        std::vector<double> etas;
102        for(ConstGenParticlePtr gp: HepMCUtils::particles(decV, Relatives::CHILDREN)) {
103          pTs.push_back(gp->momentum().perp());
104          etas.push_back(fabs(gp->momentum().eta()));
105          charges.push_back( Rivet::PID::charge3(gp->pdg_id()) );
106          // gp->print();
107        }
108        if ( (pTs[0]/Rivet::GeV < 0.1) || (pTs[1]/Rivet::GeV < 0.1) ) {
109          decision = false;
110          MSG_DEBUG("Failed pT cut: " << pTs[0]/Rivet::GeV << " " << pTs[1]/Rivet::GeV);
111        }
112        if ( etas[0] > 2.5 || etas[1] > 2.5 ) {
113          decision = false;
114          MSG_DEBUG("Failed eta cut: " << etas[0] << " " << etas[1]);
115        }
116        if ( charges[0] * charges[1] >= 0 ) {
117          decision = false;
118          MSG_DEBUG("Failed opposite charge cut: " << charges[0] << " " << charges[1]);
119        }
120      }
121      else {
122        decision = false;
123        MSG_DEBUG("Failed nDaughters cut: " << HepMCUtils::particles(decV, Relatives::CHILDREN).size());
124      }
125
126      return decision;
127    }
128
129    /// Perform the per-event analysis
130    void analyze(const Event& event) {
131
132      // ATLAS MBTS trigger requirement of at least one hit in either hemisphere
133      if (apply<FinalState>(event, "MBTS").size() < 1) {
134        MSG_DEBUG("Failed trigger cut");
135        vetoEvent;
136      }
137
138      // Veto event also when we find less than 2 particles in the acceptance region of type 211,2212,11,13,321
139      if (apply<FinalState>(event, "nstable").size() < 2) {
140        MSG_DEBUG("Failed stable particle cut");
141        vetoEvent;
142      }
143      _sum_w_passed->fill();
144
145      // This ufs holds all the Kaons and Lambdas
146      const UnstableParticles& ufs = apply<UnstableParticles>(event, "UFS");
147
148      // Some conters
149      int n_KS0 = 0;
150      int n_LAMBDA = 0;
151
152      // Particle loop
153      for (const Particle& p : ufs.particles()) {
154
155        // General particle quantities
156        const double pT = p.pT();
157        const double y = p.rapidity();
158        const PdgId apid = p.abspid();
159
160        double flightd = 0.0;
161
162        // Look for Kaons, Lambdas
163        switch (apid) {
164
165        case PID::K0S:
166          flightd = getPerpFlightDistance(p);
167          if (!inRange(flightd/mm, 4., 450.) ) {
168            MSG_DEBUG("Kaon failed flight distance cut:" << flightd);
169            break;
170          }
171          if (daughtersSurviveCuts(p) ) {
172            _hist_Ks_y ->fill(y);
173            _hist_Ks_pT->fill(pT/GeV);
174            _sum_w_ks->fill();
175            n_KS0++;
176          }
177          break;
178
179        case PID::LAMBDA:
180          if (pT < 0.5*GeV) { // Lambdas have an additional pT cut of 500 MeV
181            MSG_DEBUG("Lambda failed pT cut:" << pT/GeV << " GeV");
182            break;
183          }
184          flightd = getPerpFlightDistance(p);
185          if (!inRange(flightd/mm, 17., 450.)) {
186            MSG_DEBUG("Lambda failed flight distance cut:" << flightd/mm << " mm");
187            break;
188          }
189          if ( daughtersSurviveCuts(p) ) {
190            if (p.pid() == PID::LAMBDA) {
191              _temp_lambda_v_y->fill(fabs(y));
192              _temp_lambda_v_pT->fill(pT/GeV);
193              _hist_L_y->fill(y);
194              _hist_L_pT->fill(pT/GeV);
195              _sum_w_lambda->fill();
196              n_LAMBDA++;
197            } else if (p.pid() == -PID::LAMBDA) {
198             _temp_lambdabar_v_y->fill(fabs(y));
199              _temp_lambdabar_v_pT->fill(pT/GeV);
200            }
201          }
202          break;
203
204        }
205      }
206
207      // Fill multiplicity histos
208      _hist_Ks_mult->fill(n_KS0);
209      _hist_L_mult->fill(n_LAMBDA);
210    }
211
212
213
214    /// Normalise histograms etc., after the run
215    void finalize() {
216      MSG_DEBUG("# Events that pass the trigger: " << dbl(*_sum_w_passed));
217      MSG_DEBUG("# Kshort events: " << dbl(*_sum_w_ks));
218      MSG_DEBUG("# Lambda events: " << dbl(*_sum_w_lambda));
219
220      /// @todo Replace with normalize()?
221      scale(_hist_Ks_pT,   1.0 / *_sum_w_ks);
222      scale(_hist_Ks_y,    1.0 / *_sum_w_ks);
223      scale(_hist_Ks_mult, 1.0 / *_sum_w_passed);
224
225      /// @todo Replace with normalize()?
226      scale(_hist_L_pT,   1.0 / *_sum_w_lambda);
227      scale(_hist_L_y,    1.0 / *_sum_w_lambda);
228      scale(_hist_L_mult, 1.0 / *_sum_w_passed);
229
230      // Division of histograms to obtain lambda_bar/lambda ratios
231      divide(_temp_lambdabar_v_y, _temp_lambda_v_y, _hist_Ratio_v_y);
232      divide(_temp_lambdabar_v_pT, _temp_lambda_v_pT, _hist_Ratio_v_pT);
233    }
234
235
236  private:
237
238    /// Counters
239    CounterPtr _sum_w_ks, _sum_w_lambda, _sum_w_passed;
240
241    /// @name Persistent histograms
242    /// @{
243    Histo1DPtr _hist_Ks_pT, _hist_Ks_y, _hist_Ks_mult;
244    Histo1DPtr _hist_L_pT, _hist_L_y, _hist_L_mult;
245    Estimate1DPtr _hist_Ratio_v_pT, _hist_Ratio_v_y;
246    /// @}
247
248    /// @name Temporary histograms
249    /// @{
250    Histo1DPtr _temp_lambda_v_y, _temp_lambdabar_v_y;
251    Histo1DPtr _temp_lambda_v_pT, _temp_lambdabar_v_pT;
252    /// @}
253
254  };
255
256
257  RIVET_DECLARE_PLUGIN(ATLAS_2011_I944826);
258
259}