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.
 
 
 
 

694 lines
22 KiB

//Constants and global options
//David Gerick
//Renata Kopecna
//All the libraries are included here, I am way to lazy to clean up, so here we are
#ifndef GLOBALFUNCTIONS
#define GLOBALFUNCTIONS
#include <cmath>
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <map>
#include <unistd.h>
#include <sys/stat.h>
//ROOT Libraries
#include <TChain.h>
#include <TTree.h>
#include <TH1D.h>
#include <TH2D.h>
#include <TF1.h>
#include <TFile.h>
#include <TCanvas.h>
#include <TGaxis.h>
#include <TGraphErrors.h>
#include <TLorentzVector.h>
#include <TROOT.h>
#include <TStyle.h>
#include <TFitResult.h>
#include <TLatex.h>
#include <TLegend.h>
#include <TLine.h>
#include <TMarker.h>
#include <TNtuple.h>
#include <TPaveText.h>
#include "TRandom3.h"
#include "TMath.h"
#include "TString.h"
#include "TSystem.h"
#include "TStopwatch.h"
#include <THStack.h>
#include "TGaxis.h"
#include <TMultiGraph.h>
#include "TApplication.h"
//RooFit Libraries
#include <RooDataSet.h>
#include <RooMCStudy.h>
#include "RooGaussModel.h"
#include "RooExponential.h"
#include "RooGenericPdf.h"
#include "RooChebychev.h"
#include "RooFitResult.h"
#include "RooAddModel.h"
#include "RooPolynomial.h"
#include "RooTruthModel.h"
#include "RooDecay.h"
#include "RooPlot.h"
#include "RooGaussian.h"
#include "RooDstD0BG.h"
#include "RooAddPdf.h"
#include "RooExtendPdf.h"
#include "RooDataHist.h"
#include "RooCBShape.h"
#include "RooCategory.h"
#include "RooFormulaVar.h"
#include "RooSimultaneous.h"
#include "RooHist.h"
#include "RooStats/SPlot.h"
#include "RooTreeDataStore.h"
#include "RooBifurGauss.h"
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooConstVar.h"
#include "RooProdPdf.h"
#include "RooNDKeysPdf.h"
#include "RooKeysPdf.h"
#include "RooGlobalFunc.h"
#include "RooRealIntegral.h"
#include "RooAbsReal.h"
#include "RooMsgService.h"
//Custom RooFit libraries
#include "RooFit/RooExpAndGauss/RooExpAndGauss.hpp"
#include "RooFit/RooDoubleCB/RooDoubleCB.h"
#include "LHCbStyle.h"
//indexed auto looping over vectors
#define for_indexed(...) for_indexed_v(i, __VA_ARGS__)
#define for_indexed_v(v, ...) for(bool _i_ = true, _break_ = false; _i_;) for(size_t v = 0; _i_; _i_ = false) for(__VA_ARGS__) if(_break_) break; else for(bool _j_ = true; _j_;) for(_break_ = true; _j_; _j_ = false) for(bool _k_ = true; _k_; v++, _k_ = false, _break_ = false)
////////////////////////////////////
/////
///// DECAY options
/////
////////////////////////////////////
bool GetKSfromExePath(){
char cwd[256];
if (getcwd(cwd, sizeof(cwd)) != NULL) {
//printf("Current working dir: %s\n", cwd);
char * KS = NULL;
KS = strstr(cwd, "dgerick");
if(KS){
std::cout << "Hello David! Now running KS0 pi+ mode!" << std::endl;
return true;
}
}
std::cout << "Hello Renata! Now running K+ pi0 mode!" << std::endl;
return false;
}
const bool KshortChannel = GetKSfromExePath(); // false := pi0 channel
const bool SplitDDandLL = KshortChannel ? true : false; //for pi0 SplitDDandLL is always false!
std::string TheDecay = (KshortChannel ? "KshortPiplus" : "KplusPi0Resolved");
const bool Kst2Kpluspi0Resolved = !KshortChannel; //keep the old variables, but set global!
const bool Kst2Kpluspi0Merged = false;
const bool Kst2Kspiplus = KshortChannel;
////////////////////////////////////
///
/// Basic options
///
////////////////////////////////////
//use only small sample of data for testing purposes
const bool smallSample = false;
//folder with stored data
const std::string path_to_data = "/auto/data/dgerick/B2Kstmumu";
const std::string path_to_output_KshortPiplus = "/auto/data/dgerick/B2Kstmumu";
const std::string path_to_output_KplusPizero = "/home/lhcb/kopecna/B2KstarMuMu_clean/Data";
const std::string thePath = Kst2Kspiplus ? path_to_output_KshortPiplus : path_to_output_KplusPizero;
// Use DTF varialbes
const bool UseDTF = KshortChannel ? true : true; //use mass and momenta of particles obtained by DTF?
// Use PDG mass for LorentzVectors or PE from branch
const bool UsePDGmIn4Dvectors = KshortChannel ? false : true;
// Reweight MC to the ratio of sWeighted Jpsi Data to Jpsi MonteCarlo (both reference channel)
const bool ReweightByRefChannel = KshortChannel ? true : true;
// Always reweight MC to pure jpsi data? (also for years without jpsi MC)
const bool AlwaysUseRefChannelData = KshortChannel ? true : true;
// Include 2017 and 2018?
const bool Use2017 = KshortChannel ? true : true;
const bool Use2018 = KshortChannel ? true : true;
// Use PIDgen for MC tuples
const bool UsePIDgen = KshortChannel ? true : false;
////////////////////////////////////
///
/// Weighting options
///
////////////////////////////////////
///
const std::string firstMCweight = (KshortChannel ? "nLongTracks" : "nLongTracks");
const std::string seconMCweight = KshortChannel ? (UseDTF ? "B_plus_PT_DTF" : "B_plus_PT") : (UseDTF ? "B_plus_PT_DTF" : "B_plus_PT");
const UInt_t firstnBins = 75;
const UInt_t secondnBins = 50;
const double firstMCrange[2] = {-0.5, 149.5};
const double seconMCrange[2] = {TMath::Log(1500.), TMath::Log(50000.)};
const std::string firstMClatex = KshortChannel ? "N^{Long}_{Tracks}" : "N^{Long}_{Tracks}";
const std::string seconMClatex = KshortChannel ? "p_{T}(B^{+}) ( MeV/c )" : "p_{T}(B^{+}) ( MeV/c )";
////////////////////////////////////
///
/// TM options
///
////////////////////////////////////
// TruthMatch MC only according to the BKGCAT
const bool UseBKGCAT = KshortChannel ? true : false;
//Truthmatching: set an option to TM particles
const bool pi0TM = true;
const std::string TMtag = UseBKGCAT ? "" : "_TM" + std::string(pi0TM ? "" : "_noPi0TM");
const std::string TMbranch = "TMed" + std::string(UseBKGCAT ? "BKGCAT" : "") + std::string(pi0TM ? "" : "_noPi0");
const std::string gammaTMbranch = "TM_gammas" + std::string(pi0TM ? "" : "_noPi0");
//Function
bool isTM(std::string customTMbranch, bool TM, bool gammaTM, int gTM){
if(customTMbranch.find("BKGCAT") != std::string::npos){
return TM;
}
else{
if(gammaTM) return (TM && (gTM <4));
else return (TM && (gTM <6));
}
}
const bool gammaTMdefault = false;
////////////////////////////////////
///
/// Cuts
///
////////////////////////////////////
//DTF convergence cuts
const double cut_DTF_status = 0.5;
const double cut_DTF_chi2 = 200.0;
//Mass cuts
const double K_star_plus_mass_difference = 100.0; //MeV //difference between K* mass and PDG K* mass
const double cut_B_plus_M_low_basic = 4900.; //MeV, to account for cut on non-DTF mass in stripping
const double cut_B_plus_M_low = KshortChannel ? 5150. : 5150.; //MeV
const double cut_B_plus_M_high = KshortChannel ? 6000. : 5800.; //MeV
const double B_plus_M_signal_window = KshortChannel ? 50. : 100; //MeV -- as PDGmass +/- the window
//kinematic cut <=> pseudorapidity (for each particle, except for gammas)
const double cut_kin_Theta_low = 0.0;
const double cut_kin_Theta_up = 0.4;
//Kinematic cuts
const double cut_K_star_plus_pT = 1350.0; //MeV
const double cut_B_plus_pT = 2000.0; //MeV
const double cut_pi_zero_PT = 800.0; //MeV
const double cut_B_plus_DIRA = 0.99996;
const double cut_muon_angle = 0.001;
const double cut_B_plus_FDCHI2 = 121.0;
const double cut_K_star_plus_FDCHI2 = 9.0;
const double cut_B_plus_ConePTasym = -0.5;
const double cut_DiMuon_M = 7100.0;
//Primary vertex cuts
const double cut_muon_IPCHI2_OWNPV_low = 9.0;
const double cut_IPCHI2_OWNPV_low = 0.0;
const double cut_IPCHI2_OWNPV_high = 12.0;
//PID cuts
const double cut_muon_ProbNNmu = 0.25;
const double cut_K_plus_ProbNNk = 0.25;
const double cut_gamma_CL = 0.15;
const bool SplitInQ2 = KshortChannel ? false : false;
//std::vector<double> q2BinsUp = {0.98, 2.5, 4.0, 6.0, 8.0, 12.5, 17.0, 19.0};
//std::vector<double> q2BinsLow = {0.1, 1.1, 2.5, 4.0, 6.0, 11.0, 15.0, 17.0};
//std::vector<double> diMuonMassBinsUp = {}; ///TODO
//std::vector<double> diMuonMassBinsLow = {}; //TODO
//const int nq2Bins = q2BinsUp.size();
////////////////////////////////////
///
/// Constants
///
////////////////////////////////////
//TMVA meethod
TString TMVAmethod = KshortChannel ? "BDTG" : "MLP"; //used TMVA method
//define PDG masses:
struct PDGMASS{
Double_t B_PLUS = 5279.29;
const Double_t B_ZERO = 5279.61;
const Double_t J_PSI = 3096.90;
const Double_t PSI_2S = 3686.10;
const Double_t K_STAR_PLUS = 891.66;
const Double_t K_ONE_PLUS = 1272.0;
const Double_t K_PLUS = 493.68;
const Double_t K_SHORT = 497.61;
const Double_t PI_PLUS = 139.57;
const Double_t PI_ZERO = 134.98;
const Double_t MU = 105.66;
const Double_t GAMMA = 0;
} PDGMASS;
//define the TRUEIDs:
struct TRUEIDS{
const Int_t B_PLUS = 521;
const Int_t B_ZERO = 511;
const Int_t K_STAR_PLUS = 323;
const Int_t K_STAR_ZERO = 313;
const Int_t K_ONE_PLUS = 10323; // K1(1270)+
const Int_t K_ONE_PLUS_1400 = 20323; // K1(1400)+
const Int_t K_ONE_PLUS_1410 = 100323; // K1(1410)+
const Int_t K_ONE_ZERO = 10313; // K0(1270)+
const Int_t K_PLUS = 321;
const Int_t K_SHORT = 310;
const Int_t PI_PLUS = 211;
const Int_t PI_ZERO = 111;
const Int_t RHO_ZERO = 113;
const Int_t MU_MINUS = 13;
const Int_t GAMMA = 22;
const Int_t J_PSI = 443;
const Int_t ELECTRON = 11;
} TRUEID;
//branching ratios
//const double BR_sig = 9.6e-7; //PDG value for B+ -> K*+ mu mu
//const double BR_sig = 6.09576e-7; //BR for B+ -> K*+ mu mu without resonances from LHCb-PAPER-2014-006
const double BR_sig = 8.668e-7; //BR for B+ -> K*+ mu mu without resonances from flavio (09-05-19)
const double BR_ref = 1.43e-3 * 5.961e-2; //PDG value for B+ -> J/psi K*+ times J/psi -> mu mu
const double BR_ref2 = 6.7e-4 * 8.0e-3; //PDG value for B+ -> psi(2s) K*+ times psi(2s) -> mu mu
const float SignalRegionNsigma = 2.; //How many sigmas around the signal peak comprises the signal region
double getTMVAcut(int Run){
if (Run == 1) return 0.9985;
else if (Run == 2) return 0.996;
else return 1;
}
#ifndef SIGNALPARAMETERS
#define SIGNALPARAMETERS
struct SignalFitParameters{ //TODO: possibly add the K1 to ParamValues at some point
//signal fractions
Double_t SigmaEff = 15.;
//background parameter
Double_t bkg_mean_K1 = 5158.6;
Double_t bkg_sigma_K1 = 50.;
//background fraction
Double_t f_BplusBckGndK1 = 0.5;
} SignalFitParameter;
#endif //signalfitParams
#ifndef SIGNALPARAMETERSFIXED
#define SIGNALPARAMETERSFIXED
struct FixedParameters{//TODO: possibly add the K1 to ParamValues at some point
//background parameter
bool bkg_mean_K1 = KshortChannel ? false : true;
bool bkg_sigma_K1 = KshortChannel ? false : false;
} FixParameter;
#endif //sigparams
////////////////////////////////////
///
/// Check if file exists
///
////////////////////////////////////
inline bool exists_test (const std::string& name) {
struct stat buffer;
return (stat (name.c_str(), &buffer) == 0);
}
////////////////////////////////////
///
/// SetOutputLevel
///
////////////////////////////////////
int verboseLevel = 2;
//verboseLevel 0: cout Tests, Debugs, Infos, Warnings and Errors
//verboseLevel 1: cout Debugs, Infos, Warnings and Errors
//verboseLevel 2: cout Infos, Warnings and Errors
//verboseLevel 3: cout Warnings and Errors
//verboseLevel 4: cout Errors (always cout errors)
void setVerboseLevel(int level){
verboseLevel = level;
}
bool set_gErrorIgnoreLevel(){
gStyle -> SetOptStat(0);
LHCbStyle();
gROOT->SetBatch(kTRUE);
if (verboseLevel == 3 || verboseLevel == 2) gErrorIgnoreLevel = kWarning;
if (verboseLevel == 4) gErrorIgnoreLevel = kError;
return true;
}
bool get_gErrorIgnoreLevel = set_gErrorIgnoreLevel();
////////////////////////////////////
///
/// Colors
///
////////////////////////////////////
#define cBOLDWHITE "\033[1m\033[37m" /* Bold White */
#define cBOLDRED "\033[1m\033[31m" /* Bold Red */
#define cBOLDGREEN "\033[1m\033[32m" /* Bold Green */
#define cGREEN "\033[32m" /* Green */
#define cBOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
#define cCYAN "\033[36m" /* Cyan */
#define cRED "\033[31m" /* Red */
#define cBOLDRED "\033[1m\033[31m" /* Bold red */
#define cYELLOW "\033[33m" /* Yellow */
#define cBOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
#define cRESET "\033[0m"
////////////////////////////////////
///
/// Fancy couts
///
////////////////////////////////////
void coutTest(string message){
if (verboseLevel==0) cout << "[TEST]\t\t" << message << endl;
}
void coutDebug(string message){
if (verboseLevel<2) cout << "[DEBUG]\t\t" << message << endl;
}
void coutInfo(string message){
if (verboseLevel<3) cout << "[INFO]\t\t" << message << endl;
}
void coutWarning(string message){
if (verboseLevel<4) cout << cBOLDYELLOW << "[WARN]\t\t" << cYELLOW << message << cRESET << endl;
}
void coutERROR(string message){
cout << cBOLDRED << "[ERROR]\t\t" << cRED << message << cRESET << endl;
}
////////////////////////////////////
///
/// FUNCTIONS
///
/// bool IsDST(year,MC,ReferenceChannel,PHSP)
/// checks whether the input file is MDST or DST
/// Important for branch names in BDTSelection.cpp
///
/// void addLHCbTag(x,y,suffix, color, Scaling)
/// Draws TLatex "LHCb + suffix" with the size of 0.07*scaling
///
/// string Float2Comma(f,d)
/// Returns a comma-separated string of the input float up to the given precision.
/// NO ROUNDING!
///
/// bool replace(str,from,to)
/// replaces string 'from' by 'to'
/// replaces all occurences of 'from'
///
/// void printVector(vector)
/// couts members of a vector
///
////////////////////////////////////
double get_cut_B_plus_M_low(int Run = 2){ //setting lower B mass cut for different run/years
if (KshortChannel) return cut_B_plus_M_low;
else{
if (Run==1) return 5150.0;
else if (Run==2) return cut_B_plus_M_low;
else{
std:: cout << "[WARN] Wrong year input! Choose either 1 or 2. Lower cut set to " << cut_B_plus_M_low << "MeV" << std::endl;
return cut_B_plus_M_low;
}
}
}
double get_cut_B_plus_M_low( std::string year = "2015"){
if (KshortChannel) return cut_B_plus_M_low;
else{
if (year == "2011" || year == "2012") return 5150.0;
else if (year == "2015" || year == "2016" || year == "2017" || year =="2018" ) return cut_B_plus_M_low;
else{
std:: cout << "[WARN] Wrong year input! Choose a year from 2011, 2012, 2015, 2016, 2017 or 2018. Lower cut set to " << cut_B_plus_M_low << "MeV" << std::endl;
return cut_B_plus_M_low;
}
}
}
bool IsDST(std::string year, bool MC, bool ReferenceChannel, bool PHSP){
if (MC && (year == "2011" || year == "2012")) return true;
if (MC && (year == "2018" && KshortChannel) && !PHSP) return true;
if (MC && ReferenceChannel && (year == "2015" || year == "2016") && !KshortChannel) return true;
return false;
}
void addLHCbtag(Float_t x = 0.6, Float_t y = 0.85, std::string suffix = "", Int_t color = 1, Float_t Scaling = 1.0){
TLatex* lhcbtext = new TLatex();
lhcbtext->SetTextFont(132);
lhcbtext->SetTextColor(color);
lhcbtext->SetTextSize(0.07*Scaling);
lhcbtext->SetTextAlign(13);
lhcbtext->SetNDC(1);
lhcbtext->DrawLatex(x,y,("LHCb "+suffix).c_str());
}
std::string Float2Comma(Float_t f, Int_t d){
if(d > 5){
std::cout << "[WARNING]\tPrecision larger '5' is not given by this function! Limit to 5." << std::endl;
d = 5;
}
std::string out = Form("%i", static_cast<Int_t>(f + 1e-6));
/* just curious, why don't we use something like
* tmp = f //just to be sure nothing happens to f itself
* stringstream ss;
* ss << fixed << setprecision(d) << tmp;
* string out = ss.str()
* out.replace(out.find("."),out.find(".")+1,",")
* return out;
* Seems a bit easier to me, or?
* */
if(d <= 0)return out;
Int_t N[d];
out.append(",");
for(Int_t n = 0; n <= d; n++){
N[n] = static_cast<Int_t>((f + 1e-6) * TMath::Power(10., n));
//std::cout << "Iteration " << n << " : " << (f + 1e-6) * TMath::Power(10., n) << " and as INT: " << N[n] << std::endl;
for(Int_t m = 0; m < n; m++)N[n] -= N[m] * TMath::Power(10., n - m);
if(n != 0)out.append(Form("%i", N[n]));
}
return out;
}
bool replace(std::string& str, const std::string& from, const std::string& to) {
size_t start_pos = str.find(from);
if(start_pos == std::string::npos) return false;
while ( (start_pos = str.find(from,start_pos)) != std::string::npos){
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
}
return true;
}
void printVector (std::vector<int> vector){
for (auto e: vector) cout << e << " ";
}
void printVector (std::vector<double> vector){
for (auto e: vector) cout << e << " ";
}/*
void printVector (std::vector<float> vector){
for (float e: vector) cout << e << " ";
}*/
void printVector (std::vector<string> vector){
for (auto e: vector) cout << e << " ";
}
std::vector<string> yearsMC (bool Reference = false, bool PHSP = false, int Run = 1){
std::vector<string> yearsTmp;
if(Run != 1 && Run != 2 && Run !=12 ){
coutERROR("Invalid Run number given: " + to_string(Run) + ". Exit program!");
return yearsTmp;
}
if(Run == 1|| Run == 12) {
yearsTmp.push_back("2011");
yearsTmp.push_back("2012");
}
if(Run == 2|| Run == 12){
if (Kst2Kpluspi0Resolved){
if (Reference || PHSP) yearsTmp.push_back("2015"); //Buggy 2015 MC
yearsTmp.push_back("2016");
if (!Reference){ //No reference channel for 2017 and 2018
if(Use2017) yearsTmp.push_back("2017");
if(Use2018) yearsTmp.push_back("2018");
}
}
else if (Kst2Kspiplus){
if (!Reference){ //no reference channel for Run II
yearsTmp.push_back("2015");
yearsTmp.push_back("2016");
if(Use2017) yearsTmp.push_back("2017");
if(Use2018) yearsTmp.push_back("2018");
}
if (Reference){ //@David TODO
yearsTmp.push_back("2016");
}
}
}
return yearsTmp;
}
std::vector<string> yearsData (int Run = 1){
std::vector<string> yearsTmp;
if(Run != 1 && Run != 2 && Run !=12 ){
std::cout << "[ERROR]\t\tInvalid Run number given: " << Run << ". Exit program!" << std::endl;
return yearsTmp;
}
if(Run == 1|| Run == 12) {
yearsTmp.push_back("2011");
yearsTmp.push_back("2012");
}
if(Run == 2|| Run == 12){
yearsTmp.push_back("2015");
yearsTmp.push_back("2016");
yearsTmp.push_back("2017");
yearsTmp.push_back("2018");
}
return yearsTmp;
}
std::vector<string> yearsVector (bool MC = false, bool Reference = false, bool PHSP = false, int Run = 1){
if (MC) return yearsMC(Reference,PHSP, Run);
else return yearsData(Run);
}
std::vector<int> yearsVectorInt(bool MC = false, bool Reference = false, bool PHSP = false, int Run = 1){
std::vector<Int_t> yearsTmp;
for (auto yr: yearsVector(MC,Reference,PHSP,Run))
yearsTmp.push_back(stoi(yr));
return yearsTmp;
}
std::vector<string> yearsInc(int Run){
std::vector<string> yearsTmp;
if(Run != 1 && Run != 2 && Run !=12 ){
std::cout << "[ERROR]\t\tInvalid Run number given: " << Run << ". Exit program!" << std::endl;
return yearsTmp;
}
if(Run == 1|| Run == 12) {
yearsTmp.push_back("2011");
yearsTmp.push_back("2012");
}
if(Run == 2|| Run == 12){
yearsTmp.push_back("2016");
}
return yearsTmp;
}
std::vector<string> yearsBkgMC(bool Reference, bool B0, bool K1, bool Inc, int Run){
std::vector<string> yearsTmp;
if (B0){
if(Run == 1|| Run == 12) {
yearsTmp.push_back("2011");
yearsTmp.push_back("2012");
}
if(Run == 2|| Run == 12){
if (Kst2Kpluspi0Resolved){
yearsTmp.push_back("2015");
yearsTmp.push_back("2016");
}
}
}
else if (K1){
if(Run == 1|| Run == 12) {
if (!Reference) yearsTmp.push_back("2011");
yearsTmp.push_back("2012");
}
if(Run == 2){
coutWarning("No Run II BtoK1Jpsi no BtoK1MuMu sample!");
coutERROR("Returning an empty vector.");
}
}
else if (Inc){
if (!Reference){
coutWarning("No Run inclusive BtoXMuMu sample!");
coutERROR("Returning an empty vector.");
}
if(Run == 1|| Run == 12) {
yearsTmp.push_back("2011");
yearsTmp.push_back("2012");
}
if(Run == 2|| Run == 12){
if (Kst2Kpluspi0Resolved){
yearsTmp.push_back("2016");
}
}
}
else{
coutERROR("No background sample selected! Choose between B0, K1 and inclusive samples!.");
coutERROR("Returning an empty vector.");
}
return yearsTmp;
}
int getRunID(string year){
int RunID = -1;
if (year == "2011" || year == "2012") RunID = 1;
else if (year == "2015" || year == "2016"|| year == "2017"|| year == "2018") RunID = 2;
else coutERROR("Wrong year input!");
return RunID;
}
#endif //GlobalFunctions