Angular analysis of B+->K*+(K+pi0)mumu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

759 lines
33 KiB

//Renata Kopecna
#include <fstream>
#include <TChain.h>
#include <TH1D.h>
#include <TF1.h>
#include <TCanvas.h>
#include <TFile.h>
#include <TMath.h>
#include <TColor.h>
#include <TLegend.h>
#include <TStyle.h>
#include <TLatex.h>
#include <TROOT.h>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <RooDataSet.h>
#include <RooGaussian.h>
#include <RooFitResult.h>
#include <RooPlot.h>
#include <RooRealVar.h>
#include "EvaluateToys.hh"
#include <design.hh>
#include <helpers.hh>
#include "ScriptHelpers.hh"
#include <math.h>
//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<double> q2min;
std::vector<double> q2max;
q2Bins(basic_params params){
nBins = params.nBins;
q2min = get_TheQ2binsmin(nBins, params.reference);
q2max = get_TheQ2binsmax(nBins, params.reference);
}
};
const std::vector<std::vector<double>> 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<pullInfo> 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<unsigned int> tot_fits(bins.nBins, 0); //counter for total fits
std::vector<unsigned int> oor_fits(bins.nBins, 0); //counter for fit results outside the histogram range (oor=out of range)
std::vector<unsigned int> failed_fits(bins.nBins, 0); //counter for fits with non-300 fit result
std::vector<double> max_value(bins.nBins, -10.);
std::vector<double> min_value(bins.nBins, +10.);
std::vector<double>all_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<pullInfo> 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<pullInfo> > 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<std::string> 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<pullInfo> > 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::vector<std::string>colorPallete =
{"0d3c7b","2b6d97","499eb3","67cfcf","85ffeb","7ce9c8","72d2a5","69b282",
"5FA55F",
"84BC70", "A8D281","CCE892","F0FEA2","DABF7A","C47F51","AE4029","970000"};
/*
const std::vector<std::string>colorPallete =
{"93006A","751778","562D86","374494","185AA2","2A6D92","3C8081","4E9370",
"5FA55F",
"84BC70", "A8D281","CCE892","F0FEA2","DABF7A","C47F51","AE4029","970000"};
*/
/*
const std::vector<std::string>colorPallete =
{"0d3c7b","0e5d85","0e7d8e","0f9d97","0fbda0","0cae7b","089f56","049031",
"00800B",
"3B9714", "76ae1d","b1c526","EBDB2e","d9a523","c76e17","B5370c","A30000"};
*/
const std::vector<double> 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<pullInfo> > 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<std::string> 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<std::string> obs, const std::vector<std::string> 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<UInt_t> 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<int> 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<int> 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<pullInfo>> 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);
}