Rivet analyses referenceATLAS_2019_I1764342Z(ll)y cross-section at 13 TeVExperiment: ATLAS (LHC) Inspire ID: 1764342 Status: VALIDATED Authors:
Beam energies: (6500.0, 6500.0) GeV Run details:
The production of a prompt photon in association with a Z boson is studied in proton-proton collisions at a centre-of-mass energy $\sqrt{s}=$13 TeV. The analysis uses a data sample with an integrated luminosity of 139 fb$^{-1}$ collected by the ATLAS detector at the LHC from 2015 to 2018. The production cross-section for the process $pp \rightarrow \ell^+ \ell^- + \gamma + X$ ($\ell=e,\mu$) is measured within a fiducial phase-space region defined by kinematic requirements on the photon and the leptons, and by isolation requirements on the photon. An experimental precision of $2.9\%$ is achieved for the fiducial cross-section. Differential cross-sections are measured as a function of each of six kinematic variables characterising the $\ell^+\ell^-\gamma$ system. The data are compared with theoretical predictions based on next-to-leading-order and next-to-next-to-leading-order perturbative QCD calculations. The impact of next-to-leading-order electroweak corrections is also considered. Source code: ATLAS_2019_I1764342.cc 1// -*- C++ -*-
2#include "Rivet/Analysis.hh"
3#include "Rivet/Projections/FinalState.hh"
4#include "Rivet/Projections/VetoedFinalState.hh"
5#include "Rivet/Projections/LeptonFinder.hh"
6#include "Rivet/Projections/PromptFinalState.hh"
7#include "Rivet/Projections/InvisibleFinalState.hh"
8
9namespace Rivet {
10
11
12 /// @brief Z(ll)y cross-section at 13 TeV
13 class ATLAS_2019_I1764342 : public Analysis {
14 public:
15
16 /// Constructor
17 RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2019_I1764342);
18
19 /// @name Analysis methods
20 /// @{
21
22 /// Book histograms and initialise projections before the run
23 void init() {
24
25 // Prompt photons
26 const PromptFinalState photon_fs(Cuts::abspid == PID::PHOTON && Cuts::pT > 30*GeV && Cuts::abseta < 2.37);
27 declare(photon_fs, "Photons");
28
29 // Prompt leptons
30 const PromptFinalState bareelectron_fs = Cuts::abspid == PID::ELECTRON;
31 const PromptFinalState baremuon_fs = Cuts::abspid == PID::MUON;
32
33 // Dressed leptons
34 const FinalState allphoton_fs(Cuts::abspid == PID::PHOTON); // photons used for lepton dressing
35 const Cut leptoncut = Cuts::pT > 25*GeV && Cuts::abseta < 2.47;
36 const LeptonFinder dressedelectron_fs(bareelectron_fs, allphoton_fs, 0.1, leptoncut);
37 const LeptonFinder dressedmuon_fs(baremuon_fs, allphoton_fs, 0.1, leptoncut);
38
39 declare(dressedelectron_fs, "Electrons");
40 declare(dressedmuon_fs, "Muons");
41
42 // FS excluding the leading photon
43 VetoedFinalState vfs;
44 vfs.addVetoOnThisFinalState(photon_fs);
45 vfs.addVetoOnThisFinalState(dressedmuon_fs);
46 vfs.addVetoOnThisFinalState(InvisibleFinalState());
47 declare(vfs, "isolatedFS");
48
49 // Histograms
50 book(_hist_EgammaT, 2, 1, 1); // dSigma / dE^gamma_T
51 book(_hist_etagamma, 3, 1, 1);
52 book(_hist_mZgamma, 4, 1, 1); // dSigma / dm^{Zgamma}
53 book(_hist_EZgammaT, 5, 1, 1);
54 book(_hist_dPhiZgamma, 6, 1, 1);
55 book(_hist_ETbyMZgamma, 7, 1, 1);
56 }
57
58
59 /// Perform the per-event analysis
60 void analyze(const Event& event) {
61 // Get objects
62 Particles electrons = apply<LeptonFinder>(event, "Electrons").particlesByPt();
63 Particles muons = apply<LeptonFinder>(event, "Muons").particlesByPt();
64 const Particles& photons = apply<PromptFinalState>(event, "Photons").particlesByPt();
65
66 if (photons.empty()) vetoEvent;
67 if (electrons.size() < 2 && muons.size() < 2) vetoEvent;
68 Particles lep;
69 // Sort the dressed leptons by pt
70 if (electrons.size() >= 2) {
71 lep.push_back(electrons[0]);
72 lep.push_back(electrons[1]);
73 } else {
74 lep.push_back(muons[0]);
75 lep.push_back(muons[1]);
76 }
77 if (lep[0].Et() < 30*GeV) vetoEvent;
78 double mll = (lep[0].momentum() + lep[1].momentum()).mass();
79 if (mll < 40*GeV) vetoEvent;
80
81 Particles selectedPh;
82 Particles fs = apply<VetoedFinalState>(event, "isolatedFS").particles();
83 for (const Particle& ph : photons) {
84 // check photon isolation
85 double coneEnergy(0.0);
86 for (const Particle& p : fs) {
87 if ( deltaR(ph, p) < 0.2 ) coneEnergy += p.Et();
88 }
89 if (coneEnergy / ph.Et() > 0.07 ) continue;
90 if (deltaR(ph, lep[0]) < 0.4) continue;
91 if (deltaR(ph, lep[1]) < 0.4) continue;
92 selectedPh.push_back(ph);
93 }
94
95 if (selectedPh.size()<1) vetoEvent;
96 double mlly = (lep[0].momentum() + lep[1].momentum() + selectedPh[0].momentum()).mass();
97 if (mll + mlly <= 182*GeV) vetoEvent;
98
99 double ptlly = (lep[0].momentum() + lep[1].momentum() + selectedPh[0].momentum()).pT();
100 double dphilly = deltaPhi((lep[0].momentum() + lep[1].momentum()).phi(), selectedPh[0].momentum().phi());
101
102 // Fill plots
103 _hist_EgammaT->fill(selectedPh[0].pT()/GeV);
104 _hist_etagamma->fill(selectedPh[0].abseta());
105 _hist_mZgamma->fill(mlly/GeV);
106 _hist_EZgammaT->fill(ptlly/GeV);
107 _hist_dPhiZgamma->fill(dphilly/pi);
108 _hist_ETbyMZgamma->fill(ptlly/mlly);
109 }
110
111
112 /// Normalise histograms etc., after the run
113 void finalize() {
114 const double sf = crossSection()/femtobarn/sumOfWeights();
115 scale(_hist_EgammaT, sf);
116 scale(_hist_etagamma, sf);
117 scale(_hist_mZgamma, sf);
118 scale(_hist_EZgammaT, sf);
119 scale(_hist_dPhiZgamma, sf/pi);
120 scale(_hist_ETbyMZgamma, sf);
121 }
122
123 /// @}
124
125
126 private:
127
128 // /// Mode flag
129 // size_t _mode;
130
131 /// Histograms
132 Histo1DPtr _hist_EgammaT;
133 Histo1DPtr _hist_etagamma;
134 Histo1DPtr _hist_mZgamma;
135 Histo1DPtr _hist_EZgammaT;
136 Histo1DPtr _hist_dPhiZgamma;
137 Histo1DPtr _hist_ETbyMZgamma;
138
139 };
140
141
142 RIVET_DECLARE_PLUGIN(ATLAS_2019_I1764342);
143
144}
|