1 | #include "SampleAnalyzer/User/Analyzer/atlas_susy_2018_04.h"
|
---|
2 | #include <iostream>
|
---|
3 | #include <ctime>
|
---|
4 | using namespace MA5;
|
---|
5 |
|
---|
6 | // User defined function: overlap Removal
|
---|
7 | template<typename T1, typename T2> std::vector<const T1*>
|
---|
8 | Removal(std::vector<const T1*> &, std::vector<const T2*> &, const double &);
|
---|
9 |
|
---|
10 | // -----------------------------------------------------------------------------
|
---|
11 | // Initialize
|
---|
12 | // function called one time at the beginning of the analysis
|
---|
13 | // -----------------------------------------------------------------------------
|
---|
14 | bool atlas_susy_2018_04::Initialize(const MA5::Configuration& cfg, const std::map<std::string,std::string>& parameters)
|
---|
15 | {
|
---|
16 | INFO << " <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>" << endmsg;
|
---|
17 | INFO << " <> Analysis: ATLAS SUSY 2018 04 <>" << endmsg;
|
---|
18 | INFO << " <> SUSY, stau, hadronic decaying ditau + MET @ 13 TeV, 139 fb^-1 <>" << endmsg;
|
---|
19 | INFO << " <> arXiv:1911.06660 <>" << endmsg;
|
---|
20 | INFO << " <> Recasted by : Jongwon Lim, Chih-Ting Lu, <>" << endmsg;
|
---|
21 | INFO << " <> Jae-hyeon Park, Jiwon Park <>" << endmsg;
|
---|
22 | INFO << " <> Contact : jongwon.lim@cern.ch, timluyu@gmail.com, <>" << endmsg;
|
---|
23 | INFO << " <> jhpark@kias.re.kr, jiwon.park@cern.ch <>" << endmsg;
|
---|
24 | INFO << " <> Based on MadAnalysis 5 v1.8 and above <>" << endmsg;
|
---|
25 | INFO << " <> For more information, see <>" << endmsg;
|
---|
26 | INFO << " <> http://madanalysis.irmp.ucl.ac.be/wiki/PublicAnalysisDatabase <>" << endmsg;
|
---|
27 | INFO << " <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>" << endmsg;
|
---|
28 |
|
---|
29 | // ========================= //
|
---|
30 | // ===== Signal region ===== //
|
---|
31 | // ========================= //
|
---|
32 |
|
---|
33 | Manager()->AddRegionSelection("SRlow");
|
---|
34 | Manager()->AddRegionSelection("SRhigh");
|
---|
35 |
|
---|
36 | // ====================== //
|
---|
37 | // ===== Selections ===== //
|
---|
38 | // ====================== //
|
---|
39 |
|
---|
40 | // Baseline cut
|
---|
41 | Manager()->AddCut("Baseline cut");
|
---|
42 |
|
---|
43 | // Trigger and offline cuts
|
---|
44 | Manager()->AddCut("asymmetric di-$\\tau$ trigger", "SRlow");
|
---|
45 | Manager()->AddCut("di-$\\tau +E^{miss}_{T}$ trigger", "SRhigh");
|
---|
46 |
|
---|
47 | // Common selections
|
---|
48 | Manager()->AddCut("2 medium $\\tau$ (OS) and 3rd medium $\\tau$ veto");
|
---|
49 | Manager()->AddCut("b-jet veto");
|
---|
50 | Manager()->AddCut("light lepton veto");
|
---|
51 | Manager()->AddCut("Z/H veto");
|
---|
52 |
|
---|
53 | // SR Low Mass selections
|
---|
54 | Manager()->AddCut("$75 < E^{miss}_{T} < 150$ GeV", "SRlow");
|
---|
55 | Manager()->AddCut("2 tight $\\tau$ (OS)", "SRlow");
|
---|
56 | Manager()->AddCut("$|\\Delta\\phi(\\tau_{1},\\tau_{2})|>0.8$ [rad],low", "SRlow");
|
---|
57 | Manager()->AddCut("$\\Delta R(\\tau_{1},\\tau_{2})<3.2$,low", "SRlow");
|
---|
58 | Manager()->AddCut("$m_{T2}>70$ GeV,low", "SRlow");
|
---|
59 |
|
---|
60 | // SR High Mass selections
|
---|
61 | Manager()->AddCut("$\\geq 1$ tight $\\tau$", "SRhigh");
|
---|
62 | Manager()->AddCut("$|\\Delta\\phi(\\tau_{1},\\tau_{2})|>0.8$ [rad],high", "SRhigh");
|
---|
63 | Manager()->AddCut("$\\Delta R(\\tau_{1},\\tau_{2})<3.2$,high", "SRhigh");
|
---|
64 | Manager()->AddCut("$m_{T2}>70$ GeV,high", "SRhigh");
|
---|
65 |
|
---|
66 | // ====================== //
|
---|
67 | // ===== Histograms ===== //
|
---|
68 | // ====================== //
|
---|
69 | Manager()->AddHisto("SRlow_mT2", 5,70.0,120., "SRlow");
|
---|
70 | Manager()->AddHisto("SRhigh_mT2", 5,70.0,220., "SRhigh");
|
---|
71 |
|
---|
72 | return true;
|
---|
73 | }
|
---|
74 |
|
---|
75 | // -----------------------------------------------------------------------------
|
---|
76 | // Finalize
|
---|
77 | // function called one time at the end of the analysis
|
---|
78 | // -----------------------------------------------------------------------------
|
---|
79 | void atlas_susy_2018_04::Finalize(const SampleFormat& summary, const std::vector<SampleFormat>& files){}
|
---|
80 |
|
---|
81 | // -----------------------------------------------------------------------------
|
---|
82 | // Execute
|
---|
83 | // function called each time one event is read
|
---|
84 | // -----------------------------------------------------------------------------
|
---|
85 | bool atlas_susy_2018_04::Execute(SampleFormat& sample, const EventFormat& event)
|
---|
86 | {
|
---|
87 | // Event weight
|
---|
88 | double myWeight;
|
---|
89 | if ( Configuration().IsNoEventWeight() ) myWeight=1.;
|
---|
90 | else if ( event.mc()->weight()!=0. ) myWeight=event.mc()->weight();
|
---|
91 | else return false;
|
---|
92 | myWeight=1.;
|
---|
93 | Manager()->InitializeForNewEvent(myWeight);
|
---|
94 |
|
---|
95 | // Security for empty events
|
---|
96 | if ( event.rec()==0 ) return true;
|
---|
97 |
|
---|
98 | // ================================ //
|
---|
99 | // ===== Event reconstruction ===== //
|
---|
100 | // ================================ //
|
---|
101 |
|
---|
102 | //// Jets ////
|
---|
103 | std::vector <const RecJetFormat*> Jets;
|
---|
104 | unsigned int nb = 0;
|
---|
105 | for( unsigned int ij=0; ij<event.rec()->jets().size(); ij++ ){
|
---|
106 | const RecJetFormat *Jet = &(event.rec()->jets()[ij]);
|
---|
107 |
|
---|
108 | if( Jet->pt() > 20. && Jet->abseta() < 2.8 ){
|
---|
109 | Jets.push_back(Jet);
|
---|
110 | if( Jet->btag() && Jet->abseta() < 2.5) nb++;
|
---|
111 | }
|
---|
112 | }
|
---|
113 |
|
---|
114 | //// Electrons ////
|
---|
115 | std::vector<const RecLeptonFormat*> SignalElectrons;
|
---|
116 | for( unsigned int ie=0; ie<event.rec()->electrons().size(); ie++ ){
|
---|
117 | const RecLeptonFormat *Lep = &(event.rec()->electrons()[ie]);
|
---|
118 |
|
---|
119 | // Kinematics
|
---|
120 | double pt = Lep->pt();
|
---|
121 |
|
---|
122 | // Isolation
|
---|
123 | double iso_dR = std::min(10./pt,0.2);
|
---|
124 | double iso_tracks = PHYSICS->Isol->eflow->relIsolation(Lep,event.rec(), iso_dR, 0., IsolationEFlow::TRACK_COMPONENT);
|
---|
125 | double iso_all = PHYSICS->Isol->eflow->relIsolation(Lep,event.rec(), 0.2, 0., IsolationEFlow::ALL_COMPONENTS);
|
---|
126 | bool iso = (iso_tracks<0.15 && iso_all<0.20);
|
---|
127 | if( pt>200. ) iso = (iso_all<std::max(0.015, 3.5/pt));
|
---|
128 |
|
---|
129 | // Signal electrons
|
---|
130 | if( Lep->abseta() < 2.47 && pt > 17. && iso) SignalElectrons.push_back(Lep);
|
---|
131 | }
|
---|
132 |
|
---|
133 |
|
---|
134 | //// Muons ////
|
---|
135 | std::vector<const RecLeptonFormat*> SignalMuons;
|
---|
136 | for( unsigned int im=0; im<event.rec()->muons().size(); im++ ){
|
---|
137 | const RecLeptonFormat *Lep = &(event.rec()->muons()[im]);
|
---|
138 |
|
---|
139 | // Kinematics
|
---|
140 | double pt = Lep->pt();
|
---|
141 |
|
---|
142 | // Isolation
|
---|
143 | double iso_dR = std::min(10./pt,0.3);
|
---|
144 | double iso_tracks = PHYSICS->Isol->eflow->relIsolation(Lep,event.rec(), iso_dR, 0., IsolationEFlow::TRACK_COMPONENT);
|
---|
145 | double iso_all = PHYSICS->Isol->eflow->relIsolation(Lep,event.rec(), 0.2, 0., IsolationEFlow::ALL_COMPONENTS);
|
---|
146 | bool iso = (iso_tracks<0.15 && iso_all<0.30);
|
---|
147 |
|
---|
148 | // Signal leptons
|
---|
149 | if( Lep->abseta() < 2.7 && pt > 14. && iso ) SignalMuons.push_back(Lep);
|
---|
150 | }
|
---|
151 |
|
---|
152 |
|
---|
153 | //// Taus ////
|
---|
154 | std::vector<const RecTauFormat*> SignalTaus;
|
---|
155 | for( unsigned int it=0; it<event.rec()->taus().size(); it++ ){
|
---|
156 | const RecTauFormat * CurrentTau = &(event.rec()->taus()[it]);
|
---|
157 |
|
---|
158 | // Kinematics
|
---|
159 | double pt = CurrentTau->pt();
|
---|
160 | double eta = CurrentTau->abseta();
|
---|
161 |
|
---|
162 | if( pt > 20. && eta < 2.5 && (eta < 1.37 || eta > 1.52) ){
|
---|
163 | SignalTaus.push_back(CurrentTau);
|
---|
164 | }
|
---|
165 | }
|
---|
166 |
|
---|
167 |
|
---|
168 | //// MET ////
|
---|
169 | MALorentzVector pTmiss = event.rec()->MET().momentum();
|
---|
170 | pTmiss.SetPz(0.); // Remove eta component
|
---|
171 | double MET = pTmiss.Pt();
|
---|
172 |
|
---|
173 |
|
---|
174 | // Cleaning of the jet collection and overlap removal
|
---|
175 | SignalTaus = Removal(SignalTaus, SignalElectrons, 0.2);
|
---|
176 | SignalTaus = Removal(SignalTaus, SignalMuons, 0.2);
|
---|
177 | SignalElectrons = Removal(SignalElectrons, SignalMuons, 0.01);
|
---|
178 | Jets = PHYSICS->Isol->JetCleaning(Jets, SignalElectrons, 0.2);
|
---|
179 | Jets = PHYSICS->Isol->JetCleaning(Jets, SignalMuons, 0.2);
|
---|
180 | SignalElectrons = Removal(SignalElectrons, Jets, 0.4);
|
---|
181 | SignalMuons = Removal(SignalMuons, Jets, 0.4);
|
---|
182 | Jets = Removal(Jets, SignalTaus, 0.2);
|
---|
183 |
|
---|
184 |
|
---|
185 | // ============================ //
|
---|
186 | // ===== Event selection ===== //
|
---|
187 | // =========================== //
|
---|
188 |
|
---|
189 | // Select '2018' events according to the lumi weight
|
---|
190 | // 139 /fb = 36.2 + 44.3 + 58.5
|
---|
191 | event_num++;
|
---|
192 | srand(event_num);
|
---|
193 | bool is2018 = (rand() % 100)/100. < 0.421;
|
---|
194 |
|
---|
195 | //// Baseline cut ////
|
---|
196 | if( !Manager()->ApplyCut(SignalTaus.size() == 2 && SignalTaus[0]->pt() > 50. && SignalTaus[1]->pt() > 40.,"Baseline cut") ) return true;
|
---|
197 |
|
---|
198 | //// SRlow cut-1 : asymmetric di-tau trigger. ////a
|
---|
199 | // HLT online eff for tau candidates identified by the offline medium tau identification ~ 0.9,
|
---|
200 | // assuming that trigger object matching is done. ref: ATLAS-CONF-2017-029 Figure 13
|
---|
201 | myWeight = myWeight * 0.8 * 0.9 * 0.9;
|
---|
202 | Manager()->SetCurrentEventWeight(myWeight);
|
---|
203 | if( is2018 ){
|
---|
204 | if( !Manager()->ApplyCut(SignalTaus[0]->pt() > 95. && SignalTaus[1]->pt() > 75.,"asymmetric di-$\\tau$ trigger") )
|
---|
205 | return true;
|
---|
206 | }
|
---|
207 | else{
|
---|
208 | if( !Manager()->ApplyCut(SignalTaus[0]->pt() > 95. && SignalTaus[1]->pt() > 60.,"asymmetric di-$\\tau$ trigger") )
|
---|
209 | return true;
|
---|
210 | }
|
---|
211 |
|
---|
212 | //// SRhigh cut-1 : di-tau +mET trigger. ////
|
---|
213 | if( is2018 ){
|
---|
214 | if( !Manager()->ApplyCut(SignalTaus[0]->pt() > 75. && MET > 150., "di-$\\tau +E^{miss}_{T}$ trigger") )
|
---|
215 | return true;
|
---|
216 | }
|
---|
217 | else{
|
---|
218 | if( !Manager()->ApplyCut(MET > 150., "di-$\\tau +E^{miss}_{T}$ trigger") )
|
---|
219 | return true;
|
---|
220 | }
|
---|
221 |
|
---|
222 | // Since we don't know the efficiency of '2 taus to be
|
---|
223 | // medium tagged when 2 taus passed ditau(+met) trigger,
|
---|
224 | // it is implemented via reweighting.
|
---|
225 | // 0.7 is the ratio between MA5 and ATLAS efficiency
|
---|
226 | // from Nraw of the 2 medium tau cut, with OS selection
|
---|
227 | myWeight = myWeight * 0.7;
|
---|
228 | Manager()->SetCurrentEventWeight(myWeight);
|
---|
229 | //// Common cut-1 : 2 medium taus (OS) and 3rd medium tau veto. ////
|
---|
230 | if( !Manager()->ApplyCut(SignalTaus[0]->charge()*SignalTaus[1]->charge() < 0., "2 medium $\\tau$ (OS) and 3rd medium $\\tau$ veto") )
|
---|
231 | return true;
|
---|
232 |
|
---|
233 | //// Common cut-2 : b-jet veto. ////
|
---|
234 | if( !Manager()->ApplyCut(nb == 0,"b-jet veto") ) return true;
|
---|
235 |
|
---|
236 | //// Common cut-3 : light lepton veto. ////
|
---|
237 | if( !Manager()->ApplyCut(SignalElectrons.size() == 0 && SignalMuons.size() == 0, "light lepton veto") ) return true;
|
---|
238 |
|
---|
239 | //// Common cut-4 : Z/H veto. ////
|
---|
240 | double mtata=0;
|
---|
241 | mtata=(SignalTaus[1]->momentum()+SignalTaus[0]->momentum()).M();
|
---|
242 | if( !Manager()->ApplyCut(mtata > 120.0, "Z/H veto") ) return true;
|
---|
243 |
|
---|
244 | //// SRlow cut-2 : 75 < ETmiss < 150 GeV. ////
|
---|
245 | if( !Manager()->ApplyCut((MET > 75. && MET < 150.), "$75 < E^{miss}_{T} < 150$ GeV") ) return true;
|
---|
246 |
|
---|
247 | //// SRlow cut-3 : 2 tight taus (OS) - implementation via reweighting ////
|
---|
248 | // 0.7 is ratio of N_weighted before and after 2-tight-tau cut in SR-lowMass at
|
---|
249 | // https://atlas.web.cern.ch/Atlas/GROUPS/PHYSICS/PAPERS/SUSY-2018-04/tabaux_01.pdf
|
---|
250 | double tight_low=0.7;
|
---|
251 | Manager()->SetCurrentEventWeight(myWeight * tight_low);
|
---|
252 | if( !Manager()->ApplyCut(true, "2 tight $\\tau$ (OS)") ) return true;
|
---|
253 |
|
---|
254 | //// SRlow cut-4 : |dphi(ta1,ta2)|>0.8 [rad]. ////
|
---|
255 | double DeltaPhiTau = SignalTaus[0]->dphi_0_pi(SignalTaus[1]);
|
---|
256 | if( !Manager()->ApplyCut(DeltaPhiTau > 0.8, "$|\\Delta\\phi(\\tau_{1},\\tau_{2})|>0.8$ [rad],low") ) return true;
|
---|
257 |
|
---|
258 | //// SRlow cut-5 : dR(ta1,ta2)<3.2. ////
|
---|
259 | if( !Manager()->ApplyCut(SignalTaus[0]->dr(SignalTaus[1])<3.2, "$\\Delta R(\\tau_{1},\\tau_{2})<3.2$,low"))
|
---|
260 | return true;
|
---|
261 |
|
---|
262 | //// SRlow cut-6 : mT2>70 GeV. ////
|
---|
263 | double mt2_high = PHYSICS->Transverse->MT2(SignalTaus[0],SignalTaus[1],event.rec()->MET(),0.);
|
---|
264 | if( !Manager()->ApplyCut(mt2_high > 70, "$m_{T2}>70$ GeV,low") ) return true;
|
---|
265 |
|
---|
266 | // Histograms
|
---|
267 | Manager()->FillHisto("SRlow_mT2",mt2_high);
|
---|
268 |
|
---|
269 |
|
---|
270 | //// SRhigh cut-3 : >= 1 tight tau. ////
|
---|
271 | //eff of 2 tight tau = 0.7 = p, from 120 GeV mass point
|
---|
272 | //eff of 1 tight tau = sqrt(p)
|
---|
273 | //eff of at least 1 tau = p^2 + 2*(1-p)*p = 0.91
|
---|
274 | Manager()->SetCurrentEventWeight(myWeight * 0.91);
|
---|
275 | if( !Manager()->ApplyCut(true, "$\\geq 1$ tight $\\tau$") ) return true;
|
---|
276 |
|
---|
277 | //// SRhigh cut-4 : |dphi(ta1,ta2)|>0.8 [rad]. ////
|
---|
278 | DeltaPhiTau = SignalTaus[0]->dphi_0_pi(SignalTaus[1]);
|
---|
279 | if( !Manager()->ApplyCut(DeltaPhiTau > 0.8, "$|\\Delta\\phi(\\tau_{1},\\tau_{2})|>0.8$ [rad],high") ) return true;
|
---|
280 |
|
---|
281 | //// SRhigh cut-5 : dR(ta1,ta2)<3.2. ////
|
---|
282 | if( !Manager()->ApplyCut(SignalTaus[0]->dr(SignalTaus[1])< 3.2, "$\\Delta R(\\tau_{1},\\tau_{2})<3.2$,high"))
|
---|
283 | return true;
|
---|
284 |
|
---|
285 | //// SRhigh cut-6 : mT2>70 GeV. ////
|
---|
286 | if( !Manager()->ApplyCut(mt2_high > 70, "$m_{T2}>70$ GeV,high") ) return true;
|
---|
287 |
|
---|
288 | // Histograms
|
---|
289 | Manager()->FillHisto("SRhigh_mT2",mt2_high);
|
---|
290 |
|
---|
291 | return true;
|
---|
292 | }
|
---|
293 |
|
---|
294 | // User-defined functions for overlap removal
|
---|
295 | template<typename T1, typename T2> std::vector<const T1*>
|
---|
296 | Removal(std::vector<const T1*> &v1, std::vector<const T2*> &v2,
|
---|
297 | const double &drmin)
|
---|
298 | {
|
---|
299 | // Determining which objects should be removed
|
---|
300 | std::vector<bool> mask(v1.size(),false);
|
---|
301 | for (unsigned int j=0;j<v1.size();j++)
|
---|
302 | for (unsigned int i=0;i<v2.size();i++)
|
---|
303 | if (v2[i]->dr(v1[j]) < drmin)
|
---|
304 | {
|
---|
305 | mask[j]=true;
|
---|
306 | break;
|
---|
307 | }
|
---|
308 |
|
---|
309 | // Building the cleaned container
|
---|
310 | std::vector<const T1*> cleaned_v1;
|
---|
311 | for (unsigned int i=0;i<v1.size();i++)
|
---|
312 | if (!mask[i]) cleaned_v1.push_back(v1[i]);
|
---|
313 |
|
---|
314 | return cleaned_v1;
|
---|
315 | }
|
---|