int main(int argc, char* argv[]){ string cfg; // The configuration file string datacard_regex = ""; string root_file_regex = ""; string pulls_file = ""; string datacard_path = ""; string root_file_path = ""; string output = ""; string text1 = ""; string text2 = ""; bool postfit = true; bool mssm = false; bool ignore_corrs = false; bool rebin_to_vbf = true; bool split_zll = false; bool poisson_errors = false; po::options_description preconfig("Pre-Configuration"); preconfig.add_options()("cfg", po::value<std::string>(&cfg)->required()); po::variables_map vm; po::store(po::command_line_parser(argc, argv).options(preconfig).allow_unregistered().run(), vm); po::notify(vm); po::options_description config("Configuration"); config.add_options() ("help,h", "print the help message") ("datacard_regex", po::value<string>(&datacard_regex)->required(), "[REQUIRED] regular expression for datacards to parse") ("root_file_regex", po::value<string>(&root_file_regex)->required(), "[REQUIRED] regular expression for root files to parse") ("datacard_path", po::value<string>(&datacard_path)->required(), "[REQUIRED] path to the folder containing datacard *.txt files") ("root_file_path", po::value<string>(&root_file_path)->required(), "[REQUIRED] path to the folder containing datacard *.root files") ("pulls_file", po::value<string>(&pulls_file)->required(), "[REQUIRED] path to the file containing the pulls from a maximum-likelihood fit") ("output", po::value<string>(&output)->required(), "[REQUIRED] output name (no extension)") ("text1", po::value<string>(&text1)->default_value(""), "[REQUIRED] output name (no extension)") ("text2", po::value<string>(&text2)->default_value(""), "[REQUIRED] output name (no extension)") ("postfit", po::value<bool>(&postfit)->required(), "[REQUIRED] use the pulls file to make a post-fit plot") ("ignore_corrs", po::value<bool>(&ignore_corrs)->default_value(false), "Ignore all nuisance parameter correlations when evaulating uncertainties") ("rebin_to_vbf", po::value<bool>(&rebin_to_vbf)->default_value(true), "Use wider vbf binning for all categories") ("split_zll", po::value<bool>(&split_zll)->default_value(false), "Draw Z->ll component separately from electroweak") ("poisson_errors", po::value<bool>(&poisson_errors)->default_value(false), "Draw data with poisson error bars") ("mssm", po::value<bool>(&mssm)->default_value(false), "input is an MSSM datacard"); HTTPlot plot; config.add(plot.GenerateOptions("")); // The string here is a prefix for the options parameters po::store(po::command_line_parser(argc, argv).options(config).allow_unregistered().run(), vm); po::store(po::parse_config_file<char>(cfg.c_str(), config, true), vm); po::notify(vm); HTTSetup setup; boost::filesystem::path datacard_folder(datacard_path); boost::filesystem::directory_iterator dir_it(datacard_folder); boost::regex datacard_rgx(datacard_regex); for (; dir_it != boost::filesystem::directory_iterator(); ++dir_it) { std::string path = dir_it->path().filename().string(); if (boost::regex_match(path, datacard_rgx)) { std::cout << "Parsing datacard: " << dir_it->path().string() << std::endl; setup.ParseDatacard(dir_it->path().string(), plot.draw_signal_mass()); } } boost::filesystem::path file_folder(root_file_path); dir_it = boost::filesystem::directory_iterator(file_folder); boost::regex file_rgx(root_file_regex); for (; dir_it != boost::filesystem::directory_iterator(); ++dir_it) { std::string path = dir_it->path().filename().string(); if (boost::regex_match(path, file_rgx)) { std::cout << "Parsing ROOT file: " << dir_it->path().string() << std::endl; setup.ParseROOTFile(dir_it->path().string()); } } if (postfit) { setup.ParsePulls(pulls_file); setup.ApplyPulls(); } setup.SetIgnoreNuisanceCorrelations(ignore_corrs); // setup = setup.no_shapes(); if (rebin_to_vbf) setup.VariableRebin({0., 20., 40., 60., 80., 100., 120., 140., 160., 180., 200., 250., 300., 350.}); double sig_yield_before = setup.signals().GetRate(); setup.WeightSoverB(); double sig_yield_after = setup.signals().GetRate(); double scale_all = sig_yield_before / sig_yield_after; std::cout << "Scale all distributions: " << scale_all << std::endl; vector<string> samples = {"ZTT","QCD","W","ZL","ZJ","ZLL","VV","TT","Ztt","Fakes","EWK","ttbar"}; vector<string> signal_procs = {"ggH", "qqH", "VH"}; if (mssm) signal_procs = {"ggH","bbH"}; Plot::SetHTTStyle(); TCanvas canv; TH1F signal_hist = setup.process(signal_procs).GetShape(); SetMCStackStyle(signal_hist, kRed); signal_hist.SetFillColor(kRed); signal_hist.SetFillStyle(3004); signal_hist.SetLineColor(kRed); signal_hist.SetLineWidth(2); signal_hist.SetTitle(("H("+plot.draw_signal_mass()+")#rightarrow#tau#tau").c_str()); TH1F ztt_hist = setup.process({"ZTT","Ztt"}).GetShape(); SetMCStackStyle(ztt_hist, kOrange - 4); ztt_hist.SetTitle("Z#rightarrow#tau#tau"); TH1F qcd_hist = setup.process({"QCD","Fakes"}).GetShape(); SetMCStackStyle(qcd_hist, kMagenta-10); qcd_hist.SetTitle("QCD"); TH1F ewk_hist = setup.process({"W","ZL","ZJ","ZLL","VV","EWK"}).GetShape(); if (split_zll) ewk_hist = setup.process({"W","VV","EWK"}).GetShape(); SetMCStackStyle(ewk_hist, kRed + 2); ewk_hist.SetTitle("electroweak"); TH1F zll_hist = setup.process({"ZL","ZJ","ZLL"}).GetShape(); SetMCStackStyle(zll_hist, kAzure + 2); zll_hist.SetTitle("Z#rightarrowll"); TH1F top_hist = setup.process({"TT","ttbar"}).GetShape(); SetMCStackStyle(top_hist, kBlue - 8); top_hist.SetTitle("t#bar{t}"); // total_hist will be used to draw the background error on the main plot TH1F total_hist = setup.process({"ZTT","ZL","ZJ","ZLL","W","QCD","VV","TT","Ztt","Fakes","EWK","ttbar"}).GetShape(); total_hist.SetMarkerSize(0); total_hist.SetFillColor(1); total_hist.SetFillStyle(3013); total_hist.SetLineWidth(1); total_hist.SetTitle("bkg. uncertainty"); // copy_hist removes the bin errors from total_hist, and will be used // to determine the data-bkg histogram for the inset plot TH1F copy_hist = total_hist; for (int i = 1; i <= copy_hist.GetNbinsX(); ++i) copy_hist.SetBinError(i, 0); // err_hist removes the bin contents from total_hist, and will be used // to draw the error band on the inset plot TH1F err_hist = total_hist; for (int i = 1; i <= err_hist.GetNbinsX(); ++i) err_hist.SetBinContent(i, 0); err_hist.SetMarkerSize(0.0); err_hist.SetFillColor(1); err_hist.SetFillStyle(3013); err_hist.SetLineWidth(3); err_hist.SetTitle("bkg. uncertainty"); TH1F data_hist = setup.GetObservedShape(); TGraphAsymmErrors data_errors = setup.GetObservedShapeErrors(); SetDataStyle(data_hist); SetDataStyle(data_errors); data_hist.SetTitle("observed"); if (plot.blind()) BlindHistogram(&data_hist, plot.x_blind_min(), plot.x_blind_max()); TH1F diff_hist = data_hist; diff_hist.Add(©_hist, -1.); SetDataStyle(diff_hist); diff_hist.SetTitle("observed - bkg."); vector<TH1F *> drawn_hists; drawn_hists.push_back(&qcd_hist); drawn_hists.push_back(&ewk_hist); drawn_hists.push_back(&zll_hist); drawn_hists.push_back(&ztt_hist); drawn_hists.push_back(&top_hist); drawn_hists.push_back(&signal_hist); drawn_hists.push_back(&data_hist); drawn_hists.push_back(&diff_hist); drawn_hists.push_back(&err_hist); drawn_hists.push_back(&total_hist); for (unsigned i = 0; i < drawn_hists.size(); ++i) { drawn_hists[i]->SetLineWidth(2); drawn_hists[i]->Scale(scale_all); drawn_hists[i]->Scale(1.0, "width"); } TGraphAsymmErrors diff_errors = data_errors; for (int k = 0; k < data_errors.GetN(); ++k) { double x; double y; double width = data_hist.GetBinWidth(k+1); data_errors.GetPoint(k, x, y); data_errors.SetPoint(k, x, scale_all * (y/width)); double err_y_up = scale_all * (data_errors.GetErrorYhigh(k)/width); double err_y_dn = scale_all * (data_errors.GetErrorYlow(k)/width); data_errors.SetPointEYhigh(k, err_y_up); data_errors.SetPointEYlow(k, err_y_dn); diff_errors.SetPoint(k, x, (scale_all * (y/width)) - total_hist.GetBinContent(k+1)); diff_errors.SetPointEYhigh(k, err_y_up); diff_errors.SetPointEYlow(k, err_y_dn); } THStack thstack("stack","stack"); thstack.Add(&qcd_hist, "HIST"); thstack.Add(&top_hist, "HIST"); thstack.Add(&ewk_hist, "HIST"); if (split_zll) thstack.Add(&zll_hist, "HIST"); thstack.Add(&ztt_hist, "HIST"); thstack.Add(&signal_hist, "HIST"); thstack.SetMaximum(thstack.GetMaximum()*1.1*plot.extra_pad()); thstack.Draw(); thstack.GetXaxis()->SetTitle(plot.x_axis_label().c_str()); thstack.GetYaxis()->SetTitle(plot.y_axis_label().c_str()); thstack.GetHistogram()->SetTitleSize (0.055,"Y"); thstack.GetHistogram()->SetTitleOffset(1.200,"Y"); thstack.GetHistogram()->SetLabelOffset(0.014,"Y"); thstack.GetHistogram()->SetLabelSize (0.040,"Y"); thstack.GetHistogram()->SetLabelFont (42 ,"Y"); thstack.GetHistogram()->SetTitleSize (0.055,"X"); thstack.GetHistogram()->SetTitleOffset(1.100,"X"); thstack.GetHistogram()->SetLabelOffset(0.014,"X"); thstack.GetHistogram()->SetLabelSize (0.040,"X"); thstack.GetHistogram()->SetLabelFont (42 ,"X"); // canv.Update(); total_hist.Draw("SAMEE2"); if (!poisson_errors){ data_hist.Draw("SAME"); } else { data_errors.Draw("SAMEP"); } TLegend *legend = new TLegend(0.65,0.20,0.9,0.40,"","brNDC"); legend->AddEntry(&signal_hist, "", "F"); legend->AddEntry(&data_hist, "", "LP"); legend->AddEntry(&ztt_hist, "", "F"); if (split_zll) legend->AddEntry(&zll_hist, "", "F"); legend->AddEntry(&ewk_hist, "", "F"); legend->AddEntry(&top_hist, "", "F"); legend->AddEntry(&qcd_hist, "", "F"); LegendStyle(legend); legend->Draw(); TPad padBack("padBack","padBack",0.53,0.52,0.975,0.956);//TPad must be created after TCanvas otherwise ROOT crashes padBack.SetFillColor(0); TPad pad("diff","diff",0.45,0.45,0.9765,0.961);//TPad must be created after TCanvas otherwise ROOT crashes pad.cd(); pad.SetFillColor(0); pad.SetFillStyle(0); double sig_max_val = signal_hist.GetBinContent(signal_hist.GetMaximumBin()); double dif_max_val = 0; for (int i = 1; i < diff_hist.GetNbinsX(); ++i) { dif_max_val = std::max(diff_hist.GetBinContent(i) + diff_hist.GetBinError(i), dif_max_val); } double err_max_val = 0; for (int i = 1; i < err_hist.GetNbinsX(); ++i) { err_max_val = std::max(err_hist.GetBinContent(i) + err_hist.GetBinError(i), err_max_val); } double inset_y_max = 1.3 * std::max({sig_max_val, dif_max_val, err_max_val}); err_hist.GetYaxis()->SetNdivisions(5); err_hist.GetYaxis()->SetLabelSize(0.05); err_hist.GetXaxis()->SetTitle("#bf{m_{#tau#tau} [GeV]} "); err_hist.GetXaxis()->SetTitleColor(kBlack); err_hist.GetXaxis()->SetTitleSize(0.06); err_hist.GetXaxis()->SetTitleOffset(0.95); err_hist.GetXaxis()->SetLabelSize(0.05); err_hist.SetNdivisions(405); err_hist.Draw("E2"); err_hist.GetXaxis()->SetRangeUser(40,199); err_hist.GetYaxis()->SetRangeUser(-inset_y_max,inset_y_max); signal_hist.Draw("HISTSAME"); if (!poisson_errors){ diff_hist.Draw("SAME"); } else { diff_errors.Draw("SAMEP"); } pad.RedrawAxis(); TLine line; line.DrawLine(40,0,200,0); TLegend *inlegend = new TLegend(0.60,0.75,0.9,0.90,"","brNDC"); inlegend->AddEntry(&signal_hist, "", "F"); inlegend->AddEntry(&diff_hist, "", "LP"); inlegend->AddEntry(&err_hist, "", "F"); LegendStyle(inlegend); inlegend->Draw(); canv.cd(); padBack.Draw(); pad.Draw(); TLatex *title_latex = new TLatex(); title_latex->SetNDC(); title_latex->SetTextSize(0.03); title_latex->SetTextFont(62); title_latex->SetTextAlign(31); title_latex->DrawLatex(0.95,0.93,plot.title_right().c_str()); title_latex->SetTextAlign(11); title_latex->DrawLatex(0.15,0.93,plot.title_left().c_str()); title_latex->SetTextSize(0.04); title_latex->DrawLatex(0.20,0.87,(text1 + (postfit? "" : " (prefit)")).c_str()); title_latex->DrawLatex(0.20,0.82,text2.c_str()); canv.SaveAs((output+".pdf").c_str()); canv.SaveAs((output+".png").c_str()); return 0; }
int main(int argc, char* argv[]){ string cfg; // The configuration file string paramfile; // The paramters files string folder; // Folder containing input files string channel_str; // Channel, e.g. et unsigned method; // Use background methods for chosen category string var; // Use background methods for chosen category string cat; // Use background methods for chosen category unsigned verbosity; // Verbose output, useful for diagnostic purposes bool is_sm; bool do_ss; // Tweaking some things for the paper string datacard; string year; vector<string> set_alias; // A string like alias1:value1,alias2:value2 etc string shift_backgrounds; bool auto_titles=true; bool calc_vertex_weights; double qcd_os_ss_factor; bool interpolate; // Program options po::options_description preconfig("Pre-Configuration"); preconfig.add_options()("cfg", po::value<std::string>(&cfg)->required()); po::variables_map vm; po::store(po::command_line_parser(argc, argv).options(preconfig).allow_unregistered().run(), vm); po::notify(vm); po::options_description config("Configuration"); config.add_options() ("paramfile", po::value<string>(¶mfile)->required()) ("folder", po::value<string>(&folder)->required()) ("channel", po::value<string>(&channel_str)->required()) ("method", po::value<unsigned>(&method)->required()) ("var", po::value<string>(&var)->required()) ("cat", po::value<string>(&cat)->default_value("")) ("verbosity", po::value<unsigned>(&verbosity)->default_value(0)) ("year", po::value<string>(&year)->default_value("2015")) ("is_sm", po::value<bool>(&is_sm)->default_value(true)) ("do_ss", po::value<bool>(&do_ss)->default_value(false)) ("interpolate", po::value<bool>(&interpolate)->default_value(false)) ("datacard", po::value<string>(&datacard)->default_value("")) ("set_alias", po::value<vector<string>>(&set_alias)->composing()) ("calc_vertex_weights", po::value<bool>(&calc_vertex_weights)->default_value(false)) ("qcd_os_ss_factor", po::value<double>(&qcd_os_ss_factor)->default_value(1.06)); HTTPlot plot; config.add(plot.GenerateOptions("")); // The string here is a prefix for the options parameters po::store(po::command_line_parser(argc, argv).options(config).allow_unregistered().run(), vm); po::store(po::parse_config_file<char>(cfg.c_str(), config), vm); po::notify(vm); std::cout << "-----------------------------------------------------------------------------------" << std::endl; std::cout << "ZllPlot" << std::endl; std::cout << "-----------------------------------------------------------------------------------" << std::endl; std::cout << boost::format(param_fmt()) % "paramfile" % paramfile; std::cout << boost::format(param_fmt()) % "cfg" % cfg; std::cout << boost::format(param_fmt()) % "folder" % folder; std::cout << boost::format(param_fmt()) % "channel" % channel_str; std::cout << boost::format(param_fmt()) % "variable" % var; std::cout << boost::format(param_fmt()) % "method" % method; std::cout << boost::format(param_fmt()) % "category" % cat; std::cout << boost::format(param_fmt()) % "datacard" % datacard; std::cout << "-----------------------------------------------------------------------------------" << std::endl; // ************************************************************************ // Extract variable name and set output filename // ************************************************************************ std::string reduced_var = var; std::size_t begin_var = reduced_var.find("["); if (begin_var != reduced_var.npos) reduced_var.erase(begin_var, reduced_var.npos); begin_var = reduced_var.find("("); if (begin_var != reduced_var.npos) reduced_var.erase(begin_var, reduced_var.npos); if (plot.plot_name() == "") { plot.set_plot_name(reduced_var+"_"+datacard+"_"+channel_str+("_"+year)); } TH1::AddDirectory(false); // ************************************************************************ // Load alias overrides // ************************************************************************ std::vector<std::pair<std::string, std::string>> alias_vec; for (unsigned i = 0; i < set_alias.size(); ++i) { std::vector<std::string> alias_part; boost::split(alias_part, set_alias[i], boost::is_any_of(":")); if (alias_part.size() == 2) alias_vec.push_back(std::make_pair(alias_part[0],alias_part[1])); std::cout << "[ZllPlot] Setting alias: " << alias_part[0] << " --> \"" << alias_part[1] << "\"" << std::endl; } // ************************************************************************ // Setup HTTRun2Analysis // ************************************************************************ HTTRun2Analysis ana(String2Channel(channel_str), year, verbosity, is_sm); ana.SetQCDRatio(qcd_os_ss_factor); if (do_ss) ana.SetQCDRatio(1.0); for (auto const& a : alias_vec) ana.SetAlias(a.first, a.second); //if (is_2012 && (check_ztt_top_frac || sub_ztt_top_shape)) ana.AddSample("Embedded-TTJets_FullLeptMGDecays"); ana.ReadTrees(folder); ana.ParseParamFile(paramfile); HTTRun2Analysis::HistValueMap hmap; // std::string sel = " "+ana.ResolveAlias("sel"); std::string sel; if (channel_str != "wmnu") sel = "os && "+ana.ResolveAlias("sel"); else sel = ana.ResolveAlias("sel"); if (do_ss) { sel = "!os && "+ana.ResolveAlias("sel"); ana.SetAlias("w_os", "!os"); ana.SetAlias("w_sdb_os", "!os"); ana.SetAlias("w_vbf_os", "!os"); ana.SetAlias("w_shape_os", "!os"); } cat = ana.ResolveAlias(cat); std::string morph_var = "m_sv(70,0,350)"; std::string sig_var = var; ana.FillHistoMap(hmap, method, var, sel, cat, "wt", ""); // ************************************************************************ // Write datacard // ************************************************************************ if (datacard != "") { std::string dc_mode_label; if (channel_str == "zee") dc_mode_label = "Zee"; if (channel_str == "zmm") dc_mode_label = "Zmm"; std::string tfile_name = "datacard_"+reduced_var+"_"+datacard+"_"+channel_str+("_"+year)+".root"; TFile dc_file(tfile_name.c_str(),"RECREATE"); dc_file.cd(); gDirectory->mkdir((dc_mode_label+"_"+datacard).c_str()); gDirectory->cd((dc_mode_label+"_"+datacard).c_str()); for (auto iter : hmap) { iter.second.first.SetTitle(iter.first.c_str()); iter.second.first.SetName(iter.first.c_str()); iter.second.first.Write(); } std::cout << "[ZllPlot] Writing datacard input " << tfile_name << std::endl; dc_file.Close(); } // ************************************************************************ // Shift backgrounds // ************************************************************************ vector<string> shift_strs; boost::split(shift_strs, shift_backgrounds, boost::is_any_of(",")); if (shift_strs.size() > 0) { std::cout << "[ZllPlot] Shifting background yields... " << std::endl; for (auto shift : shift_strs) { std::vector<std::string> shift_part; boost::split(shift_part, shift, boost::is_any_of(":")); if (shift_part.size() != 2) continue; string regex_str = shift_part[0]/*+".*"*/; boost::regex rgx = boost::regex(regex_str); double shift_val = boost::lexical_cast<double>(shift_part[1]); for (auto & entry : hmap) { if (boost::regex_match(entry.first, rgx)) { std::cout << "Scaling " << entry.first << " by " << shift_val << std::endl; entry.second.first.Scale(shift_val); entry.second.second.first *= shift_val; // the yield entry.second.second.second *= shift_val; // the yield error } } } } // ************************************************************************ // Deduce titles // ************************************************************************ if (auto_titles) { double pb_lumi = ana.GetLumi(); double fb_lumi = pb_lumi/1000.; string com = "13"; plot.set_lumi_label((boost::format("%.1f fb^{-1} at %s TeV") % fb_lumi % com).str()); plot.set_cms_label("CMS"); plot.set_cms_extra("Preliminary"); std::string channel_fmt = ""; if (channel_str == "zee") channel_fmt = "Z#rightarrowee"; if (channel_str == "zmm") channel_fmt = "Z#rightarrow#mu#mu"; if (channel_str == "wmnu") channel_fmt = "W#rightarrow#mu#nu"; ic::TextElement text(channel_fmt,0.05,0.16,0.96); //ic::TextElement text2("#splitline{Same-sign}{region}",0.05,0.65,0.5); plot.AddTextElement(text); //plot.AddTextElement(text2); } if (calc_vertex_weights){ TH1F * data = &hmap["data_obs"].first; TH1F *data_test = (TH1F*)data->Clone("data_test"); TH1F * nvtx_weights = new TH1F("nvtx_weights","nvtx_weights",101,-0.5,100.5); data_test->Scale(1./data_test->Integral(1,data_test->GetNbinsX())); std::cout<<data_test->Integral()<<std::endl; vector<string>bkgs = {"ZLL","W","TT","VV"}; double bckg_yield=0; for (int i = 1; i<= data_test->GetNbinsX(); ++i){ for (auto bkg : bkgs) bckg_yield += hmap[bkg].first.GetBinContent(i); } std::cout <<bckg_yield<<std::endl; for (int i = 1; i <= data_test->GetNbinsX(); ++i){ double bkg_tot = 0; for (auto bkg : bkgs) bkg_tot += hmap[bkg].first.GetBinContent(i); bkg_tot = (double)bkg_tot/bckg_yield; if(bkg_tot !=0){ nvtx_weights->SetBinContent(nvtx_weights->FindBin(data_test->GetBinCenter(i)),(data_test->GetBinContent(i)/bkg_tot)); std::cout<<"PVMin "<<data_test->GetBinCenter(i)<<" data/bkg "<<(data_test->GetBinContent(i))/(bkg_tot)<<std::endl; } } std::string weightfilename = "VertexWeightDistribution_"+channel_str+".root"; TFile *fileout = new TFile(weightfilename.c_str(),"RECREATE"); nvtx_weights->Write(); fileout->Close(); } plot.GeneratePlot(hmap); return 0; }