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.

636 lines
30 KiB

  1. //Functions that calculate/fit the yield for given MVA response cut
  2. //and make pretty plots from it
  3. //Renata Kopecna
  4. #include "GlobalFunctions.hh"
  5. #include "Paths.hpp"
  6. #include "MassFit.hpp"
  7. #include "Utils.hpp"
  8. #include "./BmassShape/SignalType.hpp"
  9. #include "EfficiencyClass.cpp"
  10. using namespace std;
  11. using namespace RooFit;
  12. using namespace RooStats;
  13. class YieldInfo{
  14. public:
  15. string year;
  16. double sigYield;
  17. double sigYieldErr;
  18. double refYield;
  19. double refYieldErr;
  20. double bkgYield;
  21. double bkgYieldErr;
  22. double sigEff;
  23. double refEff;
  24. double allSigEvts;
  25. YieldInfo(){ //default constructor
  26. year = "";
  27. sigYield = 0;
  28. sigYieldErr = 0;
  29. refYield = 0;
  30. refYieldErr = 0;
  31. bkgYield = 0;
  32. bkgYieldErr = 0;
  33. sigEff = 0;
  34. refEff = 0;
  35. allSigEvts = 0;
  36. }
  37. void addYield(YieldInfo addInfo){
  38. sigYield += addInfo.sigYield;
  39. sigYieldErr += addInfo.sigYieldErr;
  40. refYield += addInfo.refYield;
  41. refYieldErr += addInfo.refYieldErr;
  42. bkgYield += addInfo.bkgYield;
  43. bkgYieldErr += addInfo.bkgYieldErr;
  44. sigEff += addInfo.sigEff; //this doesn't make much sense
  45. refEff += addInfo.refEff; //this doesn't make much sense
  46. allSigEvts += addInfo.allSigEvts;
  47. }
  48. ~YieldInfo(); //destuctor
  49. };
  50. YieldInfo::~YieldInfo(){//destuctor
  51. }
  52. bool FixShape = true;
  53. bool RemoveMultiple = true; //For now use as a global boolean
  54. //Function that takes upper mass sideband histogram and fits it with an exponential
  55. //Using a Tree, starting the upper mass sideband from range+PDGMASS.Bplus and possibly cutting away stuff defined by cut
  56. double GetBackgroundFromSidebandFit(TChain *Tree, double range, string cut, string path){
  57. TString massBranch = UseDTF ? "B_plus_M" : "B_plus_DTF_M";
  58. bool savePlots = true;
  59. //Fill histogram from Tree
  60. int nBins = 50;
  61. TH1D *h_B_mass = new TH1D("h_B_mass","h_B_mass",nBins,PDGMASS.B_PLUS + range, cut_B_plus_M_high);
  62. double binWidth = (cut_B_plus_M_high - PDGMASS.B_PLUS - range)/nBins;
  63. Tree->Draw(massBranch+" >> h_B_mass",cut.c_str());
  64. //Define fit function
  65. TF1 *f_bkg = new TF1("f_bkg","expo",cut_B_plus_M_low,cut_B_plus_M_high);
  66. design_function(f_bkg,kRed,1);
  67. //Fit
  68. h_B_mass->Fit(f_bkg,"Q","", PDGMASS.B_PLUS + range,cut_B_plus_M_high); //exponential is f(x) = exp(p0+p1*x)
  69. double integral = f_bkg->Integral(PDGMASS.B_PLUS-range,PDGMASS.B_PLUS+range)/binWidth;
  70. //Save the plots
  71. if (savePlots){
  72. string name = path.substr(path.find("/Kplus")+6,path.length());
  73. //Create canvas
  74. TCanvas *c = c_canvas(name);
  75. c->cd();
  76. design_TH1D(h_B_mass,"B^{+} mass [MeV]","Counts a.u.", kBlack);
  77. h_B_mass->GetYaxis()->SetTitleOffset(1.05);
  78. h_B_mass->Draw();
  79. //Create TPaveText
  80. TPaveText *fitParams= new TPaveText(0.6,0.7,0.87,0.9,"NDC");
  81. fitParams->SetFillColor(kWhite);
  82. fitParams->AddText(Form("Offset : %.2f ", f_bkg->GetParameter(0)));
  83. fitParams->AddText(Form("Exp: %.2f%%", f_bkg->GetParameter(1)*100));
  84. fitParams->AddText(Form("Integral: %.2f ", integral));
  85. fitParams->Draw("SAME");
  86. //Create file
  87. TFile *fitFile = new TFile(path.c_str(),"RECREATE");
  88. coutDebug("Opening " + string(fitFile->GetPath()));
  89. fitFile->cd();
  90. h_B_mass->Write();
  91. f_bkg->Write();
  92. c->Write();
  93. replace(path,".root",".eps");
  94. c->SaveAs(path.c_str(), ".eps");
  95. fitFile->Close();
  96. }
  97. //return the integral
  98. h_B_mass->Clear();
  99. return integral;
  100. }
  101. double GetMVAefficiency(string year, int Run, bool KshortDecaysInVelo,
  102. bool UseLowQ2Range, bool IncludeMultipleEff, bool sig, double TMVAcut){
  103. //Load the efficiencies
  104. coutDebug("Openning MVA efficiency files.");
  105. string path = GetEfficiencyFile("BDT", year, "both", Run, !sig, sig, false, KshortDecaysInVelo, IncludeMultipleEff, true, UseLowQ2Range, false,"");
  106. if (Run == 0 && std::stoi(year) > 2016 && !sig) replace(path,year,"2016"); //RefChann available for 2015-2016
  107. if (Run == 0 && year=="2015" && sig) replace(path,year,"2016"); //No reasonable MC for 2015
  108. coutDebug("Openning file: " + path);
  109. TFile * effFile = new TFile(path.c_str(), "OPEN");
  110. //Get the TGraphs
  111. coutDebug("File opened, getting the graphs now.");
  112. string graphName = "effScan_" + (Run ==0 ? year : "Run" + to_string(Run));
  113. if (Run == 0 && std::stoi(year) > 2016) replace(graphName,year,"2016");
  114. if (Run == 0 && year=="2015" && sig) replace(graphName,year,"2016");
  115. coutDebug("\t" + graphName);
  116. TGraphErrors *effGraph= (TGraphErrors*)effFile->Get(TMVAmethod+graphName.c_str());
  117. double efficiency = effGraph->Eval(TMVAcut);
  118. coutDebug(string(sig ? "Signal " : "Reference") +" MVA efficiency: " + to_string(efficiency));
  119. //Close the efficiency files
  120. effFile->Close();
  121. return efficiency;
  122. }
  123. double GetSelectionEfficiency(string year, int Run, bool KshortDecaysInVelo,
  124. bool UseLowQ2Range, bool RemoveMultiple, bool sig){
  125. //Load the efficiencies
  126. coutDebug("Openning efficiency files.");
  127. EffAndError eff = getSelectionEfficiencySimple(true,year,Run,sig,!sig, false, KshortDecaysInVelo, RemoveMultiple, true, "", -1, "", gammaTMdefault);
  128. coutDebug(string(sig ? "Signal " : "Reference") +" selection efficiency: " + to_string(eff.value));
  129. //Close the efficiency files
  130. return eff.value;
  131. }
  132. string GetBackgroundFunction(bool KshortDecaysInVelo){ //Set signal and background function separately for each decay channel
  133. string BackGroundFunction = "SingleExponential";
  134. if(Kst2Kspiplus){
  135. if(KshortDecaysInVelo) BackGroundFunction = "SingleExponential";
  136. else BackGroundFunction = "DoubleExponential";
  137. }
  138. return BackGroundFunction;
  139. }
  140. //Takes yield from the reference channel,
  141. YieldInfo GetSigAndBkgEstimation(string year, int Run, bool KshortDecaysInVelo,
  142. bool UseLowQ2Range, Double_t TMVAcut, bool scan){
  143. bool fixedMassRegion = !Kst2Kspiplus; //Calculates the signal from +- 100 MeV or +- SignalRegionNsigma*effective sigma
  144. //initialize the struct
  145. YieldInfo yield = YieldInfo();
  146. yield.year = year;
  147. bool RemoveMultiple = true;
  148. //Set signal and background function separately for each decay channel
  149. string SignalFunction = "OneCB";
  150. string BackGroundFunction = GetBackgroundFunction(KshortDecaysInVelo);
  151. //Get the reference signal yield
  152. if (!scan){
  153. coutInfo("Running the fit!");
  154. yield.refYield = basicYieldFit(year,Run,
  155. false, false, true, false,
  156. FixShape, SignalFunction, BackGroundFunction, FixShape,
  157. KshortDecaysInVelo, UseLowQ2Range,
  158. TMVAcut, fixedMassRegion, true, RemoveMultiple);
  159. }
  160. //Load the file from fitting
  161. TFile *fitFile = new TFile(GetMassFitFile(year, Run,
  162. false, false, true, false,
  163. FixShape, SignalFunction, BackGroundFunction, FixShape,
  164. KshortDecaysInVelo, UseLowQ2Range,
  165. TMVAcut, fixedMassRegion, RemoveMultiple).c_str(),"OPEN");
  166. coutDebug("Opening " + string(fitFile->GetPath()));
  167. if (scan) yield.refYield = getSigYield(fitFile);
  168. double effSigma = fixedMassRegion ? B_plus_M_signal_window : getEffSigma(fitFile);
  169. if (yield.refYield == 0) coutWarning("Reference channel yield is zero!");
  170. yield.sigEff = GetMVAefficiency(year,Run,KshortDecaysInVelo,UseLowQ2Range,RemoveMultiple,true,TMVAcut) * GetSelectionEfficiency(year, Run, KshortDecaysInVelo, UseLowQ2Range, !RemoveMultiple, true);
  171. yield.refEff = GetMVAefficiency(year,Run,KshortDecaysInVelo,UseLowQ2Range,RemoveMultiple,false,TMVAcut) * GetSelectionEfficiency(year, Run, KshortDecaysInVelo, UseLowQ2Range, !RemoveMultiple, false);
  172. coutDebug("Sig Yield efficiency = " + to_string(yield.sigEff));
  173. coutDebug("Ref Yield efficiency = " + to_string(yield.refEff));
  174. //Calculate the signal yield from reference yield, efficiencies and the Jpsi->mumu BR
  175. yield.sigYield = BR_sig / BR_ref * yield.refYield * yield.sigEff/yield.refEff;
  176. //Get the background yield from side band
  177. TChain * tree = new TChain("DecayTree");
  178. std::vector<string> years;
  179. if (Run == 0) years.push_back(year);
  180. else years = yearsData(Run);
  181. for (auto& yr : years){
  182. string BDToutputPath = GetBDToutputFile(yr,getRunID(yr),false,false,false,KshortDecaysInVelo,UseLowQ2Range,false);
  183. tree->Add(BDToutputPath.c_str());
  184. coutDebug("Opening " + BDToutputPath);
  185. }
  186. string sVariable = (UseDTF ? "B_plus_M_DTF" : "B_plus_M");
  187. string cutMass = Form("%s > %f && %s < %f",
  188. sVariable.c_str(), getBplusMeanFromResult(fitFile) - effSigma, sVariable.c_str(),
  189. getBplusMeanFromResult(fitFile) + effSigma);
  190. coutDebug("B mass cut: " + cutMass);
  191. //cut away Jpsi
  192. string cut = getFinalCut(false, false, false, "", gammaTMdefault, true, false, false, false, false, TMefficiencyClass(), -1, TMVAcut, RemoveMultiple);
  193. coutDebug("Using cut " + cut);
  194. //Get background estimation from sideband
  195. string bkgFitPath = GetBDTScanBackgroundFitFile(year,Run,KshortDecaysInVelo,UseLowQ2Range,TMVAcut);
  196. yield.bkgYield = GetBackgroundFromSidebandFit(tree, fixedMassRegion ? effSigma : B_plus_M_signal_window, cut, bkgFitPath);
  197. cut = cut + " && (" + cutMass + ")";
  198. coutDebug("Using cut " + cut);
  199. //data: create histograms from tree
  200. tree->Draw(Form("%s>>B_plus_M_plot", sVariable.c_str()), cut.c_str());
  201. TH1 * histo = ((TH1 *) gPad->GetPrimitive("B_plus_M_plot"));
  202. Int_t EventsAfterPreSelection = histo->GetEntries();
  203. yield.allSigEvts = EventsAfterPreSelection;
  204. //Print signal, background and all evts
  205. string trackType = (Kst2Kspiplus && SplitDDandLL ? (KshortDecaysInVelo ? "LL Tracks: " : "DD Tracks: ") : ":");
  206. coutDebug(TheDecay + "[SIGNAL]: " + trackType + to_string(yield.sigYield));
  207. coutDebug(TheDecay + "[BCKGND]: " + trackType + to_string(yield.bkgYield));
  208. coutDebug(TheDecay + "[ALLEVTS]: " + trackType + to_string(yield.allSigEvts));
  209. coutInfo("Expected yield is: " + to_string(yield.sigYield) + "\t+-" + to_string(yield.sigYieldErr));
  210. return yield;
  211. }
  212. YieldInfo GetSigAndBkgEstimationFromData(string year = "2011", int Run = 0, int randomSubset = 0,
  213. bool KshortDecaysInVelo = false, bool UseLowQ2Range = false,
  214. Double_t TMVAcut = -1.0, bool scan = false){
  215. gStyle->SetOptStat(0);
  216. LHCbStyle();
  217. bool fixedMassRegion = !Kst2Kspiplus; //Fix it in pi0 channel //TODO
  218. string magnet = "both"; //prepare in case of polarity studies
  219. //initialize the struct
  220. YieldInfo yield = YieldInfo();
  221. yield.year = year;
  222. //Set signal and background function separately for each decay channel
  223. string SignalFunction = "OneCB";
  224. string BackGroundFunction = GetBackgroundFunction(KshortDecaysInVelo);
  225. if (!scan) { //Do the fit first
  226. yield.refYield = massFit(year,magnet,Run,
  227. false, true, false, false,
  228. true, false,
  229. FixShape, SignalFunction, BackGroundFunction, FixShape,
  230. KshortDecaysInVelo, UseLowQ2Range,
  231. TMVAcut, randomSubset,
  232. fixedMassRegion, false,
  233. false, true, false,
  234. "", -1,
  235. RemoveMultiple, true,
  236. false, "", false,
  237. "", gammaTMdefault, false);
  238. yield.sigYield = massFit(year,magnet,Run,
  239. false, true, false, false,
  240. false, true,
  241. FixShape, SignalFunction, BackGroundFunction, FixShape,
  242. KshortDecaysInVelo, UseLowQ2Range,
  243. TMVAcut, randomSubset,
  244. fixedMassRegion, false,
  245. false, true, false,
  246. "", -1,
  247. RemoveMultiple, true,
  248. false, "", false,
  249. "", gammaTMdefault, false);
  250. }
  251. //Load fit results now:
  252. // Get reference yield
  253. TFile *fitFileRef = new TFile(GetMassFitFile(year, magnet, Run,
  254. false, true, false, false,
  255. true, false,
  256. FixShape, SignalFunction, BackGroundFunction, FixShape,
  257. KshortDecaysInVelo, UseLowQ2Range,
  258. TMVAcut, randomSubset,
  259. fixedMassRegion, false,
  260. "", -1,
  261. RemoveMultiple, false, //Data cannot be weighted technically, so the name is without "weighted"
  262. false, "", false,
  263. "", gammaTMdefault, false).c_str(),"OPEN");
  264. coutDebug("Opening " + string(fitFileRef->GetPath()));
  265. yield.refYield = getSigYield(fitFileRef);
  266. yield.refYieldErr = getSigYieldErr(fitFileRef);
  267. fitFileRef->Close();
  268. // Get signal yield
  269. TFile *fitFile = new TFile(GetMassFitFile(year, magnet, Run,
  270. false, true, false, false,
  271. false, true,
  272. FixShape, SignalFunction, BackGroundFunction, FixShape,
  273. KshortDecaysInVelo, UseLowQ2Range,
  274. TMVAcut, randomSubset,
  275. fixedMassRegion, false,
  276. "", -1,
  277. RemoveMultiple, false, //Data cannot be weighted technically, so the name is without "weighted"
  278. false, "", false,
  279. "", gammaTMdefault, false).c_str(),"OPEN");
  280. coutDebug("Opening " + string(fitFile->GetPath()));
  281. yield.sigYield = getSigYield(fitFile);
  282. yield.sigYieldErr = getSigYieldErr(fitFile);
  283. yield.bkgYield = getBkgYield(fitFile);
  284. yield.bkgYieldErr = getBkgYieldErr(fitFile);
  285. double mean_sig = getBplusMeanFromResult(fitFile);
  286. double effSigma = fixedMassRegion ? B_plus_M_signal_window : getEffSigma(fitFile);
  287. fitFile->Close();
  288. //Get the number of all events in the signal region
  289. TChain * tree = new TChain("DecayTree");
  290. std::vector<string> years;
  291. if (Run == 0) years.push_back(year);
  292. else years = yearsData(Run);
  293. for (auto& yr : years){
  294. string BDToutputPath = GetBDToutputFile(yr,getRunID(yr),false,false,false,KshortDecaysInVelo,UseLowQ2Range,false);
  295. tree->Add(BDToutputPath.c_str());
  296. coutDebug("Opening " + BDToutputPath);
  297. }
  298. coutDebug("eff sigma: " + to_string(effSigma));
  299. string sVariable = (UseDTF ? "B_plus_M_DTF" : "B_plus_M");
  300. string cutMass = Form("%s > %f && %s < %f",
  301. sVariable.c_str(), mean_sig - effSigma, sVariable.c_str(),
  302. mean_sig + effSigma);
  303. coutDebug("B mass cut: " + cutMass);
  304. //cut away resonances
  305. string cut = getFinalCut(false, false, false, "", gammaTMdefault, true, false, false, false, false, TMefficiencyClass(), -1, TMVAcut, RemoveMultiple);
  306. coutDebug("Using cut " + cut);
  307. //data: create histograms from tree
  308. tree->Draw(Form("%s>>B_plus_M_plot", sVariable.c_str()), cut.c_str());
  309. TH1 * histo = ((TH1 *) gPad->GetPrimitive("B_plus_M_plot"));
  310. Int_t EventsAfterPreSelection = histo->GetEntries();
  311. yield.allSigEvts = EventsAfterPreSelection;
  312. //Print signal, background and all evts
  313. string trackType = (Kst2Kspiplus && SplitDDandLL ? (KshortDecaysInVelo ? "LL Tracks: " : "DD Tracks: ") : ":");
  314. coutDebug(TheDecay + "[SIGNAL]: " + trackType + to_string(yield.sigYield));
  315. coutDebug(TheDecay + "[BCKGND]: " + trackType + to_string(yield.bkgYield));
  316. coutDebug(TheDecay + "[ALLEVTS]: " + trackType + to_string(yield.allSigEvts));
  317. coutInfo("Expected yield is: " + to_string(yield.sigYield) + "\t+-" + to_string(yield.sigYieldErr));
  318. coutDebug("Signal yield error: " + to_string(yield.sigYieldErr));
  319. coutDebug("Background yield error: " + to_string(yield.bkgYieldErr));
  320. coutDebug("Reference channel yield error: " + to_string(yield.refYieldErr));
  321. if (yield.refYield == 0) coutERROR("Reference channel yield is zero!");
  322. if (yield.sigYield == 0) coutERROR("Signal channel yield is zero! Abort.");
  323. return yield;
  324. }
  325. int SaveTGraphs(string path, bool fineScan, string year, int Run, string basicPath,
  326. TGraphErrors *yieldGraph, TGraphErrors *bkgGraph, TGraphErrors *bkgGraphFromAllEvts, TGraphErrors *refYieldGraph, TGraphErrors *allEvtsInSig, TGraphErrors *significance, TGraphErrors *significanceFromAllEvts){
  327. coutInfo("Making pretty plots and saving them!");
  328. coutDebug("Writting into " + path);
  329. coutDebug("Using basicPath " + basicPath);
  330. TFile * TGraphOutput = new TFile(path.c_str(), "RECREATE");
  331. TGraphOutput->cd();
  332. designYieldGraph(yieldGraph, Run, year, "sigYield", basicPath, TGraphOutput, false);
  333. designYieldGraph(bkgGraph, Run, year, "bkgYield", basicPath, TGraphOutput, false);
  334. designYieldGraph(bkgGraphFromAllEvts, Run, year, "bkgYield_fromAllEvts", basicPath, TGraphOutput, fineScan);
  335. designYieldGraph(refYieldGraph, Run, year, "refYield", basicPath, TGraphOutput, fineScan);
  336. designYieldGraph(significance, Run, year, "significance", basicPath, TGraphOutput, false);
  337. designYieldGraph(significanceFromAllEvts, Run, year, "significance_fromAllEvts", basicPath, TGraphOutput, fineScan);
  338. designYieldGraph(allEvtsInSig, Run, year, "EventsInSigRegion", basicPath, TGraphOutput, false);
  339. TGraphOutput->Close();
  340. return 1;
  341. }
  342. int ScanSignalAndBckgndEstimation(string year, int Run, Double_t BDTstep, bool KshortDecaysInVelo, bool UseLowQ2Range, bool scan, bool fineScan){
  343. //If Run==0, do the scan for year, if Run == 1/2, do the scan per run
  344. if (verboseLevel > 1)RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);
  345. bool section = true; //In case of fine scan, section the scan in more fine way
  346. int n_divisions = 3;
  347. //Get low TMVA response lower boundary
  348. Double_t lowBDTcut = (TMVAmethod == "MLP") ? 0.0 : -1.0;
  349. if (fineScan){
  350. coutInfo("Making fine BDT cut study.");
  351. lowBDTcut = 0.9;
  352. BDTstep = 0.001;
  353. }
  354. //prepare in case of polarity studies
  355. string magnet = "both";
  356. TGraphErrors *yieldGraph = new TGraphErrors();
  357. TGraphErrors *bkgGraph = new TGraphErrors();
  358. TGraphErrors *bkgGraphFromAllEvts = new TGraphErrors();
  359. TGraphErrors *refYieldGraph = new TGraphErrors();
  360. TGraphErrors *significance = new TGraphErrors();
  361. TGraphErrors *significanceFromAllEvts = new TGraphErrors();
  362. YieldInfo yield = YieldInfo(); //put zeroes everywhere
  363. //loop over BDT cuts
  364. coutInfo("Loop over BDT cuts with a step of " + to_string(BDTstep));
  365. coutDebug("Starting the loop at " + to_string(lowBDTcut));
  366. double tmpBDTcut = 0.0;
  367. for(double fBDTcut = lowBDTcut; fBDTcut < (section ? 0.999 : 1.0); fBDTcut += section ? ((1.0-fBDTcut)/double(n_divisions)) : BDTstep){
  368. for (int k = 0; k < n_divisions; k++){
  369. tmpBDTcut = fBDTcut + k*(1.0-fBDTcut)/double(n_divisions);
  370. yield = GetSigAndBkgEstimation(year, Run, KshortDecaysInVelo, UseLowQ2Range, tmpBDTcut, scan);
  371. yieldGraph ->SetPoint(yieldGraph->GetN(), tmpBDTcut, yield.sigYield);
  372. bkgGraphFromAllEvts ->SetPoint(bkgGraphFromAllEvts->GetN(), tmpBDTcut, yield.allSigEvts-yield.sigYield);
  373. bkgGraph ->SetPoint(bkgGraph->GetN(), tmpBDTcut, yield.bkgYield);
  374. refYieldGraph ->SetPoint(yieldGraph->GetN(), tmpBDTcut, yield.refYield);
  375. significance ->SetPoint(significance->GetN(), tmpBDTcut, yield.sigYield / (TMath::Sqrt(yield.sigYield + yield.bkgYield)));
  376. significanceFromAllEvts ->SetPoint(significance->GetN(), tmpBDTcut, yield.sigYield / (TMath::Sqrt(yield.allSigEvts)));
  377. coutDebug("---" + string(TMVAmethod) + " cut " + to_string(tmpBDTcut) + " yield: " + to_string(yield.sigYield) + ", background: " + to_string( yield.allSigEvts-yield.sigYield ));
  378. }
  379. }
  380. //Write to file and close
  381. string path = GetBDTScanFile(year, magnet, Run, KshortDecaysInVelo, UseLowQ2Range, fineScan);
  382. SaveTGraphs(path,fineScan,year,Run,path,yieldGraph,bkgGraph,bkgGraphFromAllEvts,refYieldGraph,NULL,significance,significanceFromAllEvts);
  383. coutInfo("Signal scan done for year " + year + "!");
  384. return 1;
  385. }
  386. int ScanSignalAndBckgndEstimationPerYear(string year = "2011", Double_t BDTstep = 0.01, bool KshortDecaysInVelo = true, bool UseLowQ2Range = false, bool scan = false, bool fineScan = false){
  387. return ScanSignalAndBckgndEstimation(year = "2011", 0, BDTstep, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
  388. }
  389. int ScanSignalAndBckgndEstimationAllYears(Double_t BDTstep = 0.01, bool KshortDecaysInVelo = true, bool UseLowQ2Range = false, bool scan = false, bool fineScan = true){
  390. for (auto yr: yearsData(12)) ScanSignalAndBckgndEstimationPerYear(yr, BDTstep, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
  391. return 1;
  392. }
  393. int ScanSignalAndBckgndEstimationSimple(string year = "2011",int Run = 1, Double_t BDTstep = 0.01, int randomSubset = 0,
  394. bool KshortDecaysInVelo = true, bool UseLowQ2Range = false, bool scan = false, bool fineScan = true){
  395. //Get low TMVA response lower boundary
  396. double lowBDTcut = (TMVAmethod == "MLP") ? 0.0 : -1.0;
  397. if (fineScan){
  398. coutInfo("Making fine BDT cut study.");
  399. lowBDTcut = 0.9;
  400. BDTstep = 0.002;
  401. }
  402. bool halve = true;
  403. //prepare in case of polarity studies
  404. string magnet = "both";
  405. TGraphErrors *yieldGraph = new TGraphErrors();
  406. TGraphErrors *bkgGraph = new TGraphErrors();
  407. TGraphErrors *bkgGraphFromAllEvts = new TGraphErrors();
  408. TGraphErrors *refYieldGraph = new TGraphErrors();
  409. TGraphErrors *allEvtsInSig = new TGraphErrors();
  410. TGraphErrors *significance = new TGraphErrors();
  411. TGraphErrors *significanceFromAllEvts = new TGraphErrors();
  412. YieldInfo yield = YieldInfo(); //put zeroes everywhere
  413. //loop over BDT cuts
  414. coutInfo("Loop over BDT cuts with a step of " + to_string(BDTstep));
  415. coutDebug("Starting the loop at " + to_string(lowBDTcut));
  416. int n_divisions = halve ? 3 : 1;
  417. double tmpcut = 0.0;
  418. for(double fBDTcut = lowBDTcut; fBDTcut < (halve ? 0.9999 : 1); fBDTcut += halve ? ((1.0-fBDTcut)/double(n_divisions)) : BDTstep){
  419. for (int k = 0; k < n_divisions-1; k++){
  420. tmpcut = fBDTcut + k*(1.0-fBDTcut)/double(n_divisions);
  421. coutDebug("Cutting at: " + to_string(tmpcut));
  422. yield =GetSigAndBkgEstimationFromData(year,Run, randomSubset, KshortDecaysInVelo, UseLowQ2Range, tmpcut, scan);
  423. //Save the efficiency
  424. yieldGraph ->SetPoint(yieldGraph->GetN(), tmpcut, yield.sigYield);
  425. yieldGraph ->SetPointError(yieldGraph->GetN()-1, 0, yield.sigYieldErr);
  426. bkgGraph ->SetPoint(bkgGraph->GetN(), tmpcut, yield.bkgYield);
  427. bkgGraph ->SetPointError(bkgGraph->GetN()-1, 0, yield.bkgYieldErr);
  428. bkgGraphFromAllEvts ->SetPoint(bkgGraph->GetN(), tmpcut, yield.allSigEvts-yield.sigYield);
  429. refYieldGraph ->SetPoint(yieldGraph->GetN(), tmpcut, yield.refYield);
  430. refYieldGraph ->SetPointError(yieldGraph->GetN()-1, 0, yield.refYieldErr);
  431. allEvtsInSig ->SetPoint(allEvtsInSig->GetN(), tmpcut, yield.allSigEvts);
  432. significance ->SetPoint(significance->GetN(), tmpcut, yield.sigYield / (TMath::Sqrt(yield.sigYield+yield.bkgYield)));
  433. significanceFromAllEvts ->SetPoint(significance->GetN(), tmpcut, yield.sigYield / (TMath::Sqrt(yield.allSigEvts)));
  434. coutDebug("---" + string(TMVAmethod) + " cut " + to_string(tmpcut) + " yield: " + to_string(yield.sigYield) + ", background: " + to_string( yield.allSigEvts-yield.sigYield ));
  435. }
  436. }
  437. //Write to file and close //TODO at some point
  438. string path = GetBDTScanFile(year, magnet, Run, KshortDecaysInVelo, UseLowQ2Range, fineScan);
  439. replace(path, ".root", "fromData.root");
  440. if (randomSubset == -1) replace(path,".root","_subset1.root");
  441. if (randomSubset == 1) replace(path,".root","_subset2.root");
  442. SaveTGraphs(path,fineScan,year,0,path,yieldGraph,bkgGraph,bkgGraphFromAllEvts,refYieldGraph,NULL,significance,significanceFromAllEvts);
  443. coutInfo("Signal scan done for Run " + to_string(Run) + "!");
  444. return 1;
  445. }
  446. 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){
  447. return ScanSignalAndBckgndEstimationSimple(year = "2011", 0, BDTstep, randomSubset, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
  448. }
  449. int ScanSignalAndBckgndEstimationSimpleAllYears(Double_t BDTstep = 0.01, int randomSubset = 0, bool KshortDecaysInVelo = true, bool UseLowQ2Range = false, bool scan = false, bool fineScan = true){
  450. for (auto yr: yearsData(12)) ScanSignalAndBckgndEstimationSimplePerYear(yr, BDTstep, randomSubset, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
  451. return 1;
  452. }
  453. double getMaxBDTresponse(string year = "2011", int Run = 0, bool fineScan = false, bool directScan = false, int randomSubset = 0, bool KshortDecaysInVelo = true, bool UseLowQ2Range = false){
  454. //prepare in case of polarity studies
  455. string magnet = "both";
  456. if (Run == 0) coutInfo("Getting BDTresponse with highest significance for YEAR " + year + ". . .");
  457. else coutInfo("Getting BDTresponse with highest significance for RUN "+to_string(Run)+". . .");
  458. string path = GetBDTScanFile(year, magnet, Run, KshortDecaysInVelo, UseLowQ2Range, fineScan);
  459. if (directScan) replace(path, ".root", "fromData.root");
  460. if (randomSubset == -1) replace(path,".root","_subset1.root");
  461. if (randomSubset == 1) replace(path,".root","_subset2.root");
  462. TGraphErrors *significance = new TGraphErrors();
  463. TFile *scanFile = new TFile(path.c_str(),"OPEN");
  464. string graphName = "significance_fromAllEvts";
  465. significance = (TGraphErrors*) scanFile->Get(graphName.c_str());
  466. if(significance == NULL){
  467. coutERROR("TGraphError was not found in the file!");
  468. coutERROR("File:\t" + path);
  469. coutERROR("TGraph:\t" + graphName);
  470. return 0;
  471. }
  472. //Get the best BDTcut
  473. double LargestFoM = -100.;
  474. double bestCut = 0.0;
  475. for(int p = 0; p < significance->GetN(); p++){
  476. if(significance->GetY()[p] > LargestFoM){
  477. LargestFoM = significance->GetY()[p];
  478. bestCut = significance->GetX()[p];
  479. }
  480. }
  481. return bestCut;
  482. }
  483. int optimizeBDTCut(string year = "2011", int Run = 0, bool KshortDecaysInVelo = true, Double_t BDTstep = 0.01, bool UseRandomSubset = false,
  484. bool UseLowQ2Range = false, bool scan = false, bool fineScan = false, bool directScan = false){
  485. //Get low TMVA response lower boundary
  486. double lowBDTcut = (TMVAmethod == "MLP") ? 0.0 : -1.0;
  487. if (fineScan){
  488. coutInfo("Making fine BDT cut study.");
  489. lowBDTcut = 0.9;
  490. BDTstep = 0.002;
  491. }
  492. double BestCut = 0;
  493. if (directScan){
  494. if (UseRandomSubset){
  495. ScanSignalAndBckgndEstimationSimple(year, Run, BDTstep, -1, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
  496. ScanSignalAndBckgndEstimationSimple(year, Run, BDTstep, +1, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
  497. double BestCut1 = getMaxBDTresponse(year, Run, fineScan, true, -1, KshortDecaysInVelo, UseLowQ2Range);
  498. double BestCut2 = getMaxBDTresponse(year, Run, fineScan, true, +1, KshortDecaysInVelo, UseLowQ2Range);
  499. BestCut = roundf(BestCut1 * 100) / 100 +roundf(BestCut2 * 100); // round to 2 decimal points, return e.g. 0.96 + 94 (easy to untangle)
  500. }
  501. else{
  502. ScanSignalAndBckgndEstimationSimple(year, Run, BDTstep, 0, KshortDecaysInVelo, UseLowQ2Range, scan, fineScan);
  503. BestCut = getMaxBDTresponse(year, Run, fineScan, true, 0, KshortDecaysInVelo, UseLowQ2Range);
  504. }
  505. //TODO
  506. }
  507. else{ //TODO: add subset fits
  508. if (Run == 0){
  509. ScanSignalAndBckgndEstimationPerYear(year,BDTstep,KshortDecaysInVelo,UseLowQ2Range,scan,fineScan);
  510. }
  511. else{
  512. ScanSignalAndBckgndEstimation(year,Run,BDTstep,KshortDecaysInVelo,UseLowQ2Range,scan,fineScan);
  513. }
  514. //TODO make a pretty plot
  515. BestCut = getMaxBDTresponse(year, Run, fineScan, false, 0, KshortDecaysInVelo, UseLowQ2Range);
  516. }
  517. return BestCut;
  518. }