rivet is hosted by Hepforge, IPPP Durham

Rivet analyses reference

ATLAS_2012_I1084540

Rapidity gap cross sections measured with the ATLAS detector in $pp$ collisions at $\sqrt{s} = 7$ TeV.
Experiment: ATLAS (LHC 7TeV)
Inspire ID: 1084540
Status: VALIDATED
Authors:
  • Oldrich Kepka
  • Tim Martin
  • Paul Newman
  • Pavel Ruzicka
References: Beams: p+ p+
Beam energies: (3500.0, 3500.0) GeV
Run details:
  • Minimum bias inelastic pp collision at 7 TeV including diffractive component and overall cross section.

Pseudorapidity gap distributions in proton-proton collisions at $\sqrt{s} = 7$ TeV are studied using a minimum bias data sample with an integrated luminosity of 7.1 inverse microbarns. Cross sections are measured differentially in terms of $\Delta \eta_F$, the larger of the pseudorapidity regions extending to the limits of the ATLAS sensitivity, at $\eta = \pm 4.9$, in which no final state particles are produced above a transverse momentum threshold $p_\perp$ cut. The measurements span the region $0 < \Delta \eta_F < 8$ for $200 < p_T\text{ cut} < 800 \text{MeV}$. At small $\Delta \eta_F$, the data test the reliability of hadronisation models in describing rapidity and transverse momentum fluctuations in final state particle production. The measurements at larger gap sizes are dominated by contributions from the single diffractive dissociation process ($pp \to Xp$), enhanced by double dissociation ($pp \to XY$) where the invariant mass of the lighter of the two dissociation systems satisfies $M_Y \lesssim 7 \text{GeV}$. The resulting cross section is $\mathrm{d} \sigma / \mathrm{d} \Delta \eta_F \sim 1$ mb for $\Delta \eta_F \gtrsim 3$. The large rapidity gap data are used to constrain the value of the pomeron intercept appropriate to triple Regge models of soft diffraction. The cross section integrated over all gap sizes is compared with other LHC inelastic cross section measurements.

