Rivet analyses
title: 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: - Expt page: ATLAS-STDM-2010-09 - arXiv: 1111.1297v2 - Phys.Rev. D85 (2012) 012001
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.
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.
Source code:ATLAS_2011_I944826.cc
```c++ // -- C++ --
include "Rivet/Analysis.hh"
include "Rivet/Projections/ChargedFinalState.hh"
include "Rivet/Projections/IdentifiedFinalState.hh"
include "Rivet/Projections/UnstableParticles.hh"
namespace Rivet {
class ATLAS_2011_I944826 : public Analysis { public:
/// Constructor
RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2011_I944826);
/// Book histograms and initialise projections before the run
void init() {
UnstableParticles ufs(Cuts::pT > 100 * MeV);
declare(ufs, "UFS");
ChargedFinalState mbts(Cuts::absetaIn(2.09, 3.84));
declare(mbts, "MBTS");
IdentifiedFinalState nstable(Cuts::abseta < 2.5 && Cuts::pT >= 100 * MeV);
nstable.acceptIdPair(PID::ELECTRON)
.acceptIdPair(PID::MUON)
.acceptIdPair(PID::PIPLUS)
.acceptIdPair(PID::KPLUS)
.acceptIdPair(PID::PROTON);
declare(nstable, "nstable");
for (double eVal : allowedEnergies()) {
const string en = toString(round(eVal));
if (isCompatibleWithSqrtS(eVal)) _sqs = en;
bool is900(en == "900");
size_t offset = is900 ? 3 : 0;
book(_h[en + "Ks_pT"], 1 + offset, 1, 1);
book(_h[en + "Ks_y"], 2 + offset, 1, 1);
book(_h[en + "Ks_mult"], 3 + offset, 1, 1);
book(_h[en + "L_pT"], 7 + offset, 1, 1);
book(_h[en + "L_y"], 8 + offset, 1, 1);
book(_h[en + "L_mult"], 9 + offset, 1, 1);
if (is900) offset = 2;
book(_e[en + "v_y"], 13 + offset, 1, 1);
book(_e[en + "v_pT"], 14 + offset, 1, 1);
//
book(_h[en + "lambda_v_y"], "TMP/lambda_v_y_" + en, is900 ? 5 : 10, 0.0, 2.5);
book(_h[en + "lambdabar_v_y"], "TMP/lambdabar_v_y_" + en, is900 ? 5 : 10, 0.0, 2.5);
book(_h[en + "lambda_v_pT"], "TMP/lambda_v_pT_" + en, is900 ? 8 : 18, 0.5, is900 ? 3.7 : 4.1);
book(_h[en + "lambdabar_v_pT"], "TMP/lambdabar_v_pT_" + en, is900 ? 8 : 18, 0.5, is900 ? 3.7 : 4.1);
}
raiseBeamErrorIf(_sqs.empty());
}
// This function is required to impose the flight time cuts on Kaons and Lambdas
double getPerpFlightDistance(const Rivet::Particle& p) {
ConstGenParticlePtr genp = p.genParticle();
ConstGenVertexPtr prodV = genp->production_vertex();
ConstGenVertexPtr decV = genp->end_vertex();
RivetHepMC::FourVector prodPos = prodV->position();
if (decV) {
const RivetHepMC::FourVector decPos = decV->position();
double dy = prodPos.y() - decPos.y();
double dx = prodPos.x() - decPos.x();
return add_quad(dx, dy);
}
return numeric_limits<double>::max();
}
bool daughtersSurviveCuts(const Rivet::Particle& p) {
// We require the Kshort or Lambda to decay into two charged
// particles with at least pT = 100 MeV inside acceptance region
ConstGenParticlePtr genp = p.genParticle();
ConstGenVertexPtr decV = genp->end_vertex();
bool decision = true;
if (!decV) return false;
if (HepMCUtils::particles(decV, Relatives::CHILDREN).size() == 2) {
std::vector<double> pTs;
std::vector<int> charges;
std::vector<double> etas;
for (ConstGenParticlePtr gp : HepMCUtils::particles(decV, Relatives::CHILDREN)) {
pTs.push_back(gp->momentum().perp());
etas.push_back(fabs(gp->momentum().eta()));
charges.push_back(Rivet::PID::charge3(gp->pdg_id()));
// gp->print();
}
if ((pTs[0] / Rivet::GeV < 0.1) || (pTs[1] / Rivet::GeV < 0.1)) {
decision = false;
MSG_DEBUG("Failed pT cut: " << pTs[0] / Rivet::GeV << " " << pTs[1] / Rivet::GeV);
}
if (etas[0] > 2.5 || etas[1] > 2.5) {
decision = false;
MSG_DEBUG("Failed eta cut: " << etas[0] << " " << etas[1]);
}
if (charges[0] * charges[1] >= 0) {
decision = false;
MSG_DEBUG("Failed opposite charge cut: " << charges[0] << " " << charges[1]);
}
}
else {
decision = false;
MSG_DEBUG("Failed nDaughters cut: " << HepMCUtils::particles(decV, Relatives::CHILDREN).size());
}
return decision;
}
/// Perform the per-event analysis
void analyze(const Event& event) {
// ATLAS MBTS trigger requirement of at least one hit in either hemisphere
if (apply<FinalState>(event, "MBTS").size() < 1) {
MSG_DEBUG("Failed trigger cut");
vetoEvent;
}
// Veto event also when we find less than 2 particles in the acceptance region of type 211,2212,11,13,321
if (apply<FinalState>(event, "nstable").size() < 2) {
MSG_DEBUG("Failed stable particle cut");
vetoEvent;
}
// This ufs holds all the Kaons and Lambdas
const UnstableParticles& ufs = apply<UnstableParticles>(event, "UFS");
// Some conters
int n_KS0 = 0, n_LAMBDA = 0;
// Particle loop
for (const Particle& p : ufs.particles()) {
// General particle quantities
const double pT = p.pT();
const double y = p.rapidity();
const PdgId apid = p.abspid();
double flightd = 0.0;
// Look for Kaons, Lambdas
switch (apid) {
case PID::K0S:
flightd = getPerpFlightDistance(p);
if (!inRange(flightd / mm, 4., 450.)) {
MSG_DEBUG("Kaon failed flight distance cut:" << flightd);
break;
}
if (daughtersSurviveCuts(p)) {
_h[_sqs + "Ks_y"]->fill(y);
_h[_sqs + "Ks_pT"]->fill(pT / GeV);
++n_KS0;
}
break;
case PID::LAMBDA:
if (pT < 0.5 * GeV) { // Lambdas have an additional pT cut of 500 MeV
MSG_DEBUG("Lambda failed pT cut:" << pT / GeV << " GeV");
break;
}
flightd = getPerpFlightDistance(p);
if (!inRange(flightd / mm, 17., 450.)) {
MSG_DEBUG("Lambda failed flight distance cut:" << flightd / mm << " mm");
break;
}
if (daughtersSurviveCuts(p)) {
if (p.pid() == PID::LAMBDA) {
_h[_sqs + "lambda_v_y"]->fill(fabs(y));
_h[_sqs + "lambda_v_pT"]->fill(pT / GeV);
_h[_sqs + "L_y"]->fill(y);
_h[_sqs + "L_pT"]->fill(pT / GeV);
++n_LAMBDA;
}
else if (p.pid() == -PID::LAMBDA) {
_h[_sqs + "lambdabar_v_y"]->fill(fabs(y));
_h[_sqs + "lambdabar_v_pT"]->fill(pT / GeV);
}
}
break;
}
}
// Fill multiplicity histos
_h[_sqs + "Ks_mult"]->fill(n_KS0);
_h[_sqs + "L_mult"]->fill(n_LAMBDA);
}
/// Normalise histograms etc., after the run
void finalize() {
// Division of histograms to obtain lambda_bar/lambda ratios
for (double eVal : allowedEnergies()) {
const string en = toString(round(eVal));
if (_h[en + "L_pT"]->sumW()) scale(_h[en + "L_y"], 1.0 / _h[en + "L_pT"]->sumW());
divide(_h[en + "lambdabar_v_y"], _h[en + "lambda_v_y"], _e[en + "v_y"]);
divide(_h[en + "lambdabar_v_pT"], _h[en + "lambda_v_pT"], _e[en + "v_pT"]);
}
normalize(_h);
}
private:
/// @name Persistent histograms
/// @{
map<string, Histo1DPtr> _h;
map<string, Estimate1DPtr> _e;
string _sqs = "";
/// @}
};
RIVET_DECLARE_PLUGIN(ATLAS_2011_I944826);
} ```