2 #include "boost/program_options.hpp"
3 #include "boost/format.hpp"
11 namespace po = boost::program_options;
16 std::vector<float> contents(h.GetNbinsX());
17 std::vector<float> errors(h.GetNbinsX());
18 for (
int i = 0; i < h.GetNbinsX(); ++i) {
19 contents[i] = h.GetBinContent(i + 1);
20 errors[i] = h.GetBinError(i + 1);
22 for (
int i = 0; i < h.GetNbinsX(); ++i) {
23 h.SetBinContent(h.GetNbinsX() - i, contents[i]);
24 h.SetBinError(h.GetNbinsX() - i, errors[i]);
29 int main(
int argc,
char* argv[]) {
31 gSystem->Load(
"libHiggsAnalysisCombinedLimit");
34 string workspace =
"";
35 string fitresult =
"";
38 bool sampling =
false;
39 bool no_sampling =
false;
42 unsigned samples = 500;
43 std::string freeze_arg =
"";
44 bool covariance =
false;
45 string data =
"data_obs";
46 bool skip_prefit =
false;
47 bool skip_proc_errs =
false;
48 bool total_shapes =
false;
49 std::vector<std::string> reverse_bins_;
51 po::options_description help_config(
"Help");
52 help_config.add_options()
53 (
"help,h",
"produce help message");
55 po::options_description config(
"Configuration");
58 po::value<string>(&workspace)->required(),
59 "The input workspace-containing file [REQUIRED]")
61 po::value<string>(&data)->default_value(data),
62 "The input dataset name")
64 po::value<string>(&datacard),
65 "The input datacard, only used for rebinning")
67 po::value<string>(&output)->required(),
68 "Name of the output root file to create [REQUIRED]")
70 po::value<string>(&fitresult)->default_value(fitresult),
71 "Path to a RooFitResult, only needed for postfit")
73 po::value<string>(&mass)->default_value(
""),
74 "Signal mass point of the input datacard")
76 po::value<bool>(&postfit)
77 ->default_value(postfit)->implicit_value(
true),
78 "Create post-fit histograms in addition to pre-fit")
80 po::value<bool>(&sampling)->default_value(sampling)->implicit_value(
true),
81 "Use the cov. matrix sampling method for the post-fit uncertainty (deprecated, this is the default)")
83 po::value<bool>(&no_sampling)->default_value(no_sampling)->implicit_value(
true),
84 "Do not use the cov. matrix sampling method for the post-fit uncertainty")
86 po::value<unsigned>(&samples)->default_value(samples),
87 "Number of samples to make in each evaluate call")
89 po::value<bool>(&factors)->default_value(factors)->implicit_value(
true),
90 "Print tables of background shifts and relative uncertainties")
92 po::value<string>(&freeze_arg)->default_value(freeze_arg),
93 "Format PARAM1,PARAM2=X,PARAM3=Y where the values X and Y are optional")
95 po::value<bool>(&covariance)->default_value(covariance)->implicit_value(
true),
96 "Save the covariance and correlation matrices of the process yields")
98 po::value<bool>(&skip_prefit)->default_value(skip_prefit)->implicit_value(
true),
99 "Skip the pre-fit evaluation")
101 po::value<bool>(&skip_proc_errs)->default_value(skip_proc_errs)->implicit_value(
true),
102 "Skip evaluation of errors on individual processes")
104 po::value<bool>(&total_shapes)->default_value(total_shapes)->implicit_value(
true),
105 "Save signal- and background shapes added for all channels/categories")
106 (
"reverse-bins", po::value<vector<string>>(&reverse_bins_)->multitoken(),
"List of bins to reverse the order for");
109 po::variables_map vm;
113 po::store(po::command_line_parser(argc, argv)
114 .options(help_config).allow_unregistered().run(), vm);
116 if (vm.count(
"help")) {
117 cout << config <<
"\nExample usage:\n";
118 cout <<
"PostFitShapesFromWorkspace.root -d htt_mt_125.txt -w htt_mt_125.root -o htt_mt_125_shapes.root -m 125 "
119 "-f mlfit.root:fit_s --postfit --print\n";
124 po::store(po::command_line_parser(argc, argv).options(config).run(), vm);
128 std::cout<<
"WARNING: the default behaviour of PostFitShapesFromWorkspace is to use the covariance matrix sampling method for the post-fit uncertainty. The option --sampling is deprecated and will be removed in future versions of CombineHarvester"<<std::endl;
131 TFile infile(workspace.c_str());
133 RooWorkspace *ws =
dynamic_cast<RooWorkspace*
>(gDirectory->Get(
"w"));
136 throw std::runtime_error(
137 FNERROR(
"Could not locate workspace in input file"));
142 cmb.
SetFlag(
"workspaces-use-clone",
true);
146 if(! freeze_arg.empty())
148 vector<string> freeze_vec;
149 boost::split(freeze_vec, freeze_arg, boost::is_any_of(
","));
150 for (
auto const& item : freeze_vec) {
151 vector<string> parts;
152 boost::split(parts, item, boost::is_any_of(
"="));
153 if (parts.size() == 1) {
156 else throw std::runtime_error(
157 FNERROR(
"Requested variable to freeze does not exist in workspace"));
159 if (parts.size() == 2) {
162 par->
set_val(boost::lexical_cast<double>(parts[1]));
165 else throw std::runtime_error(
166 FNERROR(
"Requested variable to freeze does not exist in workspace"));
174 cmb_card.
SetFlag(
"workspaces-use-clone",
true);
175 if (datacard !=
"") {
181 bool no_shape = !proc->
shape() && !proc->
data() && !proc->
pdf();
183 cout <<
"Filtering process with no shape:\n";
191 TFile outfile(output.c_str(),
"RECREATE");
192 TH1::AddDirectory(
false);
196 map<string, map<string, TH1F>> pre_shapes;
201 map<string, TH1F> pre_shapes_tot;
209 std::cout <<
">> Doing prefit: TotalBkg" << std::endl;
210 pre_shapes_tot[
"TotalBkg"] =
212 std::cout <<
">> Doing prefit: TotalSig" << std::endl;
213 pre_shapes_tot[
"TotalSig"] =
215 std::cout <<
">> Doing prefit: TotalProcs" << std::endl;
216 pre_shapes_tot[
"TotalProcs"] =
219 if (datacard !=
"") {
221 for (
auto & it : pre_shapes_tot) {
228 for (
auto& iter : pre_shapes_tot) {
232 for (
auto bin : bins) {
242 std::cout <<
">> Doing prefit: " << bin <<
"," << proc << std::endl;
243 if (skip_proc_errs) {
244 pre_shapes[bin][proc] =
247 pre_shapes[bin][proc] =
248 cmb_bin.
cp().
process({proc}).GetShapeWithUncertainty();
253 std::cout <<
">> Doing prefit: " << bin <<
"," <<
"TotalBkg" << std::endl;
254 pre_shapes[bin][
"TotalBkg"] =
256 std::cout <<
">> Doing prefit: " << bin <<
"," <<
"TotalSig" << std::endl;
257 pre_shapes[bin][
"TotalSig"] =
259 std::cout <<
">> Doing prefit: " << bin <<
"," <<
"TotalProcs" << std::endl;
260 pre_shapes[bin][
"TotalProcs"] =
264 if (datacard !=
"") {
265 TH1F ref = cmb_card.
cp().
bin({bin}).GetObservedShape();
266 for (
auto & it : pre_shapes[bin]) {
271 for (
auto const& rbin : reverse_bins_) {
272 if (rbin != bin)
continue;
273 auto & hists = pre_shapes[bin];
274 for (
auto it = hists.begin(); it != hists.end(); ++it) {
280 for (
auto& iter : pre_shapes[bin]) {
287 cout << boost::format(
"%-25s %-32s\n") %
"Bin" %
288 "Total relative bkg uncert. (prefit)";
289 cout << string(58,
'-') <<
"\n";
290 for (
auto bin : bins) {
294 cout << boost::format(
"%-25s %-10.5f") % bin %
295 (rate > 0. ? (err / rate) : 0.) << std::endl;
304 RooFitResult res = ch::OpenFromTFile<RooFitResult>(fitresult);
309 map<string, map<string, TH1F>> post_shapes;
310 map<string, TH2F> post_yield_cov;
311 map<string, TH2F> post_yield_cor;
313 map<string, TH1F> post_shapes_tot;
320 std::cout <<
">> Doing postfit: TotalBkg" << std::endl;
321 post_shapes_tot[
"TotalBkg"] =
323 : cmb_bkgs.GetShapeWithUncertainty(res, samples);
324 std::cout <<
">> Doing postfit: TotalSig" << std::endl;
325 post_shapes_tot[
"TotalSig"] =
326 no_sampling ? cmb_sigs.GetShapeWithUncertainty()
327 : cmb_sigs.GetShapeWithUncertainty(res, samples);
328 std::cout <<
">> Doing postfit: TotalProcs" << std::endl;
329 post_shapes_tot[
"TotalProcs"] =
333 if (datacard !=
"") {
335 for (
auto & it : post_shapes_tot) {
342 for (
auto & iter : post_shapes_tot) {
344 "postfit/" + iter.first);
349 for (
auto bin : bins) {
353 auto cmb_proc = cmb_bin.
cp().
process({proc});
356 std::cout <<
">> Doing postfit: " << bin <<
"," << proc << std::endl;
357 if (skip_proc_errs) {
358 post_shapes[bin][proc] = cmb_proc.GetShape();
360 post_shapes[bin][proc] =
361 no_sampling ? cmb_proc.GetShapeWithUncertainty()
362 : cmb_proc.GetShapeWithUncertainty(res, samples);
365 if (!no_sampling && covariance) {
372 std::cout <<
">> Doing postfit: " << bin <<
"," <<
"TotalBkg" << std::endl;
373 post_shapes[bin][
"TotalBkg"] =
375 : cmb_bkgs.GetShapeWithUncertainty(res, samples);
376 std::cout <<
">> Doing postfit: " << bin <<
"," <<
"TotalSig" << std::endl;
377 post_shapes[bin][
"TotalSig"] =
378 no_sampling ? cmb_sigs.GetShapeWithUncertainty()
379 : cmb_sigs.GetShapeWithUncertainty(res, samples);
380 std::cout <<
">> Doing postfit: " << bin <<
"," <<
"TotalProcs" << std::endl;
381 post_shapes[bin][
"TotalProcs"] =
385 if (datacard !=
"") {
386 TH1F ref = cmb_card.
cp().
bin({bin}).GetObservedShape();
387 for (
auto & it : post_shapes[bin]) {
395 for (
auto const& rbin : reverse_bins_) {
396 if (rbin != bin)
continue;
397 std::cout <<
">> reversing hists in bin " << bin <<
"\n";
398 auto & hists = post_shapes[bin];
399 for (
auto it = hists.begin(); it != hists.end(); ++it) {
404 for (
auto & iter : post_shapes[bin]) {
406 bin +
"_postfit/" + iter.first);
408 for (
auto & iter : post_yield_cov) {
412 for (
auto & iter : post_yield_cor) {
420 cout << boost::format(
"\n%-25s %-32s\n") %
"Bin" %
421 "Total relative bkg uncert. (postfit)";
422 cout << string(58,
'-') <<
"\n";
423 for (
auto bin : bins) {
425 double rate = cmb_bkgs.
GetRate();
428 cout << boost::format(
"%-25s %-10.5f") % bin %
429 (rate > 0. ? (err / rate) : 0.) << std::endl;
435 if (factors && postfit) {
436 cout << boost::format(
"\n%-25s %-20s %-10s\n") %
"Bin" %
"Process" %
438 cout << string(58,
'-') <<
"\n";
439 for (
auto bin : bins) {
444 TH1
const& pre = pre_shapes[bin][proc];
445 TH1
const& post = post_shapes[bin][proc];
446 cout << boost::format(
"%-25s %-20s %-10.5f\n") % bin % proc %
447 (pre.Integral() > 0. ? (post.Integral() / pre.Integral())
int main(int argc, char *argv[])
void ReverseBins(TH1F &h)
TH2F GetRateCovariance(RooFitResult const &fit, unsigned n_samples)
CombineHarvester & backgrounds()
CombineHarvester & signals()
TH2F GetRateCorrelation(RooFitResult const &fit, unsigned n_samples)
CombineHarvester & process(std::vector< std::string > const &vec, bool cond=true)
void SetFlag(std::string const &flag, bool const &value)
Set a named flag value.
std::set< std::string > process_set()
TH1F GetShapeWithUncertainty()
CombineHarvester & bin(std::vector< std::string > const &vec, bool cond=true)
void UpdateParameters(std::vector< ch::Parameter > const ¶ms)
std::set< std::string > bin_set()
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 & FilterProcs(Function func)
CombineHarvester cp()
Creates and returns a shallow copy of the CombineHarvester instance.
ch::Parameter const * GetParameter(std::string const &name) const
void set_frozen(bool const &frozen)
void set_val(double const &val)
RooAbsReal const * pdf() const
RooAbsData const * data() const
static std::ostream & PrintHeader(std::ostream &out)
TH1 const * shape() const
void WriteToTFile(T *ptr, TFile *file, std::string const &path)
TH1F RestoreBinning(TH1F const &src, TH1F const &ref)
void ParseCombineWorkspace(CombineHarvester &cb, RooWorkspace &ws, std::string const &modelcfg, std::string const &data, bool verbose=false)