Rivet analyses referenceATLAS_2024_I2762099WZ polarisation at 13 TeVExperiment: ATLAS (LHC) Inspire ID: 149992 Status: UNPHYSICAL Authors:
Beam energies: (6500.0, 6500.0) GeV Run details:
This Letter presents the first study of the energy dependence of diboson polarization fractions in $WZ\to \ell\nu\ell^\prime$ ($\ell,\ell^\prime = e,\mu$) production. The dataset used corresponds to an integrated luminosity of 140 fb$^{-1}$ of proton-proton collisions at a center-of-mass energy of 13 TeV recorded by the ATLAS detector. Two fiducial regions with an enhanced presence of events featuring two longitudinally polarized bosons are defined. A nonzero fraction of events with two longitudinally polarized bosons is measured with an observed significance of 5.3 standard deviations in the region with 100 $< p_\text{T}^Z<$ 200 GeV and 1.6 standard deviations in the region with $p_\text{T}^Z >$ 200 GeV, where $p_\text{T}^Z$ is the transverse momentum of the $Z$ boson. This Letter also reports the first study of the radiation-amplitude-zero effect. Events with two transversely polarized bosons are analyzed for the $\Delta Y(\ell_WZ)$ and $\Delta Y(WZ)$ distributions defined respectively as the rapidity difference between the lepton from the $W$ boson decay and the $Z$ boson and the rapidity difference between the $W$ boson and the $Z$ boson. Significant suppression of events near zero is observed in both distributions. Unfolded $\Delta Y(\ell_WZ)$ and $\Delta Y(WZ)$ distributions are also measured and compared to theoretical predictions. Users should note that explicit matching of lepton flavour between individual SM neutrinos and charged leptons is used in this analysis routine, to match the MC-based correction to the fiducial region applied in the paper. The data are therefore only valid under the assumption of the Standard Model and cannot be used for BSM reinterpretation. Source code: ATLAS_2024_I2762099.cc 1// -*- C++ -*-
2
3#include "Rivet/Analysis.hh"
4#include "Rivet/Projections/FinalState.hh"
5#include "Rivet/Projections/FastJets.hh"
6#include "Rivet/Projections/VetoedFinalState.hh"
7#include "Rivet/Projections/IdentifiedFinalState.hh"
8#include "Rivet/Projections/MissingMomentum.hh"
9#include "Rivet/Projections/LeptonFinder.hh"
10#include "Rivet/Projections/PromptFinalState.hh"
11
12namespace Rivet {
13
14
15 /// @brief WZ polarisation at 13 TeV
16 class ATLAS_2024_I2762099 : public Analysis {
17 public:
18
19 /// Constructor
20 RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2024_I2762099);
21
22 /// @name Analysis methods
23 //@{
24
25 /// Book histograms and initialise projections before the run
26 void init() {
27
28 // Get photons to dress leptons
29 PromptFinalState photons(Cuts::abspid == PID::PHOTON);
30
31 // Electrons and muons in Fiducial PS
32 PromptFinalState leptons(Cuts::abspid == PID::ELECTRON || Cuts::abspid == PID::MUON);
33 LeptonFinder dressedleptons(leptons, photons, 0.1, Cuts::open());
34 declare(dressedleptons, "DressedLeptons");
35
36 // Prompt neutrinos (yikes!)
37 IdentifiedFinalState nu_id;
38 nu_id.acceptNeutrinos();
39 PromptFinalState neutrinos(nu_id);
40 declare(neutrinos, "Neutrinos");
41 MSG_WARNING("\033[91;1mLIMITED VALIDITY - check info file for details!\033[m");
42
43 // Muons
44 PromptFinalState bare_mu(Cuts::abspid == PID::MUON, TauDecaysAs::PROMPT);
45 LeptonFinder all_dressed_mu(bare_mu, photons, 0.1, Cuts::abseta < 2.5);
46
47 // Electrons
48 PromptFinalState bare_el(Cuts::abspid == PID::ELECTRON, TauDecaysAs::PROMPT);
49 LeptonFinder all_dressed_el(bare_el, photons, 0.1, Cuts::abseta < 2.5);
50
51 //Jet forming
52 VetoedFinalState vfs(FinalState(Cuts::abseta < 5.0));
53 vfs.addVetoOnThisFinalState(all_dressed_el);
54 vfs.addVetoOnThisFinalState(all_dressed_mu);
55
56 FastJets jets(vfs, JetAlg::ANTIKT, 0.4, JetMuons::ALL, JetInvisibles::DECAY);
57 declare(jets, "Jets");
58
59 // CUT 2 PtWZ < 20 GeV
60 book(_h["PtWZ20CR_DY_WZ"], 25,1,1);
61 book(_h["PtWZ20CR_DY_lWZ"], 22,1,1);
62
63 // CUT 2 PtWZ < 40 GeV
64 book(_h["PtWZ40CR_DY_WZ"], 26,1,1);
65 book(_h["PtWZ40CR_DY_lWZ"], 23,1,1);
66
67 // CUT 2 PtWZ < 70 GeV
68 book(_h["PtWZ70CR_DY_WZ"], 27,1,1);
69 book(_h["PtWZ70CR_DY_lWZ"], 24,1,1);
70 }
71
72 void analyze(const Event& event) {
73
74 // Selection cuts
75 const vector<DressedLepton>& dressedleptons = apply<LeptonFinder>(event, "DressedLeptons").dressedLeptons();
76 const Particles& neutrinos = apply<PromptFinalState>(event, "Neutrinos").particlesByPt();
77 Jets jets = apply<FastJets>(event, "Jets").jetsByPt();
78
79 int i, j, k;
80 double MassZ01 = 0., MassZ02 = 0., MassZ12 = 0.;
81 double MassW0 = 0., MassW1 = 0., MassW2 = 0.;
82 double WeightZ1, WeightZ2, WeightZ3;
83 double WeightW1, WeightW2, WeightW3;
84 double M1, M2, M3;
85 double WeightTotal1, WeightTotal2, WeightTotal3;
86
87 //---Fiducial PS: assign leptons to W and Z bosons using Resonant shape algorithm
88 if (dressedleptons.size() < 3 || neutrinos.size() < 1) vetoEvent;
89
90 int icomb = 0;
91 // try Z pair of leptons 01
92 if ( (dressedleptons[0].pid() == -(dressedleptons[1].pid())) &&
93 (dressedleptons[2].pid()*neutrinos[0].pid()< 0) &&
94 (dressedleptons[2].abspid()==neutrinos[0].abspid()-1) ) {
95 MassZ01 = (dressedleptons[0].mom() + dressedleptons[1].mom()).mass();
96 MassW2 = (dressedleptons[2].mom() + neutrinos[0].mom()).mass();
97 icomb = 1;
98 }
99 // try Z pair of leptons 02
100 if ( (dressedleptons[0].pid() == -(dressedleptons[2].pid())) &&
101 (dressedleptons[1].pid()*neutrinos[0].pid()< 0) &&
102 (dressedleptons[1].abspid()==neutrinos[0].abspid()-1) ) {
103 MassZ02 = (dressedleptons[0].mom() + dressedleptons[2].mom()).mass();
104 MassW1 = (dressedleptons[1].mom() + neutrinos[0].mom()).mass();
105 icomb = 2;
106 }
107 // try Z pair of leptons 12
108 if ( (dressedleptons[1].pid() == -(dressedleptons[2].pid())) &&
109 (dressedleptons[0].pid()*neutrinos[0].pid()< 0) &&
110 (dressedleptons[0].abspid()==neutrinos[0].abspid()-1) ) {
111 MassZ12 = (dressedleptons[1].mom() + dressedleptons[2].mom()).mass();
112 MassW0 = (dressedleptons[0].mom() + neutrinos[0].mom()).mass();
113 icomb = 3;
114 }
115
116 if (icomb<=0) vetoEvent;
117
118 WeightZ1 = 1/(sqr(MassZ01*MassZ01 - MZ_PDG*MZ_PDG) + sqr(MZ_PDG*GammaZ_PDG));
119 WeightW1 = 1/(sqr(MassW2*MassW2 - MW_PDG*MW_PDG) + sqr(MW_PDG*GammaW_PDG));
120 WeightTotal1 = WeightZ1*WeightW1;
121 M1 = -1*WeightTotal1;
122
123 WeightZ2 = 1/(sqr(MassZ02*MassZ02- MZ_PDG*MZ_PDG) + sqr(MZ_PDG*GammaZ_PDG));
124 WeightW2 = 1/(sqr(MassW1*MassW1- MW_PDG*MW_PDG) + sqr(MW_PDG*GammaW_PDG));
125 WeightTotal2 = WeightZ2*WeightW2;
126 M2 = -1*WeightTotal2;
127
128 WeightZ3 = 1/(sqr(MassZ12*MassZ12 - MZ_PDG*MZ_PDG) + sqr(MZ_PDG*GammaZ_PDG));
129 WeightW3 = 1/(sqr(MassW0*MassW0 - MW_PDG*MW_PDG) + sqr(MW_PDG*GammaW_PDG));
130 WeightTotal3 = WeightZ3*WeightW3;
131 M3 = -1*WeightTotal3;
132
133 if( (M1 < M2 && M1 < M3) || (MassZ01 != 0 && MassW2 != 0 && MassZ02 == 0 && MassZ12 == 0) ) {
134 i = 0; j = 1; k = 2;
135 }
136 if((M2 < M1 && M2 < M3) || (MassZ02 != 0 && MassW1 != 0 && MassZ01 == 0 && MassZ12 == 0) ) {
137 i = 0; j = 2; k = 1;
138 }
139 if((M3 < M1 && M3 < M2) || (MassZ12 != 0 && MassW0 != 0 && MassZ01 == 0 && MassZ02 == 0) ) {
140 i = 1; j = 2; k = 0;
141 }
142
143 DressedLepton Z_Lep_1 = dressedleptons[i];
144 DressedLepton Z_Lep_2 = dressedleptons[j];
145 DressedLepton W_Lep = dressedleptons[k];
146
147 FourMomentum Zlepton1 = dressedleptons[i].mom();
148 FourMomentum Zlepton2 = dressedleptons[j].mom();
149 FourMomentum Wlepton = dressedleptons[k].mom();
150 FourMomentum Zboson = dressedleptons[i].mom()+dressedleptons[j].mom();
151 FourMomentum Wboson = dressedleptons[k].mom()+neutrinos[0].mom();
152
153 const double pT_WZ = (Wboson+Zboson).pT();
154
155 double cosLepNeut;
156 double norm = Wlepton.pT() * neutrinos[0].pt();
157 double mTW = 0;
158 if (norm != 0){
159 cosLepNeut = ( Wlepton.px()*neutrinos[0].px() + Wlepton.py()*neutrinos[0].py() )/norm ;
160 if(1-cosLepNeut >= 0 ) mTW = sqrt( 2 * Wlepton.pT() * neutrinos[0].pt() * (1-cosLepNeut ) );
161 }
162
163 //========================================================================================================//
164 //=========================== Using RIVET to calculate all the kinematic variables =======================//
165 //========================================================================================================//
166
167 // For kinematic variable calculations
168 FourMomentum WZ, W_WZframe, Z_WZframe, Wlep_WZframe, ZlepM_WZframe, ZlepP_WZframe;
169 FourMomentum Wlep_Wframe, Wlep_Wframe_WZ, ZlepM_Zframe, ZlepM_Zframe_WZ, ZlepP_Zframe, ZlepP_Zframe_WZ;
170
171 WZ = Zboson+Wboson;
172
173 W_WZframe = Wboson;
174 Z_WZframe = Zboson;
175 Wlep_WZframe = Wlepton;
176
177 FourMomentum ZleptonM, ZleptonP;
178
179 if (Z_Lep_1.pid()>0) {
180 ZleptonM = Zlepton1;
181 ZleptonP = Zlepton2;
182 }
183 else {
184 ZleptonM = Zlepton2;
185 ZleptonP = Zlepton1;
186 }
187
188 ZlepM_WZframe = ZleptonM;
189 ZlepP_WZframe = ZleptonP;
190
191 LorentzTransform LT_WZ = LorentzTransform();
192 LT_WZ = LT_WZ.mkObjTransformFromBeta(-(WZ.betaVec()));
193
194 W_WZframe = LT_WZ.transform(W_WZframe);
195 Z_WZframe = LT_WZ.transform(Z_WZframe);
196 Wlep_WZframe = LT_WZ.transform(Wlep_WZframe);
197 ZlepM_WZframe = LT_WZ.transform(ZlepM_WZframe);
198 ZlepP_WZframe = LT_WZ.transform(ZlepP_WZframe);
199
200 Wlep_Wframe = Wlepton;
201 Wlep_Wframe_WZ = Wlep_WZframe;
202 ZlepM_Zframe = ZleptonM;
203 ZlepM_Zframe_WZ = ZlepM_WZframe;
204 ZlepP_Zframe = ZleptonP;
205 ZlepP_Zframe_WZ = ZlepP_WZframe;
206
207 LorentzTransform LT_W = LorentzTransform();
208 LT_W = LT_W.mkObjTransformFromBeta(-(Wboson.betaVec()));
209
210 LorentzTransform LT_Z = LorentzTransform();
211 LT_Z = LT_Z.mkObjTransformFromBeta(-(Zboson.betaVec()));
212
213 Wlep_Wframe = LT_W.transform(Wlep_Wframe);
214 ZlepM_Zframe = LT_Z.transform(ZlepM_Zframe);
215 ZlepP_Zframe = LT_Z.transform(ZlepP_Zframe);
216
217 LorentzTransform LT_W_WZ = LorentzTransform();
218 LT_W_WZ = LT_W_WZ.mkObjTransformFromBeta(-(W_WZframe.betaVec()));
219
220 LorentzTransform LT_Z_WZ = LorentzTransform();
221 LT_Z_WZ = LT_Z_WZ.mkObjTransformFromBeta(-(Z_WZframe.betaVec()));
222
223 Wlep_Wframe_WZ = LT_W_WZ.transform(Wlep_Wframe_WZ);
224 ZlepM_Zframe_WZ = LT_Z_WZ.transform(ZlepM_Zframe_WZ);
225 ZlepP_Zframe_WZ = LT_Z_WZ.transform(ZlepP_Zframe_WZ);
226
227 Jets jets30;
228 for (const Jet& jet : jets){
229 if (jet.pt() > 30.*GeV && jet.abseta() < 4.5 &&
230 deltaR(Zlepton1, jet.mom()) > 0.3 &&
231 deltaR(Zlepton2, jet.mom()) > 0.3 &&
232 deltaR(Wlepton, jet.mom()) > 0.3) {
233 jets30 += jet;
234 }
235 }
236
237 const double DY_WZ = Zboson.rap() - Wboson.rap();
238 const double DY_lWZ = Zboson.rap() - Wlepton.rap();
239
240 if (Wlepton.pT() <= 20*GeV || Zlepton1.pT() <= 15*GeV || Zlepton2.pT() <= 15*GeV) vetoEvent;
241 if (Wlepton.abseta() >= 2.5 || Zlepton1.abseta() >= 2.5 || Zlepton2.abseta() >= 2.5) vetoEvent;
242 if (fabs(Zboson.mass()/GeV - MZ_PDG) >= 10.) vetoEvent;
243 if (mTW <= 30*GeV) vetoEvent;
244 if (deltaR(Zlepton1, Zlepton2) <= 0.2) vetoEvent;
245 if (deltaR(Zlepton1, Wlepton) <= 0.3) vetoEvent;
246 if (deltaR(Zlepton2, Wlepton) <= 0.3) vetoEvent;
247
248 // Selection cuts
249 if (pT_WZ >= 70) vetoEvent;
250 _h["PtWZ70CR_DY_WZ"]->fill(fabs(DY_WZ));
251 _h["PtWZ70CR_DY_lWZ"]->fill(fabs(DY_lWZ));
252
253 if (pT_WZ >= 40) vetoEvent;
254 _h["PtWZ40CR_DY_WZ"]->fill(fabs(DY_WZ));
255 _h["PtWZ40CR_DY_lWZ"]->fill(fabs(DY_lWZ));
256
257 if (pT_WZ >= 20) vetoEvent;
258 _h["PtWZ20CR_DY_WZ"]->fill(fabs(DY_WZ));
259 _h["PtWZ20CR_DY_lWZ"]->fill(fabs(DY_lWZ));
260
261 }
262
263 void finalize() {
264
265 normalize(_h);
266
267 }
268
269 //@}
270
271
272 private:
273
274
275 /// @name Histograms
276 //@{
277
278 map<string,Histo1DPtr> _h;
279
280 //@}
281
282 const double MZ_PDG = 91.1876;
283 const double MW_PDG = 83.385;
284 const double GammaZ_PDG = 2.4952;
285 const double GammaW_PDG = 2.085;
286
287 };
288
289 // The hook for the plugin system
290 RIVET_DECLARE_PLUGIN(ATLAS_2024_I2762099);
291}
|