22 #include "TGraphAsymmErrors.h" 28 #include "RooWorkspace.h" 29 #include "RooRealVar.h" 30 #include "RooArgList.h" 31 #include "RooFitResult.h" 50 int main(
int argc,
char *argv[]){
62 string id_string = oss.str();
66 cout <<
"Creating workspaces..." << endl;
67 vector<future<void> > injected(
injections.size());
71 for(
size_t i = 0; i < injected.size(); ++i){
76 vector<vector<double> > yvals_nc(
injections.size(), vector<double>(
ntoys, -9876543210.));
77 vector<vector<double> > yvals_c(
injections.size(), vector<double>(
ntoys, -9876543210.));
78 vector<vector<double> > pulls_nc(
injections.size(), vector<double>(
ntoys, -9876543210.));
79 vector<vector<double> > pulls_c(
injections.size(), vector<double>(
ntoys, -9876543210.));
82 cout <<
"Extracting signal strength from toys..." << endl;
83 vector<vector<future<pair<double,double> > > > toyed_nc(ntoys);
84 vector<vector<future<pair<double,double> > > > toyed_c(ntoys);
85 for(
int toy = 0; toy <
ntoys; ++toy){
86 vector<future<pair<double,double> > > (
injections.size()).swap(toyed_nc.at(toy));
87 vector<future<pair<double,double> > > (
injections.size()).swap(toyed_c.at(toy));
89 toyed_nc.at(toy).at(i) = thread_pool.
Push(
ExtractSignal, id_string, i, toy,
true);
90 toyed_c.at(toy).at(i) = thread_pool.
Push(
ExtractSignal, id_string, i, toy,
false);
93 for(
int toy = 0; toy <
ntoys; ++toy){
95 auto res_nc = toyed_nc.at(toy).at(i).get();
96 yvals_nc.at(i).at(toy) = res_nc.first;
97 pulls_nc.at(i).at(toy) = res_nc.second;
98 auto res_c = toyed_c.at(toy).at(i).get();
99 yvals_c.at(i).at(toy) = res_c.first;
100 pulls_c.at(i).at(toy) = res_c.second;
103 execute(
"rm -f *_sig_inj_*.root");
106 cout <<
"Generating plots..." << endl;
107 for(
size_t i = 0; i <
injections.size(); ++i){
118 MakePlot(inj_nc, yvals_nc,
true,
false);
119 MakePlot(inj_c, yvals_c,
false,
false);
120 MakePlot(inj_nc, pulls_nc,
true,
true);
121 MakePlot(inj_c, pulls_c,
false,
true);
124 void InjectSignal(
const string id_string,
double inject,
size_t index){
127 cout <<
"Starting to inject signal with strength " << inject << endl;
130 oss <<
"./run/make_workspace.exe --method m1bk" 132 <<
" --sig_strength " << inject <<
" --identifier sig_inj_" << id_string <<
"_" << index
133 <<
" < /dev/null &> /dev/null" << flush;
136 cout <<
"Executing " << oss.str() << endl;
141 cout <<
"Done injecting signal with strength " << inject << endl;
145 pair<double, double>
ExtractSignal(
const string id_string,
size_t index,
size_t toy,
bool is_nc){
148 cout <<
"Extracting signal given strength " <<
injections.at(index) <<
" in toy " << toy << endl;
151 oss <<
"ls -rt m1bk*" << (is_nc ?
"_nc_" :
"_c_")
152 <<
"*sig_inj_" << id_string <<
"_" << index <<
".root | tail -n 1" << flush;
154 while(file_name.back() ==
'\n' || file_name.back() ==
' '){
155 file_name.pop_back();
161 oss <<
"export origdir=$(pwd); " 162 <<
"cd ~/cmssw/CMSSW_7_1_5/src; " 163 <<
"eval `scramv1 runtime -sh` &> /dev/null; " 165 <<
"cp " << file_name <<
' ' << workdir <<
"; " 166 <<
"cd " << workdir <<
"; " 167 <<
"combine -M MaxLikelihoodFit --skipBOnlyFit --dataset data_obs_" << toy <<
" --preFitValue " << max(
injections.at(index),0.01) <<
' ' << file_name <<
" &> /dev/null; " 170 cout <<
"Executing " << oss.str() << endl;
172 string output =
execute(oss.str());
175 TFile r_file((workdir+
"/mlfit.root").c_str(),
"read");
176 if(!r_file.IsOpen())
return pair<double, double>(-1., -1.);
177 RooFitResult *
f =
static_cast<RooFitResult*
>(r_file.Get(
"fit_s"));
178 if(f ==
nullptr)
return pair<double, double>(-1., -1.);
179 RooArgList pars = f->floatParsFinal();
180 for(
int ipar = 0; ipar < pars.getSize(); ++ipar){
181 RooRealVar *var =
static_cast<RooRealVar*
>(pars.at(ipar));
182 if(var ==
nullptr)
continue;
183 if(var->GetName() != string(
"r"))
continue;
184 double val = var->getVal();
195 pull = -fabs(delta)/fabs(ehi);
197 pull = fabs(delta)/fabs(elo);
199 cout <<
"Extracted strength " << val <<
" + " << ehi <<
" - " << fabs(elo) <<
" given strength " <<
injections.at(index) <<
" in toy " << toy <<
". pull=" << pull << endl;
202 return pair<double, double>(val, pull);
207 return pair<double, double>(-1., -1.);
211 if(var.hasAsymError()){
212 ehi = var.getAsymErrorHi();
213 elo = var.getAsymErrorLo();
214 double aehi = fabs(ehi);
215 double aelo = fabs(elo);
216 double delta = aehi - aelo;
217 return aelo + 0.5*delta;
218 }
else if(var.hasError()){
219 ehi = var.getError();
230 const RooFitResult &
f){
232 RooAbsReal* cloneFunc =
static_cast<RooAbsReal*
>(var.cloneTree());
233 RooArgSet* errorParams = cloneFunc->getObservables(f.floatParsFinal());
234 RooArgSet* nset = cloneFunc->getParameters(*errorParams);
237 RooArgList paramList;
238 const RooArgList& fpf = f.floatParsFinal();
240 for (
int i=0; i<fpf.getSize(); i++) {
241 RooAbsArg* par = errorParams->find(fpf[i].
GetName());
244 fpf_idx.push_back(i);
248 vector<double> errors(paramList.getSize());
249 for (Int_t ivar=0; ivar<paramList.getSize(); ivar++) {
250 RooRealVar& rrv =
static_cast<RooRealVar&
>(fpf[fpf_idx[ivar]]);
252 double cenVal = rrv.getVal();
253 double errVal = rrv.getError();
256 static_cast<RooRealVar*
>(paramList.at(ivar))->setVal(cenVal+0.5*errVal);
257 double up = cloneFunc->getVal(nset);
260 static_cast<RooRealVar*
>(paramList.at(ivar))->setVal(cenVal-0.5*errVal);
261 double down = cloneFunc->getVal(nset);
263 errors.at(ivar) = (up-down);
265 static_cast<RooRealVar*
>(paramList.at(ivar))->setVal(cenVal);
268 vector<double> right(errors.size());
269 for(
size_t i = 0; i < right.size(); ++i){
271 for(
size_t j = 0; j < errors.size(); ++j){
272 right.at(i) += f.correlation(paramList.at(i)->GetName(),paramList.at(j)->GetName())*errors.at(j);
276 for(
size_t i = 0; i < right.size(); ++i){
277 sum += errors.at(i)*right.at(i);
280 if(cloneFunc !=
nullptr){
284 if(errorParams !=
nullptr){
286 errorParams =
nullptr;
296 void GetStats(
const vector<double> &vals,
double &mean,
double &median,
297 double &up,
double &down,
298 double &up2,
double &down2){
299 double tail = erfc(1./sqrt(2.))*0.5;
300 double tail2 = erfc(sqrt(2.))*0.5;
302 mean = vals.size() > 0 ? accumulate(vals.cbegin(), vals.cend(), 0.)/vals.size() : 0.;
304 double high =
GetValue(vals, 1.-tail);
305 double low2 =
GetValue(vals, tail2);
306 double high2 =
GetValue(vals, 1.-tail2);
307 up = max(high-median,0.);
308 down = max(median-low,0.);
309 up2 = max(high2-median,0.);
310 down2 = max(median-low2,0.);
313 double GetValue(vector<double> vals,
double fraction){
314 if(vals.size() == 0)
return 0.;
315 if(vals.size() == 1)
return vals.front();
316 sort(vals.begin(), vals.end());
317 double frac_index = fraction*vals.size()-0.5;
318 long lo_index =
static_cast<long>(floor(frac_index));
319 long hi_index =
static_cast<long>(ceil(frac_index));
324 if(static_cast<size_t>(hi_index) >= vals.size()){
325 lo_index = vals.size() - 2;
326 hi_index = vals.size() - 1;
328 double lo_value = vals.at(lo_index);
329 double hi_value = vals.at(hi_index);
330 return lo_value+(hi_value-lo_value)*(frac_index - lo_index);
333 double GetMode(
const vector<double> &v,
double frac){
336 }
else if( v.size() == 1){
340 if(temp.size() == v.size()){
342 return v.front()+0.5*(v.back()-v.front());
344 double fdiff = v.at(1)-v.at(0);
345 double bdiff = v.at(2)-v.at(1);
347 return GetMode(vector<double>(v.cbegin()+1, v.cend()), frac);
349 return GetMode(vector<double>(v.cbegin(), v.cend()-1), frac);
362 if(frac < 0.) frac = 0.;
363 if(frac > 1.) frac = 1.;
364 size_t dist = ceil(frac*(v.size()-1));
365 if(dist == v.size()-1)
return v;
366 size_t best_start = 0;
367 double best_sep = v.back() - v.front();
368 for(
size_t i = 0; i < v.size()-dist; ++i){
369 double sep = v.at(i+dist)-v.at(i);
375 return vector<double>(v.cbegin()+best_start, v.cbegin()+best_start+dist);
380 set<double> injection_set;
382 static struct option long_options[] = {
383 {
"toys", required_argument, 0,
't'},
384 {
"inject", required_argument, 0,
'i'},
385 {
"lumi", required_argument, 0,
'l'},
386 {
"asym", no_argument, 0,
'a'},
387 {
"syst", no_argument, 0,
's'},
388 {
"draw", no_argument, 0,
'd'},
394 opt = getopt_long(argc, argv,
"t:i:l:asd", long_options, &option_index);
395 if( opt == -1)
break;
400 ntoys = atoi(optarg);
403 injection_set.insert(atof(optarg));
418 printf(
"Bad option! getopt_long returned character code 0%o\n", opt);
422 if(injection_set.size() == 0){
427 injections = vector<double>(injection_set.cbegin(), injection_set.cend());
431 void MakePlot(
const vector<double> &injections_list,
432 const vector<vector<double> > &yvals,
433 bool is_nc,
bool is_pull){
434 vector<double> zeros(injections_list.size(), 0.);
435 vector<double> means(injections_list.size()), medians(injections_list.size());
436 vector<double> ups(injections_list.size()), downs(injections_list.size());
437 vector<double> ups2(injections_list.size()), downs2(injections_list.size());
438 vector<double> tops(injections_list.size()), bots(injections_list.size());
439 vector<double> tops2(injections_list.size()), bots2(injections_list.size());
440 for(
size_t i = 0; i < injections_list.size(); ++i){
441 GetStats(yvals.at(i), means.at(i), medians.at(i),
442 ups.at(i), downs.at(i),
443 ups2.at(i), downs2.at(i));
444 tops.at(i) = medians.at(i) + ups.at(i);
445 bots.at(i) = medians.at(i) - downs.at(i);
446 tops2.at(i) = medians.at(i) + ups2.at(i);
447 bots2.at(i) = medians.at(i) - downs2.at(i);
450 TGraphAsymmErrors g(injections_list.size(), &injections_list.at(0), &medians.at(0),
451 &zeros.at(0), &zeros.at(0),
452 &downs.at(0), &ups.at(0));
453 TGraphAsymmErrors g2(injections_list.size(), &injections_list.at(0), &medians.at(0),
454 &zeros.at(0), &zeros.at(0),
455 &downs2.at(0), &ups2.at(0));
456 TGraph gm(injections_list.size(), &injections_list.at(0), &means.at(0));
457 g.SetMarkerStyle(20);
459 g.SetMarkerColor(kRed+2);
462 g.SetLineColor(kRed+2);
463 g2.SetMarkerStyle(0);
465 g2.SetMarkerColor(0);
468 g2.SetLineColor(kRed+2);
469 gm.SetMarkerStyle(20);
471 gm.SetMarkerColor(kBlue);
472 double xmax = *max_element(injections_list.cbegin(), injections_list.cend());
473 double xright = 1.0625*
xmax;
474 double ymax = *max_element(tops.cbegin(), tops.cend());
476 oss <<
";Injected " << (is_nc ?
"NC" :
"C") <<
" Signal Strength;";
480 oss <<
"Extracted " << (is_nc ?
"NC" :
"C") <<
" Signal Strength";
483 TH1D h(
"", oss.str().c_str(), 1, 0., xright);
492 TF1
f(
"",
"x", 0., xright);
493 f.SetLineColor(kBlack);
505 hline.SetLineColor(kBlack);
506 hline.SetLineWidth(1);
507 hline.SetLineStyle(3);
509 hline.DrawLine(0, -2., xright, -2.);
510 hline.DrawLine(0, -1., xright, -1.);
511 hline.DrawLine(0, 0., xright, 0.);
512 hline.DrawLine(0, 1., xright, 1.);
513 hline.DrawLine(0, 2., xright, 2.);
518 << (is_nc ?
"_nc" :
"_c")
525 string plot_name = oss.str();
529 c.Print(plot_name.c_str());
531 for(
size_t i = 0; i < injections_list.size(); ++i){
532 Plot1D(injections_list.at(i), yvals.at(i),
533 means.at(i), medians.at(i),
534 ups.at(i), downs.at(i),
535 ups2.at(i), downs2.at(i),
540 void Plot1D(
double inj,
const vector<double> &vals,
541 double mean,
double median,
542 double up,
double down,
543 double up2,
double down2,
544 bool is_nc,
bool is_pull){
545 if(vals.size() == 0)
return;
548 << (is_pull ?
"pull" :
"siginj")
549 <<
"_" << (is_nc ?
"nc" :
"c")
554 string name = oss.str();
556 oss <<
"Inj. " << (is_nc ?
"NC" :
"C") <<
" Sig.=" << inj <<
", N_{toys}=" << vals.size() <<
";";
561 oss <<
"Extracted NC Signal Strength";
563 oss <<
"Extracted C Signal Strength";
566 oss <<
";# of Toys" << flush;
568 TH1D h(
"", oss.str().c_str(), floor(sqrt(vals.size())),
569 *min_element(vals.cbegin(), vals.cend())-0.001,
570 *max_element(vals.cbegin(), vals.cend())+0.001);
572 h.SetLineColor(kBlack);
574 for(
const auto &val: vals){
578 for(
int bin = 1; bin <= h.GetNbinsX(); ++bin){
579 double content = h.GetBinContent(bin)+h.GetBinError(bin);
580 if(content > hmax) hmax = content;
584 TLine ldown2(median-down2, 0., median-down2, hmax);
585 ldown2.SetLineColor(kRed+2);
586 ldown2.SetLineStyle(3);
587 ldown2.SetLineWidth(2);
588 TLine ldown(median-down, 0., median-down, hmax);
589 ldown.SetLineColor(kRed+2);
590 ldown.SetLineStyle(2);
591 ldown.SetLineWidth(4);
592 TLine lmedian(median, 0., median, hmax);
593 lmedian.SetLineColor(kRed+2);
594 lmedian.SetLineWidth(5);
595 TLine lmean(mean, 0., mean, hmax);
596 lmean.SetLineColor(kBlue);
597 lmean.SetLineWidth(5);
598 TLine lup(median+up, 0., median+up, hmax);
599 lup.SetLineColor(kRed+2);
602 TLine lup2(median+up2, 0., median+up2, hmax);
603 lup2.SetLineColor(kRed+2);
604 lup2.SetLineStyle(3);
605 lup2.SetLineWidth(2);
610 lmedian.Draw(
"same");
614 c.Print(name.c_str());
618 if(vals.size() != pulls.size())
ERROR(
"Vals and pull must have same length");
619 vector<size_t> bad_indices;
620 for(
size_t i = 0; i < vals.size(); ++i){
622 || fabs(pulls.at(i)) >= 1000.){
623 bad_indices.push_back(i);
626 sort(bad_indices.begin(), bad_indices.end(), greater<size_t>());
627 for(
size_t ii = 0; ii < bad_indices.size(); ++ii){
628 size_t i = bad_indices.at(ii);
629 vals.erase(vals.begin()+i);
630 pulls.erase(pulls.begin()+i);
635 vector<vector<double> > &yvals,
636 vector<vector<double> > &pulls,
639 oss <<
"txt/siginj/lumi_" <<
lumi <<
"_" << (is_nc ?
"nc" :
"c") <<
".txt" << flush;
640 string path = oss.str();
643 ifstream infile(path);
644 while(getline(infile, line)){
645 istringstream iss(line);
647 iss >> inj >> y >> pull;
649 if(i == static_cast<size_t>(-1)){
651 yvals.push_back(vector<double>());
652 pulls.push_back(vector<double>());
655 yvals.at(i).push_back(y);
656 pulls.at(i).push_back(pull);
660 ofstream outfile(path);
661 outfile.precision(std::numeric_limits<double>::max_digits10);
662 for(
size_t iinj = 0; iinj < injs.size(); ++iinj){
663 for(
size_t itoy = 0; itoy < yvals.at(iinj).size() || itoy < pulls.at(iinj).size(); ++itoy){
665 << setw(32) << injs.at(iinj)
666 <<
' ' << setw(32) << (itoy < yvals.at(iinj).size() ? yvals.at(iinj).at(itoy) : -9876543210.)
667 <<
' ' << setw(32) << (itoy < pulls.at(iinj).size() ? pulls.at(iinj).at(itoy) : -9876543210.)
675 for(
size_t i = 0; i < v.size(); ++i){
676 if(v.at(i) ==
x)
return i;
682 vector<vector<double> > &yvals,
683 vector<vector<double> > &pulls){
684 vector<size_t> vi(inj.size());
685 for(
size_t i = 0; i < vi.size(); ++i) vi.at(i) = i;
686 sort(vi.begin(), vi.end(), [&](
size_t a,
size_t b){
return inj.at(a)<inj.at(
b);});
688 auto yvals_temp = yvals;
689 auto pulls_temp = pulls;
690 for(
size_t i = 0; i < vi.size(); ++i){
691 inj.at(i) = inj_temp.at(vi.at(i));
692 yvals.at(i) = yvals_temp.at(vi.at(i));
693 pulls.at(i) = pulls_temp.at(vi.at(i));
694 sort(yvals.at(i).begin(), yvals.at(i).end());
695 sort(pulls.at(i).begin(), pulls.at(i).end());
void GetStats(const vector< double > &vals, double &mean, double &median, double &up, double &down, double &up2, double &down2)
double GetError(const RooAbsReal &var, const RooFitResult &f)
void RemoveBadResults(vector< double > &vals, vector< double > &pulls)
void ReplaceAll(std::string &str, const std::string &orig, const std::string &rep)
double GetAsymError(const RooRealVar &var, double &ehi, double &elo)
int main(int argc, char *argv[])
vector< double > GetSmallestRange(const vector< double > &v, double frac)
auto Push(FuncType &&func, ArgTypes &&...args) -> std::future< decltype(func(args...))>
void MakePlot(const vector< double > &injections_list, const vector< vector< double > > &yvals, bool is_nc, bool is_pull)
std::string execute(const std::string &cmd)
size_t GetIndex(const vector< double > &v, double x)
void SortByInjectionStrength(vector< double > &inj, vector< vector< double > > &yvals, vector< vector< double > > &pulls)
def style(h, width, style, color)
void GetOptions(int argc, char *argv[])
double GetValue(vector< double > vals, double fraction)
void InjectSignal(const string id_string, double inject, size_t index)
double GetMode(const vector< double > &v, double frac)
void MergeWithText(vector< double > &injs, vector< vector< double > > &yvals, vector< vector< double > > &pulls, bool is_nc)
pair< double, double > ExtractSignal(const string id_string, size_t index, size_t toy, bool is_nc)
void Plot1D(double inj, const vector< double > &vals, double mean, double median, double up, double down, double up2, double down2, bool is_nc, bool is_pull)
vector< double > injections
std::string MakeDir(std::string prefix)