//Renata Kopecna #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "EvaluateToys.hh" #include #include #include "ScriptHelpers.hh" #include //This code is as broken as it gets, the string for latex names and var names should be in a struct so when one has to skip stuff one can also skip the name and value actually //This way it is error prone and god knows whether it even saves everything properly //And it should've been connected directly with the csv file... like... no wonder some stuff took that long before const bool UnbinnedFit = true; const bool UseCellColor = true; Int_t Idx = 0; const UInt_t nPDFs = 2; struct pullInfo{ double sigma; double sigmaErr; double mean; double meanErr; double failRate; pullInfo(){ sigma = DEFAULT_TREE_VAL; sigmaErr = DEFAULT_TREE_ERR; mean = DEFAULT_TREE_VAL; meanErr = DEFAULT_TREE_ERR; failRate = DEFAULT_TREE_VAL; } pullInfo(double sig, double sigErr, double mu, double muErr, double rate){ sigma = sig; sigmaErr = sigErr; mean = mu; meanErr = muErr; failRate = rate; } }; struct q2Bins{ unsigned int nBins; std::vector q2min; std::vector q2max; q2Bins(basic_params params){ nBins = params.nBins; q2min = get_TheQ2binsmin(nBins, params.reference); q2max = get_TheQ2binsmax(nBins, params.reference); } }; const std::vector> bkg_340 = {{47.0,57.0},{0.0,15.0},{-10.0,0.0},{-25.0,-10.0},{-5.0,5.0},{-5.0,3.0},{-48.0,-38.0}}; //draw legend to the pull plots void drawLegend(TLatex * leg, double q2min, double q2max, pullInfo info, int tot_fits, int oor_fits, int failed_fits){ std::ostringstream bindescription; //draw q2 bin bindescription << std::setprecision(2) << std::fixed << "( " << q2min << " < q^{2} < " << q2max << " )"; spdlog::trace(bindescription.str()); leg->DrawLatex(0.21,0.88, bindescription.str().c_str()); //draw mean value std::ostringstream sMean; sMean << std::fixed << std::setprecision(4) << std::fixed << info.mean << " #pm " << info.meanErr; spdlog::trace(sMean.str()); leg->DrawLatex(0.13,0.80, "#bf{mean:}"); leg->DrawLatex(0.13,0.77, sMean.str().c_str()); //draw sigma value std::ostringstream sRMS; sRMS << std::fixed << std::setprecision(4) << std::fixed << info.sigma << " #pm " << info.sigmaErr; spdlog::trace(sRMS.str()); leg->DrawLatex(0.13,0.73, "#bf{sigma:}"); leg->DrawLatex(0.13,0.69, sRMS.str().c_str()); //draw percentage of results in histo range // //std::ostringstream sInRange; //sInRange << std::fixed << std::setprecision(1) << std::fixed << 100. * (tot_fits - oor_fits - failed_fits) / (tot_fits - failed_fits) << "% in range"; //spdlog::trace(sInRange.str()); //leg->DrawLatex(0.13,0.64, sInRange.str().c_str()); //draw failRate std::ostringstream sfailRate; if(!UnbinnedFit){ sfailRate << std::fixed << std::setprecision(1) << std::fixed << info.failRate << "% failed"; spdlog::trace(sfailRate.str()); leg->DrawLatex(0.13,0.59, sfailRate.str().c_str()); } return; } //function to load toy fit results of one angular observables and create pull (or residual) plots for each q2 bin. //In this function the histogram is fitted using a single Gaussian bell shape. Either a standard binned fit or a RooFit unbinned fit //weirdShape is there for the cases the fitter generates stuff with different parameters than it fits, eg different polynomial bkg description std::vector eval_toys(std::string filename, std::string treename, basic_params params, bool doPulls, double pullRange_low, double pullRange_high, int whichPDf){ const q2Bins bins(params); //configure TPad style format and suppress pop-up windows from TCanvas: gROOT->SetBatch(kTRUE); gROOT->SetStyle("Plain"); TPad foo; set_gStyle(); gStyle->SetOptTitle(0); gStyle->SetTitleFont(132, "t"); gStyle->SetTextFont(132); gStyle->SetEndErrorSize(10.0); gErrorIgnoreLevel = kWarning; RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR); //start loading the values from the toy fit results root files: std::vector tot_fits(bins.nBins, 0); //counter for total fits std::vector oor_fits(bins.nBins, 0); //counter for fit results outside the histogram range (oor=out of range) std::vector failed_fits(bins.nBins, 0); //counter for fits with non-300 fit result std::vector max_value(bins.nBins, -10.); std::vector min_value(bins.nBins, +10.); std::vectorall_Values[bins.nBins]; //load chain with all results of bootstrapping TChain * ch = new TChain(treename.c_str()); Int_t nFiles = 0; //when wildcard [0-9] is used, add all files and the digits of the counter until no files are found //[0-9] stands for any digit, i.e. the combination 'file_[0-9][0-9][0-9][0-9].root' would add all files from 'file_0000.root' to 'file_9999.root' if(filename.find("[0-9]") != std::string::npos){ Int_t addedFiles = 1; while(addedFiles > 0){ addedFiles = ch->Add(filename.c_str()); //add another wildcard to the filename in order to search for files with job IDs in the next order of magnitude filename.replace(filename.find("[0-9]"), 5, "[0-9][0-9]"); //Can someone explain to me why the fuck shoudl this be needed? //add the number of found files to the total number of files nFiles += addedFiles; } } else{ //if no wildcard '[0-9]' or the general wildcard '*' is used, simply add all files: nFiles = ch->Add(filename.c_str()); } //check that at least one file with at least one entry is found: if(nFiles == 0){ spdlog::error("No files found for name='"+filename+"'."); return {}; } UInt_t nEntries = ch->GetEntries(); if(nEntries == 0){ spdlog::error("No entries found in files for tree='"+treename+"'."); return {}; } //make sure that the number of entries is equivalent to the number of files times the number of q2 bins times the number of simultaneous PDFs if(TMath::Abs((int)(nEntries/(nPDFs*bins.nBins))) != TMath::Abs(nFiles)){ spdlog::error("Number of entries found in files for tree='"+treename+"' does not match the number of files."); return {}; } spdlog::info("[LOAD]\t\tReading {0:d} events from {1:d} files for variable='{2:s}'.", nEntries, nFiles, treename); //link variables to branches double startvalue= DEFAULT_TREE_VAL; //TODO: check the start_value of the parameter is not changed anywhere, as it isn't a const it is very likely it is changed double value = DEFAULT_TREE_VAL; double error = DEFAULT_TREE_ERR; double errorup = DEFAULT_TREE_ERR; double errordown = DEFAULT_TREE_ERR; int migrad = DEFAULT_TREE_INT; int cov = DEFAULT_TREE_INT; int bin = DEFAULT_TREE_INT; int pdf = DEFAULT_TREE_INT; ch->SetBranchStatus("*",1); //TODO optimize ch->SetBranchAddress("value", &value); ch->SetBranchAddress("start_value", &startvalue); ch->SetBranchAddress("error", &error); ch->SetBranchAddress("error_up", &errorup); ch->SetBranchAddress("error_down", &errordown); ch->SetBranchAddress("migrad", &migrad); ch->SetBranchAddress("status_cov", &cov); ch->SetBranchAddress("bin", &bin); ch->SetBranchAddress("pdf", &pdf); //create a new simple tree that used the calculated pull or residual value, in case that unbinned fit is selected //this tree is used as input to the RooFitter TTree * unbinnedTree = nullptr; double x; //this variable is used for either the pull or residual value (depending on arg 'doPulls') if(UnbinnedFit){ unbinnedTree = new TTree("tmp_tree", "tmp_tree"); unbinnedTree->Branch("value", &x); unbinnedTree->Branch("bin", &bin); } //or else create histograms for the binned fit: TH1D * h_pull[bins.nBins]; TH1D * h_values[bins.nBins]; double binwidth = doPulls ? 0.5 : 0.05;//0.05; double xrange = doPulls ? 2.0*pullRange_high : 1.0;//2.0; if(!UnbinnedFit){ for(UInt_t b = 0; b < bins.nBins; b++){ //FUCK PEOPLE WHO DON'T DO BRACKETS h_pull[b] = new TH1D((treename+"_bin"+std::to_string(b)).c_str(), (treename+" in q^{2} bin #"+std::to_string(b)+(doPulls ? ";(x-x_{nomi.})/#sigma" : ";(x-x_{nomi.})")+";entries").c_str(), 2*xrange/binwidth, -xrange, +xrange); } } spdlog::debug("Finished initializing the histograms"); //load results from files: for(UInt_t e = 0; e < nEntries; e++){ //since all PDFs are saved in the TTree, only use 8(5) q2bins out of 32(10) for the KS0(pi0) channel //Eeee... e? //if(e%(bins.nBins*nPDFs) > (bins.nBins-1)) continue; ch->GetEntry(e); if(pdf != whichPDf) continue; spdlog::trace("Parameter value at entry {0:d}: {1:f}", e, value); all_Values[bin].push_back(value); tot_fits.at(bin)++; //require convered migrad if(migrad != 0){ failed_fits.at(bin)++; continue; } //require fitresult = 300 or 100 (or 200) if(!(cov == 1 || cov == 3 || cov == 2)){ failed_fits.at(bin)++; continue; } //derive residual and pull double diff = value - startvalue; if(error == 0. || isnan(error)){ spdlog::error("[{0:s}][BIN{1:d}]{2:d}\tError equal to zero!", treename, bin, e); return {}; } double pull = diff/error; spdlog::trace("[{0:s}][BIN{1:d}]{2:d}\tdiff={3:f}\tpull={4:f}\terr={5:f}", treename, bin, e, diff, pull, error); if(UnbinnedFit){ //assign pull or residual to 'x' and save in TTree x = doPulls ? pull : diff; //x, pull and diff is never used? //TODO unbinnedTree->Fill(); } else{//Binned fit if(TMath::Abs(diff) <= xrange){ if(doPulls){ //fill pull to histogram: h_pull[bin]->Fill(pull); //determine range of pull values max_value.at(bin) = std::max(max_value.at(bin),pull); min_value.at(bin) = std::min(min_value.at(bin),pull); } else{ h_pull[bin]->Fill(diff); //determine range of diff values max_value.at(bin) = std::max(max_value.at(bin),diff); min_value.at(bin) = std::min(min_value.at(bin),diff); } } else{ oor_fits.at(bin)++; } } } spdlog::debug("Filled all histograms/TTrees with values of variable="+treename+"."); spdlog::debug("Tree size="+treename+"."); //vectors to store the measured mean and widths of the pull(residual) distributions std::vector allInfo; //init some nullptr RooFit objects, to make the compiler happy. (These two are needed later in the plotting of the histograms) RooGaussian * roogaus[bins.nBins]; RooDataSet * roodata[bins.nBins]; RooRealVar * roovalue[bins.nBins]; for(UInt_t b = 0; b < bins.nBins; b++){ //loop over q2bins to fit all distributions if(UnbinnedFit){ //initialise RooFit objects for the unbinned fit: RooRealVar * roomean, * roosigma, * roobin; roovalue[b] = new RooRealVar("value", "value", pullRange_low, pullRange_high, ""); roomean = new RooRealVar("mean", "mean", bin_center(pullRange_low,pullRange_high), pullRange_low, pullRange_high); roosigma = new RooRealVar("sigma", "sigma", doPulls ? 0.85: 0.1, 0., 2.); roobin = new RooRealVar("bin", "q2 bin", -1., 10.0, ""); RooArgSet rooarg = RooArgSet(*roovalue[b]); rooarg.add(*roobin); roogaus[b] = new RooGaussian("RooGaus", "RooGaus", *roovalue[b], *roomean, *roosigma); //RooFitResult * result = new RooFitResult("FitResult","FitResult"); spdlog::debug("Start fitting q2 bin {0:d} for par={1:s}.", b, treename); roodata[b] = new RooDataSet("RooDataSet", "RooDataSet", unbinnedTree, rooarg, ("abs(bin-"+std::to_string(b)+") < 0.1").c_str()); spdlog::debug("Fit {0:d} events", roodata[b]->numEntries()); if(roodata[b]->numEntries() == 0){ spdlog::critical("Empty fit not possible for var={0:s} in q2bin={1:d}", treename, b); assert(0); } int fitstatus = roogaus[b]->fitTo(*roodata[b], RooFit::Save(kTRUE),RooFit::PrintLevel(spdlog_trace()?1 : -1))->status(); spdlog::debug("[{0:s}][BIN{1:d}]\tFitstatus={2:d}", treename, b, fitstatus); allInfo.push_back(pullInfo(roosigma->getVal(),roosigma->getError(), roomean->getVal(),roomean->getError(),fitstatus)); }//end unbinned fit else{//binned fit double entries = h_pull[b]->Integral(); bool dofit = entries > 10.0 && h_pull[b]->GetRMS(1) > 0.001; spdlog::debug("var={0:s}\t q2bin={1:d}\t DOFIT={2:s}", treename, b, (dofit ? "TRUE" : "FALSE")); if(entries < 0.0){ spdlog::warn("Negative entries for: q2bin={0:d}\t par={1:s}\t entries={2:d}", b, treename, entries); } int fitstatus = 0.0; if(tot_fits.at(b) > 0) fitstatus = (100.0 * failed_fits.at(b) / tot_fits.at(b)); if(dofit){ double minfit = -xrange; double maxfit = +xrange; TF1 * fGauss = new TF1("theGaussian", "gaus(0)", minfit, maxfit); fGauss->SetParameter(0, entries); fGauss->SetParameter(1, h_pull[b]->GetXaxis()->GetBinCenter(h_pull[b]->GetMaximumBin())); if(!doPulls){ double mean_range = (treename.find("P") != std::string::npos || treename == "Fl") ? 0.05 : 0.01; fGauss->SetParLimits(1, h_pull[b]->GetXaxis()->GetBinCenter(h_pull[b]->GetMaximumBin()) - mean_range, h_pull[b]->GetXaxis()->GetBinCenter(h_pull[b]->GetMaximumBin()) + mean_range); } fGauss->SetParameter(2, h_pull[b]->GetRMS(1)); fGauss->SetParLimits(2, 0.0, doPulls ? 1.5 : 0.1); fGauss->SetLineStyle(kDashed); fGauss->SetLineColor(kMagenta - 3); h_pull[b]->Fit(fGauss, "RQM+"); //save values in a vector allInfo.push_back(pullInfo(fGauss->GetParameter(2),fGauss->GetParError(2), fGauss->GetParameter(1),fGauss->GetParError(1),fitstatus)); } else{//only use RMS and MEAN obtained by TH1F allInfo.push_back(pullInfo(h_pull[b]->GetRMS(1),h_pull[b]->GetRMSError(1), h_pull[b]->GetMean(1),h_pull[b]->GetMeanError(1),fitstatus)); } }//end of binned fit }//end of loops of q2 bins //save histogram with pulls (or residuals) and the value distributions to file TCanvas* c1 = new TCanvas("c1", "c1", 1600, 1200); c1->cd()->SetMargin(0.1,0.05,0.1,0.05); for(UInt_t b = 0; b < bins.nBins; b++){ //loop over bins.nBins spdlog::debug("Plotting bin {0:b}.",b); c1->cd(); if(UnbinnedFit){ RooPlot * rooframe = roovalue[b]->frame(); roodata[b]->plotOn(rooframe); roogaus[b]->plotOn(rooframe); rooframe->Draw(); } else{ h_pull[b]->Draw(); } //initiliaze and format a legend: TLatex * leg = getPrettyTex(0.07,13); leg->SetTextColor(kBlack); //draw variable name leg->DrawLatex(0.13,0.89, treename.c_str()); leg->SetTextSize(0.04); drawLegend(leg,bins.q2min.at(b) ,bins.q2max.at(b), allInfo[b],tot_fits[b],oor_fits[b],failed_fits[b]); c1->Print((get_ToyPullPlot_tag(b,treename,params,false,doPulls) +".eps").c_str(), "eps"); if(!UnbinnedFit) delete h_pull[b]; double max = *max_element(all_Values[b].begin(), all_Values[b].end()); double min = *min_element(all_Values[b].begin(), all_Values[b].end()); h_values[b] = new TH1D(treename.c_str(), (treename+" in q^{2} bin #"+std::to_string(b)+";"+treename+";Entries").c_str(), nFiles/5, min, max); for (auto val: all_Values[b]){ h_values[b]->Fill(val); } //save histogram with values to file plotAndSave(h_values[b],treename,get_ToyPullPlot_tag(b,treename,params,true, false),"eps"); }//end loop over q2 bins delete c1; return allInfo; } //print the results of the toy studies to latex tables: int print_latex_tables(bool Pprimes, bool doPulls, std::vector< std::string> LaTeXnames, std::vector< std::vector > lePullInfo, const q2Bins bins, int jobID){ if(lePullInfo.size() == 0){ spdlog::error("No results found for widths of pull/residual distributrionn"); return 1; } //generate color palette: TPad foo; TColor::InitializeColors(); Double_t stops[9] = { 0.0000, 0.1250, 0.2500, 0.3750, 0.5000, 0.6250, 0.7500, 0.8750, 1.0000}; Double_t red[9] = { 55./255., 55./255., 55./255., 55./255., 55./255., 105./255., 155./255., 205./255., 255./255.}; Double_t green[9] = { 55./255., 105./255., 155./255., 205./255., 255./255., 205./255., 155./255., 105./255., 55./255.}; Double_t blue[9] = { 255./255., 205./255., 155./255., 105./255., 55./255., 55./255., 55./255., 55./255., 55./255.}; Idx = TColor::CreateGradientColorTable(9, stops, red, green, blue, 255); //in what range should the colors be defined: double colorrange[] = {doPulls ? 0.2 : (Pprimes ? 0.2 : 0.05), doPulls ? 0.2 : (Pprimes ? 0.2 : 0.05), UnbinnedFit ? 2. : 20.}; std::vector tabnames = {"width", "mean"};//, (UnbinnedFit ? "fitstatus" : "failRate")}; clear_Latex_noteFile(latex_toyFile()+"_"+std::to_string(jobID)+std::string(doPulls?"":"_res")); //First make sure you don't append stuff std::ofstream myFile; //TODO: fix the latex name file open_Latex_noteFile(latex_toyFile()+"_"+std::to_string(jobID)+std::string(doPulls?"":"_res"), myFile); //open latex file for(unsigned int i = 0; i < tabnames.size(); i++){ myFile << "\\begin{frame} \\footnotesize \\centering" << std::endl; myFile << "\\begin{tabular}{|l|"; for(unsigned int b = 0; b < bins.nBins; b++) myFile << "p{2.2cm}"; myFile << "|}\\hline" << std::endl; myFile << "\\textbf{" << tabnames[i] << "}"; //for(unsigned int b = 0; b < bins.nBins; b++)myFile << "\t& " << b; for(unsigned int b = 0; b < bins.nBins; b++)myFile << std::setprecision(2) << std::fixed << "\t&[" << bins.q2min.at(b) << "--" << bins.q2max.at(b) << "]"; myFile << "\\\\" << std::endl; myFile << "\\hline\\hline" << std::endl; //TABLE CONTENT: for(unsigned int v = 0; v < lePullInfo.size(); v++){ if (lePullInfo.at(v).size()==0) continue; myFile << "$" << LaTeXnames.at(v) << "$ "; for(unsigned int b = 0; b < bins.nBins; b++){ //get correct value for mean,sigma,failRate at q2bin and variable double levalue = 0.0; double leerror = 0.0; if(i == 0){ levalue = lePullInfo.at(v)[b].sigma; leerror = lePullInfo.at(v)[b].sigmaErr; } else if(i == 1){ levalue = lePullInfo.at(v)[b].mean; leerror = lePullInfo.at(v)[b].meanErr; } else{ levalue = lePullInfo.at(v)[b].failRate; //TODO } myFile << "\t&"; //generate cell background color accordingly to the value: if(UseCellColor){ //TColor * colour = gROOT->GetColor(Idx + TMath::Min(254, (int) ((TMath::Abs((doPulls && i == 0 ? levalue - 1. : levalue))/2./colorrange[i]+0.5)*255.))); int coloridx = ((doPulls && i == 0 ? levalue - 1.0 : levalue)/colorrange[i])*127; if(coloridx < -127)coloridx = -127; if(coloridx > 127)coloridx = 127; TColor * colour = gROOT->GetColor(Idx + 127 + coloridx); if(colour==nullptr)spdlog::error("Color with idx={0:d} not found", Idx + 127 + coloridx); else{ std::string leColour(colour->AsHexString()); std::transform(leColour.begin(), leColour.end(),leColour.begin(), ::toupper); myFile << "\\cellcolor[HTML]{" << leColour.substr(1,6) << "} "; } } //draw cell content myFile << "$"; if(levalue>=0.0)myFile << "\\phantom{-}";//align columns by adding an invisible minus sign myFile << std::setprecision(3) << std::fixed << levalue << " \\pm " << leerror << "$"; } myFile << "\\\\" << std::endl; } //END OF TABLE CONTENT myFile << "\\hline" << std::endl; myFile << "\\end{tabular}" << std::endl << std::endl; myFile << "\\end{frame}" << std::endl; } myFile.close(); return 0; } void save2rootFile( basic_params params, std::vector< std::string> treeNames, std::vector< std::string> LaTeXnames, std::vector< std::vector > lePullInfo, const q2Bins bins){ TFile * file = new TFile((get_ToyPullPlot_folder(params)+"pullResults.root").c_str(), "RECREATE"); spdlog::debug("Opening "+std::string(file->GetPath())); file->cd(); for(UInt_t t = 0; t < treeNames.size(); t++){ if (lePullInfo[t].size()==0) continue; TTree * tree = new TTree(treeNames[t].c_str(), LaTeXnames[t].c_str()); spdlog::debug("Saving tree "+ treeNames[t]); double mean = DEFAULT_TREE_VAL; double width = DEFAULT_TREE_ERR; tree->Branch("mean", &mean, "mean/D"); tree->Branch("width", &width, "width/D"); for(UInt_t b = 0; b < bins.nBins; b++){ mean = lePullInfo[t][b].mean; width = lePullInfo[t][b].sigma; spdlog::debug("mean:\t{0:f}",mean); spdlog::debug("width:\t{0:f}",width); tree->Fill(); } tree->Write(); delete tree; } file->Close(); delete file; } const std::vectorcolorPallete = {"0d3c7b","2b6d97","499eb3","67cfcf","85ffeb","7ce9c8","72d2a5","69b282", "5FA55F", "84BC70", "A8D281","CCE892","F0FEA2","DABF7A","C47F51","AE4029","970000"}; /* const std::vectorcolorPallete = {"93006A","751778","562D86","374494","185AA2","2A6D92","3C8081","4E9370", "5FA55F", "84BC70", "A8D281","CCE892","F0FEA2","DABF7A","C47F51","AE4029","970000"}; */ /* const std::vectorcolorPallete = {"0d3c7b","0e5d85","0e7d8e","0f9d97","0fbda0","0cae7b","089f56","049031", "00800B", "3B9714", "76ae1d","b1c526","EBDB2e","d9a523","c76e17","B5370c","A30000"}; */ const std::vector colStops = {-1.000,-0.8750,-0.7500,-0.6250,-0.5000,-0.3750,-0.2500,-0.1250, 0.0000, 0.1250, 0.2500, 0.3750, 0.5000, 0.6250, 0.7500, 0.8750, 1.0000}; std::string getCol(double val){ int len = colStops.size(); for (int i = 0; i < len; i++){ if (colStops[i+1]>val) return colorPallete[i]; } return colorPallete[len-1]; } int save2texFileNew(std::vector< std::string> LaTeXnames, std::vector< std::vector > lePullInfo, const q2Bins bins, int jobID){ if(lePullInfo.size() == 0){ spdlog::error("No results found for widths of pull/residual distributrionn"); return 1; } std::vector tabnames = {"width", "mean"};//, (UnbinnedFit ? "fitstatus" : "failRate")}; clear_Latex_noteFile(latex_toyFile()+"_"+std::to_string(jobID)); //First make sure you don't append stuff std::ofstream myFile; //TODO: fix the latex name file open_Latex_noteFile(latex_toyFile()+"_"+std::to_string(jobID), myFile); //open latex file for(unsigned int i = 0; i < tabnames.size(); i++){ myFile << "\\begin{frame} \\footnotesize \\centering" << std::endl; myFile << "\\begin{tabular}{|l|"; for(unsigned int b = 0; b < bins.nBins; b++) myFile << "p{2.2cm}"; myFile << "|}\\hline" << std::endl; myFile << "\\textbf{" << tabnames[i] << "}"; //for(unsigned int b = 0; b < bins.nBins; b++)myFile << "\t& " << b; for(unsigned int b = 0; b < bins.nBins; b++)myFile << std::setprecision(2) << std::fixed << "\t&[" << bins.q2min.at(b) << "--" << bins.q2max.at(b) << "]"; myFile << "\\\\" << std::endl; myFile << "\\hline\\hline" << std::endl; //TABLE CONTENT: for(unsigned int v = 0; v < lePullInfo.size(); v++){ if (lePullInfo.at(v).size()==0) continue; myFile << "$" << LaTeXnames.at(v) << "$ "; for(unsigned int b = 0; b < bins.nBins; b++){ //get correct value for mean,sigma,failRate at q2bin and variable double levalue = 0.0; double leerror = 0.0; if(i == 0){ levalue = lePullInfo.at(v)[b].sigma; leerror = lePullInfo.at(v)[b].sigmaErr; } else if(i == 1){ levalue = lePullInfo.at(v)[b].mean; leerror = lePullInfo.at(v)[b].meanErr; } else{ levalue = lePullInfo.at(v)[b].failRate; //TODO } myFile << "\t&"; //generate cell background color accordingly to the value: if(UseCellColor){ if (i==0) myFile << "\\cellcolor[HTML]{" << getCol(levalue-1.0) << "} "; else myFile << "\\cellcolor[HTML]{" << getCol(levalue) << "} "; } //draw cell content myFile << "$"; if(levalue>=0.0)myFile << "\\phantom{-}";//align columns by adding an invisible minus sign myFile << std::setprecision(3) << std::fixed << levalue << " \\pm " << leerror << "$"; } myFile << "\\\\" << std::endl; } //END OF TABLE CONTENT myFile << "\\hline" << std::endl; myFile << "\\end{tabular}" << std::endl << std::endl; myFile << "\\end{frame}" << std::endl; } myFile.close(); return 0; } //MAIN FUNCTION to run over all observables and q2bin. //the function calls the loading and fitting function 'eval_toys()' //then runs the print and save functions int EvaluateToyStudy(const std::vector obs, const std::vector obs_latex, basic_params params, bool UseFolds, bool doPulls, bool Pprimes, bool onlySig, bool onlyBkg){ //define names of observables and which foldings are taken for which observable std::vector folding_idx; if(Pprimes) folding_idx = {3, 3, 0, 0, 1, 2, 3, 4}; else folding_idx = {3, 3, 1, 2, 0, 3, 4, 0}; std::vector weirdRangeJobs = {340, 343, 344, 349, 350, 353, 354, 355, 362, 379, 382, 497,558, 559, 560, 561, 562, 563}; //jobIDs with off pull ranges double lowRange = -5.0; double highRange = 5.0; std::vector ctkRange = {497, 558, 559, 560, 561, 562, 563, 566, 567, 568, 569, 570, 571, 620, 621, 622, 623, 624, 625, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648}; //configure the path and tags of the toy study result files std::string PPtag = Pprimes ? "_Pprimes" : ""; std::string suffix = ""; //TODO makeFolder(get_ToyPullPlot_folder(params)); const q2Bins bins(params); //using this status for error propagation std::vector< std::vector> leInfo = {}; for(UInt_t p = 0; p < obs.size(); p++){ lowRange = -5.0; //Reset the ranges again in case highRange = 5.0; if(params.reference && ( isInVec(obs.at(p),ANG_OBS) || isInVec(obs.at(p),SWAVE))){ lowRange = -1.0; //Reset the ranges again in case highRange = 1.0; } if(params.reference && params.folding>-1 && ( isInVec(obs.at(p),ANG_OBS) || isInVec(obs.at(p),SWAVE))){ lowRange = -0.5; //Reset the ranges again in case highRange = 0.5; } if(params.reference && params.folding==4 && ( isInVec(obs.at(p),ANG_OBS) || isInVec(obs.at(p),SWAVE))){ lowRange = -5.0; //TODO highRange = 5.0; } if(params.reference && params.folding>-1 && obs.at(p)=="FS"){ lowRange = -0.25; //Reset the ranges again in case highRange = 0.25; } if(UseFolds)params.folding = folding_idx.at(p); //get a filename accordingly to the basic_params settings, then replace the number 1111 by the wildcard //and then replace the folder ToysFit by the subfolder created by condor std::string files = final_result_name_toys(1111, params.reference, params.nBins, true, params, params.Run, false, false, onlySig, onlyBkg, false, true); replace(files, "1111", "*"); //integer replaced by a string * replace(files, "ToysFit/", "ToysFit/"+std::to_string(params.jobID)+"/"); spdlog::info("Read pdfs from file='"+files+"'"); //Set the range for weird pulls in ctk if (isInVec(params.jobID, weirdRangeJobs) && p>7 && p<15){ //This is a dirty hack lowRange = -50.0; highRange = +50.0; } if ((params.jobID==503 || (params.jobID>=509 && params.jobID<=512)) && (p==11 || p ==12)){ //This is a dirty hack lowRange = -50.0; highRange = +50.0; } if ((params.jobID==551 && (p==1))){ //This is a dirty hack leInfo.push_back({}); continue; } if ((params.jobID==551 && (p==3))){ lowRange = -10.0; highRange = 0.0; } if (params.jobID==566 && (p==9)){ //This is a dirty hack leInfo.push_back({}); continue; } if (params.jobID==567 && (p==9)){ //This is a dirty hack leInfo.push_back({}); continue; } if (isInVec(params.jobID,ctkRange) && (p==8|| p==9)){ lowRange = -5.0; highRange = 15.0; } if (isInVec(params.jobID,ctkRange) && params.jobID>619 && (obs.at(p)=="cbkgctk1")){ leInfo.push_back({}); continue; //TODO WTF lowRange = 10.0; highRange = 30.0; } if (isInVec(params.jobID,ctkRange) && params.jobID>619 && (obs.at(p)=="cbkgctk2")){ leInfo.push_back({}); continue;//TODO WTF lowRange = 20.0; highRange = 45.0; } if (params.jobID==571 && (p==9)){ //This is a dirty hack leInfo.push_back({}); continue; } if (params.jobID>619 && (obs.at(p)=="cbkgctl2")){ //This is a dirty hack leInfo.push_back({}); continue;//TODO, actually anythig below zero possible depending on the bin lowRange = -15.0; highRange = -5.0; } //if (params.jobID==637 && (obs.at(p)=="SS5")){ //This is a dirty hack // continue; //} if (params.jobID==630 && (p==9)){ //This is a dirty hack leInfo.push_back({}); continue; } if (params.jobID==650 && (p==9)){ leInfo.push_back({}); continue; } //evalute the files for this observable and check the status leInfo.push_back(eval_toys(files, obs.at(p), params, doPulls, lowRange, highRange, 1)); } if (doPulls){ //print results to latex table into 'cout' and save to a root file if (params.reference) save2rootFile(params,obs, obs_latex,leInfo, bins); //This could be done for each value return save2texFileNew(obs_latex,leInfo,bins,params.jobID); } else return print_latex_tables(params.usePprime,false,obs_latex,leInfo, bins, params.jobID); }