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.
 
 
 
 

412 lines
15 KiB

/**
* @file bu2kstarmumu.cc
* @author Christoph Langenbruch, David Gerick, Renata Kopecna
* @date 2020-30-11
*
* Main control file for the Bu -> K*+mumu analysis
*/
#include <sys/stat.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdio>
//Yes, I know that <> is not ideal for compilation time,
//but I was lazy to always put the correct path there at the begining
//when files were moved around rather often
#include <parameters.hh>
#include <parse.hh>
#include <toystudy.hh>
#include <angularcorr.hh>
#include <massfit.hh>
#include <mainfit.hh>
#include <backgroundfit.hh>
#include <mcfit.hh>
#include <momfit.hh>
#include <genlvlfit.hh>
#include <toysfit.hh>
#include <help.hh>
#include <constants.hh>
#include <generatetoys.hh>
#include <helpers.hh>
#include <event.hh>
#include <design.hh>
#include <paths.hh>
#include "sources/Scripts/RunningScripts.hh"
#include <TROOT.h>
#include <colors.hh>
int main ( int argc, char *argv[] )
{
//Set gROOT and gStyle
gROOT->SetStyle("Plain");
set_gStyle();
//Initiliaze pretty colors
myColorScheme::init();
//gStyle->SetPaintTextFormat("4.1f m");
//gStyle->SetCanvasPreferGL(true);
///set the fitting options
fcnc::options opts;
opts = fcnc::options("-1");
//how many events should be taken per Test/ToyFit?
UInt_t nMCEvents = 350;
//Retun errors:
//1: wrong options
//5: Inexplicable stuff
//404: not found
basic_params pars = basic_params();
basic_actions acts = basic_actions();
//The pars and acts are a bit wonky at the moment, hopefully as I progress this will get better
if (parseOpts(argc, argv, pars, acts, nMCEvents) == 1) return 1;
if (checkOpts(pars,acts) == 1) return 1;
//Set opts.folding according to the parsed options
//default should be -1
opts.folding = pars.folding;
////////////////////////////////////////////
// [START] GLOBAL OPTIONS
////////////////////////////////////////////
//Use only DTF, could be removed
opts.DTF = true;
//SET OUTPUT DESIGN
reset_spdlog();
set_spdlog_level(pars.verbosity);
//Make ROOT shut up
gStyle -> SetOptStat(0);
gROOT->SetBatch(kTRUE);
gErrorIgnoreLevel = kWarning;
//gErrorIgnoreLevel = kError;
opts.ncores = NCORES;
if(opts.ncores > 1) spdlog::info("[CPU]\tUse parallelisation on {0:d} CPU cores", opts.ncores);
//FIXED to true, since we have flatQ2 phase-space MC
opts.IsFlatQ2 = true;
//get individual angular acceptance corrections for every year
opts.angacccorrperyear = false;
//Decide in what format everything should be saved in
opts.write_eps = true;
opts.write_C = false;
opts.write_jpg = false;
opts.write_pdf = true;
//Set the default path for plots_folder, somehow it doesn't want to accept PLOTS_PATH in the options constructor, possibly fix TODO
opts.plot_folder = PLOTS_PATH;
//fit pdfs over complete phi range [-pi, +pi]
opts.full_angular = opts.folding == -1;
//use a two tailed CrystalBall function instead of a Gaussian
opts.twotailedcrystalball = DOUBLE_CB;
opts.crystalball = !DOUBLE_CB;
//No exponential, but flat background model
opts.flat_bkg = false;
//////////////////////////
// HARDCODED FUNCTIONS: //
//////////////////////////
//default is NOT Kshort channel:
opts.KS = false;
//Set 'globally' fl and afb to (not) be used
opts.fit_fl = true;
opts.fit_afb = true;
//Set 'globaly' to use lambda in the background fit
//fit exponential with exp(-lambda*x) instead of exp(-x/tau), it has better precision
opts.fit_lambda = true;
//Assymetries to be included in the fit itself
opts.fit_asymmetries = false; //you don't have enough stats for this to be true
/////////////////////////////////////
// Set the order of the polynomial //
/////////////////////////////////////
opts.bkg_order_costhetal = 2; //TODO: put as a const into constants.cc and modify it accordingly in options.cc
opts.bkg_order_costhetak = 5;
////////////////////////
// ANGULAR RESOLUTION //
////////////////////////
//Set the order of legendre polynomial
opts.eff_order_costhetal = ORDER_COSTHETAL;
opts.eff_order_costhetak = ORDER_COSTHETAK;
opts.eff_order_phi = ORDER_PHI;
opts.eff_order_q2 = ORDER_Q2;
std::vector<std::vector<double>> resolution = get_resolution();
//Have angular correction per each Run (false)
opts.angacccorrbothruns = false;
//Don't use angular acceptance convoluted in the likelihood (false)
opts.use_angular_acc = false;
////////////////////////////////////////////
// GLOBAL OPTIONS //
////////////////////////////////////////////
//TODO fix this (actually nice, but can be done elsewhere)
//maximum range of considered B mass:
opts.m_low = B_MASS_LOW;
opts.m_high = B_MASS_HIGH;
//signal window of B mass:
opts.m_min = PDGMASS_B-B_MASS_TIGHT_WINDOW;
opts.m_max = PDGMASS_B+B_MASS_TIGHT_WINDOW;
//If MC, use MC weights//TODO: check for data
opts.multiply_eff = pars.dataset >0;
//TODO move to paths
std::string angularsuffix = opts.full_angular ? "full_angular" : "folding"+std::to_string(opts.folding);
//generate vector with years for every run option, including just one year
std::vector<Int_t>years = (pars.Run == 0 ? std::vector<Int_t>{pars.year} : get_years(pars.Run, pars.dataset==1, pars.dataset==2));
spdlog::debug("Using years: " + convert_vector_to_string(years));
//---------------------------------------------
// Put stuff from pars and acts into opts
//---------------------------------------------
//yes it is dumb but I cannot be bothered to change the whole options
opts.verbose = pars.verbosity;
opts.run = pars.Run; //This is not ideal when fitting per year,
//From now on passing the pars as well
opts.useMC = pars.dataset > 0;
opts.fit_pprimes = pars.usePprime;
//-------------------------------
// Get corresponding Q2 bins
//-------------------------------
if (pars.reference) pars.nBins = 1; //For reference, always use 1 bin
opts.TheQ2binsmin = get_TheQ2binsmin(pars.nBins, pars.reference);
opts.TheQ2binsmax = get_TheQ2binsmax(pars.nBins, pars.reference);
spdlog::debug("Using {0:d} q2 bins.", opts.TheQ2binsmax.size());
if (spdlog::default_logger_raw()->level()==spdlog::level::info){
spdlog::info("Using the following binning scheme:");
for(UInt_t b = 0; b < opts.TheQ2binsmin.size(); b++){
assert(opts.TheQ2binsmin.at(b) != 0.0);
assert(opts.TheQ2binsmax.at(b) != 0.0);
assert(opts.TheQ2binsmin.at(b) < opts.TheQ2binsmax.at(b));
std::cout << std::fixed << std::setprecision(2) << "\tbin" << b+1 << ": [" << opts.TheQ2binsmin.at(b) << "-" << opts.TheQ2binsmax.at(b) << "] GeV^2/c^4" << std::endl;
}
}
//-------------------------------
// Set ranges of the angles
//-------------------------------
//Not ideal to have it as an opts and as a constant, but this is how it is going to be now
opts.reset_angle_ranges();
//The ranges might change in the folding, hence I will keep the opts.angle_min/max for this case
//Check if something is wrong; if any task is assigned, raise this flag
bool isItDoingAnything_flag = false;
int returnCode = 0;
//-------------------------------
// create branches for FCNCfitter
//-------------------------------
if(acts.convert){ //these booleans are only for running, used only here
//maybe put it into a new class //TODO
isItDoingAnything_flag = true;
return convert_tuples(pars.dataset, get_theFCNCpath(pars.dataset, opts.run), opts,years);
}
//-------------------------------
// scan angular acceptance max. order of legendre
//-------------------------------
if(acts.angCorrScan){
isItDoingAnything_flag = true;
bool quickTest = false;
bool test_4times1D = false;
bool checkSignificance = false;
bool runMinuit = false;
bool checkFactorization = false;
bool do3Dmoments = false;
const bool assumePhiEven = IS_PHI_EVEN;
spdlog::debug("Scanning angular acceptance corrections...");
returnCode = scan_max_order_angular_ccorrection(opts, assumePhiEven, quickTest, test_4times1D,
checkSignificance, runMinuit, checkFactorization, do3Dmoments);
if (returnCode!=0) return returnCode;
}
//-------------------------------
// fit angular acceptance
//-------------------------------
if (acts.angCorr){
if (pars.testInt > -1) sanityCheck_MC(opts);
else{
isItDoingAnything_flag = true;
bool testSaving = false;
spdlog::debug("Calculating angular acceptance correction parameters...");
returnCode = get_angular_acceptance(opts, testSaving);
if (returnCode!=0) return returnCode;
}
}
//--------------------------------
// FIT MASS
//--------------------------------
if(acts.fitType == 2){
isItDoingAnything_flag = true;
bool splitRuns = true;
massfit(opts, pars.reference, splitRuns, pars);
}
//--------------------------------
// MC FIT
//--------------------------------
if(acts.fitType == 4){
isItDoingAnything_flag = true;
opts.only_angles = false;//(nBins == 8); //Do not fit the mass, just angles //Apply only when fitting B0 binning
//Reference MC is broken (K* is PHSP), so when fitting the reference, fit only mass
opts.only_Bmass = pars.reference; //Do not fit the angles, just mass
opts.initSM = !pars.reference; //Set to true only for reference
returnCode = mcfit_4D(opts, pars.reference, pars.dataset==3, pars);
//yes, fitRef could be included in params, but I like to keep my options open :)
if (returnCode!=0) return returnCode;
}
//--------------------------------
// COMPLETE FIT
//--------------------------------
if(acts.fitType == 1){
isItDoingAnything_flag = true;
bool fitToy = pars.testInt > -1; //If test, then do fit toys
if (pars.folding == 5){ //We do not need this here, we can run the code 5 times, no?
for (int f = 0; f < 5; f++){
pars.folding = f;
opts.folding = f;
spdlog::debug("Fitting with folding={0:d}", pars.folding);
mainfit(opts, pars, pars.reference, fitToy, pars.likelyhood, pars.FeldCous);
}
}
else {
mainfit(opts, pars, pars.reference, fitToy, pars.likelyhood, pars.FeldCous);
}
}
//--------------------------------
// BACKGROUND ONLY FIT
//--------------------------------
if(acts.fitType == 0){
isItDoingAnything_flag = true;
//Clear the bkgFit file
clear_Latex_noteFile("_bkgFit");
//Set options
//One can also fit only upper/lower mass sideband, to set this use -index
bool LowMassFit = (pars.index == 1);
bool HighMassFit = (pars.index == 2);
bool Use2DAngularBins = false;
bool fitKpiMass = true;
//Run the background only fit
int bkgfit = 0;
if (pars.folding == 5){ //We do not need this here, we can run the code 5 times, no?
for (int f = 0; f < 5; f++){
pars.folding = f;
opts.folding = f;
bkgfit =+ backgroundfit(opts, pars.reference,
LowMassFit, HighMassFit, fitKpiMass,
Use2DAngularBins, pars);
}
}
else bkgfit = backgroundfit(opts, pars.reference,
LowMassFit, HighMassFit, fitKpiMass,
Use2DAngularBins, pars);
if (bkgfit != 0) return bkgfit;
}
//--------------------------------
// start GENERATOR LEVEL MC FIT
//--------------------------------
if(acts.fitType == 5){
isItDoingAnything_flag = true;
opts.initSM = pars.nBins != 8; //SM for 8 bins not implemented
genlvlfit(opts, pars.dataset==4, pars);
}
//--------------------------------
// method of moment fit
//--------------------------------
//TODO
if(acts.fitType == 3){
isItDoingAnything_flag = true;
bool blind = true;
bool Fit2bins = false, Fit1bin = false, FitAllbins = false; //TODO: remove
momfit(opts, pars.nBins==0, pars.dataset==1, pars.dataset==0, blind,
Fit1bin, Fit2bins, FitAllbins);
}
//--------------------------------
// BEGIN angular resolution
//--------------------------------
if(acts.angRes){
isItDoingAnything_flag = true;
get_angular_resolution(opts, get_years(opts.run, true, false));
}
//-------------------------------
// generate Toy events
//-------------------------------
if (acts.genToys){
isItDoingAnything_flag = true;
spdlog::debug("Generating and fitting toys");
bool onlySig = true;
bool onlyBkg = false;
if (pars.folding == 5){ //We do not need this here, we can run the code 5 times, no?
for (int f = 0; f < 5; f++){
pars.folding = f;
opts.folding = f;
spdlog::debug("Generating and fitting a toy sample with folding={0:d}", pars.folding);
toysfit(opts, pars.nBins, pars.reference, pars, onlySig, onlyBkg);
}
}
else {
if (pars.testInt > -1)saveToys(pars, opts, pars.dataset>0, false); //if MC generate without bkg
else{
if(pars.folding != -1)spdlog::debug("Generating and fitting a toy sample with folding={0:d}", pars.folding);
toysfit(opts, pars.nBins, pars.reference, pars, onlySig, onlyBkg);
}
}
}
//-------------------------------------------
// Run whatever script you decide to run
//-------------------------------------------
//Yes, this is tedious, but I don't want to hardcode everything just so root is happy
//nor I wanna compile everything, so here we are
if(acts.script){
isItDoingAnything_flag = true;
int status = runWhatever(pars, acts); //FILL IN RunningScripts.cc BY HAND
if(status)return status;
}
if (!isItDoingAnything_flag) spdlog::warn("Nothing to do! Exitting.");
else spdlog::info("Done with everything. Exit.");
return 0;
}