|
|
//Functions used for the B plus mass fit
//Renata Kopecna
#include "GlobalFunctions.hh"
#include "MassFit.hpp"
#include "BmassShape/BackgroundPdf.hpp"
#include "BmassShape/SignalPdf.hpp"
#include "Paths.hpp"
#include "MVAclass.hpp"
#include "RooFit/RooDoubleCB/RooDoubleCB.h"
#include "Design.hpp"
#include "Utils.hpp"
using namespace std; using namespace RooFit; using namespace RooStats;
bool useExtraVarBool(string extraVar){ //Shoudl be easy to add others
vector<string> allVars {"q2", "q2_binned", "q2_binned_fit", "thetak", "thetal", "phi", "pi_zero_ETA", "pi_zero_ETA-K_plus_ETA", "pi_zero_P", "pi_zero_P_DTF", "pi_zero_PT", "pi_zero_PT_DTF","K_plus_P","K_plus_PT"}; for (auto &var: allVars){ if (extraVar == var) return true; if (extraVar == var+"_equal") return true; } return false; }
string GetsWeightPlots(string year, bool UseOnlyJpsiEvents, bool UseOnlyMuMuEvents, bool KshortDecaysInVelo, bool GetShapeFromMC, string SignalType, string BkgType, bool ConstrainParameters){
string path = GetMassFitFile(year,false,UseOnlyJpsiEvents,UseOnlyMuMuEvents, KshortDecaysInVelo, GetShapeFromMC, SignalType,BkgType, ConstrainParameters,true,false); replace(path,"BplusMassModel","Sweight"); return path; }
double massFit(string year, string magnet, int Run, bool MC, bool Preselected, bool TM, bool PHSP, //input/output file selection
bool UseOnlyJpsiEvents, bool UseOnlyMuMuEvents, //signal/reference
bool GetShapeFromMC, string SigType, string BkgType, bool ConstrainParameters, //shape
bool KshortDecaysInVelo, bool UseLowQ2Range, //LL/DD? q2range?
Double_t TMVAcut, int randomSubset, //TMVA options
bool fixedMassRegion, bool yieldOverFullRange, //yield calculation region
bool sWeight, //sWeight data?
bool loopFit, bool IsEfficiency, //additional options
string sExtraVar, int nExtraBin, //fit in bins of extra variable
bool removeMultiple, //Remove multiple candidates?
bool weighted, bool weightedFromPi0, string whichWeight, //use weight in the fit?
bool nonTM, string customTMbranch, bool gammaTM, //TM options
bool InclusiveSample){ //Fit inclusive sample?
//bool notTM: if true and MC, fits the nonTM part of MC with a CB
// To fit the CB as a background either in MC or Data, add "OneCB" to the BkgType string
//randomSubset \in {-1,0,1}
//loopFit means that MC fit is not performed, but parameters are fixed to previous fit, useful since one doesn't have to fit MC all the time in a loop
//IsEfficiency: Just stored in a different folder
//TODO: possibly add splittig in low/high Q2
//Make ROOT quiet
gStyle -> SetOptStat(0); LHCbStyle(); gROOT->SetBatch(kTRUE); //Load all libraries for ROOT
gSystem->Load("./BmassShape/SignalType_cpp.so"); gSystem->Load("./BmassShape/BackgroundType_cpp.so"); gSystem->Load("./BmassShape/ParamValues_cpp.so"); gSystem->Load("./BmassShape/SignalPdf_cpp.so"); gSystem->Load("./BmassShape/BackgroundPdf_cpp.so"); int printLevel = 1; if (verboseLevel > 1){ printLevel = -1; RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL); }
//sanity checks
magnet = correct_magnet_string(magnet);
checkMC(MC,false,PHSP,false); if (!checkTM(MC,TM,nonTM,Preselected)) return 0; checkKshort(KshortDecaysInVelo); if (!SplitInQ2 && UseLowQ2Range) { coutWarning("Cannot use low Q2 region if the data is not split in Q2! Setting UseLowQ2Range to false!"); UseLowQ2Range = false; } if (!checkQ2Range(UseOnlyJpsiEvents,UseOnlyMuMuEvents)) return 0; if (TMVAcut > -1.0 && !Preselected){ //if TMVAcut == -1, no TMVA cut is applied
coutWarning("TMVA cut can be only aplied on preselected data! Setting Preselected to true!"); Preselected = true; //Cannot do BDT cut on stripped data
} if(TM && MC && (GetShapeFromMC || ConstrainParameters)){ coutWarning("Cannot fix MC fit to an MC fit! Setting GetShapeFromMC and ConstrainParameters to false."); GetShapeFromMC = false; //never run MC twice!
ConstrainParameters = false; // never use constrains on MC samples
} if (sWeight && MC){ coutWarning("MC cannot be sWeighted! Setting sWeight to false!"); sWeight = false; } if (sWeight && UseOnlyMuMuEvents){ coutWarning("Data cannot be sWeighted only in the MuMu region! Setting UseOnlyMuMuEvents to false!"); UseOnlyMuMuEvents = false; }
if (customTMbranch =="") customTMbranch = TMbranch; if (customTMbranch =="TMedBKGCAT" && gammaTM == false) gammaTM = true;
bool useExtraVar = useExtraVarBool(sExtraVar); //perform once so it doesn't have to run through all the ifs every time
TMefficiencyClass extraVar = TMefficiencyClass(sExtraVar);
//To make life easier, make a bool for using RefChannel MC
bool UseRefMC = (MC && !PHSP && UseOnlyJpsiEvents);
//Make a years vecotr based on Run and selected proper RunID based on a year
std::vector<string> years; int RunID = 0; if (Run == 0){ RunID = getRunID(year); if (MC && UseRefMC){ //can't use yearVector since we can replace 2017 and 2018 MC by 2016
if (!checkRefYear(year)) years.push_back("2016"); else years.push_back(year); } else years.push_back(checkIf2015MC(year,MC,UseRefMC,PHSP)); } else{ RunID = Run; if (InclusiveSample) years = yearsBkgMC(UseOnlyJpsiEvents,false, false,true, Run); else if (MC) years = yearsMC(UseRefMC,PHSP,Run); else years = yearsData(Run); }
coutInfo("Using year/s "); cout << "[INFO]\t"; printVector(years); cout << endl; coutInfo(" with RunID "+to_string(RunID));
///signal shape
SignalPdf SigShape; SigShape.setSignalType(SigType,GetShapeFromMC,ConstrainParameters);
///background shape
BackgroundPdf BkgShape; BkgShape.setBackgroundType(BkgType,TM,GetShapeFromMC,ConstrainParameters);
///----------------------------------------------------
///Get Fit parameters from fit to TMed MC if requested:
///----------------------------------------------------
//Turn off MC fit in case of fitting in a loop, except for when TMVAcut == lowBDTcut
//When performing scans, always fix the parameters to the MC value
//however, the parameters are not calculated each iteration of the scan, because the MC shape does not change
Float_t lowBDTcutCheck = (TMVAmethod == "MLP") ? 0.0 : -1.0; //check if at lower limit
bool runMCforTMVAcut = (TMVAcut == lowBDTcutCheck || TMVAcut == 0.9); //if TMVA at lower limit/0.9 for fine scans, do the MC fit again
coutDebug("Run MC for TMVA cut? " +to_string(runMCforTMVAcut)); coutDebug("TMVA cut: " +to_string(TMVAcut));
bool MC_UseOnlyJpsiEvents, MC_UseOnlyMuMuEvents; if(GetShapeFromMC && (runMCforTMVAcut || !loopFit)){ //In case of CB in the background model, fit the nonTMed MC by oneCB
if (sExtraVar == "q2_binned"){ MC_UseOnlyJpsiEvents = false; MC_UseOnlyMuMuEvents = true; } else{ MC_UseOnlyJpsiEvents = UseOnlyJpsiEvents; MC_UseOnlyMuMuEvents = UseOnlyMuMuEvents; } if (BkgShape.bkgOneCB){
std::cout << std::endl; coutInfo("||==============================================||"); coutInfo("|| Fitting the MC to obtain background shape! ||"); coutInfo("||==============================================||"); std::cout << std::endl; if(massFit(year,magnet,Run, true,true,false,PHSP, MC_UseOnlyJpsiEvents, MC_UseOnlyMuMuEvents, false,"NoSig","OneCB",false, KshortDecaysInVelo,UseLowQ2Range, TMVAcut, 0, fixedMassRegion, yieldOverFullRange, false, false, IsEfficiency, sExtraVar, nExtraBin, removeMultiple, weighted, weightedFromPi0, whichWeight, true, customTMbranch, gammaTMdefault, InclusiveSample) == 0){ coutERROR("Fit to MC data did not work out!"); return 0; } } //Now fit the TMed MC
if (false){ //TODO: possibly switch to true
std::cout << std::endl; coutInfo("||==================================================||"); coutInfo("|| Fitting the MVAed data to obtain signal shape! ||"); coutInfo("||==================================================||"); std::cout << std::endl; if(massFit(year,magnet,Run, false, true, false,PHSP, true, false, false, SigType,BkgType, false, KshortDecaysInVelo, UseLowQ2Range, getTMVAcut(RunID), 0, fixedMassRegion, yieldOverFullRange, false, false, IsEfficiency, sExtraVar, nExtraBin, true, false, false, "", false, "", gammaTMdefault, false) == 0){ coutERROR("Fit to MC data did not work out!"); return 0; } } else{ std::cout << std::endl; coutInfo("||===========================================||"); coutInfo("|| Fitting the MC to obtain signal shape! ||"); coutInfo("||===========================================||"); std::cout << std::endl; if(massFit(year,magnet,Run, true,true, true,PHSP, MC_UseOnlyJpsiEvents, MC_UseOnlyMuMuEvents, false,SigType,"NoBckGnd",false, KshortDecaysInVelo, UseLowQ2Range, -1.0, 0, fixedMassRegion, yieldOverFullRange, false, false, IsEfficiency, sExtraVar, nExtraBin, removeMultiple, weighted, weightedFromPi0, whichWeight, false, customTMbranch, gammaTM, InclusiveSample) == 0){ coutERROR("Fit to MC data did not work out!"); return 0; } } std::cout << std::endl; coutInfo("||===========================================||"); coutInfo("|| Apply signal shape and fit data with it! ||"); coutInfo("||===========================================||"); std::cout << std::endl; }
//For now only MC can be weighted
if (weighted && !MC){ coutWarning("For now only weighted MC can be done! Setting weight to false!"); weighted = false; } if (weighted) SumW2Error(kTRUE);
//print info about signal and background shape
coutInfo("Using a " + SigType + " for the Signal shape!"); coutInfo("Using a " + BkgType + " for the Background shape!");
///------------------------------
///Load file
///------------------------------
TChain* tree = new TChain(treeName(MC,Preselected).c_str()); coutInfo("Reading data from TTree... ");
if (TMVAcut != -1 || weightedFromPi0 || removeMultiple) tree = get_BDT_TChain(years, MC, MC && UseOnlyJpsiEvents, PHSP, KshortDecaysInVelo, weightedFromPi0); else if (weighted) tree = get_weighted_TChain(years, MC, UseOnlyJpsiEvents, PHSP, KshortDecaysInVelo); else tree = get_basic_TChain(magnet,years,Preselected,MC,UseOnlyJpsiEvents,PHSP,false, false, InclusiveSample);
if(tree->GetEntries() == 0){ coutERROR("No entries found in TTree. Exit program!"); return 0; } else coutDebug("DONE!");
///------------------------------
/// Set branches
///------------------------------
string B_mass_branch = UseDTF ? (Preselected ? "B_plus_M_DTF" : "B_plus_DTF_M") : ("B_plus_M");
coutDebug("Deactivating all not needed branches.. "); tree->SetBranchStatus("*",0); //activating all needed branches
tree->SetBranchStatus("Q2", 1); tree->SetBranchStatus(B_mass_branch.c_str(),1); string weightBranch = weighted ? getWeightName(customTMbranch,gammaTM) : ""; if (weighted) coutDebug("WeightBranch = " + weightBranch + "."); if (TMVAcut > -1.0) tree->SetBranchStatus(TMVAmethod+"response",1); if (TM || nonTM) tree->SetBranchStatus(customTMbranch.c_str(),1); if (TM || nonTM) tree->SetBranchStatus(gammaTMbranch.c_str(),1); if (TM || nonTM) tree->SetBranchStatus(customTMbranch.c_str(),1); if (randomSubset!=0) tree->SetBranchStatus("RandomSubSet",1); if (Kst2Kspiplus && SplitDDandLL) tree->SetBranchStatus("KshortDecayInVeLo",1); if (weighted) tree->SetBranchStatus(weightBranch.c_str(), 1); if (weightedFromPi0) tree->SetBranchStatus(Form("w_%s",whichWeight.c_str()),1); if (useExtraVar){ for (auto var:extraVar.sBranchName) tree->SetBranchStatus(var.c_str(),1); //add last branch (or the only one)
} if (removeMultiple) tree->SetBranchStatus(getAloneBranch(MC,TM,customTMbranch,gammaTM).c_str(),1);
coutInfo("DONE!");
///------------------------------
///Fill all needed variables in RooDataSet
///------------------------------
coutInfo("Loading the dataset..."); RooRealVar *B_plus_M; B_plus_M = new RooRealVar(B_mass_branch.c_str(), (Kst2Kspiplus ? (UseDTF ? "m(K_{S}^{0}#pi^{+}#mu^{+}#mu^{-})" : "m(#pi^{+}#pi^{-}#pi^{+}#mu^{+}#mu^{-})") : (UseDTF ? "m(K^{+}#pi^{0}#mu^{+}#mu^{-})" : "m(K^{+}#gamma#gamma#mu^{+}#mu^{-})") ), get_cut_B_plus_M_low(year), cut_B_plus_M_high, " MeV/c^{2} ");
//In case we want to change binning, this is really not ideal but oh well
string finalCut = getFinalCut(MC,TM, nonTM, customTMbranch, gammaTM, UseOnlyMuMuEvents, UseOnlyJpsiEvents, SplitInQ2, UseLowQ2Range, useExtraVar, extraVar, nExtraBin, TMVAcut, removeMultiple); if (!Preselected) finalCut = "B_plus_DTF_M >0"; //Dummy
coutDebug("Using cuts " + finalCut);
RooRealVar Q2Bin ("Q2", " ", -0.1e6, 21.1e6," "); RooRealVar TMVAresponse (TMVAmethod+"response", " ", -1.0, 1.0, " "); RooRealVar TMvar (customTMbranch.c_str(), " ", -0.1, 1.1, " "); RooRealVar TMgammaVar (gammaTMbranch.c_str(), " ", -0.1, 6.1, " "); RooRealVar KshortDecayInVeLo("KshortDecayInVeLo", " ", KshortDecaysInVelo ? 0.9 : -0.1, KshortDecaysInVelo ? 1.1 : 0.1," "); RooRealVar RandomSubSet ("RandomSubSet", " ", randomSubset - 0.1, randomSubset + 0.1," ");
const int nExtraVars = extraVar.sBranchName.size(); RooRealVar *RooExtraVars[nExtraVars]; for_indexed (auto var:extraVar.sBranchName){ RooExtraVars[i] = new RooRealVar(var.c_str(), var.c_str(), extraVar.vVarRange.at(i).at(0), extraVar.vVarRange.at(i).at(1)," "); coutDebug("Var: " + string(var.c_str())); coutDebug("Range: " + to_string(extraVar.vVarRange.at(i).at(0)) + " to " + to_string(extraVar.vVarRange.at(i).at(1))); }
RooRealVar IsAlone (getAloneBranch(MC,TM,customTMbranch,gammaTM).c_str(), " ", -1.0, 2.0, " ");
RooRealVar *FinalWeight; if (weighted && weightedFromPi0){ //TODO: the question is if this works, test it at some point!
FinalWeight = new RooRealVar("weight","weight",-10.0,10.0,""); double w; double w_pi0; tree->SetBranchAddress(weightBranch.c_str(),&w); tree->SetBranchAddress(Form("w_%s",whichWeight.c_str()),&w_pi0); for (int e = 0; e<tree->GetEntries();e++){ tree->GetEntry(e); FinalWeight->setVal(w*w_pi0); } } else if (weighted){ FinalWeight = new RooRealVar(weightBranch.c_str(), weightBranch.c_str(), -10.0, 10.0," "); } else if (weightedFromPi0){ FinalWeight = new RooRealVar(Form("w_%s",whichWeight.c_str()), Form("w_%s",whichWeight.c_str()), 0.0, 10.0," "); }
RooArgSet argSet = RooArgSet(*B_plus_M);
argSet.add(Q2Bin); if (TM||nonTM) argSet.add(TMvar); if (TM||nonTM) argSet.add(TMgammaVar); if (useExtraVar) for(int i = 0; i < nExtraVars;i++) argSet.add(*RooExtraVars[i]); if (TMVAcut > -1.0) argSet.add(TMVAresponse); if (randomSubset) argSet.add(RandomSubSet); if (SplitDDandLL&&Kst2Kspiplus) argSet.add(KshortDecayInVeLo); if (removeMultiple) argSet.add(IsAlone); if (weighted||weightedFromPi0) argSet.add(*FinalWeight);
RooDataSet* data= NULL;
if (weighted||weightedFromPi0) data = new RooDataSet("data","data",argSet,Import(*tree),Cut(finalCut.c_str()), WeightVar(*FinalWeight)); else data = new RooDataSet("data","data",argSet,Import(*tree),Cut(finalCut.c_str()));
coutInfo(" DONE!"); if (verboseLevel < 3) data->Print(); coutDebug("Using weighted events? " + to_string (data->isWeighted())); coutDebug("The dataset contains " + to_string(data->numEntries()) + " events!");
///------------------------------
///Build the B+ mass signal shape
///------------------------------
gROOT->ProcessLine(".L ./RooFit/RooDoubleCB/RooDoubleCB_cpp.so"); gROOT->ProcessLine(".L ./GlobalFunctions.hh"); //This is very weird, but it works ¯\_(ツ)_/¯
coutInfo("Setting signal fit parameters ... ");
//set mean of B_plus mass peak
RooRealVar* meanBplus = SigShape.getRooRealVar("mean",true);
///------------------------------
///Yields and Background + Signal Fit-Model
///------------------------------
//yields
coutDebug("The dataset has " + to_string(data->numEntries()) + " entries!"); RooRealVar N_Bplus("N_Bplus", "#B^{+}", data->numEntries()/2., 0., 2*data->numEntries()); RooRealVar N_comb("N_comb","N_comb", data->numEntries()/2., 0., 2*data->numEntries());
//Create the signal PDF
//Check if one selected any sigPdf and bkgPdf
if (SigShape.NoSig && BkgShape.NoBackground){ coutERROR("No fit model was selected. Abort."); return 0; }
coutDebug("Creating BplusMassModel..."); RooAddPdf *BplusMassModel = NULL; if (!SigShape.NoSig) BplusMassModel = SigShape.getBplusMassModel(B_plus_M,meanBplus, UseOnlyJpsiEvents);
coutInfo("Signal PDF is created!");
if (!SigShape.NoSig){ coutInfo("Constraints PDF:"); SigShape.ConsPDF->Print(); } coutDebug("Creating BplusBckGndModel...");
///Build the B+ mass background model
RooAddPdf * BplusBckGndModel = NULL; if (!BkgShape.NoBackground) BplusBckGndModel = BkgShape.getBplusBkgModel(B_plus_M); coutInfo("Background PDF is created!");
//add all required pdfs
RooAbsPdf* pdf = NULL; if (BkgShape.NoBackground){ //Create the signal PDF
pdf = new RooAddPdf("pdf", "pdf", RooArgList(*BplusMassModel), RooArgList(N_Bplus)); } else{ if (SigShape.NoSig) pdf = new RooAddPdf("pdf", "pdf", RooArgList(*BplusBckGndModel), RooArgList(N_comb)); else pdf = new RooAddPdf("pdf", "pdf", RooArgList(*BplusMassModel, *BplusBckGndModel), RooArgList(N_Bplus, N_comb)); } if (verboseLevel<2) pdf->Print();
///Gaussian Constraint to MC values
if (!SigShape.AtLeastOneConstrainFound) coutDebug("No parameters in signal costrained."); if (!BkgShape.AtLeastOneConstrainFound) coutDebug("No parameters in background costrained.");
///------------------------------
///Fit
///------------------------------
RooFitResult *result = new RooFitResult("FitResult","FitResult");
//Add constrained PDFs
if (SigShape.AtLeastOneConstrainFound || BkgShape.AtLeastOneConstrainFound){ RooArgSet *constrPdfs; if (SigShape.AtLeastOneConstrainFound) constrPdfs = new RooArgSet(*SigShape.ConsPDF); if (BkgShape.AtLeastOneConstrainFound) constrPdfs = new RooArgSet(*BkgShape.BkgConsPDF);
RooProdPdf *FitPDF_constraint = new RooProdPdf("FitPDF_constraint","FitPDF_constraint",RooArgSet(*pdf,*constrPdfs));
if (!IsEfficiency){ coutDebug("Constrained parameters are:" ); SigShape.ConsParameter->Print(); coutDebug("The following PDF is fitted to the data:" ); FitPDF_constraint->Print(); coutDebug("Start the fit with constrains! " ); } result = FitPDF_constraint->fitTo(*data,Save(kTRUE),Extended(kTRUE),NumCPU(3),Constrain(*constrPdfs),PrintLevel(printLevel),SumW2Error(weighted ? kTRUE : kFALSE)); delete FitPDF_constraint; } else{ coutDebug("The following PDF is fitted to the data:" ); if (verboseLevel<2) pdf->Print(); coutDebug("Start the fit! " ); result = pdf->fitTo(*data,Save(kTRUE),Extended(kTRUE),NumCPU(3),PrintLevel(printLevel),SumW2Error(weighted ? kTRUE : kFALSE)); }
coutDebug("The fit result is --------------- " ); if (verboseLevel<2) result->Print();
//Saving the results in case of constrianing to MC
SigShape.setValuesAndErrors(true); BkgShape.setValuesAndErrors(false);
///------------------------------
///calculate # (signal)background events in signal region
///------------------------------
coutDebug("The effective sigma is: " + to_string(SigShape.getEffSigmaFromResult())); if (fixedMassRegion) B_plus_M->setRange("SigRange",meanBplus->getVal() - B_plus_M_signal_window, meanBplus->getVal() + B_plus_M_signal_window ); else B_plus_M->setRange("SigRange",meanBplus->getVal() - SignalRegionNsigma * SignalFitParameter.SigmaEff, meanBplus->getVal() + SignalRegionNsigma * SignalFitParameter.SigmaEff);
coutInfo("Determining the signal and background yield");
//Get signal yield
RooAbsReal* S_fr = NULL; Double_t S = 0.0, S_error_test = 0.0, S_error = 0.0; if (!SigShape.NoSig){ S_fr = BplusMassModel->createIntegral(*B_plus_M,NormSet(*B_plus_M),Range("SigRange")); S = S_fr->getVal() * N_Bplus.getVal(); S_error_test = S_fr->getPropagatedError(*result) * N_Bplus.getVal(); S_error = S_fr->getVal() *N_Bplus.getError(); }
//Get background yield
RooAbsReal* B_fr = nullptr; Double_t B = 0.0, B_error = 0.0, B_error_test = 0.0; if(!BkgShape.NoBackground){ B_fr = BplusBckGndModel->createIntegral(*B_plus_M,NormSet(*B_plus_M),Range("SigRange")); B = B_fr->getVal() * N_comb.getVal(); B_error_test = B_fr->getPropagatedError(*result) * N_comb.getVal(); B_error = B_fr->getVal() * N_comb.getError(); //B * (N_comb.getError()/N_comb.getVal());
}
coutInfo("S/sqrt(S+B)= " + to_string(S/sqrt(S+B))); if(B != 0.)coutInfo("S/B= " + to_string(S/B)); coutInfo("S= " + to_string(S)+ "+-" + to_string(S_error));//+ "/+-" + to_string(S_error_test));
coutInfo("B= " + to_string(B)+ "+-" + to_string(B_error));//+ "/+-" + to_string(B_error_test));
cout << endl << endl;
///------------------------------
///Plot the models with indidivual components
///------------------------------
//configurables for plotting
Float_t pullHeight = 0.32; Int_t Bins = 100; if (UseOnlyMuMuEvents && Preselected && !MC) Bins = useExtraVar ? 30 : 50;
//create two pads into one canvas
TCanvas* c1= new TCanvas(""); TPad *pad1 = new TPad("pad1", "plot",0.0,pullHeight,1.0,1.0,0); TPad *pad2 = new TPad("pad2", "pull",0.0,0.0,1.0,pullHeight,0); pad1->Draw(); pad2->Draw();
//modifiy pad for main plot
pad1->SetBorderSize (0); pad1->SetBottomMargin(1e-6); pad1->SetTopMargin(pad1->GetTopMargin() / pullHeight * ( 1 - pullHeight) ); pad1->cd(); RooPlot* frame_m = B_plus_M->frame();
//some axis-modifications on the main plot
TGaxis::SetExponentOffset(1e+9,1e+9,"y");//offset = pad size * 1e+7
//make the frame pretty
designMassFitFrame(frame_m, pullHeight);
data->plotOn(frame_m,Name("data"),MarkerSize(0.5),Binning(Bins),DataError(RooAbsData::SumW2)); pdf->plotOn(frame_m,Name("pdf"),LineColor(kBlack),LineWidth(2));
if (!SigShape.NoSig) pdf->plotOn(frame_m,Components("BplusMassModel"),LineColor(kBlue),LineStyle(kDashed),LineWidth(1)); if (!BkgShape.NoBackground){pdf->plotOn(frame_m,Components("BplusBckGndModel"),LineColor(kRed),LineStyle(kDashed),LineWidth(1)); //in case you want to plot ExpGaus
//pdf->plotOn(frame_m,Components("bkg_exp1"),LineColor(kRed),LineStyle(kDashed),LineWidth(1));
//pdf->plotOn(frame_m,Components("ExpG"),LineColor(kRed),LineStyle(kDashed),LineWidth(1));
}
//Plot the pdf and the box with fit results into the frame
data->plotOn(frame_m,Name("data"),MarkerSize(0.5),Binning(Bins)); //pdf->paramOn(frame_m, Format("NEU",AutoPrecision(1)));
pdf->paramOn(frame_m, ShowConstants(kTRUE), Format("NEU",AutoPrecision(2)), Layout(0.65, 0.95, 0.88));
frame_m->Draw(); c1->Update();
// TODO: Add a box with constrained parameters posibly
//signal/background yield
Float_t posX = MC ? 0.40 : 0.41, posY = 0.84; if(Kst2Kspiplus) posX = 0.34; TLatex* fitresult = new TLatex(); fitresult->SetTextFont(132); fitresult->SetTextColor(1); fitresult->SetTextSize(0.04); fitresult->SetTextAlign(13); fitresult->SetNDC(1);
//TODO
if (!SigShape.NoSig) fitresult->DrawLatex(posX, posY - 0.08, Form("Signal: %.0f #pm %.0f", S, S_error)); //Signal defined by N sigma around peak mean value or in the mass window, depends on bool fixedMassRegion and B_plus_M_signal_window
if(!BkgShape.NoBackground) fitresult->DrawLatex(posX, posY - 0.13, Form("Background: %.0f #pm %.0f", B, B_error)); frame_m->addObject(fitresult) ; frame_m->Draw("SAME"); if (MC) addLHCbtag(posX, 0.82, "simulation", 1./(1. - pullHeight)); else addLHCbtag(posX, 0.82, "data", 1./(1. - pullHeight));
//create pull histogram
pad2->Clear(); pad2->SetTopMargin(1e-6); pad2->SetBottomMargin(pad2->GetBottomMargin() / pullHeight ); pad2->cd();
//Design pull histogram
RooPlot* pullFrame = B_plus_M->frame(); designPullFrame(pullFrame,frame_m,pullHeight);
//Add two 3-sigma lines:
TLine * lUp = threeSigmaLine(true); TLine * lLow = threeSigmaLine(false); pullFrame->addObject(lUp); pullFrame->addObject(lLow);
//Draw the pull
pullFrame->Draw() ;
//choose path to save files //TODO: check
string filePath = ""; if (IsEfficiency) filePath = GetEfficiencyMassFitFile(year, magnet, Run, Preselected, TM, PHSP, UseOnlyJpsiEvents, UseOnlyMuMuEvents, GetShapeFromMC, SigType, BkgType, ConstrainParameters, KshortDecaysInVelo, UseLowQ2Range, TMVAcut, fixedMassRegion, sExtraVar, nExtraBin, removeMultiple, weighted, weightedFromPi0, whichWeight, customTMbranch, gammaTM); else filePath = GetMassFitFile(year,magnet,Run,MC,Preselected,TM,PHSP,UseOnlyJpsiEvents,UseOnlyMuMuEvents, GetShapeFromMC, SigType, BkgType, ConstrainParameters, KshortDecaysInVelo, UseLowQ2Range, TMVAcut, randomSubset, fixedMassRegion, yieldOverFullRange, sExtraVar, nExtraBin,removeMultiple, weighted, weightedFromPi0, whichWeight, nonTM, customTMbranch, gammaTM, InclusiveSample);
coutDebug("Saving into file "+ filePath); TFile *fitFile = new TFile(filePath.c_str(),"RECREATE"); //save canvas to pdf and root format
coutInfo("Writting signal and background pdfs into the file " + filePath + ".");
fitFile->cd(); result->Write(); c1->Write();
//Save Signal yield, background yield and it's error
TVectorD yield(1); yield[0] = S; yield.Write("yield");
TVectorD yield_err(1); yield_err[0] = S_error; yield_err.Write("yield_err");
TVectorD B_vec(1); B_vec[0] = B; B_vec.Write("background");
TVectorD B_vec_err(1); B_vec_err[0] = B_error; B_vec_err.Write("background_err");
TVectorD sigma_eff(1); sigma_eff[0] = SignalFitParameter.SigmaEff; sigma_eff.Write("sigma_eff");
fitFile->Close(); coutDebug("File " + filePath + " closed." );
//Plot the fit
replace(filePath,".root",".eps"); coutInfo("Plotting into " + filePath + "."); c1->Print(filePath.c_str());
if(sWeight){
if (BkgType == "NoBckGnd"){ //It crashes here if no background is selected
coutERROR("No background selected! Splot needs SingleExponential, DoubleExponential or ExpGauss."); return 0; }
meanBplus->setConstant(); SigShape.setAllRooVarsConstant(); BkgShape.setAllRooVarsConstant();
SPlot* sData = new SPlot("sData","An SPlot",*data,pdf,RooArgList(N_Bplus, N_comb)); ///Plot the sWeight distributions as a function of mass
TCanvas* SwBplus = new TCanvas("Bplus sWeight","Bplus sWeight distribution"); TH2 * SwBplusHist; SwBplusHist = (TH2*)data->createHistogram((UseDTF ? "B_plus_M_DTF,N_Bplus_sw" : "B_plus_M,N_Bplus_sw")); SwBplusHist->GetYaxis()->SetTitle("Signal sWeights"); SwBplusHist->SetTitle(""); //SwBplus->Write("",TObject::kWriteDelete);
SwBplusHist->Draw(); addLHCbtag(0.65, 0.85, "data", 1);
filePath = GetsWeightPlots(year, UseOnlyJpsiEvents,UseOnlyMuMuEvents, KshortDecaysInVelo,GetShapeFromMC,SigType,BkgType,ConstrainParameters); SwBplus->SaveAs(filePath.c_str()); replace(filePath,".root",".eps"); SwBplus->Print(filePath.c_str());
///Create output file
TFile* output = nullptr; output = new TFile(GetBDTinputFile(year,false,UseOnlyJpsiEvents,PHSP,KshortDecaysInVelo).c_str() ,"RECREATE"); if(!output->IsOpen()){ coutERROR("Could not create output file. Abort!"); return 0; }
output->cd();
tree->SetBranchStatus("*",1); coutInfo("Copy Tree... " ); TTree * new_tree = nullptr; string sVariable = (UseDTF ? "B_plus_M_DTF" : "B_plus_M"); string q2Cut = ""; if (UseOnlyJpsiEvents) //If for OnlyMuMu not needed so far //TODO
q2Cut = "&& " + getJpsicut(); if (SplitInQ2){ if (UseLowQ2Range) q2Cut = "&& Q2 < 8.68e6"; else q2Cut = "&& 10.09e6 < Q2"; } //no use of saving only mumu data
if(Kst2Kspiplus && SplitDDandLL){ new_tree = tree->CopyTree(Form("%s >= %f && %s <= %f %s && KshortDecayInVeLo==%i", sVariable.c_str(), get_cut_B_plus_M_low(year), sVariable.c_str(), cut_B_plus_M_high, q2Cut.c_str(), KshortDecaysInVelo)); } else{ new_tree = tree->CopyTree(Form("%s >= %f && %s <= %f %s", sVariable.c_str(), get_cut_B_plus_M_low(year), sVariable.c_str(), cut_B_plus_M_high, q2Cut.c_str())); } coutDebug("Finished!" ); double w; TBranch* Bra_sw = new_tree->Branch("N_Bplus_sw", &w, "N_Bplus_sw/D");
///loop over events
int numEvents = new_tree->GetEntries();
coutDebug("Entries in TTree:\t"+ to_string(numEvents) ); coutDebug("Entries in RooDataSet:\t"+to_string(data->numEntries()));
if(numEvents != data->numEntries()){ coutERROR("Number of weights not equal to number of events"); return 0; }
coutDebug("Loop over data sample " + year + TheDecay + " to save sWeights from mass fit results!" ); for(int i = 0; i < numEvents; i++){ if ((0ul == (i % 10000ul) || i + 1 == numEvents) && i != 0) coutInfo("Read event " + to_string(i) + "/" + to_string(numEvents)); tree->GetEntry(i); w = sData->GetSWeight(i,"N_Bplus_sw"); Bra_sw->Fill(); } coutInfo("Loop finished!!!"); output->cd(); new_tree->Write("",TObject::kWriteDelete);
delete new_tree;
output->Close();
delete SwBplus; delete SwBplusHist; delete sData; }
if (S < 0.1) S = 0.01; //protect zeroes from happening
delete frame_m; delete tree; delete result;
coutInfo("Mass fit is done."); return S; }
int quickFit(string year, bool MC, bool sWeight, bool UseOnlyJpsiEvents, bool UseOnlyMuMuEvents, bool KshortDecaysInVelo, bool GetShapeFromMC, string SigType, string BkgType, bool ConstrainParameters){
return massFit(year,"both", 0, MC, true, MC, false, UseOnlyJpsiEvents, UseOnlyMuMuEvents, GetShapeFromMC,SigType,BkgType,ConstrainParameters, KshortDecaysInVelo,false, -1.0, 0, false, false, sWeight, false, false, "",-1, false, false, false, "", false, "", false, false); }
int quickTest(bool gammaTM = false, string customTMbranch = "TMed"){ setVerboseLevel(1); return massFit("2015","both", 0, false, true, true, false, false, false, true,"OneCB","SingleExponential",true, false,false, -1.0, 0, false, false, false, false, false, "",-1,false, true, false, "",false, customTMbranch, gammaTM, false); }
int testOneCbBackground(bool MC = false, string SigType = "OneCB", string BkgType = "SingleExponentialOneCB", string customTMbranch = "", bool gammaTM = false){ setVerboseLevel(1); return massFit("2016","both",0, false, true, true, false, !MC, false, true,SigType,BkgType,true, false, false, -1.0, 0, true, false, false, false, false, "",-1, false, false, false, "", false, customTMbranch, gammaTM, false); }
int efficiencyFit(string year = "2011", string magnet = "down", int Run = 0, bool Preselected = true, bool TM = true, bool PHSP = false, //input/output file selection
bool UseOnlyJpsiEvents = false, bool UseOnlyMuMuEvents = false, //signal/reference
bool GetShapeFromMC = false, string SigType = "OneCB", string BkgType = "SingleExponential", bool ConstrainParameters = false, //shape
bool KshortDecaysInVelo = Kst2Kspiplus, //LL/DD?
Double_t TMVAcut = -1.0, //TMVA options
bool fixedMassRegion = !Kst2Kspiplus, //yield calculation region
bool UseLowQ2Range =false, //q2 ranges
string sExtraVar = "", int nExtraBin = -1,bool removeMultiple = false, bool weighted = false, bool weightedFromPi0 = false, string whichWeight = "", //fit in bins of extra variable
string customTMbranch = "", bool gammaTM = false ){
return massFit(year,magnet,Run, true, Preselected, TM, PHSP, UseOnlyJpsiEvents, UseOnlyMuMuEvents, GetShapeFromMC,SigType,BkgType,ConstrainParameters, KshortDecaysInVelo, UseLowQ2Range, TMVAcut, 0, fixedMassRegion, false, false, false, true, sExtraVar, nExtraBin, removeMultiple, weighted, weightedFromPi0,whichWeight, false, customTMbranch, gammaTM, false ); }
int basicYieldFit(string year, int Run, bool MC, bool PHSP, //input/output file selection
bool UseOnlyJpsiEvents, bool UseOnlyMuMuEvents, //signal/reference
bool GetShapeFromMC, string SigType, string BkgType, bool ConstrainParameters, //shape
bool KshortDecaysInVelo, bool UseLowQ2Range, //LL/DD? q2range?
Double_t TMVAcut, //TMVA options
bool fixedMassRegion, bool loopFit,//yield calculation region
bool removeMultiple //remove multiple candidates
){ //TODO: shape from MC if TMVA cut?
return massFit(year,"both",Run, MC, true, MC, PHSP,//if MC then truthMatched
UseOnlyJpsiEvents, UseOnlyMuMuEvents, GetShapeFromMC,SigType,BkgType,ConstrainParameters, KshortDecaysInVelo, UseLowQ2Range, TMVAcut, 0, fixedMassRegion, false, false, loopFit, false, "", -1, removeMultiple, true, false, "", //weighted=true only for MC, but also data then takes the shape from MC that is weighted
false, "", gammaTMdefault, false); }
int basicYieldFitAllYears(//Fits all years separately
bool MC = true, bool PHSP = false, //input/output file selection
bool UseOnlyJpsiEvents = false, bool UseOnlyMuMuEvents = false, //signal/reference
bool GetShapeFromMC = false, string SigType = "OneCB", string BkgType = "SingleExponential", bool ConstrainParameters = false, //shape
bool KshortDecaysInVelo = Kst2Kspiplus, bool UseLowQ2Range =false, //LL/DD? q2range?
Double_t TMVAcut = -1.0, //TMVA options
bool fixedMassRegion = !Kst2Kspiplus, bool loopFit = false, //yield calculation region
bool removeMultiple = false //remove multiple candidates
){ for(auto &y : yearsVector(MC,UseOnlyJpsiEvents,false, 12)){ if (basicYieldFit(y,0, MC, PHSP, UseOnlyJpsiEvents,UseOnlyMuMuEvents,GetShapeFromMC, SigType, BkgType, ConstrainParameters, KshortDecaysInVelo,UseLowQ2Range,TMVAcut, fixedMassRegion,loopFit, removeMultiple) ==0) return 0; } return 1; }
int basicFitAllYearsAndRegions(bool MC = true, bool PHSP = false, //input/output file selection
bool GetShapeFromMC = false, string SigType = "OneCB", string BkgType = "SingleExponential", bool ConstrainParameters = false, //shape
bool KshortDecaysInVelo = Kst2Kspiplus, bool UseLowQ2Range =false, //LL/DD? q2range?
Double_t TMVAcut = -1.0, bool removeMultiple = false //TMVA options
){
vector <bool> UseOnlyJpsiEvents = {true,false}; vector <bool> UseOnlyMuMuEvents = {true,false}; vector <bool> fixedMassRegion = {true,false}; for(auto const&jpsi: UseOnlyJpsiEvents){ for(auto const&mumu: UseOnlyMuMuEvents){ for(auto const&fixedWindow: fixedMassRegion){ if (basicYieldFitAllYears(MC,PHSP, jpsi,mumu,GetShapeFromMC, SigType, BkgType, ConstrainParameters, KshortDecaysInVelo,UseLowQ2Range,TMVAcut, fixedWindow,false,removeMultiple)==0) return 0; } } }
return 1; }
int getYieldBasicOptionsMC(bool TM, string year, int Run, bool ReferenceChannel, bool PHSP, bool removeMultiple){ string bkg = TM ? "NoBckGnd" : "SingleExponential"; bool useJpsiOnly = ReferenceChannel; bool useMuMuOnly = !PHSP && !ReferenceChannel; bool weighted = false; return massFit(year,"both",Run, true, true, TM, PHSP, useJpsiOnly, useMuMuOnly, false, "OneCB",bkg,false, false, false, -1.0, 0, true, false, false, false, false, "", -1, removeMultiple, weighted, false, "", //weighted=true only for MC, but also data then takes the shape from MC that is weighted
false, "", gammaTMdefault, false); }
int getYieldBasicOptionsMCAllYears(bool TM, bool ReferenceChannel, bool PHSP, bool removeMultiple){ for (auto year: yearsMC(ReferenceChannel,PHSP,12)){ if (getYieldBasicOptionsMC(TM, year, 0, ReferenceChannel, PHSP, removeMultiple)==0) return 0; } if (getYieldBasicOptionsMC(TM, "2011", 1, ReferenceChannel, PHSP, removeMultiple) == 0) return 0; if (getYieldBasicOptionsMC(TM, "2015", 2, ReferenceChannel, PHSP, removeMultiple) == 0) return 0; return 1; }
int getYieldAllYearsBasicOptions(bool TM, bool removeMultiple){ if (getYieldBasicOptionsMCAllYears(TM,false,false, removeMultiple)==0) return 0; if (getYieldBasicOptionsMCAllYears(TM,true ,false, removeMultiple)==0) return 0; if (getYieldBasicOptionsMCAllYears(TM,false,true, removeMultiple)==0) return 0; //if (basicYieldFitAllYears(false, false, true, false, true, "OneCB", "SingleExponential", true,
// false, false, -1, true,false,true)==0) return 0;
//if (basicYieldFitAllYears(false, false, false, true, true, "OneCB", "SingleExponential", true,
// false, false, -1, true,false,true)==0) return 0;
return 1; }
int basicYieldFitAllRuns( //Fits data per year
bool MC = true, bool PHSP = false, //input/output file selection
bool UseOnlyJpsiEvents = false, bool UseOnlyMuMuEvents = false, //signal/reference
bool GetShapeFromMC = false, string SigType = "OneCB", string BkgType = "SingleExponential", bool ConstrainParameters = false, //shape
bool KshortDecaysInVelo = Kst2Kspiplus, bool UseLowQ2Range =false, //LL/DD? q2range?
Double_t TMVAcut = -1.0, //TMVA options
bool fixedMassRegion = !Kst2Kspiplus, bool loopFit = false,//yield calculation region
bool removeMultiple = false //remove multiple candidates
){
if ( basicYieldFit("2011",1, MC, PHSP, UseOnlyJpsiEvents,UseOnlyMuMuEvents,GetShapeFromMC, SigType, BkgType, ConstrainParameters, KshortDecaysInVelo,UseLowQ2Range,TMVAcut, fixedMassRegion,loopFit,removeMultiple)==0) return 0; if ( basicYieldFit("2015",2, MC, PHSP,UseOnlyJpsiEvents,UseOnlyMuMuEvents,GetShapeFromMC, SigType, BkgType, ConstrainParameters, KshortDecaysInVelo,UseLowQ2Range,TMVAcut, fixedMassRegion,loopFit,removeMultiple)==0) return 0; return 1; }
int massFitTestAll(bool GetShapeFromMC = true, bool ConstrainParameters = false, int Run = 1){
bool KshortDecaysInVelo= false; bool UseLowQ2Range = false; bool TM = false; bool MC = true; bool UseOnlyJpsiEvents = false; bool UseOnlyMuMuEvents = false; bool UseFixedMassRegion = false; bool yieldOverFullRange = false;
std::vector<string> years = yearsData(Run); std::vector<string> signalShape = {//"SingleGaussian",
"DoubleGaussian", //"CBLeft",
//"CBRight",
"CBDouble" };
std::vector<string> backgroundShape = {//"SingleExponential",
"DoubleExponential", "ExpGaus" };
std::vector<string> polarity = { //"down",
//"up",
"both" };
for (auto& y: years){ for (auto& sig: signalShape){ for (auto& bkg: backgroundShape){ for (auto& magnet: polarity){ if(massFit(y, magnet, 0, MC, true, TM, false,UseOnlyJpsiEvents, UseOnlyMuMuEvents, GetShapeFromMC, sig, bkg, ConstrainParameters, KshortDecaysInVelo, UseLowQ2Range, -1.0, false, UseFixedMassRegion,yieldOverFullRange,false, false, false, "", -1,false, false, false, "",false,"",false,false) == 0)return 0; } } } } return 1; }
//check distributions in q2
int massFitTestQ2All(int Run, bool PHSP, bool UseOnlyMuMuEvents, bool UseOnlyJpsiEvents){
bool KshortDecaysInVelo= false; bool UseLowQ2Range = false;
bool UseFixedMassRegion = false; bool yieldOverFullRange = false;
bool removeMultiple = false; bool weighted = PHSP;
string signalShape = "OneCB"; string backgroundShape = "ExpGaus";
for (int n = 4; n < 5; n++){ if(massFit("2011", "both", Run, PHSP, true, PHSP, PHSP, UseOnlyJpsiEvents, UseOnlyMuMuEvents, true, signalShape, backgroundShape, true, KshortDecaysInVelo, UseLowQ2Range, -1.0, false, UseFixedMassRegion,yieldOverFullRange, false, false, false, "q2_binned", n, removeMultiple, weighted, false, "",false, "",gammaTMdefault,false) == 0)return 0; } return 1; }
//Print efficiencies and fit parameters
int PrintFitResults(RooFitResult* fitRes){ RooArgSet fitargs = fitRes->floatParsFinal(); if (fitargs.getSize() <=0){ coutERROR("RooArgSet size is zero/nonDef!"); return 0; } TIterator* iter(fitargs.createIterator()); cout << " ======= results ====== " << endl; for (TObject *a = iter->Next(); a != 0; a = iter->Next()) { RooRealVar *rrv = dynamic_cast<RooRealVar *>(a); string name = rrv->GetName(); cout<< name << ": " << rrv->getVal() <<" +/- "<<rrv->getError() << endl; }
return 1; }
int fitJpsi(string year, int Run, bool MC, double TMVAcut, bool RemoveMultiple){ return massFit(year,"both", Run, MC, true, MC, false, true, false, !MC, "OneCB", "SingleExponential", true, false,false, TMVAcut, 0, false, false, false, false, false, "",-1, RemoveMultiple, false, false, "", false, "", gammaTMdefault, false); }
|