29parser = argparse.ArgumentParser()
30parser.add_argument(
"--lumi-scale", type=float, default=0.05,
31 help=
"Run only on a fraction of the total available 10 fb^-1 (only usable together with --full-dataset)")
32parser.add_argument(
"--full-dataset", action=
"store_true", default=
False,
33 help=
"Use the full dataset (use --lumi-scale to run only on a fraction of it)")
34parser.add_argument(
"-b", action=
"store_true", default=
False, help=
"Use ROOT batch mode")
35parser.add_argument(
"-t", action=
"store_true", default=
False, help=
"Use implicit multi threading (for the full dataset only possible with --lumi-scale 1.0)")
36if 'df107_SingleTopAnalysis.py' in sys.argv[0]:
38 args = parser.parse_args()
41 args = parser.parse_args(args=[])
43if args.b: ROOT.gROOT.SetBatch(
True)
46if not args.full_dataset: lumi_scale = 0.05
47else: lumi_scale = args.lumi_scale
49print(
'Run on data corresponding to {:.1f} fb^-1 ...'.
format(lumi * lumi_scale / 1000.0))
51if args.full_dataset: dataset_path =
"root://eospublic.cern.ch//eos/opendata/atlas/OutreachDatasets/2020-01-22"
52else: dataset_path =
"root://eospublic.cern.ch//eos/root-eos/reduced_atlas_opendata/singletop"
56files = json.load(open(os.path.join(ROOT.gROOT.GetTutorialsDir(),
"dataframe/df107_SingleTopAnalysis.json")))
57processes = files.keys()
70 samples.append(sample)
74 if args.full_dataset
and lumi_scale < 1.0:
75 df[sample] = df[sample].
Range(
int(num_events * lumi_scale))
80ROOT.gInterpreter.Declare(
"""
81using cRVecF = const ROOT::RVecF &;
82using cRVecI = const ROOT::RVecI &;
83int FindGoodLepton(cRVecI goodlep, cRVecI type, cRVecF lep_pt, cRVecF lep_eta, cRVecF lep_phi, cRVecF lep_e, cRVecF trackd0pv, cRVecF tracksigd0pv, cRVecF z0)
85 int idx = -1; // Return -1 if no good lepton is found.
86 for(auto i = 0; i < type.size(); i++) {
87 if(!goodlep[i]) continue;
88 if (type[i] == 11 && abs(lep_eta[i]) < 2.47 && (abs(lep_eta[i]) < 1.37 || abs(lep_eta[i]) > 1.52) && abs(trackd0pv[i] / tracksigd0pv[i]) < 5) {
89 const ROOT::Math::PtEtaPhiEVector p(lep_pt[i], lep_eta[i], lep_phi[i], lep_e[i]);
90 if (abs(z0[i] * sin(p.Theta())) < 0.5) {
91 if (idx == -1) idx = i;
92 else return -1; // Accept only events with exactly one good lepton
95 if (type[i] == 13 && abs(lep_eta[i]) < 2.5 && abs(trackd0pv[i] / tracksigd0pv[i]) < 3) {
96 const ROOT::Math::PtEtaPhiEVector p(lep_pt[i], lep_eta[i], lep_phi[i], lep_e[i]);
97 if (abs(z0[i] * sin(p.Theta())) < 0.5) {
98 if (idx == -1) idx = i;
99 else return -1; // Accept only events with exactly one good lepton
109 df[s] = df[s].Filter(
"trigE || trigM")\
110 .Filter(
"met_et > 30000")
113 df[s] = df[s].Define(
"goodlep",
"lep_isTightID && lep_pt > 35000 && lep_ptcone30 / lep_pt < 0.1 && lep_etcone20 / lep_pt < 0.1")\
114 .Filter(
"ROOT::VecOps::Sum(goodlep) > 0")
117 df[s] = df[s].Define(
"idx_lep",
"FindGoodLepton(goodlep, lep_type, lep_pt, lep_eta, lep_phi, lep_E, lep_trackd0pvunbiased, lep_tracksigd0pvunbiased, lep_z0)")\
118 .Filter(
"idx_lep != -1")
122 df[s] = df[s].Define(
"mtw",
"sqrt(2 * lep_pt[idx_lep] * met_et * (1 - cos(lep_phi[idx_lep] - met_phi)))")\
123 .Filter(
"mtw > 60000")
126 df[s] = df[s].Filter(
"ROOT::VecOps::Sum(jet_pt > 30000 && abs(jet_eta) < 2.5) > 0")
129 df[s] = df[s].Define(
"goodjet",
"jet_pt > 60000 || abs(jet_eta) > 2.4 || jet_jvt > 0.59")\
130 .Filter(
"ROOT::VecOps::Sum(goodjet) == 2")\
131 .Define(
"goodbjet",
"goodjet && jet_MV2c10 > 0.8244273")\
132 .Filter(
"ROOT::VecOps::Sum(goodbjet) == 1")\
133 .Define(
"idx_tagged",
"ROOT::VecOps::ArgMax(goodjet && goodbjet)")\
134 .Define(
"idx_untagged",
"ROOT::VecOps::ArgMax(goodjet && !goodbjet)")
138 df[s] = df[s].Filter(
"abs(jet_eta[idx_untagged]) > 1.5 && abs(jet_eta[idx_tagged] - jet_eta[idx_untagged]) > 1.5")\
139 .Filter(
"lep_pt[idx_lep] + jet_pt[idx_tagged] + jet_pt[idx_untagged] + met_et > 195000")
144 df[s] = df[s].Define(
"weight",
"1.0")
147 if "single" in s: stop_norm =
"mcWeight / abs(mcWeight)"
148 else: stop_norm =
"mcWeight"
149 df[s] = df[s].Define(
"weight",
"scaleFactor_ELE * scaleFactor_MUON * scaleFactor_LepTRIGGER * scaleFactor_PILEUP * scaleFactor_BTAG * {} * {} / {} * {}".
format(stop_norm, xsecs[s], sumws[s], lumi))
154ROOT.gInterpreter.Declare(
"""
155float ComputeTopMass(float lep_pt, float lep_eta, float lep_phi, float lep_e, float jet_pt, float jet_eta, float jet_phi, float jet_e, float met_et, float met_phi)
157 const ROOT::Math::PtEtaPhiEVector lep(lep_pt / 1000.0, lep_eta, lep_phi, lep_e / 1000.0);
158 const ROOT::Math::PtEtaPhiEVector met(met_et / 1000.0, 0, met_phi, met_et / 1000.0);
159 const ROOT::Math::PtEtaPhiEVector bjet(jet_pt / 1000.0, jet_eta, jet_phi, jet_e / 1000.0);
160 // Please note that we treat here the missing transverse energy as the neutrino, even though the z component is missing!
161 return (lep + met + bjet).M();
167 df[s] = df[s].Define(
"top_mass",
"ComputeTopMass(lep_pt[idx_lep], lep_eta[idx_lep], lep_phi[idx_lep], lep_E[idx_lep], jet_pt[idx_tagged], jet_eta[idx_tagged], jet_phi[idx_tagged], jet_E[idx_tagged], met_et, met_phi)")
168 histos[s] = df[s].Histo1D(
ROOT.RDF.TH1DModel(
"top_mass",
"", 10, 100, 400),
"top_mass",
"weight")
178def merge_histos(label):
180 for i, d
in enumerate(files[label]):
181 t = histos[d[1]].GetValue()
182 if i == 0: h = t.Clone()
184 h.SetNameTitle(label, label)
187data = merge_histos(
"data")
188twtb = merge_histos(
"twtb")
189singletop = merge_histos(
"singletop")
190wjets = merge_histos(
"wjets")
195ROOT.gROOT.SetStyle(
"ATLAS")
198c = ROOT.TCanvas(
"c",
"", 600, 600)
199pad = ROOT.TPad(
"upper_pad",
"", 0, 0, 1, 1)
206stack = ROOT.THStack()
209 [wjets, twtb, singletop],
210 [(222, 90, 106), (155, 152, 204), (208, 240, 193)]):
213 h.SetFillColor(ROOT.TColor.GetColor(*color))
216stack.GetXaxis().SetTitle(
"m_{W(l#nu)+b} [GeV]")
217stack.GetYaxis().SetTitle(
"Events")
218stack.GetYaxis().SetLabelSize(0.04)
219stack.GetYaxis().SetTitleSize(0.045)
220stack.GetXaxis().SetLabelSize(0.04)
221stack.GetXaxis().SetTitleSize(0.045)
223stack.SetMaximum(5000 * lumi_scale)
224stack.GetYaxis().ChangeLabel(1, -1, 0)
227data.SetMarkerStyle(20)
228data.SetMarkerSize(1.2)
230data.SetLineColor(ROOT.kBlack)
234legend = ROOT.TLegend(0.60, 0.65, 0.92, 0.92)
235legend.SetTextFont(42)
236legend.SetFillStyle(0)
237legend.SetBorderSize(0)
238legend.SetTextSize(0.035)
239legend.SetTextAlign(32)
240legend.AddEntry(data,
"Data" ,
"lep")
241legend.AddEntry(singletop,
"Single top + jet",
"f")
242legend.AddEntry(twtb,
"t#bar{t},Wt,t#bar{b}",
"f")
243legend.AddEntry(wjets,
"W+jets",
"f")
250text.SetTextSize(0.045)
251text.DrawLatex(0.21, 0.86,
"ATLAS")
253text.DrawLatex(0.21 + 0.16, 0.86,
"Open Data")
254text.SetTextSize(0.04)
255text.DrawLatex(0.21, 0.80,
"#sqrt{{s}} = 13 TeV, {:.1f} fb^{{-1}}".
format(lumi * lumi_scale / 1000.0))
258c.SaveAs(
"df107_SingleTopAnalysis.png")
259print(
"Saved figure to df107_SingleTopAnalysis.png")
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t format
ROOT's RDataFrame offers a modern, high-level interface for analysis of data stored in TTree ,...
void RunGraphs(std::vector< RResultHandle > handles)
Trigger the event loop of multiple RDataFrames concurrently.
void EnableImplicitMT(UInt_t numthreads=0)
Enable ROOT's implicit multi-threading for all objects and methods that provide an internal paralleli...
A struct which stores the parameters of a TH1D.