4 #include "boost/lexical_cast.hpp"
5 #include "boost/algorithm/string.hpp"
6 #include "boost/format.hpp"
7 #include "boost/bind.hpp"
8 #include "boost/program_options.hpp"
13 namespace po = boost::program_options;
30 BkgInfo(
string const& l, vector<string>
const& p) : label(l), procs(p) {}
33 int main(
int argc,
char* argv[]) {
35 vector<string> columns;
37 vector<string> datacards;
38 vector<string> sig_datacards;
39 string fitresult_file =
"";
40 string signal_mass =
"";
43 std::string header =
"";
45 po::options_description config(
"Configuration");
48 po::value<string>(&channel)->required(),
"channel")
50 po::value<vector<string>> (&columns)->multitoken()->required(),
"labels")
52 po::value<vector<string>> (&eras)->multitoken()->required(),
"eras")
54 po::value<vector<string>> (&datacards)->multitoken()->required())
56 po::value<vector<string>> (&sig_datacards)->multitoken()->required())
58 po::value<string> (&fitresult_file))
60 po::value<string>(&signal_mass)->required(),
"signal_mass")
62 po::value<string>(&tanb)->default_value(
"8"),
"tanb")
64 po::value<string>(&header)->default_value(
""),
"header")
66 po::value<bool>(&postfit)->required(),
"postfit");
68 po::store(po::command_line_parser(argc, argv)
75 double d_tanb = boost::lexical_cast<double>(tanb);
78 vector<string> signal_procs = {
"ggH",
"bbH"};
79 unsigned n_sig = signal_procs.size();
82 unsigned n_eras = eras.size();
83 vector<string> v_eras;
84 vector<string> v_eras_lumi;
85 for (
unsigned i = 0; i < eras.size(); ++i) {
87 boost::split(tmp, eras[i], boost::is_any_of(
":"));
88 v_eras.push_back(tmp.at(0));
89 v_eras_lumi.push_back(tmp.at(1));
93 vector<ColInfo> col_info;
94 col_info.resize(columns.size() * n_eras);
95 for (
unsigned k =0; k < n_eras; ++k) {
96 for (
unsigned i = 0; i < columns.size(); ++i) {
97 unsigned idx = k * columns.size() + i;
99 vector<string> tmp_split;
100 boost::split(tmp_split, columns[i], boost::is_any_of(
":"));
101 info.
label = tmp_split[0];
102 boost::split(info.
cats_str, tmp_split[1], boost::is_any_of(
"+"));
103 for (
auto const& str : info.
cats_str)
104 info.
cats_int.push_back(boost::lexical_cast<int>(str));
105 info.
era = v_eras[k];
106 info.
lumi = boost::lexical_cast<double>(v_eras_lumi[k]);
109 unsigned n_cols = col_info.size();
112 double signal_den[n_cols][n_sig];
113 double signal_num[n_cols][n_sig];
114 double signal_eff[n_cols][n_sig];
117 for (
unsigned i = 0; i < n_sig; ++i) {
118 for (
unsigned j = 0; j < n_cols; ++j) {
119 signal_den[j][i] = col_info[j].lumi;
124 vector<BkgInfo> bkgs;
125 vector<string> total_bkg;
126 if (channel ==
"et" || channel ==
"mt" || channel ==
"tt") {
128 BkgInfo(
"$\\cPZ\\rightarrow \\Pgt\\Pgt$", {
"ZTT"}),
131 BkgInfo(
"$\\cPZ$+jets (l/jet faking $\\Pgt$)", {
"ZL",
"ZJ"}),
132 BkgInfo(
"$\\cPqt\\cPaqt$", {
"TT"}),
133 BkgInfo(
"Di-bosons + single top", {
"VV"})
135 total_bkg = {
"ZTT",
"QCD",
"W",
"ZL",
"ZJ",
"TT",
"VV"};
137 if (channel ==
"em") {
139 BkgInfo(
"$\\cPZ\\rightarrow \\Pgt\\Pgt$", {
"Ztt"}),
141 BkgInfo(
"$\\cPqt\\cPaqt$", {
"ttbar"}),
142 BkgInfo(
"Di-bosons + single top", {
"EWK"})
144 total_bkg = {
"Ztt",
"Fakes",
"ttbar",
"EWK"};
146 if (channel ==
"mm") {
148 BkgInfo(
"$\\cPZ\\rightarrow \\Pgt\\Pgt$", {
"ZTT"}),
149 BkgInfo(
"$\\cPZ\\rightarrow \\mu\\mu$", {
"ZMM"}),
151 BkgInfo(
"$\\cPqt\\cPaqt$", {
"TTJ"}),
152 BkgInfo(
"Di-bosons + single top", {
"WJets",
"Dibosons"})
154 total_bkg = {
"ZTT",
"ZMM",
"QCD",
"TTJ",
"WJets",
"Dibosons"};
156 unsigned n_bkg = bkgs.size();
163 for (
auto const& d : datacards) {
168 "$ANALYSIS_$CHANNEL_$BINID_$ERA"));
175 for (
auto const& d : sig_datacards) {
176 sig_cmb.
ParseDatacard(d,
"$MASS/$ANALYSIS_$CHANNEL_$BINID_$ERA.txt");
179 RooFitResult *fitresult =
nullptr;
180 if (fitresult_file.length() && postfit) {
182 new RooFitResult(ch::OpenFromTFile<RooFitResult>(fitresult_file));
189 double bkg_yields[n_cols][n_bkg];
190 double bkg_errors[n_cols][n_bkg];
191 double tot_yields[n_cols];
192 double tot_errors[n_cols];
193 double sig_yields[n_cols];
194 double sig_errors[n_cols];
195 double data_yields[n_cols];
198 unsigned samples = 500;
200 for (
unsigned i = 0; i < n_cols; ++i) {
202 std::move(cmb.
cp().
era({col_info[i].era}).
bin_id(col_info[i].cats_int));
206 sig_errors[i] = postfit ?
210 tot_errors[i] = postfit ?
213 for (
unsigned j = 0; j < n_bkg; ++j) {
215 bkg_errors[i][j] = postfit ?
219 for (
unsigned k = 0; k < n_sig; ++k) {
220 signal_num[i][k] = sig_cmb.
cp()
221 .
era({col_info[i].era})
222 .bin_id(col_info[i].cats_int)
224 .era({col_info[i].era})
226 signal_eff[i][k] = signal_num[i][k] / signal_den[i][k];
230 cout <<
"\\begin{tabular}{l";
231 for (
unsigned i = 0; i < n_cols; ++i) cout <<
"r@{$ \\,\\,\\pm\\,\\, $}l";
232 cout <<
"}\n\\hline\n";
233 cout << boost::format(
"\\multicolumn{%i}{c}{%s} \\\\\n") %
234 (n_cols * 2 + 1) % header;
236 for (
unsigned i = 0; i < v_eras.size(); ++i) {
237 std::string fmt = v_eras[i];
238 boost::replace_all(fmt,
"TeV",
"~\\TeV");
239 std::cout << boost::format(
"& \\multicolumn{%i}{c}{$\\sqrt{s}$ = %s} ") %
240 (columns.size() * 2) % fmt;
244 for (
unsigned i = 0; i < n_cols; ++i)
245 cout <<
" & \\multicolumn{2}{c}{" + col_info[i].label +
"}";
248 string fmt =
"& %-10.0f & %-10.0f";
249 string fmts =
"& %-10.0f & %-10.1f";
251 for (
unsigned k = 0; k < bkgs.size(); ++k) {
252 cout << boost::format(
"%-38s") % bkgs[k].label;
253 for (
unsigned i = 0; i < n_cols; ++i)
254 cout << boost::format(bkg_errors[i][k] < 1. ? fmts : fmt) %
255 bkg_yields[i][k] % bkg_errors[i][k];
260 cout << boost::format(
"%-38s") %
"Total Background";
261 for (
unsigned i = 0; i < n_cols; ++i)
262 cout << boost::format(fmt) % tot_yields[i] % tot_errors[i];
265 cout << boost::format(
"%-38s") %
"A+H+h\\,$\\rightarrow\\Pgt\\Pgt$";
266 for (
unsigned i = 0; i < n_cols; ++i)
267 cout << boost::format(sig_errors[i] < 1. ? fmts : fmt) % sig_yields[i] %
272 cout << boost::format(
"%-38s") %
"Data";
273 for (
unsigned i = 0; i < n_cols; ++i)
274 cout << boost::format(
"& \\multicolumn{2}{c}{%-10.0f}") % data_yields[i];
278 cout << boost::format(
279 "\\multicolumn{%i}{l}{Efficiency $\\times$ acceptance}\\\\\n") %
282 cout << boost::format(
"%-38s") %
"gluon-fusion Higgs (160~\\GeV)";
283 for (
unsigned i = 0; i < n_cols; ++i) {
284 std::string fmte = (boost::format(
"%.2e") % signal_eff[i][0]).str();
285 boost::replace_all(fmte,
"e-0",
"\\cdot 10^{-");
288 cout << boost::format(
"& \\multicolumn{2}{c}{%s}") % fmte;
293 cout << boost::format(
"%-38s") %
"b-associated Higgs (160~\\GeV)";
294 for (
unsigned i = 0; i < n_cols; ++i) {
295 std::string fmte = (boost::format(
"%.2e") % signal_eff[i][1]).str();
296 boost::replace_all(fmte,
"e-0",
"\\cdot 10^{-");
299 cout << boost::format(
"& \\multicolumn{2}{c}{%s}") % fmte; }
303 cout <<
"\\end{tabular}\n";
int main(int argc, char *argv[])
CombineHarvester & bin_id(std::vector< int > const &vec, bool cond=true)
CombineHarvester & signals()
CombineHarvester & process(std::vector< std::string > const &vec, bool cond=true)
void ForEachProc(Function func)
CombineHarvester & era(std::vector< std::string > const &vec, bool cond=true)
void UpdateParameters(std::vector< ch::Parameter > const ¶ms)
int ParseDatacard(std::string const &filename, std::string const &analysis, std::string const &era, std::string const &channel, int bin_id, std::string const &mass)
CombineHarvester cp()
Creates and returns a shallow copy of the CombineHarvester instance.
void ForEachObj(Function func)
CombineHarvester & channel(std::vector< std::string > const &vec, bool cond=true)
void set_rate(double const &rate)
std::vector< ch::Parameter > ExtractFitParameters(RooFitResult const &res)
void SetFromBinName(ch::Object *input, std::string parse_rules)
BkgInfo(string const &l, vector< string > const &p)
vector< string > cats_str