/** * @file feldman_cousins.hh * @author Christoph Langenbruch, David Gerick, Renata Kopecna * @date 2021-01-12 * */ #include //TODO: removed what all is unused #include #include #include #include #include #include #include #include #include #include #include #include "folder.hh" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include bool fcnc::feldman_cousins::fc_1d(std::string parname, unsigned int nsteps, double parmin, double parmax, unsigned int ntoys, unsigned int pdfidx, std::vector probs, std::vector params, generator* gen, fitter* f, std::vector *> events, unsigned int bin, int from, int to){ std::ostringstream sout; bool TwoBins = false; if(opts->TheQ2binsmin.size() == 8) TwoBins = false; else if(opts->TheQ2binsmin.size() == 2) TwoBins = true; else assert(opts->TheQ2binsmin.size() == 2 || opts->TheQ2binsmin.size() == 8); sout << "FCresult" << (TwoBins ? "_2BINS_" : "") << bin << "_" << parname << "_" << from << "_" << to << ".root"; struct stat buffer; if(stat (sout.str().c_str(), &buffer) == 0){ spdlog::warn("[SKIP]\t\tFC job already run as root-file '" + sout.str() + "' exists, continue to next job!"); return false; } else{ spdlog::info("Feldman-Cousins study for parameter="+ parname + " in q2bin={0:d}", bin); } // if(!opts->full_angular) // opts->always_generate_full_angular = false; bool cache_minos = opts->minos_errors; bool cache_hesse = opts->hesse_postrun; bool cache_sq_hesse = opts->squared_hesse; bool cache_shift = opts->shift_lh; //int cache_print = spdlog::default_logger_raw()->level(); const unsigned int nPDF = probs.size(); assert(params.size() == nPDF); assert(events.size() == nPDF); assert(pdfidx < nPDF); //temp save parameter set unsigned int nparameters = params.at(pdfidx)->nparameters(); std::vector > smvalues (nPDF, std::vector (nparameters, 0.0)); for(unsigned int n = 0; n < nPDF; n++){ for (unsigned int k=0; kget_parameter(k)->get_value(); } } parameter* par = params.at(pdfidx)->get_parameter(parname); if (par != 0){ opts->minos_errors = false; opts->squared_hesse = false; opts->hesse_postrun = false; opts->simplex_prerun = false; opts->shift_lh = false; opts->minuit_strategy = 2.0; //fitter f(opts); int statusdatafloated = f->fit(probs, params, events); double lhdatafloated = f->likelihood(); double valuedatafloated = par->get_value(); spdlog::info("Data fit finished with -2logLh = {0:f}",lhdatafloated ); std::vector > floatingvalues(nPDF, std::vector (nparameters, 0.0)); std::vector > prev_error_low(nPDF, std::vector (nparameters, 0.0)); std::vector > prev_error_high(nPDF, std::vector (nparameters, 0.0)); std::vector > prev_meas(nPDF, std::vector (nparameters, 0.0)); std::vector > isConstraint(nPDF, std::vector (nparameters, false)); for(unsigned int n = 0; n < nPDF; n++){ for (unsigned int k=0; kget_parameter(k)->get_value(); prev_error_low.at(n).at(k) = params.at(n)->get_parameter(k)->get_previous_error_low(); prev_error_high.at(n).at(k) = params.at(n)->get_parameter(k)->get_previous_error_high(); prev_meas.at(n).at(k) = params.at(n)->get_parameter(k)->get_previous_measurement(); isConstraint.at(n).at(k) = params.at(n)->get_parameter(k)->get_gaussian_constraint(); } } for(unsigned int n = 0; n < nPDF; n++){ for (unsigned int k=0; kget_parameter(k)->get_name(), prev_meas.at(n).at(k),prev_error_low.at(n).at(k) ,prev_error_high.at(n).at(k)); } } } //opts->minuit_strategy = 1.0;//this should be 2 for the fixed data fit I think if (from < 0) from = 0; if (to > int(nsteps) || to < 0) to = nsteps; std::vector lhdatafixed(to-from, 0.0); std::vector statusdatafixed(to-from, 0); std::vector > lhtoysfixed; std::vector > lhtoysfloated; std::vector > statustoysfixed; std::vector > statustoysfloated; std::vector > params_dfloated (nPDF, std::vector< double> (nparameters, 0.0)); std::vector>>params_dfixed(nPDF,std::vector> (to-from, std::vector(nparameters, 0.0))); std::vector > > > params_tfixed (nPDF, std::vector > > (to - from, std::vector< std::vector< double> > (ntoys, std::vector< double> (nparameters, 0.0)))); std::vector > > > params_tfloated (nPDF, std::vector > > (to - from, std::vector< std::vector< double> > (ntoys, std::vector< double> (nparameters, 0.0)))); //buffer floated data values for(unsigned int n = 0; n < nPDF; n++){ for (unsigned int k=0; kget_parameter(k)->get_value(); } } std::string pardesc = par->get_description(); for (int j=from; jget_parameter(k)->init(floatingvalues.at(n).at(k), params.at(n)->get_parameter(k)->get_min(), params.at(n)->get_parameter(k)->get_max(), params.at(n)->get_parameter(k)->get_step_size(), prev_error_low.at(n).at(k), prev_error_high.at(n).at(k)); params.at(n)->get_parameter(k)->set_previous_measurement(prev_meas.at(n).at(k)); } else{ params.at(n)->get_parameter(k)->init(floatingvalues.at(n).at(k), params.at(n)->get_parameter(k)->get_min(), params.at(n)->get_parameter(k)->get_max(), params.at(n)->get_parameter(k)->get_step_size()); } } params.at(n)->reset_parameters(); } for(unsigned int n = 0; n < nPDF; n++){ params.at(n)->get_parameter(parname)->init(parcur, parmin, parmax, 0.0); } opts->minuit_strategy = 2.0;//more precise for fixed data fit (used for lh) opts->hesse_postrun = false; opts->simplex_prerun = false; spdlog::info("Start fit with fixed parameter"); statusdatafixed.at(j-from) = f->fit(probs, params, events); lhdatafixed.at(j-from) = f->likelihood(); spdlog::info("[DONE]\tFinished fit with fixed parameter"); opts->minuit_strategy = 1.0;//less precise for toys -> speed more important opts->hesse_postrun = false; opts->simplex_prerun = false; std::vector > fitvalues (nPDF, std::vector (nparameters, 0.0)); for(unsigned int n = 0; n < nPDF; n++){ //parameters from fixed point for (unsigned int k=0; kget_parameter(k)->get_value(); } //buffer fixed data values for (unsigned int k=0; kget_parameter(k)->get_value(); } } //make all toys with these params! std::vector > >toys(ntoys, std::vector > ()); spdlog::info("Start generating toys"); for (unsigned int k = 0; k < ntoys; k++){ spdlog::debug("[TOYS]\tGenerating toy sample {0:d}/{1:d}",k+1,ntoys ); for(unsigned int n = 0; n < nPDF; n++){ std::vector toy = gen->generate(events.at(n)->size(), params.at(n), probs.at(n)); if(!opts->full_angular){ fcnc::folder fldr(opts); for(UInt_t e = 0; e < toy.size(); e++){ fldr.fold(&toy.at(e)); if(toy.at(e).m < 1000.){ spdlog::warn("[CORRUPT]\tEvent={0:d} pdf={0:f} toy={0:f}",e, n, k ); spdlog::warn("[CORRUPT]\tctl={0:f} ctk={0:f} phi={0:f} q2={0:f}", toy.at(e).costhetal, toy.at(e).costhetak, toy.at(e).phi, toy.at(e).q2 ); } } } toys.at(k).push_back(toy); } } spdlog::info("[DONE]\tGenerating toys"); //init parameters from fixed point for(unsigned int n = 0; n < nPDF; n++){ for(unsigned int k=0; kget_parameter(k)->init(fitvalues.at(n).at(k), params.at(n)->get_parameter(k)->get_min(), params.at(n)->get_parameter(k)->get_max(), params.at(n)->get_parameter(k)->get_step_size(), prev_error_low.at(n).at(k), prev_error_high.at(n).at(k)); params.at(n)->get_parameter(k)->set_previous_measurement(prev_meas.at(n).at(k)); } else{ params.at(n)->get_parameter(k)->init(fitvalues.at(n).at(k), params.at(n)->get_parameter(k)->get_min(), params.at(n)->get_parameter(k)->get_max(), params.at(n)->get_parameter(k)->get_step_size()); } } } //fit toys repeatedly std::vector toysfixed; std::vector toysfloated; std::vector statusfixed; std::vector statusfloated; spdlog::info("Start fitting all toys"); for (unsigned int k=0; kreset_parameters();//these are not the fitted/generated parameters->fix, they should float however, so should be ok? } for(unsigned int n = 0; n < nPDF; n++){ params.at(n)->get_parameter(parname)->init(parcur, parmin, parmax, 0.0); } //save pointers to toy events into vector: std::vector * > leToys; for(unsigned int n = 0; n < nPDF; n++){ leToys.push_back(&toys.at(k).at(n)); } //fit with fixed parameter spdlog::info("[TOYS]\tFitting fixed toy sample {0:d}/{1:d} at step {2:d}/{3:d}", k+1, ntoys, j-from+1, to-from ); int resultfixed = f->fit(probs, params, leToys); toysfixed.push_back(f->likelihood()); statusfixed.push_back(resultfixed); //buffer fixed toy values for(unsigned int n = 0; n < nPDF; n++){ for (unsigned int l=0; lget_parameter(l)->get_value(); } params.at(n)->reset_parameters(); } for(unsigned int n = 0; n < nPDF; n++){ params.at(n)->get_parameter(parname)->init(parcur, parmin, parmax, 0.01); } //fit with floated parameter spdlog::info("[TOYS]\tFitting freed toy sample0:d}/{1:d} at step {2:d}/{3:d}", k+1, ntoys, j-from+1, to-from ); int resultfloated = f->fit(probs, params, leToys); toysfloated.push_back(f->likelihood()); statusfloated.push_back(resultfloated); //buffer fixed toy values for(unsigned int n = 0; n < nPDF; n++){ for (unsigned int l=0; lget_parameter(l)->get_value(); } } } lhtoysfixed.push_back(toysfixed); lhtoysfloated.push_back(toysfloated); statustoysfixed.push_back(statusfixed); statustoysfloated.push_back(statusfloated); }// end loop over steps spdlog::info("[DONE]\tFitting all toys"); spdlog::debug("tLoop over all {0:d} steps completed. Writing results to file!",nsteps ); //save to root file TFile* fout = new TFile(sout.str().c_str(), "RECREATE"); fout->cd(); TTree* t = new TTree(parname.c_str(), pardesc.c_str()); int pdf=0, step=0, statustfixed=0, statustfloated=0, toy=0, statusdfixed=0, statusdfloated=0; double value=0.0, lhdfloated=lhdatafloated, lhdfixed=0.0, lhtfixed=0.0, lhtfloated=0.0; t->Branch("bin",&bin,"bin/I"); t->Branch("pdf",&pdf,"pdf/I"); t->Branch("step",&step,"step/I"); t->Branch("value",&value,"value/D"); t->Branch("toy",&toy,"toy/I"); t->Branch("statusdatafixed",&statusdfixed,"statusdatafixed/I"); t->Branch("statusdatafloated",&statusdfloated,"statusdatafloated/I"); t->Branch("statustoyfixed",&statustfixed,"statustoyfixed/I"); t->Branch("statustoyfloated",&statustfloated,"statustoyfloated/I"); t->Branch("lhdatafloated",&lhdfloated,"lhdatafloated/D"); t->Branch("valuedatafloated",&valuedatafloated,"valuedatafloated/D"); t->Branch("lhdatafixed",&lhdfixed,"lhdatafixed/D"); t->Branch("lhtoyfixed",&lhtfixed,"lhtoyfixed/D"); t->Branch("lhtoyfloated",&lhtfloated,"lhtoyfloated/D"); //also save the fitted values std::vector tfloated(nparameters, 0.0), tfixed(nparameters, 0.0), dfloated(nparameters, 0.0), dfixed(nparameters, 0.0); for (unsigned int k = 0; k < nparameters; k++){ fcnc::parameter* param = params.at(pdfidx)->get_parameter(k); if (param->get_step_size() != 0.0){ std::string parname(param->get_name()); std::string pardesc(param->get_description()); //TTree* t = new TTree(parname.c_str(), pardesc.c_str()); t->Branch((std::string("datafixed_")+parname).c_str(),&dfixed.at(k),(std::string("datafixed_")+parname+std::string("/D")).c_str()); t->Branch((std::string("datafloated_")+parname).c_str(),&dfloated.at(k),(std::string("datafloated_")+parname+std::string("/D")).c_str()); t->Branch((std::string("toyfixed_")+parname).c_str(),&tfixed.at(k),(std::string("toyfixed_")+parname+std::string("/D")).c_str()); t->Branch((std::string("toyfloated_")+parname).c_str(),&tfloated.at(k),(std::string("toyfloated_")+parname+std::string("/D")).c_str()); } } for(unsigned int n = 0; n < nPDF; n++){ pdf = n; //TODO: what is this supposed to do? for (int j=from; jFill(); } } } t->Write(); fout->Write(); fout->Close(); delete fout; /* //analyse results std::string suffix = ""; TH1D* cl = new TH1D((std::string("cl")+parname+suffix).c_str(), (std::string(";")+pardesc+std::string(";Confidence level")).c_str(), nsteps, parmin, parmax); TH1D* lh = new TH1D((std::string("lh")+parname+suffix).c_str(), (std::string(";")+pardesc+std::string(";Confidence level")).c_str(), nsteps, parmin, parmax); for (unsigned int j=0; j ddata) nlarger++; } lh->SetBinContent(j+1, TMath::Erf(sqrt(lhdatafixed.at(j)-lhdatafloated)/sqrt(2.0))); cl->SetBinContent(j+1, 1.0-double(nlarger)/ntoys); } double low = parmin; const double thecl = 0.683; if (cl->GetBinContent(1) > thecl)//??? { for (int i=0; iGetBinContent(i+1) > thecl && cl->GetBinContent(i+2) < thecl) { low = cl->GetBinCenter(i+1) + (thecl-cl->GetBinContent(i+1))*(cl->GetBinCenter(i+2)-cl->GetBinCenter(i+1))/(cl->GetBinContent(i+2)-cl->GetBinContent(i+1)); break; } } double high = parmax; if (cl->GetBinContent(nsteps) > thecl) { for (int i=nsteps-1; i>=0; i--) if (cl->GetBinContent(i+1) < thecl && cl->GetBinContent(i+2) > thecl) { high = cl->GetBinCenter(i+1) + (thecl-cl->GetBinContent(i+1))*(cl->GetBinCenter(i+2)-cl->GetBinCenter(i+1))/(cl->GetBinContent(i+2)-cl->GetBinContent(i+1)); break; } } TCanvas* c1 = new TCanvas("c1", "c1", 1600, 1200); TLine* l = new TLine(); c1->cd(); cl->SetMinimum(0.0); cl->SetMaximum(1.1); cl->Draw(); lh->SetLineColor(4); lh->Draw("lsame"); l->SetLineColor(2); l->DrawLine(low, 0.0, low, 1.1); l->DrawLine(high, 0.0, high, 1.1); c1->Print((std::string("plots/cl")+parname+suffix+std::string(".eps")).c_str(),"eps"); //delete cl; delete l; delete c1; delete cl; */ } else{ spdlog::critical("Could not find parameter "+parname); assert(0); } spdlog::info("Finished Feldman-Cousins study for parameter "+ parname); opts->hesse_postrun = cache_hesse; opts->squared_hesse = cache_sq_hesse; opts->minos_errors = cache_minos; opts->shift_lh = cache_shift; return true; } bool fcnc::feldman_cousins::fc_1d(std::string parname, unsigned int nsteps, double parmin, double parmax, unsigned int ntoys, pdf* prob, parameters* params, generator* gen, fitter* f, std::vector * events, unsigned int bin, int from, int to){ std::vector the_probs; the_probs.push_back(prob); std::vector the_params; the_params.push_back(params); std::vector* > the_events; the_events.push_back(events); return fc_1d(parname, nsteps, parmin, parmax, ntoys, 0, the_probs, the_params, gen, f, the_events, bin, from, to); } bool fcnc::feldman_cousins::fc_2d(std::string parxname, unsigned int nstepsx, double parxmin, double parxmax, std::string paryname, unsigned int nstepsy, double parymin, double parymax, unsigned int ntoys, unsigned int pdfidx, //this parameter just changes output file std::vector probs, std::vector params, generator* gen, fitter* f, std::vector *> events, unsigned int bin, int from, int to){ spdlog::info("Feldman-Cousins study for parameters" + parxname +", " +paryname ); /* bool cache_minos = opts->minos_errors; bool cache_hesse = opts->hesse_postrun; bool cache_shift = opts->shift_lh; int cache_print = opts->print_level; const unsigned int nPDF = probs.size(); assert(params.size() == nPDF); assert(events.size() == nPDF); assert(pdfidx < nPDF); parameter* parx = params.at(pdfidx)->get_parameter(parxname); parameter* pary = params.at(pdfidx)->get_parameter(paryname); if (parx != 0 && pary != 0) { opts->minos_errors = false; opts->hesse_postrun = false; opts->shift_lh = false; //fitter f(opts); f->fit(probs, params, events); double lhdatafloated = f.likelihood(); double valuexdatafloated = parx->get_value(); double valueydatafloated = pary->get_value(); spdlog::info("Data fit finished with -2logLh = {0:f}",lhdatafloated ); opts->print_level = -1; //std::cout << from << " {0:f}",to << " {0:f}",from - to << std::endl; if (from < 0) from = 0; if (to > int(nstepsx*nstepsy) || to < 0) to = nstepsx*nstepsy; std::vector lhdatafixed(to-from, 0.0); std::vector > lhtoysfixed; std::vector > lhtoysfloated; std::vector > statustoysfixed; std::vector > statustoysfloated; std::string parxdesc = parx->get_description(); std::string parydesc = pary->get_description(); for (int j=from; jinit(parxname, parxdesc, parxcur, parxmin, parxmax, 0.0); pary->init(paryname, parydesc, parycur, parymin, parymax, 0.0); f->fit(probs, params, events); lhdatafixed.at(j-from) = f->likelihood(); //make all toys with these params! std::vector > toys; for (unsigned int k=0; k toy = gen->generate(events.size(), params, prob); toys.push_back(toy); } //fit toys repeatedly std::vector toysfixed; std::vector toysfloated; std::vector statusfixed; std::vector statusfloated; for (unsigned int k=0; kfix, they should float however, so should be ok? parx->init(parxname, parxdesc, parxcur, parxmin, parxmax, 0.0); pary->init(paryname, parydesc, parycur, parymin, parymax, 0.0); int resultfixed = f->fit(probs, params, &toys.at(k)); toysfixed.push_back(f->likelihood()); statusfixed.push_back(resultfixed); params.reset_parameters(); parx->init(parxname, parxdesc, parxcur, parxmin, parxmax, 0.01); pary->init(paryname, parydesc, parycur, parymin, parymax, 0.01); int resultfloated = f->fit(probs, params, &toys.at(k)); toysfloated.push_back(f->likelihood()); statusfloated.push_back(resultfloated); } lhtoysfixed.push_back(toysfixed); lhtoysfloated.push_back(toysfloated); statustoysfixed.push_back(statusfixed); statustoysfloated.push_back(statusfloated); } //std::cout <<"after loop" ); //save to root file std::ostringstream sout; sout << "FCresult_" << bin << "_" << parxname << "_" << paryname << "_" << from << "_" << to << ".root"; TFile* fout = new TFile(sout.str().c_str(), "RECREATE"); fout->cd(); TTree* t = new TTree((parxname+std::string("_")+paryname).c_str(), (std::string(";")+parxdesc+std::string(";")+parydesc).c_str()); int step=0, stepx=0, stepy=0, statustfixed=0, statustfloated=0, toy=0; double valuex=0.0, valuey, lhdfloated=lhdatafloated, lhdfixed=0.0, lhtfixed=0.0, lhtfloated=0.0; t->Branch("bin",&bin,"bin/I"); t->Branch("step",&step,"step/I"); t->Branch("stepx",&stepx,"stepx/I"); t->Branch("stepy",&stepy,"stepy/I"); t->Branch("valuex",&valuex,"valuex/D"); t->Branch("valuey",&valuey,"valuey/D"); t->Branch("valuexdatafloated",&valuexdatafloated,"valuexdatafloated/D"); t->Branch("valueydatafloated",&valueydatafloated,"valueydatafloated/D"); t->Branch("toy",&toy,"toy/I"); t->Branch("statustoyfixed",&statustfixed,"statustoyfixed/I"); t->Branch("statustoyfloated",&statustfloated,"statustoyfloated/I"); t->Branch("lhdatafloated",&lhdfloated,"lhdatafloated/D"); t->Branch("lhdatafixed",&lhdfixed,"lhdatafixed/D"); t->Branch("lhtoyfixed",&lhtfixed,"lhtoyfixed/D"); t->Branch("lhtoyfloated",&lhtfloated,"lhtoyfloated/D"); for (int j=from; jFill(); } } t->Write(); fout->Write(); fout->Close(); delete fout; } else{ if (parx == 0) spdlog::error("Could not find parameter" +parxname ); if (pary == 0) spdlog::error("Could not find parameter" +paryname ); assert(0); } spdlog::info("Finished Feldman-Cousins study for parameters "+parxname + "," +paryname ); opts->hesse_postrun = cache_hesse; opts->minos_errors = cache_minos; opts->shift_lh = cache_shift; opts->print_level = cache_print; */ return true; } bool fcnc::feldman_cousins::fc_2d(std::string parxname, unsigned int nstepsx, double parxmin, double parxmax, std::string paryname, unsigned int nstepsy, double parymin, double parymax, unsigned int ntoys, //this parameter just changes output file pdf* prob, parameters* params, generator* gen, fitter* f, std::vector * events, unsigned int bin, int from, int to){ std::vector the_probs; the_probs.push_back(prob); std::vector the_params; the_params.push_back(params); std::vector* > the_events; the_events.push_back(events); return fc_2d(parxname, nstepsx, parxmin, parxmax, paryname, nstepsy, parymin, parymax, ntoys, 0, the_probs, the_params, gen, f, the_events, bin, from, to); }