Source code: ATLAS_2012_I1084540.cc
  1// -*- C++ -*-
  2/**
  3 * @name ATLAS Diffractive Gaps Rivet Analysis
  4 * @author Tim Martin, tim.martin@cern.ch
  5 * @version 1.0
  6 * @date 16/01/2012
  7 * @see http://arxiv.org/abs/1201.2808
  8 * @note pp, sqrt(s) = 7 TeV
  9 * @note Rapidity gap finding algorithm designed to compliment
 10 * the ATLAS detector acceptance. Forward rapidity gap sizes
 11 * are calculated for each event, considering all stable
 12 * particles above pT cut values 200, 400, 600 and 800 MeV in
 13 * turn. A forward rapidity gap is defined to be the largest
 14 * continuous region stretching inward from either edge of the
 15 * detector at eta = |4.9| which contains zero particles above
 16 * pT Cut. Soft diffractive topologies are isolated at large
 17 * gap sizes.
 18 *
 19 */
 20#include "Rivet/Analysis.hh"
 21#include "Rivet/Projections/FinalState.hh"
 22
 23namespace Rivet {
 24
 25
 26  class ATLAS_2012_I1084540 : public Analysis {
 27  public:
 28
 29    ATLAS_2012_I1084540() : Analysis("ATLAS_2012_I1084540") {}
 30
 31
 32    /// @name Analysis methods
 33    /// @{
 34    /// Book histograms and initialise projections before the run
 35    void init() {
 36      //All final states. Rapidity range = ATLAS calorimetry. Lowest pT cut = 200 MeV.
 37      const FinalState cnfs2((Cuts::etaIn(-_etaMax, _etaMax) && Cuts::pT >=  0.2 * GeV));
 38      const FinalState cnfs4((Cuts::etaIn(-_etaMax, _etaMax) && Cuts::pT >=  0.4 * GeV));
 39      const FinalState cnfs6((Cuts::etaIn(-_etaMax, _etaMax) && Cuts::pT >=  0.6 * GeV));
 40      const FinalState cnfs8((Cuts::etaIn(-_etaMax, _etaMax) && Cuts::pT >=  0.8 * GeV));
 41      declare(cnfs2, "CNFS2");
 42      declare(cnfs4, "CNFS4");
 43      declare(cnfs6, "CNFS6");
 44      declare(cnfs8, "CNFS8");
 45
 46      _etaBinSize = (2. * _etaMax)/(double)_etaBins;
 47
 48      //Book histogram
 49      book(_h_DeltaEtaF_200 ,1, 1, 1);
 50      book(_h_DeltaEtaF_400 ,2, 1, 1);
 51      book(_h_DeltaEtaF_600 ,3, 1, 1);
 52      book(_h_DeltaEtaF_800 ,4, 1, 1);
 53    }
 54
 55  private:
 56    void fillMap(const FinalState& fs, bool* energyMap, double pTcut) {
 57      // Fill true/false array by iterating over particles and compare their
 58      // pT with pTcut
 59      for (const Particle& p : fs.particles(cmpMomByEta)) {
 60        int checkBin = -1;
 61        double checkEta = -_etaMax;
 62        while (1) {
 63          checkEta += _etaBinSize;
 64          ++checkBin;
 65          if (p.eta() < checkEta) {
 66            energyMap[checkBin] = (p.pT() > pTcut * GeV);
 67            break;
 68          }
 69        }
 70      }
 71    }
 72
 73  public:
 74    /// Perform the per-event analysis
 75    void analyze(const Event& event) {
 76      static unsigned int event_count = 0;
 77      ++event_count;
 78      const FinalState& fs2 = apply<FinalState>(event, "CNFS2");
 79      const FinalState& fs4 = apply<FinalState>(event, "CNFS4");
 80      const FinalState& fs6 = apply<FinalState>(event, "CNFS6");
 81      const FinalState& fs8 = apply<FinalState>(event, "CNFS8");
 82
 83      // Set up Yes/No arrays for energy in each eta bin at each pT cut
 84      bool energyMap_200[_etaBins];
 85      bool energyMap_400[_etaBins];
 86      bool energyMap_600[_etaBins];
 87      bool energyMap_800[_etaBins];
 88      for (int i = 0; i < _etaBins; ++i) {
 89        energyMap_200[i] = false;
 90        energyMap_400[i] = false;
 91        energyMap_600[i] = false;
 92        energyMap_800[i] = false;
 93      }
 94
 95      // Veto bins based on final state particles > Cut (Where Cut = 200 - 800 MeV pT)
 96      fillMap(fs2, energyMap_200, 0.2);
 97      fillMap(fs4, energyMap_400, 0.4);
 98      fillMap(fs6, energyMap_600, 0.6);
 99      fillMap(fs8, energyMap_800, 0.8);
100
101      // Apply gap finding algorithm
102      // Detector layout follows...
103      // -Eta [Proton  ---  DetectorCSide  ---  DetectorBarrel  ---  DetectorASide  ---  Proton] +Eta
104      bool gapDirectionAt200 = false; //False is gap on C size, True is gap on A side.
105      double largestEdgeGap_200 = 0.;
106      double largestEdgeGap_400 = 0.;
107      double largestEdgeGap_600 = 0.;
108      double largestEdgeGap_800 = 0.;
109
110      for (int E = 200; E <= 800; E += 200) {
111        double EdgeGapSizeA = -1, EdgeGapSizeC = -1;
112        bool* energyMap = 0;
113        switch (E) {
114          case 200: energyMap = energyMap_200; break;
115          case 400: energyMap = energyMap_400; break;
116          case 600: energyMap = energyMap_600; break;
117          case 800: energyMap = energyMap_800; break;
118        }
119
120        // Look left to right
121        for (int a = 0; a < _etaBins; ++a) {
122          if (energyMap[a] == true) {
123            EdgeGapSizeA = (_etaBinSize * a);
124            break;
125          }
126        }
127
128        // And look right to left
129        for (int c = _etaBins-1; c >= 0; --c) {
130          if (energyMap[c] == true) {
131            EdgeGapSizeC = (2 * _etaMax) - (_etaBinSize * (c+1));
132            if (fuzzyEquals(EdgeGapSizeC, 4.47035e-08)) EdgeGapSizeC = 0.0;
133            break;
134          }
135        }
136        // Put your hands on your hips
137
138        // Find the largest gap
139        double largestEdgeGap = 0.;
140        if (E == 200) {
141          // If the 200 MeV pass, take the biggest of the two gaps. Make note of which side for higher pT cuts.
142          largestEdgeGap = std::max(EdgeGapSizeA,EdgeGapSizeC);
143          gapDirectionAt200 = (EdgeGapSizeA > EdgeGapSizeC);
144        } else {
145          // Use the direction from 200 MeV pass, most accurate measure of which side gap is on.
146          if (gapDirectionAt200) {
147            largestEdgeGap = EdgeGapSizeA;
148          }
149          else largestEdgeGap = EdgeGapSizeC;
150        }
151
152        // Check case of empty detector
153        if (largestEdgeGap < 0.0) largestEdgeGap = 2.0 * _etaMax;
154
155        // Fill bin centre
156        switch (E) {
157          case 200: _h_DeltaEtaF_200->fill(largestEdgeGap + _etaBinSize/2.); break;
158          case 400: _h_DeltaEtaF_400->fill(largestEdgeGap + _etaBinSize/2.); break;
159          case 600: _h_DeltaEtaF_600->fill(largestEdgeGap + _etaBinSize/2.); break;
160          case 800: _h_DeltaEtaF_800->fill(largestEdgeGap + _etaBinSize/2.); break;
161        }
162
163        if (E == 200) largestEdgeGap_200 = largestEdgeGap;
164        if (E == 400) largestEdgeGap_400 = largestEdgeGap;
165        if (E == 600) largestEdgeGap_600 = largestEdgeGap;
166        if (E == 800) largestEdgeGap_800 = largestEdgeGap;
167      }
168
169      // Algorithm result every 1000 events
170      if (event_count % 1000 == 0) {
171        for (int E = 200; E <= 800; E += 200) {
172          bool* energyMap = 0;
173          double largestEdgeGap = 0;
174          switch (E) {
175            case 200: energyMap = energyMap_200; largestEdgeGap = largestEdgeGap_200; break;
176            case 400: energyMap = energyMap_400; largestEdgeGap = largestEdgeGap_400; break;
177            case 600: energyMap = energyMap_600; largestEdgeGap = largestEdgeGap_600; break;
178            case 800: energyMap = energyMap_800; largestEdgeGap = largestEdgeGap_800; break;
179          }
180          MSG_DEBUG("Largest Forward Gap at pT Cut " << E << " MeV=" << largestEdgeGap
181            << " eta, NFinalState pT > 200 in ATLAS acceptance:" << fs2.particles().size());
182          std::string hitPattern = "Detector HitPattern=-4.9[";
183          for (int a = 0; a < _etaBins; ++a) {
184            if (energyMap[a] == true) hitPattern += "X";
185            else hitPattern += "_";
186          }
187          hitPattern += "]4.9";
188          MSG_DEBUG(hitPattern);
189          std::string gapArrow = "                         ";
190            if (!gapDirectionAt200) {
191            int drawSpaces = (int)(_etaBins - (largestEdgeGap/_etaBinSize) + 0.5);
192            for (int i = 0; i < drawSpaces; ++i) gapArrow += " ";
193          }
194          int drawArrows = (int)((largestEdgeGap/_etaBinSize) + 0.5);
195          for (int i = 0; i < drawArrows; ++i) gapArrow += "^";
196          MSG_DEBUG(gapArrow);
197        }
198      }
199    }
200
201    /// Normalise histograms after the run, Scale to cross section
202    void finalize() {
203      MSG_DEBUG("Cross Section=" << crossSection() / millibarn << "mb, SumOfWeights=" << sumOfWeights());
204      scale(_h_DeltaEtaF_200, (crossSection() / millibarn)/sumOfWeights());
205      scale(_h_DeltaEtaF_400, (crossSection() / millibarn)/sumOfWeights());
206      scale(_h_DeltaEtaF_600, (crossSection() / millibarn)/sumOfWeights());
207      scale(_h_DeltaEtaF_800, (crossSection() / millibarn)/sumOfWeights());
208    }
209    /// @}
210
211  private:
212    /// @name Histograms
213    /// @{
214    Histo1DPtr _h_DeltaEtaF_200;
215    Histo1DPtr _h_DeltaEtaF_400;
216    Histo1DPtr _h_DeltaEtaF_600;
217    Histo1DPtr _h_DeltaEtaF_800;
218    /// @}
219    /// @name Private variables
220    /// @{
221    static constexpr int _etaBins = 49;
222    static constexpr double _etaMax = 4.9;
223    double _etaBinSize;
224    /// @}
225  };
226
227  RIVET_DECLARE_PLUGIN(ATLAS_2012_I1084540);
228
229}