Rivet analyses referenceATLAS_2022_I2614196Zy+jets at 13 TeVExperiment: ATLAS (LHC) Inspire ID: 2614196 Status: VALIDATED Authors:
Beam energies: (6500.0, 6500.0) GeV Run details:
Differential cross-section measurements of $Z\gamma$ production in association with hadronic jets are presented, using the full 139 fb${}^{-1}$ dataset of $\sqrt{s}$=13 TeV proton-proton collisions collected by the ATLAS detector during Run 2 of the LHC. Distributions are measured using events in which the $Z$ boson decays leptonically and the photon is usually radiated from an initial-state quark. Measurements are made in both one and two observables, including those sensitive to the hard scattering in the event and others which probe additional soft and collinear radiation. Different Standard Model predictions, from both parton-shower Monte Carlo simulation and fixed-order QCD calculations, are compared with the measurements. In general, good agreement is observed between data and predictions from MATRIX and MiNNLOPS, as well as next-to-leading-order predictions from MadGraph5_aMC@NLO and Sherpa. Source code: ATLAS_2022_I2614196.cc 1// -*- C++ -*-
2#include "Rivet/Analysis.hh"
3#include "Rivet/Projections/FinalState.hh"
4#include "Rivet/Projections/FastJets.hh"
5#include "Rivet/Projections/VetoedFinalState.hh"
6#include "Rivet/Projections/LeptonFinder.hh"
7#include "Rivet/Projections/PromptFinalState.hh"
8#include "Rivet/Projections/InvisibleFinalState.hh"
9
10namespace Rivet {
11
12
13 /// @brief Zy+jets at 13 TeV
14 class ATLAS_2022_I2614196 : public Analysis {
15 public:
16
17 /// Constructor
18 RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2022_I2614196);
19
20 /// @name Analysis methods
21 /// @{
22
23 /// Book histograms and initialise projections before the run
24 void init() {
25
26 // Prompt photons
27 const PromptFinalState photon_fs(Cuts::abspid == PID::PHOTON && Cuts::pT > 30*GeV && Cuts::abseta < 2.37);
28 declare(photon_fs, "Photons");
29
30 // Prompt leptons
31 const PromptFinalState bareelectron_fs(Cuts::abspid == PID::ELECTRON);
32 const PromptFinalState baremuon_fs(Cuts::abspid == PID::MUON);
33
34 // Dressed leptons
35 const FinalState allphoton_fs(Cuts::abspid == PID::PHOTON);
36 const Cut leptoncut = Cuts::pT > 25*GeV && Cuts::abseta < 2.47;
37 const LeptonFinder dressedelectron_fs(bareelectron_fs, allphoton_fs, 0.1, leptoncut);
38 const LeptonFinder dressedmuon_fs(baremuon_fs, allphoton_fs, 0.1, leptoncut);
39
40 declare(dressedelectron_fs, "Electrons");
41 declare(dressedmuon_fs, "Muons");
42
43 // FS excluding the leading photon
44 VetoedFinalState vfs;
45 vfs.addVetoOnThisFinalState(photon_fs);
46 vfs.addVetoOnThisFinalState(dressedmuon_fs);
47 vfs.addVetoOnThisFinalState(InvisibleFinalState());
48 declare(vfs, "isolatedFS");
49
50 VetoedFinalState hadrons(FinalState(Cuts::abseta < 4.4));
51 hadrons.addVetoOnThisFinalState(dressedelectron_fs);
52 hadrons.addVetoOnThisFinalState(dressedmuon_fs);
53 declare(hadrons, "hadrons");
54
55 //Jets
56 FastJets jets(hadrons, JetAlg::ANTIKT, 0.4, JetMuons::ALL, JetInvisibles::DECAY);
57 declare(jets, "jets");
58
59 // Histograms
60 book(_h["pTll"], 1, 1, 1);
61 book(_h["DiffpTll_pTy"], 2, 1, 1);
62 book(_h["SumpTll_pTy"], 3, 1, 1);
63 book(_h["DeltaRll"], 4, 1, 1);
64 book(_h["NJetsMix"], 5, 1, 1);
65 book(_h["pTJet1"], 6, 1, 1);
66 book(_h["pTJet2"], 7, 1, 1);
67 book(_h["RatiopTJet12"], 8, 1, 1);
68 book(_h["mjj"], 9, 1, 1);
69 book(_h["mllyj"], 10, 1, 1);
70 book(_h["HT"], 11, 1, 1);
71 book(_h["pTysqrtHT"], 12, 1, 1);
72 book(_h["DeltaPhiJetY"], 13, 1, 1);
73 book(_h["pTllyj"], 14, 1, 1);
74 book(_h["phi_CS_Slice1"], 51, 1, 1);
75 book(_h["phi_CS_Slice2"], 51, 1, 2);
76 book(_h["phi_CS_Slice3"], 51, 1, 3);
77 book(_h["phi_CS_Slice4"], 51, 1, 4);
78 book(_h["phi_CS_Slice5"], 51, 1, 5);
79 book(_h["ctheta_CS_Slice1"], 52, 1, 1);
80 book(_h["ctheta_CS_Slice2"], 52, 1, 2);
81 book(_h["ctheta_CS_Slice3"], 52, 1, 3);
82 book(_h["ctheta_CS_Slice4"], 52, 1, 4);
83 book(_h["ctheta_CS_Slice5"], 52, 1, 5);
84 book(_h["RatiopTlly_mlly_Slice1"], 17, 1, 1);
85 book(_h["RatiopTlly_mlly_Slice2"], 18, 1, 1);
86 book(_h["RatiopTlly_mlly_Slice3"], 19, 1, 1);
87 book(_h["DiffpTll_pTy_Slice1"], 20, 1, 1);
88 book(_h["DiffpTll_pTy_Slice2"], 21, 1, 1);
89 book(_h["DiffpTll_pTy_Slice3"], 22, 1, 1);
90 book(_h["pTllyj_Slice1"], 23, 1, 1);
91 book(_h["pTllyj_Slice2"], 24, 1, 1);
92 book(_h["pTllyj_Slice3"], 25, 1, 1);
93
94 _ptllAxis = YODA::Axis<double>({0, 35, 60, 90, 135, 2500});
95 }
96
97
98 /// Perform the per-event analysis
99 void analyze(const Event& event) {
100
101 // Get objects
102 Particles electrons = apply<LeptonFinder>(event, "Electrons").particlesByPt();
103 Particles muons = apply<LeptonFinder>(event, "Muons").particlesByPt();
104 Particles photons = apply<PromptFinalState>(event, "Photons").particlesByPt();
105
106 if (photons.empty()) vetoEvent;
107 if (electrons.size()<2 && muons.size()<2) vetoEvent;
108
109 Particles lep;
110 // Sort the dressed leptons by pt
111 if (electrons.size() >= 2) {
112 lep.push_back(electrons[0]);
113 lep.push_back(electrons[1]);
114 }
115 else {
116 lep.push_back(muons[0]);
117 lep.push_back(muons[1]);
118 }
119
120 if (lep[0].momentum().pT() < 30*GeV) vetoEvent;
121
122 const double mll = (lep[0].momentum() + lep[1].momentum()).mass();
123 if (mll < 40*GeV) vetoEvent;
124
125 Particles selectedPh;
126 Particles fs = apply<VetoedFinalState>(event, "isolatedFS").particles();
127 for (const Particle& ph : photons) {
128 // check photon isolation
129 double coneEnergy(0.0);
130 for (const Particle& p : fs) {
131 if ( deltaR(ph, p) < 0.2 ) coneEnergy += p.Et();
132 }
133 if (coneEnergy / ph.momentum().pT() > 0.07 ) continue;
134 if (any(electrons, deltaRLess(ph, 0.4))) continue;
135 if (any(muons, deltaRLess(ph, 0.4))) continue;
136 selectedPh.push_back(ph);
137 }
138
139 if(selectedPh.size()<1) vetoEvent;
140
141 const double mlly = (lep[0].momentum() + lep[1].momentum() + selectedPh[0].momentum()).mass();
142 if (mll + mlly <= 182*GeV) vetoEvent;
143
144
145 // Get jets
146 // abseta
147 const Cut jetscut = (Cuts::pT > 30*GeV && Cuts::absrap < 2.5) || (Cuts::pT > 50*GeV && Cuts::absrapIn(2.5, 4.5));
148 const Cut jetscut25 = (Cuts::pT > 25*GeV && Cuts::abseta < 2.5) || (Cuts::pT > 50*GeV && Cuts::absetaIn(2.5, 4.4));
149 Jets jetsMix = apply<FastJets>(event, "jets").jetsByPt(jetscut);
150 Jets jetsMix25 = apply<FastJets>(event, "jets").jetsByPt(jetscut25);
151 iselectIfAnyDeltaRLess(jetsMix, photons, 0.4);
152 iselectIfAnyDeltaRLess(jetsMix, electrons, 0.2);
153 iselectIfAnyDeltaRLess(jetsMix25, photons, 0.4);
154 iselectIfAnyDeltaRLess(jetsMix25, electrons, 0.2);
155
156 // Jet multiplicity
157 size_t njets = jetsMix.size();
158 _h["NJetsMix"]->fill(njets);
159
160 double pTJet1 = njets>0 ? jetsMix[0].pT(): -1.;
161 double pTJet2 = njets>1 ? jetsMix[1].pT(): -1.;
162 double mjj = njets>1 ? (jetsMix[0].mom() + jetsMix[1].mom()).mass() : -1.;
163 double mllyj = njets>0 ? (lep[0].mom() + lep[1].mom() + selectedPh[0].mom() + jetsMix[0].mom()).mass() : -1.;
164
165 double HT = lep[0].pT() + lep[1].pT() + selectedPh[0].pT();
166 HT = sum(jetsMix25, Kin::pT, HT);
167
168 double pTy = selectedPh[0].pT();
169 double DeltaPhijy = njets>0 ? fabs(deltaPhi(jetsMix[0], selectedPh[0])) : -1.;
170 double DeltaRll = fabs(deltaR(lep[0], lep[1]));
171 double pTll = (lep[0].momentum() + lep[1].momentum()).pT();
172
173 double pTlly = (lep[0].mom() + lep[1].mom() + selectedPh[0].mom()).pT();
174 double Ratio_pTlly_mlly = pTlly/mlly;
175 double Diff_pTll_pTy = pTll-pTy;
176 double Sum_pTll_pTy = pTll+pTy;
177 double pTllyj = njets>0 ? (lep[0].mom() + lep[1].mom() + selectedPh[0].mom() + jetsMix[0].mom()).pT() : -1.;
178
179 // Fill plots
180 _h["pTJet1"]->fill(pTJet1/GeV);
181 _h["pTJet2"]->fill(pTJet2/GeV);
182 _h["RatiopTJet12"]->fill(pTJet2/pTJet1);
183 _h["mllyj"]->fill(mllyj/GeV);
184 _h["mjj"]->fill(mjj/GeV);
185 _h["HT"]->fill(HT/GeV);
186 _h["pTysqrtHT"]->fill((pTy/GeV)/sqrt(HT/GeV));
187 _h["DeltaPhiJetY"]->fill(DeltaPhijy);
188 _h["DeltaRll"]->fill(DeltaRll);
189 _h["pTll"]->fill(pTll/GeV);
190
191 if (mlly > 125*GeV && mlly < 200*GeV) _h["RatiopTlly_mlly_Slice1"]->fill(Ratio_pTlly_mlly);
192 else if (mlly > 200*GeV && mlly < 300*GeV) _h["RatiopTlly_mlly_Slice2"]->fill(Ratio_pTlly_mlly);
193 else if (mlly > 300*GeV) _h["RatiopTlly_mlly_Slice3"]->fill(Ratio_pTlly_mlly);
194
195 _h["SumpTll_pTy"]->fill(Sum_pTll_pTy/GeV);
196 _h["DiffpTll_pTy"]->fill(Diff_pTll_pTy/GeV);
197 if (Sum_pTll_pTy < 200*GeV) _h["DiffpTll_pTy_Slice1"]->fill(Diff_pTll_pTy/GeV);
198 else if (Sum_pTll_pTy > 200*GeV && Sum_pTll_pTy < 300*GeV) _h["DiffpTll_pTy_Slice2"]->fill(Diff_pTll_pTy/GeV);
199 else if (Sum_pTll_pTy > 300*GeV) _h["DiffpTll_pTy_Slice3"]->fill(Diff_pTll_pTy/GeV);
200
201 _h["pTllyj"]->fill(pTllyj/GeV);
202 if (pTlly < 50*GeV) _h["pTllyj_Slice1"]->fill(pTllyj/GeV);
203 else if (pTlly > 50*GeV && pTlly < 75*GeV) _h["pTllyj_Slice2"]->fill(pTllyj/GeV);
204 else if (pTlly > 75*GeV) _h["pTllyj_Slice3"]->fill(pTllyj/GeV);
205
206 // polarization variables
207 FourMomentum lep1, lep2;
208 if (lep[0].pid() > 0 && lep[1].pid() < 0) {
209 lep1 = lep[0].mom();
210 lep2 = lep[1].mom();
211 }
212 else if (lep[0].pid() < 0 && lep[1].pid() > 0) {
213 lep1 = lep[1].mom();
214 lep2 = lep[0].mom();
215 }
216 else {
217 MSG_DEBUG("Same sign lepton!");
218 vetoEvent;
219 }
220
221 FourMomentum Dilepton = (lep1+lep2);
222 FourMomentum lep1_CS;
223 LorentzTransform boost;
224 boost.setBetaVec(-Dilepton.betaVec());
225 lep1_CS = boost.transform(lep1);
226 const double ctheta_CS = cos(lep1_CS.p3().theta());
227 const double phi_CS = lep1_CS.p3().azimuthalAngle();
228
229 size_t idx = _ptllAxis.index(pTll);
230 if (mll > 80*GeV && mll<100*GeV && idx && idx <= _ptllAxis.numBins()) {
231 const string s = "_Slice" + to_string(idx);
232 _h["ctheta_CS" + s]->fill(ctheta_CS);
233 _h["phi_CS" + s]->fill(phi_CS);
234 }
235 }
236
237
238 /// Normalise histograms etc., after the run
239 void finalize() {
240 const double sf = crossSection()/femtobarn/sumOfWeights();
241 scale(_h, sf);
242 }
243
244 /// @}
245
246
247 private:
248
249 /// Histograms
250 map<string, Histo1DPtr> _h;
251
252 YODA::Axis<double> _ptllAxis;
253
254 };
255
256
257 RIVET_DECLARE_PLUGIN(ATLAS_2022_I2614196);
258
259}
|