637 lines
30 KiB
C++
637 lines
30 KiB
C++
|
//Functions that calculate/fit the yield for given MVA response cut
|
||
|
//and make pretty plots from it
|
||
|
//Renata Kopecna
|
||
|
|
||
|
#include "GlobalFunctions.hh"
|
||
|
#include "Paths.hpp"
|
||
|
#include "MassFit.hpp"
|
||
|
#include "Utils.hpp"
|
||
|
#include "./BmassShape/SignalType.hpp"
|
||
|
#include "EfficiencyClass.cpp"
|
||
|
|
||
|
|
||
|
using namespace std;
|
||
|
using namespace RooFit;
|
||
|
using namespace RooStats;
|
||
|
|
||
|
class YieldInfo{
|
||
|
public:
|
||
|
string year;
|
||
|
double sigYield;
|
||
|
double sigYieldErr;
|
||
|
double refYield;
|
||
|
double refYieldErr;
|
||
|
double bkgYield;
|
||
|
double bkgYieldErr;
|
||
|
double sigEff;
|
||
|
double refEff;
|
||
|
double allSigEvts;
|
||
|
YieldInfo(){ //default constructor
|
||
|
year = "";
|
||
|
sigYield = 0;
|
||
|
sigYieldErr = 0;
|
||
|
refYield = 0;
|
||
|
refYieldErr = 0;
|
||
|
bkgYield = 0;
|
||
|
bkgYieldErr = 0;
|
||
|
sigEff = 0;
|
||
|
refEff = 0;
|
||
|
allSigEvts = 0;
|
||
|
}
|
||
|
void addYield(YieldInfo addInfo){
|
||
|
sigYield += addInfo.sigYield;
|
||
|
sigYieldErr += addInfo.sigYieldErr;
|
||
|
refYield += addInfo.refYield;
|
||
|
refYieldErr += addInfo.refYieldErr;
|
||
|
bkgYield += addInfo.bkgYield;
|
||
|
bkgYieldErr += addInfo.bkgYieldErr;
|
||
|
sigEff += addInfo.sigEff; //this doesn't make much sense
|
||
|
refEff += addInfo.refEff; //this doesn't make much sense
|
||
|
allSigEvts += addInfo.allSigEvts;
|
||
|
}
|
||
|
|
||
|
~YieldInfo(); //destuctor
|
||
|
};
|
||
|
|
||
|
YieldInfo::~YieldInfo(){//destuctor
|
||
|
|
||
|
}
|
||
|
|
||
|
bool FixShape = true;
|
||
|
|
||
|
bool RemoveMultiple = true; //For now use as a global boolean
|
||
|
|
||
|
//Function that takes upper mass sideband histogram and fits it with an exponential
|
||
|
//Using a Tree, starting the upper mass sideband from range+PDGMASS.Bplus and possibly cutting away stuff defined by cut
|
||
|
double GetBackgroundFromSidebandFit(TChain *Tree, double range, string cut, string path){
|
||
|
|
||
|
TString massBranch = UseDTF ? "B_plus_M" : "B_plus_DTF_M";
|
||
|
bool savePlots = true;
|
||
|
|
||
|
//Fill histogram from Tree
|
||
|
int nBins = 50;
|
||
|
TH1D *h_B_mass = new TH1D("h_B_mass","h_B_mass",nBins,PDGMASS.B_PLUS + range, cut_B_plus_M_high);
|
||
|
double binWidth = (cut_B_plus_M_high - PDGMASS.B_PLUS - range)/nBins;
|
||
|
Tree->Draw(massBranch+" >> h_B_mass",cut.c_str());
|
||
|
|
||
|
//Define fit function
|
||
|
TF1 *f_bkg = new TF1("f_bkg","expo",cut_B_plus_M_low,cut_B_plus_M_high);
|
||
|
design_function(f_bkg,kRed,1);
|
||
|
|
||
|
//Fit
|
||
|
h_B_mass->Fit(f_bkg,"Q","", PDGMASS.B_PLUS + range,cut_B_plus_M_high); //exponential is f(x) = exp(p0+p1*x)
|
||
|
double integral = f_bkg->Integral(PDGMASS.B_PLUS-range,PDGMASS.B_PLUS+range)/binWidth;
|
||
|
|
||
|
//Save the plots
|
||
|
if (savePlots){
|
||
|
string name = path.substr(path.find("/Kplus")+6,path.length());
|
||
|
//Create canvas
|
||
|
TCanvas *c = c_canvas(name);
|
||
|
c->cd();
|
||
|
design_TH1D(h_B_mass,"B^{+} mass [MeV]","Counts a.u.", kBlack);
|
||
|
h_B_mass->GetYaxis()->SetTitleOffset(1.05);
|
||
|
h_B_mass->Draw();
|
||
|
//Create TPaveText
|
||
|
TPaveText *fitParams= new TPaveText(0.6,0.7,0.87,0.9,"NDC");
|
||
|
fitParams->SetFillColor(kWhite);
|
||
|
fitParams->AddText(Form("Offset : %.2f ", f_bkg->GetParameter(0)));
|
||
|
fitParams->AddText(Form("Exp: %.2f%%", f_bkg->GetParameter(1)*100));
|
||
|
fitParams->AddText(Form("Integral: %.2f ", integral));
|
||
|
fitParams->Draw("SAME");
|
||
|
|
||
|
//Create file
|
||
|
TFile *fitFile = new TFile(path.c_str(),"RECREATE");
|
||
|
coutDebug("Opening " + string(fitFile->GetPath()));
|
||
|
fitFile->cd();
|
||
|
h_B_mass->Write();
|
||
|
f_bkg->Write();
|
||
|
c->Write();
|
||
|
replace(path,".root",".eps");
|
||
|
c->SaveAs(path.c_str(), ".eps");
|
||
|
fitFile->Close();
|
||
|
}
|
||
|
//return the integral
|
||
|
h_B_mass->Clear();
|
||
|
return integral;
|
||
|
|
||
|
}
|
||
|
|
||
|
double GetMVAefficiency(string year, int Run, bool KshortDecaysInVelo,
|
||
|
bool UseLowQ2Range, bool IncludeMultipleEff, bool sig, double TMVAcut){
|
||
|
//Load the efficiencies
|
||
|
coutDebug("Openning MVA efficiency files.");
|
||
|
string path = GetEfficiencyFile("BDT", year, "both", Run, !sig, sig, false, KshortDecaysInVelo, IncludeMultipleEff, true, UseLowQ2Range, false,"");
|
||
|
|
||
|
if (Run == 0 && std::stoi(year) > 2016 && !sig) replace(path,year,"2016"); //RefChann available for 2015-2016
|
||
|
if (Run == 0 && year=="2015" && sig) replace(path,year,"2016"); //No reasonable MC for 2015
|
||
|
|
||
|
coutDebug("Openning file: " + path);
|
||
|
TFile * effFile = new TFile(path.c_str(), "OPEN");
|
||
|
|
||
|
//Get the TGraphs
|
||
|
coutDebug("File opened, getting the graphs now.");
|
||
|
string graphName = "effScan_" + (Run ==0 ? year : "Run" + to_string(Run));
|
||
|
if (Run == 0 && std::stoi(year) > 2016) replace(graphName,year,"2016");
|
||
|
if (Run == 0 && year=="2015" && sig) replace(graphName,year,"2016");
|
||
|
coutDebug("\t" + graphName);
|
||
|
|
||
|
TGraphErrors *effGraph= (TGraphErrors*)effFile->Get(TMVAmethod+graphName.c_str());
|
||
|
double efficiency = effGraph->Eval(TMVAcut);
|
||
|
|
||
|
coutDebug(string(sig ? "Signal " : "Reference") +" MVA efficiency: " + to_string(efficiency));
|
||
|
|
||
|
//Close the efficiency files
|
||
|
effFile->Close();
|
||
|
return efficiency;
|
||
|
|
||
|
}
|
||
|
|
||
|
double GetSelectionEfficiency(string year, int Run, bool KshortDecaysInVelo,
|
||
|
bool UseLowQ2Range, bool RemoveMultiple, bool sig){
|
||
|
//Load the efficiencies
|
||
|
coutDebug("Openning efficiency files.");
|
||
|
EffAndError eff = getSelectionEfficiencySimple(true,year,Run,sig,!sig, false, KshortDecaysInVelo, RemoveMultiple, true, "", -1, "", gammaTMdefault);
|
||
|
|
||
|
coutDebug(string(sig ? "Signal " : "Reference") +" selection efficiency: " + to_string(eff.value));
|
||
|
|
||
|
//Close the efficiency files
|
||
|
return eff.value;
|
||
|
}
|
||
|
|
||
|
|
||
|
string GetBackgroundFunction(bool KshortDecaysInVelo){ //Set signal and background function separately for each decay channel
|
||
|
string BackGroundFunction = "SingleExponential";
|
||
|
if(Kst2Kspiplus){
|
||
|
if(KshortDecaysInVelo) BackGroundFunction = "SingleExponential";
|
||
|
else BackGroundFunction = "DoubleExponential";
|
||
|
}
|
||
|
return BackGroundFunction;
|
||
|
}
|
||
|
|
||
|
//Takes yield from the reference channel,
|
||
|
YieldInfo GetSigAndBkgEstimation(string year, int Run, bool KshortDecaysInVelo,
|
||
|
bool UseLowQ2Range, Double_t TMVAcut, bool scan){
|
||
|
|
||
|
bool fixedMassRegion = !Kst2Kspiplus; //Calculates the signal from +- 100 MeV or +- SignalRegionNsigma*effective sigma
|
||
|
|
||
|
//initialize the struct
|
||
|
YieldInfo yield = YieldInfo();
|
||
|
yield.year = year;
|
||
|
|
||
|
bool RemoveMultiple = true;
|
||
|
|
||
|
//Set signal and background function separately for each decay channel
|
||
|
string SignalFunction = "OneCB";
|
||
|
string BackGroundFunction = GetBackgroundFunction(KshortDecaysInVelo);
|
||
|
|
||
|
//Get the reference signal yield
|
||
|
if (!scan){
|
||
|
coutInfo("Running the fit!");
|
||
|
yield.refYield = basicYieldFit(year,Run,
|
||
|
false, false, true, false,
|
||
|
FixShape, SignalFunction, BackGroundFunction, FixShape,
|
||
|
KshortDecaysInVelo, UseLowQ2Range,
|
||
|
TMVAcut, fixedMassRegion, true, RemoveMultiple);
|
||
|
}
|
||
|
|
||
|
//Load the file from fitting
|
||
|
TFile *fitFile = new TFile(GetMassFitFile(year, Run,
|
||
|
false, false, true, false,
|
||
|
FixShape, SignalFunction, BackGroundFunction, FixShape,
|
||
|
KshortDecaysInVelo, UseLowQ2Range,
|
||
|
TMVAcut, fixedMassRegion, RemoveMultiple).c_str(),"OPEN");
|
||
|
|
||
|
coutDebug("Opening " + string(fitFile->GetPath()));
|
||
|
|
||
|
if (scan) yield.refYield = getSigYield(fitFile);
|
||
|
double effSigma = fixedMassRegion ? B_plus_M_signal_window : getEffSigma(fitFile);
|
||
|
|
||
|
if (yield.refYield == 0) coutWarning("Reference channel yield is zero!");
|
||
|
|
||
|
yield.sigEff = GetMVAefficiency(year,Run,KshortDecaysInVelo,UseLowQ2Range,RemoveMultiple,true,TMVAcut) * GetSelectionEfficiency(year, Run, KshortDecaysInVelo, UseLowQ2Range, !RemoveMultiple, true);
|
||
|
yield.refEff = GetMVAefficiency(year,Run,KshortDecaysInVelo,UseLowQ2Range,RemoveMultiple,false,TMVAcut) * GetSelectionEfficiency(year, Run, KshortDecaysInVelo, UseLowQ2Range, !RemoveMultiple, false);
|
||
|
|
||
|
coutDebug("Sig Yield efficiency = " + to_string(yield.sigEff));
|
||
|
coutDebug("Ref Yield efficiency = " + to_string(yield.refEff));
|
||
|
|
||
|
//Calculate the signal yield from reference yield, efficiencies and the Jpsi->mumu BR
|
||
|
yield.sigYield = BR_sig / BR_ref * yield.refYield * yield.sigEff/yield.refEff;
|
||
|
|
||
|
//Get the background yield from side band
|
||
|
TChain * tree = new TChain("DecayTree");
|
||
|
|
||
|
std::vector<string> years;
|
||
|
if (Run == 0) years.push_back(year);
|
||
|
else years = yearsData(Run);
|
||
|
|
||
|
for (auto& yr : years){
|
||
|
string BDToutputPath = GetBDToutputFile(yr,getRunID(yr),false,false,false,KshortDecaysInVelo,UseLowQ2Range,false);
|
||
|
tree->Add(BDToutputPath.c_str());
|
||
|
coutDebug("Opening " + BDToutputPath);
|
||
|
}
|
||
|
|
||
|
string sVariable = (UseDTF ? "B_plus_M_DTF" : "B_plus_M");
|
||
|
string cutMass = Form("%s > %f && %s < %f",
|
||
|
sVariable.c_str(), getBplusMeanFromResult(fitFile) - effSigma, sVariable.c_str(),
|
||
|
getBplusMeanFromResult(fitFile) + effSigma);
|
||
|
coutDebug("B mass cut: " + cutMass);
|
||
|
|
||
|
//cut away Jpsi
|
||
|
string cut = getFinalCut(false, false, false, "", gammaTMdefault, true, false, false, false, false, TMefficiencyClass(), -1, TMVAcut, RemoveMultiple);
|
||
|
coutDebug("Using cut " + cut);
|
||
|
|
||
|
//Get background estimation from sideband
|
||
|
string bkgFitPath = GetBDTScanBackgroundFitFile(year,Run,KshortDecaysInVelo,UseLowQ2Range,TMVAcut);
|
||
|
yield.bkgYield = GetBackgroundFromSidebandFit(tree, fixedMassRegion ? effSigma : B_plus_M_signal_window, cut, bkgFitPath);
|
||
|
cut = cut + " && (" + cutMass + ")";
|
||
|
coutDebug("Using cut " + cut);
|
||
|
|
||
|
//data: create histograms from tree
|
||
|
tree->Draw(Form("%s>>B_plus_M_plot", sVariable.c_str()), cut.c_str());
|
||
|
TH1 * histo = ((TH1 *) gPad->GetPrimitive("B_plus_M_plot"));
|
||
|
Int_t EventsAfterPreSelection = histo->GetEntries();
|
||
|
|
||
|
yield.allSigEvts = EventsAfterPreSelection;
|
||
|
|
||
|
//Print signal, background and all evts
|
||
|
string trackType = (Kst2Kspiplus && SplitDDandLL ? (KshortDecaysInVelo ? "LL Tracks: " : "DD Tracks: ") : ":");
|
||
|
coutDebug(TheDecay + "[SIGNAL]: " + trackType + to_string(yield.sigYield));
|
||
|
coutDebug(TheDecay + "[BCKGND]: " + trackType + to_string(yield.bkgYield));
|
||
|
coutDebug(TheDecay + "[ALLEVTS]: " + trackType + to_string(yield.allSigEvts));
|
||
|
|
||
|
coutInfo("Expected yield is: " + to_string(yield.sigYield) + "\t+-" + to_string(yield.sigYieldErr));
|
||
|
|
||
|
return yield;
|
||
|
}
|
||
|
|
||
|
YieldInfo GetSigAndBkgEstimationFromData(string year = "2011", int Run = 0, int randomSubset = 0,
|
||
|
bool KshortDecaysInVelo = false, bool UseLowQ2Range = false,
|
||
|
Double_t TMVAcut = -1.0, bool scan = false){
|
||
|
gStyle->SetOptStat(0);
|
||
|
LHCbStyle();
|
||
|
|
||
|
bool fixedMassRegion = !Kst2Kspiplus; //Fix it in pi0 channel //TODO
|
||
|
string magnet = "both"; //prepare in case of polarity studies
|
||
|
|
||
|
//initialize the struct
|
||
|
YieldInfo yield = YieldInfo();
|
||
|
yield.year = year;
|
||
|
|
||
|
//Set signal and background function separately for each decay channel
|
||
|
string SignalFunction = "OneCB";
|
||
|
string BackGroundFunction = GetBackgroundFunction(KshortDecaysInVelo);
|
||
|
|
||
|
if (!scan) { //Do the fit first
|
||
|
yield.refYield = massFit(year,magnet,Run,
|
||
|
false, true, false, false,
|
||
|
true, false,
|
||
|
FixShape, SignalFunction, BackGroundFunction, FixShape,
|
||
|
KshortDecaysInVelo, UseLowQ2Range,
|
||
|
TMVAcut, randomSubset,
|
||
|
fixedMassRegion, false,
|
||
|
false, true, false,
|
||
|
"", -1,
|
||
|
RemoveMultiple, true,
|
||
|
false, "", false,
|
||
|
"", gammaTMdefault, false);
|
||
|
yield.sigYield = massFit(year,magnet,Run,
|
||
|
false, true, false, false,
|
||
|
false, true,
|
||
|
FixShape, SignalFunction, BackGroundFunction, FixShape,
|
||
|
KshortDecaysInVelo, UseLowQ2Range,
|
||
|
TMVAcut, randomSubset,
|
||
|
fixedMassRegion, false,
|
||
|
false, true, false,
|
||
|
"", -1,
|
||
|
RemoveMultiple, true,
|
||
|
false, "", false,
|
||
|
"", gammaTMdefault, false);
|
||
|
}
|
||
|
//Load fit results now:
|
||
|
|
||
|
// Get reference yield
|
||
|
TFile *fitFileRef = new TFile(GetMassFitFile(year, magnet, Run,
|
||
|
false, true, false, false,
|
||
|
true, false,
|
||
|
FixShape, SignalFunction, BackGroundFunction, FixShape,
|
||
|
KshortDecaysInVelo, UseLowQ2Range,
|
||
|
TMVAcut, randomSubset,
|
||
|
fixedMassRegion, false,
|
||
|
"", -1,
|
||
|
RemoveMultiple, false, //Data cannot be weighted technically, so the name is without "weighted"
|
||
|
false, "", false,
|
||
|
"", gammaTMdefault, false).c_str(),"OPEN");
|
||
|
|
||
|
coutDebug("Opening " + string(fitFileRef->GetPath()));
|
||
|
yield.refYield = getSigYield(fitFileRef);
|
||
|
yield.refYieldErr = getSigYieldErr(fitFileRef);
|
||
|
fitFileRef->Close();
|
||
|
|
||
|
// Get signal yield
|
||
|
TFile *fitFile = new TFile(GetMassFitFile(year, magnet, Run,
|
||
|
false, true, false, false,
|
||
|
false, true,
|
||
|
FixShape, SignalFunction, BackGroundFunction, FixShape,
|
||
|
KshortDecaysInVelo, UseLowQ2Range,
|
||
|
TMVAcut, randomSubset,
|
||
|
fixedMassRegion, false,
|
||
|
"", -1,
|
||
|
RemoveMultiple, false, //Data cannot be weighted technically, so the name is without "weighted"
|
||
|
false, "", false,
|
||
|
"", gammaTMdefault, false).c_str(),"OPEN");
|
||
|
|
||
|
coutDebug("Opening " + string(fitFile->GetPath()));
|
||
|
yield.sigYield = getSigYield(fitFile);
|
||
|
yield.sigYieldErr = getSigYieldErr(fitFile);
|
||
|
yield.bkgYield = getBkgYield(fitFile);
|
||
|
yield.bkgYieldErr = getBkgYieldErr(fitFile);
|
||
|
double mean_sig = getBplusMeanFromResult(fitFile);
|
||
|
double effSigma = fixedMassRegion ? B_plus_M_signal_window : getEffSigma(fitFile);
|
||
|
fitFile->Close();
|
||
|
|
||
|
//Get the number of all events in the signal region
|
||
|
TChain * tree = new TChain("DecayTree");
|
||
|
std::vector<string> years;
|
||
|
if (Run == 0) years.push_back(year);
|
||
|
else years = yearsData(Run);
|
||
|
|
||
|
for (auto& yr : years){
|
||
|
string BDToutputPath = GetBDToutputFile(yr,getRunID(yr),false,false,false,KshortDecaysInVelo,UseLowQ2Range,false);
|
||
|
tree->Add(BDToutputPath.c_str());
|
||
|
coutDebug("Opening " + BDToutputPath);
|
||
|
}
|
||
|
|
||
|
coutDebug("eff sigma: " + to_string(effSigma));
|
||
|
string sVariable = (UseDTF ? "B_plus_M_DTF" : "B_plus_M");
|
||
|
string cutMass = Form("%s > %f && %s < %f",
|
||
|
sVariable.c_str(), mean_sig - effSigma, sVariable.c_str(),
|
||
|
mean_sig + effSigma);
|
||
|
coutDebug("B mass cut: " + cutMass);
|
||
|
|
||
|
//cut away resonances
|
||
|
string cut = getFinalCut(false, false, false, "", gammaTMdefault, true, false, false, false, false, TMefficiencyClass(), -1, TMVAcut, RemoveMultiple);
|
||
|
coutDebug("Using cut " + cut);
|
||
|
|
||
|
//data: create histograms from tree
|
||
|
tree->Draw(Form("%s>>B_plus_M_plot", sVariable.c_str()), cut.c_str());
|
||
|
TH1 * histo = ((TH1 *) gPad->GetPrimitive("B_plus_M_plot"));
|
||
|
Int_t EventsAfterPreSelection = histo->GetEntries();
|
||
|
|
||
|
yield.allSigEvts = EventsAfterPreSelection;
|
||
|
|
||
|
//Print signal, background and all evts
|
||
|
string trackType = (Kst2Kspiplus && SplitDDandLL ? (KshortDecaysInVelo ? "LL Tracks: " : "DD Tracks: ") : ":");
|
||
|
coutDebug(TheDecay + "[SIGNAL]: " + trackType + to_string(yield.sigYield));
|
||
|
coutDebug(TheDecay + "[BCKGND]: " + trackType + to_string(yield.bkgYield));
|
||
|
coutDebug(TheDecay + "[ALLEVTS]: " + trackType + to_string(yield.allSigEvts));
|
||
|
|
||
|
coutInfo("Expected yield is: " + to_string(yield.sigYield) + "\t+-" + to_string(yield.sigYieldErr));
|
||
|
coutDebug("Signal yield error: " + to_string(yield.sigYieldErr));
|
||
|
coutDebug("Background yield error: " + to_string(yield.bkgYieldErr));
|
||
|
coutDebug("Reference channel yield error: " + to_string(yield.refYieldErr));
|
||
|
|
||
|
if (yield.refYield == 0) coutERROR("Reference channel yield is zero!");
|
||
|
if (yield.sigYield == 0) coutERROR("Signal channel yield is zero! Abort.");
|
||
|
|
||
|
return yield;
|
||
|
|
||
|
}
|
||
|
|
||
|
int SaveTGraphs(string path, bool fineScan, string year, int Run, string basicPath,
|
||
|
TGraphErrors *yieldGraph, TGraphErrors *bkgGraph, TGraphErrors *bkgGraphFromAllEvts, TGraphErrors *refYieldGraph, TGraphErrors *allEvtsInSig, TGraphErrors *significance, TGraphErrors *significanceFromAllEvts){
|
||
|
|
||
|
coutInfo("Making pretty plots and saving them!");
|
||
|
coutDebug("Writting into " + path);
|
||
|
coutDebug("Using basicPath " + basicPath);
|
||
|
|
||
|
TFile * TGraphOutput = new TFile(path.c_str(), "RECREATE");
|
||
|
TGraphOutput->cd();
|
||
|
|
||
|
designYieldGraph(yieldGraph, Run, year, "sigYield", basicPath, TGraphOutput, false);
|
||
|
designYieldGraph(bkgGraph, Run, year, "bkgYield", basicPath, TGraphOutput, false);
|
||
|
designYieldGraph(bkgGraphFromAllEvts, Run, year, "bkgYield_fromAllEvts", basicPath, TGraphOutput, fineScan);
|
||
|
designYieldGraph(refYieldGraph, Run, year, "refYield", basicPath, TGraphOutput, fineScan);
|
||
|
designYieldGraph(significance, Run, year, "significance", basicPath, TGraphOutput, false);
|
||
|
designYieldGraph(significanceFromAllEvts, Run, year, "significance_fromAllEvts", basicPath, TGraphOutput, fineScan);
|
||
|
designYieldGraph(allEvtsInSig, Run, year, "EventsInSigRegion", basicPath, TGraphOutput, false);
|
||
|
|
||
|
TGraphOutput->Close();
|
||
|
return 1;
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
int ScanSignalAndBckgndEstimation(string year, int Run, Double_t BDTstep, bool KshortDecaysInVelo, bool UseLowQ2Range, bool scan, bool fineScan){
|
||
|
//If Run==0, do the scan for year, if Run == 1/2, do the scan per run
|
||
|
|
||
|
if (verboseLevel > 1)RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);
|
||
|
|
||
|
bool section = true; //In case of fine scan, section the scan in more fine way
|
||
|
int n_divisions = 3;
|
||
|
|
||
|
//Get low TMVA response lower boundary
|
||
|
Double_t lowBDTcut = (TMVAmethod == "MLP") ? 0.0 : -1.0;
|
||
|
if (fineScan){
|
||
|
coutInfo("Making fine BDT cut study.");
|
||
|
lowBDTcut = 0.9;
|
||
|
BDTstep = 0.001;
|
||
|
}
|
||
|
|
||
|
//prepare in case of polarity studies
|
||
|
string magnet = "both";
|
||
|
|
||
|
TGraphErrors *yieldGraph = new TGraphErrors();
|
||
|
TGraphErrors *bkgGraph = new TGraphErrors();
|
||
|
TGraphErrors *bkgGraphFromAllEvts = new TGraphErrors();
|
||
|
TGraphErrors *refYieldGraph = new TGraphErrors();
|
||
|
TGraphErrors *significance = new TGraphErrors();
|
||
|
TGraphErrors *significanceFromAllEvts = new TGraphErrors();
|
||
|
YieldInfo yield = YieldInfo(); //put zeroes everywhere
|
||
|
|
||
|
//loop over BDT cuts
|
||
|
coutInfo("Loop over BDT cuts with a step of " + to_string(BDTstep));
|
||
|
coutDebug("Starting the loop at " + to_string(lowBDTcut));
|
||
|
double tmpBDTcut = 0.0;
|
||
|
|
||
|
for(double fBDTcut = lowBDTcut; fBDTcut < (section ? 0.999 : 1.0); fBDTcut += section ? ((1.0-fBDTcut)/double(n_divisions)) : BDTstep){
|
||
|
for (int k = 0; k < n_divisions; k++){
|
||
|
tmpBDTcut = fBDTcut + k*(1.0-fBDTcut)/double(n_divisions);
|
||
|
yield = GetSigAndBkgEstimation(year, Run, KshortDecaysInVelo, UseLowQ2Range, tmpBDTcut, scan);
|
||
|
yieldGraph ->SetPoint(yieldGraph->GetN(), tmpBDTcut, yield.sigYield);
|
||
|
bkgGraphFromAllEvts ->SetPoint(bkgGraphFromAllEvts->GetN(), tmpBDTcut, yield.allSigEvts-yield.sigYield);
|
||
|
bkgGraph ->SetPoint(bkgGraph->GetN(), tmpBDTcut, yield.bkgYield);
|
||
|
refYieldGraph ->SetPoint(yieldGraph->GetN(), tmpBDTcut, yield.refYield);
|
||
|
significance ->SetPoint(significance->GetN(), tmpBDTcut, yield.sigYield / (TMath::Sqrt(yield.sigYield + yield.bkgYield)));
|
||
|
significanceFromAllEvts ->SetPoint(significance->GetN(), tmpBDTcut, yield.sigYield / (TMath::Sqrt(yield.allSigEvts)));
|
||
|
coutDebug("---" + string(TMVAmethod) + " cut " + to_string(tmpBDTcut) + " yield: " + to_string(yield.sigYield) + ", background: " + to_string( yield.allSigEvts-yield.sigYield ));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Write to file and close
|
||
|
string path = GetBDTScanFile(year, magnet, Run, KshortDecaysInVelo, UseLowQ2Range, fineScan);
|
||
|
SaveTGraphs(path,fineScan,year,Run,path,yieldGraph,bkgGraph,bkgGraphFromAllEvts,refYieldGraph,NULL,significance,significanceFromAllEvts);
|
||
|
|
||
|
coutInfo("Signal scan done for year " + year + "!");
|
||
|
return 1;
|
||
|
|
||
|
}
|
||
|
|
||
|
int ScanSignalAndBckgndEstimationPerYear(string year = "2011", Double_t BDTstep = 0.01, bool KshortDecaysInVelo = true, bool UseLowQ2Range = false, bool scan = false, bool fineScan = false){
|
||
|
return ScanSignalAndBckgndEstimation(year = "2011", 0, BDTstep, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
|
||
|
}
|
||
|
int ScanSignalAndBckgndEstimationAllYears(Double_t BDTstep = 0.01, bool KshortDecaysInVelo = true, bool UseLowQ2Range = false, bool scan = false, bool fineScan = true){
|
||
|
for (auto yr: yearsData(12)) ScanSignalAndBckgndEstimationPerYear(yr, BDTstep, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int ScanSignalAndBckgndEstimationSimple(string year = "2011",int Run = 1, Double_t BDTstep = 0.01, int randomSubset = 0,
|
||
|
bool KshortDecaysInVelo = true, bool UseLowQ2Range = false, bool scan = false, bool fineScan = true){
|
||
|
//Get low TMVA response lower boundary
|
||
|
|
||
|
double lowBDTcut = (TMVAmethod == "MLP") ? 0.0 : -1.0;
|
||
|
if (fineScan){
|
||
|
coutInfo("Making fine BDT cut study.");
|
||
|
lowBDTcut = 0.9;
|
||
|
BDTstep = 0.002;
|
||
|
}
|
||
|
bool halve = true;
|
||
|
|
||
|
|
||
|
//prepare in case of polarity studies
|
||
|
string magnet = "both";
|
||
|
|
||
|
TGraphErrors *yieldGraph = new TGraphErrors();
|
||
|
TGraphErrors *bkgGraph = new TGraphErrors();
|
||
|
TGraphErrors *bkgGraphFromAllEvts = new TGraphErrors();
|
||
|
TGraphErrors *refYieldGraph = new TGraphErrors();
|
||
|
TGraphErrors *allEvtsInSig = new TGraphErrors();
|
||
|
TGraphErrors *significance = new TGraphErrors();
|
||
|
TGraphErrors *significanceFromAllEvts = new TGraphErrors();
|
||
|
YieldInfo yield = YieldInfo(); //put zeroes everywhere
|
||
|
|
||
|
//loop over BDT cuts
|
||
|
coutInfo("Loop over BDT cuts with a step of " + to_string(BDTstep));
|
||
|
coutDebug("Starting the loop at " + to_string(lowBDTcut));
|
||
|
int n_divisions = halve ? 3 : 1;
|
||
|
double tmpcut = 0.0;
|
||
|
for(double fBDTcut = lowBDTcut; fBDTcut < (halve ? 0.9999 : 1); fBDTcut += halve ? ((1.0-fBDTcut)/double(n_divisions)) : BDTstep){
|
||
|
for (int k = 0; k < n_divisions-1; k++){
|
||
|
tmpcut = fBDTcut + k*(1.0-fBDTcut)/double(n_divisions);
|
||
|
coutDebug("Cutting at: " + to_string(tmpcut));
|
||
|
yield =GetSigAndBkgEstimationFromData(year,Run, randomSubset, KshortDecaysInVelo, UseLowQ2Range, tmpcut, scan);
|
||
|
//Save the efficiency
|
||
|
yieldGraph ->SetPoint(yieldGraph->GetN(), tmpcut, yield.sigYield);
|
||
|
yieldGraph ->SetPointError(yieldGraph->GetN()-1, 0, yield.sigYieldErr);
|
||
|
bkgGraph ->SetPoint(bkgGraph->GetN(), tmpcut, yield.bkgYield);
|
||
|
bkgGraph ->SetPointError(bkgGraph->GetN()-1, 0, yield.bkgYieldErr);
|
||
|
bkgGraphFromAllEvts ->SetPoint(bkgGraph->GetN(), tmpcut, yield.allSigEvts-yield.sigYield);
|
||
|
refYieldGraph ->SetPoint(yieldGraph->GetN(), tmpcut, yield.refYield);
|
||
|
refYieldGraph ->SetPointError(yieldGraph->GetN()-1, 0, yield.refYieldErr);
|
||
|
allEvtsInSig ->SetPoint(allEvtsInSig->GetN(), tmpcut, yield.allSigEvts);
|
||
|
significance ->SetPoint(significance->GetN(), tmpcut, yield.sigYield / (TMath::Sqrt(yield.sigYield+yield.bkgYield)));
|
||
|
significanceFromAllEvts ->SetPoint(significance->GetN(), tmpcut, yield.sigYield / (TMath::Sqrt(yield.allSigEvts)));
|
||
|
coutDebug("---" + string(TMVAmethod) + " cut " + to_string(tmpcut) + " yield: " + to_string(yield.sigYield) + ", background: " + to_string( yield.allSigEvts-yield.sigYield ));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Write to file and close //TODO at some point
|
||
|
string path = GetBDTScanFile(year, magnet, Run, KshortDecaysInVelo, UseLowQ2Range, fineScan);
|
||
|
replace(path, ".root", "fromData.root");
|
||
|
if (randomSubset == -1) replace(path,".root","_subset1.root");
|
||
|
if (randomSubset == 1) replace(path,".root","_subset2.root");
|
||
|
SaveTGraphs(path,fineScan,year,0,path,yieldGraph,bkgGraph,bkgGraphFromAllEvts,refYieldGraph,NULL,significance,significanceFromAllEvts);
|
||
|
|
||
|
coutInfo("Signal scan done for Run " + to_string(Run) + "!");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int ScanSignalAndBckgndEstimationSimplePerYear(string year = "2011", Double_t BDTstep = 0.01, int randomSubset = 0, bool KshortDecaysInVelo = true, bool UseLowQ2Range = false, bool scan = false, bool fineScan = true){
|
||
|
return ScanSignalAndBckgndEstimationSimple(year = "2011", 0, BDTstep, randomSubset, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
|
||
|
}
|
||
|
|
||
|
int ScanSignalAndBckgndEstimationSimpleAllYears(Double_t BDTstep = 0.01, int randomSubset = 0, bool KshortDecaysInVelo = true, bool UseLowQ2Range = false, bool scan = false, bool fineScan = true){
|
||
|
for (auto yr: yearsData(12)) ScanSignalAndBckgndEstimationSimplePerYear(yr, BDTstep, randomSubset, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
double getMaxBDTresponse(string year = "2011", int Run = 0, bool fineScan = false, bool directScan = false, int randomSubset = 0, bool KshortDecaysInVelo = true, bool UseLowQ2Range = false){
|
||
|
|
||
|
//prepare in case of polarity studies
|
||
|
string magnet = "both";
|
||
|
|
||
|
if (Run == 0) coutInfo("Getting BDTresponse with highest significance for YEAR " + year + ". . .");
|
||
|
else coutInfo("Getting BDTresponse with highest significance for RUN "+to_string(Run)+". . .");
|
||
|
|
||
|
string path = GetBDTScanFile(year, magnet, Run, KshortDecaysInVelo, UseLowQ2Range, fineScan);
|
||
|
if (directScan) replace(path, ".root", "fromData.root");
|
||
|
if (randomSubset == -1) replace(path,".root","_subset1.root");
|
||
|
if (randomSubset == 1) replace(path,".root","_subset2.root");
|
||
|
|
||
|
TGraphErrors *significance = new TGraphErrors();
|
||
|
TFile *scanFile = new TFile(path.c_str(),"OPEN");
|
||
|
string graphName = "significance_fromAllEvts";
|
||
|
significance = (TGraphErrors*) scanFile->Get(graphName.c_str());
|
||
|
if(significance == NULL){
|
||
|
coutERROR("TGraphError was not found in the file!");
|
||
|
coutERROR("File:\t" + path);
|
||
|
coutERROR("TGraph:\t" + graphName);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//Get the best BDTcut
|
||
|
double LargestFoM = -100.;
|
||
|
double bestCut = 0.0;
|
||
|
for(int p = 0; p < significance->GetN(); p++){
|
||
|
if(significance->GetY()[p] > LargestFoM){
|
||
|
LargestFoM = significance->GetY()[p];
|
||
|
bestCut = significance->GetX()[p];
|
||
|
}
|
||
|
}
|
||
|
return bestCut;
|
||
|
}
|
||
|
|
||
|
int optimizeBDTCut(string year = "2011", int Run = 0, bool KshortDecaysInVelo = true, Double_t BDTstep = 0.01, bool UseRandomSubset = false,
|
||
|
bool UseLowQ2Range = false, bool scan = false, bool fineScan = false, bool directScan = false){
|
||
|
|
||
|
//Get low TMVA response lower boundary
|
||
|
double lowBDTcut = (TMVAmethod == "MLP") ? 0.0 : -1.0;
|
||
|
if (fineScan){
|
||
|
coutInfo("Making fine BDT cut study.");
|
||
|
lowBDTcut = 0.9;
|
||
|
BDTstep = 0.002;
|
||
|
}
|
||
|
|
||
|
double BestCut = 0;
|
||
|
|
||
|
if (directScan){
|
||
|
if (UseRandomSubset){
|
||
|
ScanSignalAndBckgndEstimationSimple(year, Run, BDTstep, -1, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
|
||
|
ScanSignalAndBckgndEstimationSimple(year, Run, BDTstep, +1, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
|
||
|
double BestCut1 = getMaxBDTresponse(year, Run, fineScan, true, -1, KshortDecaysInVelo, UseLowQ2Range);
|
||
|
double BestCut2 = getMaxBDTresponse(year, Run, fineScan, true, +1, KshortDecaysInVelo, UseLowQ2Range);
|
||
|
BestCut = roundf(BestCut1 * 100) / 100 +roundf(BestCut2 * 100); // round to 2 decimal points, return e.g. 0.96 + 94 (easy to untangle)
|
||
|
}
|
||
|
else{
|
||
|
ScanSignalAndBckgndEstimationSimple(year, Run, BDTstep, 0, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
|
||
|
BestCut = getMaxBDTresponse(year, Run, fineScan, true, 0, KshortDecaysInVelo, UseLowQ2Range);
|
||
|
}
|
||
|
|
||
|
//TODO
|
||
|
}
|
||
|
else{ //TODO: add subset fits
|
||
|
if (Run == 0){
|
||
|
ScanSignalAndBckgndEstimationPerYear(year,BDTstep,KshortDecaysInVelo,UseLowQ2Range,scan,fineScan);
|
||
|
}
|
||
|
else{
|
||
|
ScanSignalAndBckgndEstimation(year,Run,BDTstep,KshortDecaysInVelo,UseLowQ2Range,scan,fineScan);
|
||
|
}
|
||
|
//TODO make a pretty plot
|
||
|
|
||
|
BestCut = getMaxBDTresponse(year, Run, fineScan, false, 0, KshortDecaysInVelo, UseLowQ2Range);
|
||
|
|
||
|
}
|
||
|
|
||
|
return BestCut;
|
||
|
|
||
|
}
|