//Renata Kopecna #include #include #include // std::istringstream #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //Do the actuall background fit int backgroundfit(fcnc::options opts, bool fitReference, bool LowMassFit, bool HighMassFit, bool fitKpi, bool Use2DAngularBins, basic_params params){ //params now only used to tag nBins in the names //Technically, this should be simFit between Run 1 and 2, but since we need it only for the toys atm, no need for it gROOT->SetBatch(kTRUE); gROOT->SetStyle("Plain"); set_gStyle(); //Open texFile std::ofstream myFile; open_Latex_noteFile(latex_bkgFit(), myFile); spdlog::info("[FIT]\t\tFit only angular and m(Kpi) background"); //Used to check whether the background is "correlated" between each other //TODO: not needed atm, maybe fix later /* 1D angular bins 1: ctl < -0.5 2: -0.5 < ctl < 0.0 3: 0.0 < ctl < 0.5 4: 0.5 < ctl 5: ctk < -0.5 6: -0.5 < ctk < 0.0 7: 0.0 < ctk < 0.5 8: 0.5 < ctk */ /* 2D angular bins 1: ctl < 0.0 && ctk < 0.0 2: ctl < 0.0 && ctk > 0.0 3: ctl > 0.0 && ctk < 0.0 4: ctl > 0.0 && ctk > 0.0 */ double HighBpeakCut = fitReference ? B_MASS_HIGH_BKG_REF : B_MASS_HIGH_BKG; double LowBpeakCut = fitReference ? B_MASS_LOW_BKG_REF : B_MASS_LOW_BKG; assert(!(HighMassFit && LowMassFit)); opts.fit_full_angular_bkg = true; opts.only_angles = !(HighMassFit || LowMassFit); //Fit mass only if one sideband is selected opts.only_Bmass = false; opts.only_mkpi = false; opts.swave = false; opts.bkg_order_costhetak = 5; opts.shift_lh = false; //keep it, it was there before opts.weighted_fit = true; opts.squared_hesse = true; opts.minos_errors = false; opts.asymptotic = false; opts.flat_bkg = false; opts.fit_mkpi = false; //set to true only later opts.use_mkpi = false; opts.simple_mkpi = false; //S-wave model opts.isobar = false; //S-wave model //Plotting options opts.plot_chi2 = false; opts.plots_m_bins = 20; opts.plots_mkpi_bins = 20; //load events from data tuple std::vector>events; std::vector run_idx; if (opts.run == 1 || opts.run == 12){ std::vector tmp = fcnc::load_events(get_theFCNCpath(0,1), "Events", -1); if (!fitReference) events.push_back(fcnc::filterResonances(tmp)); else events.push_back(tmp); run_idx.push_back(1); } if (opts.run == 2 || opts.run == 12){ std::vector tmp = fcnc::load_events(get_theFCNCpath(0,2), "Events", -1); if (!fitReference) events.push_back(fcnc::filterResonances(tmp)); else events.push_back(tmp); run_idx.push_back(2); } std::vector fitresults; //determine number of bins: const UInt_t nBins = opts.TheQ2binsmin.size(); //current fitter, plotter, parameteres and pdfs: fcnc::fitter f(&opts); fcnc::folder fldr(&opts); fcnc::bu2kstarmumu_plotter thePlotter(&opts); fcnc::bu2kstarmumu_parameters * theParams[nBins]; fcnc::bu2kstarmumu_pdf * theProb[nBins]; std::vector * theEvents[nBins]; for(UInt_t b = 0; b < nBins; b++){ theParams[b] = new fcnc::bu2kstarmumu_parameters(&opts); theProb[b] = new fcnc::bu2kstarmumu_pdf(&opts, theParams[b]); theEvents[b] = new std::vector(); //Init parameters theParams[b]->f_sig.init_fixed(0.0); theParams[b]->m_b.init(PDGMASS_B, HighMassFit ? HighBpeakCut : B_MASS_LOW, LowMassFit ? LowBpeakCut : B_MASS_HIGH, 0.0); //The rest of the mass parameters can be left to default values //They are defined in bu2kstamumu_parameters //Init the bkg shape theParams[b]->init_angular_background_parameters(fitReference,0.1); //Init the mass bkg shape theParams[b]->init_mass_background_parameters(nBins,b,true); //theParams[b]->cbkgctk3.init_fixed(-2.5); //Select events for_indexed(auto evts: events){ //update weights according to sub-set for all events opts.run = run_idx.at(i); opts.update_efficiencies = true; theProb[b]->load_coeffs_eff_phsp_4d(); theProb[b]->update_cached_normalization(theParams[b]); theProb[b]->update_cached_efficiencies(theParams[b], &evts); opts.update_angle_ranges(); //Update angles to get rid of events that cannot be folded //select events spdlog::debug("Loop over {0:d} events and select the suitable ones", evts.size()); for(auto meas: evts){ if(meas.q2 < opts.TheQ2binsmin.at(b) || meas.q2 > opts.TheQ2binsmax.at(b)) continue; if(meas.m < opts.m_low || meas.m > opts.m_high) continue; if(LowMassFit && meas.m > LowBpeakCut) continue; else if(HighMassFit && meas.m < HighBpeakCut) continue; else if(meas.m > LowBpeakCut && meas.m < HighBpeakCut) continue; if(meas.mkpi < opts.mkpi_min || meas.mkpi > opts.mkpi_max) continue; if(params.bin > 1){ bool keep_event = true; if(Use2DAngularBins){ switch(params.bin){ case 2: if(meas.costhetal > 0.0 || meas.costhetak > 0.0) keep_event = false; break; case 3: if(meas.costhetal > 0.0 || meas.costhetak < 0.0) keep_event = false; break; case 4: if(meas.costhetal < 0.0 || meas.costhetak > 0.0) keep_event = false; break; case 5: if(meas.costhetal < 0.0 || meas.costhetak < 0.0) keep_event = false; break; } } else{ //1D angular bins switch(params.bin){ case 2: if(meas.costhetal > -0.5) keep_event = false; break; case 3: if(meas.costhetal < -0.5 || meas.costhetal > 0.0) keep_event = false;; break; case 4: if(meas.costhetal < 0.0 || meas.costhetal > 0.5) keep_event = false;; break; case 5: if(meas.costhetal > 0.5) keep_event = false;; break; case 6: if(meas.costhetak > -0.5) keep_event = false;; break; case 7: if(meas.costhetak < -0.5 || meas.costhetak > 0.0) keep_event = false;; break; case 8: if(meas.costhetak < 0.0 || meas.costhetak > 0.5) keep_event = false;; break; case 9: if(meas.costhetak > 0.5) keep_event = false;; break; } } if(!keep_event) continue; } if(!filterFldFour(&meas, &opts)) continue; fldr.fold(&meas); //only one combined event vector theEvents[b]->push_back(meas); } spdlog::debug("Selected {0:d} events.", theEvents[b]->size()); } spdlog::info("[BIN {0:d}]\tDone!",b); }//end loop over bins //do not update cached efficiencies anyomre, to keep individual ones for four sub-sets opts.update_efficiencies = false; //create 2D correlation plots for all angles (3) and all bins (8): 3! * 8 = 24 const unsigned int nANGLES = 3; double hmin[nANGLES] = {CTL_MIN, CTK_MIN, PHI_MIN}; double hmax[nANGLES] = {CTL_MAX, CTK_MAX, PHI_MAX}; double corrfactor[nBins][nANGLES][nANGLES]; const int nCorrBins = 10; for(UInt_t b = 0; b < nBins; b++){ spdlog::info("[START]\tStart the background 2D correlation plotting for bin #{0:d}", b); for(UInt_t a = 0; a < nANGLES - 1; a++){ for(UInt_t aa = a + 1; aa < nANGLES; aa++){ std::string mainName = "bckgnd_correl_"+ANGLES[a]+"_"+ANGLES[aa]+"_q2bin"+std::to_string(b); TCanvas * cAngCorr = new TCanvas(("c"+mainName).c_str(), ("c"+mainName).c_str(), 1400, 1200); cAngCorr->cd()->SetMargin(0.1,0.125,0.125,0.125); cAngCorr->cd(); TH2D * h = new TH2D((mainName).c_str(), (mainName+";"+latex_angles[a]+";"+latex_angles[aa]).c_str(), nCorrBins, hmin[a], hmax[a], nCorrBins, hmin[aa], hmax[aa]); for(UInt_t e = 0; e < theEvents[b]->size(); e++){ fcnc::event meas = theEvents[b]->at(e); double x=0.0, y=0.0; switch(a){ //TODO: make a function in helpers case 0: x = meas.costhetal; break; case 1: x = meas.costhetak; break; } switch(aa){ case 1: y = meas.costhetak; break; case 2: y = meas.phi; break; } h->Fill(x, y); } h->GetZaxis()->SetRangeUser(0, fitReference ? 25 : 5); h->GetZaxis()->SetTitle("Number of entries"); h->GetXaxis()->SetTitleSize(0.05); h->GetXaxis()->SetLabelSize(0.05); h->GetXaxis()->SetTitleOffset(0.95); h->GetYaxis()->SetTitleSize(0.05); h->GetYaxis()->SetLabelSize(0.05); h->GetYaxis()->SetTitleOffset(0.75); h->GetZaxis()->SetTitleSize(0.05); h->GetZaxis()->SetLabelSize(0.05); h->GetZaxis()->SetTitleOffset(0.75); h->SetTitle(""); h->Draw("COLZ"); corrfactor[b][a][aa] = h->GetCorrelationFactor(); TLatex * leg = getPrettyTex(0.06,13); leg->SetTextColor(kBlack); std::ostringstream sCorrout; //TODO: move the path sCorrout << std::fixed << std::setprecision(2) << "corr(" << latex_angles[a] << ", " << latex_angles[aa] <<") = " << corrfactor[b][a][aa]*100. << "\%"; leg->DrawLatex(0.22,0.98, sCorrout.str().c_str()); leg->SetTextSize(0.04); leg->DrawLatex(0.25,0.92, ("Events: "+std::to_string((int) h->GetEntries())).c_str()); cAngCorr->Print(get_bkgCorrPlot_path(ANGLES[a],ANGLES[aa],b,nBins,fitReference, LowMassFit, HighMassFit, fitKpi, params).c_str(), "eps"); } } //Save the correlations s myFile << "\\begin{tabular}{r|ccc}\\hline" << std::endl; myFile << std::fixed << std::setprecision(2) << "[" << opts.TheQ2binsmin.at(b) << ", " << opts.TheQ2binsmax.at(b) << "]"; for(UInt_t a = 0; a < nANGLES; a++) myFile << "\t&" << latex_2angles[a]; myFile << "\\\\" << std::endl; myFile << "\\hline\\hline" << std::endl; for(UInt_t a = 0; a < nANGLES; a++){ myFile << latex_2angles[a]; for(UInt_t aa = 0; aa < nANGLES; aa++){ myFile << "\t&"; if(aa > a) myFile << std::setprecision(3) << std::fixed << corrfactor[b][a][aa]; else if(aa == a) myFile << "1.00"; else if(aa < a) myFile << " "; } myFile << "\\\\" << std::endl; } myFile << "\\hline" << std::endl; myFile << "\\end{tabular}"<< std::endl; myFile << std::endl; } //FIT ANGULAR BACKGROUND + B mass opts.update_angle_ranges(); //Just in case //fit all bins: for(UInt_t b = 0; b < nBins; b++){ spdlog::info("[START]\tStart the fit for bin #{0:d}", b); //fit the events: int fitresult = f.fit(theProb[b], theParams[b], theEvents[b]); fitresults.push_back(fitresult); spdlog::info("[BIN{0:d}]:\tFitresult: {1:d}", b, fitresult); //plot pdf with the data points: opts.plot_label = "LHCb data"; opts.q2_label = q2_label(opts.TheQ2binsmin.at(b), opts.TheQ2binsmax.at(b)); if(opts.write_eps){ std::string label = get_bkg_tag(b,nBins,fitReference, LowMassFit, HighMassFit, false, params); spdlog::info("[PLOT]\t" + label); thePlotter.plot_data(theProb[b], theParams[b], theEvents[b], get_bkgFitPlot_path(), label, false); } //print all parameters std::string fitResultTxt = get_bkgFitResult_path()+ "fitresult_" + get_bkg_tag(b,nBins,fitReference, LowMassFit, HighMassFit, false, params); spdlog::debug("Saving into "+fitResultTxt); print_all_parameters(nBins, theParams, 2, fitResultTxt); } //print all fitresults print_fit_results(nBins, fitresults); //Save results to root file std::string results_file = final_result_name_bkg(nBins, fitReference, LowMassFit, HighMassFit, false, params); save_results(results_file, nBins, params.Run, fitresults, theParams, &opts); //FIT M(KPI) BACKGROUND if (!fitKpi){ //first check if you really want to fit M(KPI) :) //Close Latex file myFile.close(); return 0; } //Reset the options opts.only_angles = false; opts.only_mkpi = true; opts.fit_mkpi = true; //fit all bins: spdlog::info("[BKGFIT]\tFit the Kpi mass"); for(UInt_t b = 0; b < nBins; b++){ theParams[b]->use_default_bkg(); //null the lambda(s) and taus theParams[b]->m_lambda.init_fixed(0.0); theParams[b]->m_lambda_2.init_fixed(0.0); theParams[b]->m_tau.init_fixed(0.0); theParams[b]->m_tau_2.init_fixed(0.0); //Init the floating parameters theParams[b]->init_kpi_background_parameters(fitReference,0.01); spdlog::info("[START]\tStart the fit for bin #{0:d}", b); //fit the events: fitresults.push_back(f.fit(theProb[b], theParams[b], theEvents[b])); spdlog::info("[BIN{0:d} ]:\tFitresult: {1:d}",b, fitresults.at(b)); //plot pdf with the data points: opts.q2_label = q2_label(opts.TheQ2binsmin.at(b), opts.TheQ2binsmax.at(b)); if(opts.write_eps){ std::string label = get_bkg_tag(b,nBins,fitReference, LowMassFit, HighMassFit, false, params); spdlog::info("[PLOT]\t" + label); thePlotter.plot_data(theProb[b], theParams[b], theEvents[b], get_bkgFitPlot_path(), label, false); } //Print all parameters, but don't save print_all_parameters(nBins, theParams, 2, ""); //print all parameters to txt file std::string fitResultTxt = get_bkgFitResult_path()+ "fitresult_" + get_bkg_tag(b,nBins,fitReference, LowMassFit, HighMassFit, true, params); spdlog::debug("Saving into "+fitResultTxt); print_all_parameters(nBins, theParams, 2, fitResultTxt); } spdlog::info("[BKGFIT]\tDone with Kpi fit."); //Save results to root file results_file = final_result_name_bkg(nBins, fitReference, LowMassFit, HighMassFit, true, params); save_results(results_file, nBins, params.Run, fitresults, theParams, &opts); //Close Latex file myFile.close(); spdlog::info("[BKGFIT]\tFinished."); return 0; }