760 lines
33 KiB
C++
760 lines
33 KiB
C++
//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);
|
|
}
|
|
|
|
|