//Renata Kopecna #include #include #include // std::istringstream #include #include #include #include #include #include #include #include //fixConstr constructor fixConstr::fixConstr(bool b_fix,bool b_constr){ if (b_fix && b_constr){ //Check if both constrain and fix are set to true //If yes, set constrain to false without modifying the input bools spdlog::warn("Cannot both fix and constrain a parameter.\n The parameter is fixed, setting constrain to false."); spdlog::warn("Check your options."); fix = true; constrain = false; return; } fix = b_fix; constrain = b_constr; return; } using namespace fcnc; void bu2kstarmumu_parameters::use_default_bkg(){ //Set all backgrounds to be flat cbkgctl0.init(1.0, -1.0, 1.0, 0.0); cbkgctl1.init(0.0, -1.0, 1.0, 0.0); cbkgctl2.init(0.0, -1.0, 1.0, 0.0); cbkgctl3.init(0.0, -1.0, 1.0, 0.0); cbkgctl4.init(0.0, -1.0, 1.0, 0.0); cbkgctk0.init(1.0, -1.0, 1.0, 0.0); cbkgctk1.init(0.0, -1.0, 1.0, 0.0); cbkgctk2.init(0.0, -1.0, 1.0, 0.0); cbkgctk3.init(0.0, -1.0, 1.0, 0.0); cbkgctk4.init(0.0, -1.0, 1.0, 0.0); cbkgctk5.init(0.0, -1.0, 1.0, 0.0); cbkgctk6.init(0.0, -1.0, 1.0, 0.0); cbkgphi0.init(1.0, -1.0, 1.0, 0.0); cbkgphi1.init(0.0, -1.0, 1.0, 0.0); cbkgphi2.init(0.0, -1.0, 1.0, 0.0); cbkgphi3.init(0.0, -1.0, 1.0, 0.0); cbkgphi4.init(0.0, -1.0, 1.0, 0.0); cbkgmkpi0.init(1.0, -1.0, 1.0, 0.0); cbkgmkpi1.init(0.0, -1.0, 1.0, 0.0); cbkgmkpi2.init(0.0, -1.0, 1.0, 0.0); cbkgmkpi3.init(0.0, -1.0, 1.0, 0.0); cbkgmkpi4.init(0.0, -1.0, 1.0, 0.0); cswavemkpi0.init(1.0, -1.0, 1.0, 0.0); cswavemkpi1.init(0.0, -1.0, 1.0, 0.0); cswavemkpi2.init(0.0, -1.0, 1.0, 0.0); cswavemkpi3.init(0.0, -1.0, 1.0, 0.0); cswavemkpi4.init(0.0, -1.0, 1.0, 0.0); cbkgp20.init(1.0, -1.0, 1.0, 0.0); cbkgp21.init(0.0, -1.0, 1.0, 0.0); cbkgp22.init(0.0, -1.0, 1.0, 0.0); cbkgp23.init(0.0, -1.0, 1.0, 0.0); cbkgp24.init(0.0, -1.0, 1.0, 0.0); } void bu2kstarmumu_parameters::use_default_observables(){ if (opts->fit_pprimes){ Fl.init (0.7, 0.0, 2.0*PAR_ANG_RANGE, 0.0); P1.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); P2.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); P3.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); P4.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); P5.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); P6.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); P8.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); } else{ Fl.init (0.7, 0.0, 2.0*PAR_ANG_RANGE, 0.0); S1s.init(0.7, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S3.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S4.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S5.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); Afb.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S6s.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S7.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S8.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S9.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); } return; } //This function is used in the parameters constructor! void bu2kstarmumu_parameters::use_default(){ Fl.init (0.7, 0.0, 2.0*PAR_ANG_RANGE, 0.0); S1s.init(0.7, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S3.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S4.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S5.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); Afb.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S6s.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S7.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S8.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); S9.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); P1.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); P2.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); P3.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); P4.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); P5.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); P6.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); P8.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); //S-wave parameters FS.init (0.0, 0.0, 2*PAR_ANG_RANGE, 0.0); SS1.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); SS2.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); SS3.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); SS4.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); SS5.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); //signal fraction f_sig.init(PAR_N_SIG/(PAR_N_SIG+PAR_N_BKG), 0.0, 1.0, 0.0); n_sig.init(PAR_N_SIG, 0.0, 1.0e+6, 0.0); n_bkg.init(PAR_N_BKG, 0.0, 1.0e+6, 0.0); //mass parameters m_b.init (PDGMASS_B, B_MASS_LOW, B_MASS_HIGH, 0.0); m_res_1.init (DOUBLE_CB ? 1.0 : 0.5, 0.0, 1.0, 0.0); m_sigma_1.init(PAR_SIGMA, PAR_SIGMA_LOW, PAR_SIGMA_HIGH, 0.0); m_sigma_2.init(DOUBLE_CB ? 0.0 : PAR_SIGMA, PAR_SIGMA_LOW, PAR_SIGMA_HIGH, 0.0); //crystal ball m_scale.init(1.0, 0.0, 2.0, 0.0); alpha_1.init(1.0, 0.1, 10.0, 0.0); n_1.init (1.0, 0.1, 10.0, 0.0); alpha_2.init(1.0, 0.1, 10.0, 0.0); n_2.init (1.0, 0.1, 10.0, 0.0); fm_tau.init(FIX_FM ? 1.0 : 0.5, 0.0, 1.0, 0.0); m_tau.init(PAR_TAU, PAR_TAU/PAR_TAU_SCALE, PAR_TAU*PAR_TAU_SCALE, 0.0); m_tau_2.init(PAR_TAU, PAR_TAU/PAR_TAU_SCALE, PAR_TAU*PAR_TAU_SCALE, 0.0); m_lambda.init(PAR_LAMBDA, PAR_LAMBDA/PAR_LAMBDA_SCALE, PAR_LAMBDA*PAR_LAMBDA_SCALE, 0.0); m_lambda_2.init(PAR_LAMBDA, PAR_LAMBDA/PAR_LAMBDA_SCALE, PAR_LAMBDA*PAR_LAMBDA_SCALE, 0.0); //Welp, this will end up in Jpsi, but whatever :) eff_q2.init(bin_center(Q2_MIN_RANGE,Q2_MAX_RANGE), Q2_MIN_RANGE, Q2_MAX_RANGE, 0.0); //TODO: figure out what these are asphase.init(MY_PI, 0.0, 2.0*MY_PI, 0.0); a.init(1.0, 0.0, 10.0, 0.0); r.init(1.0, 0.0, 10.0, 0.0); gammakstar.init(PAR_KSTAR_WIDTH/1.0e3, 0.01, PAR_KSTAR_WIDTH/0.5e3, 0.0); //With of K* mkstar.init(PDGMASS_K_STAR_PLUS/1.0e3, (K_ONE_PLUS-PAR_KSTAR_WIDTH)/1.0e3, (K_ONE_PLUS+PAR_KSTAR_WIDTH)/1.0e3, 0.0); //This is a K1 or K something mkstarplus.init(K_ONE_PLUS/1.0e3, (K_ONE_PLUS-PAR_K1_WIDTH)/1.0e3, (K_ONE_PLUS+PAR_K1_WIDTH)/1.0e3, 0.0); gammakstarplus.init(PAR_K1_WIDTH/1.0e3, 0.01, PAR_K1_WIDTH/0.5e3, 0.0); //Width of K1 nthreshold.init(PAR_NTRESHOLD, 1.0, 10.0, 0.0); R.init(1.6, 0.0, 10.0, 0.0); //Some other fancy resonances //TODO ask Eluned mf800.init(0.682, 0.1, 1.0, 0.0); gammaf800.init(0.547, 0.1, 1.0, 0.0); f800mag.init(0.1, 0.0, 1.0, 0.0); f800phase.init(0.5*MY_PI, -2.0*MY_PI, +2.0*MY_PI, 0.0); //Set all backgrounds to be flat use_default_bkg(); } void bu2kstarmumu_parameters::load_param_values(std::string filename){ std::ifstream file(filename.c_str());; std::string line = ""; if (file.is_open()){ spdlog::info("Parameter values are being read from file "+filename+"."); } else{ spdlog::error("Could not load values from file " + filename);; assert(0); } UInt_t p_index; std::string p_name; Float_t p_value; Float_t p_error; //loop over lines in file and read values and errors of all parameters while(true){ //Jesus christ, another while(true). Shoot me, please. getline(file, line); spdlog::debug("Line: "+line);; if(file.eof()) break; std::istringstream istr(line); istr >> p_index; istr >> p_name; istr >> p_value; istr >> p_error; //sanity check to make sure the parameter index fits to the parameter name: if(p_name != this->get_parameter(p_index)->get_name()){ spdlog::critical("Trying to assign values of var=" + p_name + " to parameter=" + this->get_parameter(p_index)->get_name());; assert(p_name == this->get_parameter(p_index)->get_name()); } //assign value and error from file to parameters this->get_parameter(p_index)->set_values_n_errors(p_value, p_error); } file.close(); } void bu2kstarmumu_parameters::load_param(std::string filename, std::string parname){ std::ifstream file(filename.c_str());; std::string line = ""; if (!file.is_open()){ spdlog::error("\tCould not open file " + filename); assert(0); } UInt_t p_index; std::string p_name; Float_t p_value; Float_t p_error; //loop over lines in file and read values and errors of all parameters while(true){ //Dear kids, getline(file, line); spdlog::debug("Line: " + line); if(file.eof()) break; //never ever write code like this. Even at gunpoint. Don't. std::istringstream istr(line); istr >> p_index; istr >> p_name; istr >> p_value; istr >> p_error; //continue if param name is identical if(p_name != parname) continue; spdlog::debug("Load parameter: " + p_name + "={0:f}", p_value); //sanity check to make sure the parameter index fits to the parameter name: assert(p_name == this->get_parameter(p_index)->get_name()); //assign value and error from file to parameters this->get_parameter(p_index)->set_values_n_errors(p_value, p_error); } file.close(); return; } double get_param_valueError_from_rootfile(std::string fileName, std::string name, int PDF, int bin, bool getError){ //Retuns a value for given parametr from a given rootfile //Open file spdlog::info("Opening " + fileName); TFile* file = new TFile(fileName.c_str(), "READ"); if (!file->GetListOfKeys()->Contains(name.c_str())){ spdlog::critical("Wrong tree name " + name + "! Abort."); assert(0); } //Get the tree and set the branches to active TTree* tree = (TTree*)file->Get(name.c_str()); tree->SetBranchStatus("*",1); //Activate all branches //The root file is saved in a way that first bins in first pdf is saved //then the next pdf is saved, bin by bin //Meaning if I want to load event from bin 2 and pdf 1 //tree->GetEntry(2) //If I want to load event from bin 2 and pdf 2, one needs to do //tree->GetEntry(totBins+2) //PDFs are named according to the Run! So if only Run 2 is fitted, the returned pdf is 2 //This implementation is actually useful for checks //Therefore, starting entry is equal to int bin int entry_position = bin; //Read the q2 bins int totBins = DEFAULT_TREE_INT; int pdf_idx = DEFAULT_TREE_INT; int bin_idx = DEFAULT_TREE_INT; double value = DEFAULT_TREE_VAL; double error = DEFAULT_TREE_ERR; int migrad = DEFAULT_TREE_INT; tree->SetBranchAddress("totBins", &totBins); tree->SetBranchAddress("pdf", &pdf_idx); tree->SetBranchAddress("bin", &bin_idx); tree->SetBranchAddress("value",&value); tree->SetBranchAddress("migrad",&migrad); tree->SetBranchAddress("error",&error); tree->GetEntry(entry_position); //Check whether we got the right bin position if (bin_idx != bin){ spdlog::critical("Something went very wrong for "+name); spdlog::critical("The read pdf {0:d} from position {1:d} doesn't agree with the wanted bin {2:d}", pdf_idx, entry_position, bin); assert(0); } while (pdf_idx != PDF){ entry_position += totBins; if (entry_position >= tree->GetEntries()){ spdlog::critical("Required PDF {0:d} for " + name + " not found!",PDF); assert(0); } tree->GetEntry(entry_position); } //Check if migrad makes sense if (migrad != 0){ spdlog::warn("Careful! You are reading a fit that had failed migrad for " + name + "!"); printMigradStatus(migrad); } file->Close(); spdlog::debug("Loaded " + name + " value is {0:f}", value); return getError ? error : value; } double get_param_value_from_rootfile(std::string fileName, std::string name, int PDF, int bin){ return get_param_valueError_from_rootfile(fileName, name, PDF, bin, false); } double get_param_error_from_rootfile(std::string fileName, std::string name, int PDF, int bin){ return get_param_valueError_from_rootfile(fileName, name, PDF, bin, true); } int bu2kstarmumu_parameters::get_param_from_rootfile(std::string fileName, std::vector names, int PDF, int bin, fixConstr FC){ //Open file spdlog::info("Opening " + fileName); TFile* file = new TFile(fileName.c_str(), "READ"); for (auto name: names){ if (!file->GetListOfKeys()->Contains(name.c_str())){ spdlog::critical("Wrong tree name " + name + "! Abort."); assert(0); } //Get the tree and set the branches to active TTree* tree = (TTree*)file->Get(name.c_str()); tree->SetBranchStatus("*",1); //Activate all branches //The root file is saved in a way that first bins in first pdf is saved //then the next pdf is saved, bin by bin //Meaning if I want to load event from bin 2 and pdf 1 //tree->GetEntry(2) //If I want to load event from bin 2 and pdf 2, one needs to do //tree->GetEntry(totBins+2) //PDFs are named according to the Run! So if only Run 2 is fitted, the returned pdf is 2 //This implementation is actually useful for checks //Therefore, starting entry is equal to int bin int entry_position = bin; //Read the q2 bins int totBins = DEFAULT_TREE_INT; int pdf_idx = DEFAULT_TREE_INT; int bin_idx = DEFAULT_TREE_INT; tree->SetBranchAddress("totBins", &totBins); tree->SetBranchAddress("pdf", &pdf_idx); tree->SetBranchAddress("bin", &bin_idx); //Now get all the parameters int migrad = DEFAULT_TREE_INT; int param_index = DEFAULT_TREE_INT; double value = DEFAULT_TREE_VAL; double error = DEFAULT_TREE_ERR; double error_up = DEFAULT_TREE_ERR; double error_down = DEFAULT_TREE_ERR; double start_value = DEFAULT_TREE_VAL; double prev_value = DEFAULT_TREE_VAL; double prev_error = DEFAULT_TREE_ERR; tree->SetBranchAddress("value",&value); tree->SetBranchAddress("error",&error); tree->SetBranchAddress("error_up",&error_up); tree->SetBranchAddress("error_down",&error_down); tree->SetBranchAddress("start_value",&start_value); //Not really used: TODO tree->SetBranchAddress("prev_value",&prev_value); //Not really used: TODO tree->SetBranchAddress("prev_error",&prev_error); //Not really used: TODO tree->SetBranchAddress("index",¶m_index); tree->SetBranchAddress("migrad",&migrad); tree->GetEntry(entry_position); //Check whether the file contains correct numbers of bins //If totBins are 1, let's assume this is fine and we are reading from ReferenceChannel if (unsigned (totBins) != opts->TheQ2binsmin.size() && totBins != 1){ spdlog::warn("Wrong number of bins for " + name + "!"); spdlog::warn("totBins = {0:d}\tnQ2bins= {1:d}",totBins,opts->TheQ2binsmin.size()); } if (bin_idx != bin){ spdlog::critical("Something went very wrong for "+name); spdlog::critical("The read pdf {0:d} from position {1:d} doesn't agree with the wanted bin {2:d}", pdf_idx, entry_position, bin); assert(0); } while (pdf_idx != PDF){ entry_position += totBins; if (entry_position >= tree->GetEntries()){ spdlog::critical("Required PDF {0:d} for " + name + " not found!",PDF); assert(0); } tree->GetEntry(entry_position); } //Check if migrad makes sense if (migrad != 0){ spdlog::warn("Careful! You are reading a fit that had failed migrad for " + name + "!"); printMigradStatus(migrad); } //if opts->hesse is non-active, use error for both error_up and error_down if(error_down == DEFAULT_TREE_ERR) error_down = error; if(error_up == DEFAULT_TREE_ERR) error_up = error; //Init parameter double stepsize = GetParamStepsize(name); //TODO check if (FC.fix) stepsize = 0.0; else if (stepsize < 0.001) stepsize = 0.01; //Protect zeroes //TODO: possibly add some protection against very very small numbers, but if it works as it is, no need to make it fancier this->get_parameter(param_index)->set_previous_measurement(prev_value); if (FC.constrain){ if (error_down==0) error_down = 0.01; if (error_up==0) error_up = 0.01; } std::vector param_range = GetParamRange(name); this->get_parameter(param_index)->init(value, param_range.front(), param_range.back(), stepsize,error_down,error_up,FC.constrain); } file->Close(); return 0; } int bu2kstarmumu_parameters::fix_param_from_rootfile(std::string fileName,std::vector names, int PDF, int bin){ return get_param_from_rootfile(fileName, names, PDF, bin, fixConstr(true,false)); } int bu2kstarmumu_parameters::constrain_param_from_rootfile(std::string fileName,std::vector names, int PDF, int bin){ return get_param_from_rootfile(fileName, names, PDF, bin, fixConstr(false,true)); } int bu2kstarmumu_parameters::load_param_from_rootfile(std::string fileName,std::vector names, int PDF, int bin){ return get_param_from_rootfile(fileName, names, PDF, bin, fixConstr(false, false)); } //TODO: the following ones are not needed, as the string vector can be used instead.... void bu2kstarmumu_parameters::load_only_bckgnd_param_values(std::string filename){ this->load_param(filename, "cbkgmkpi0"); this->load_param(filename, "cbkgmkpi1"); this->load_param(filename, "cbkgmkpi2"); this->load_param(filename, "cbkgmkpi3"); this->load_param(filename, "cbkgmkpi4"); this->load_param(filename, "cbkgctl0"); this->load_param(filename, "cbkgctl1"); this->load_param(filename, "cbkgctl2"); this->load_param(filename, "cbkgctl3"); this->load_param(filename, "cbkgctl4"); this->load_param(filename, "cbkgctk0"); this->load_param(filename, "cbkgctk1"); this->load_param(filename, "cbkgctk2"); this->load_param(filename, "cbkgctk3"); this->load_param(filename, "cbkgctk4"); this->load_param(filename, "cbkgctk5"); this->load_param(filename, "cbkgctk6"); this->load_param(filename, "cbkgphi0"); this->load_param(filename, "cbkgphi1"); this->load_param(filename, "cbkgphi2"); this->load_param(filename, "cbkgphi3"); this->load_param(filename, "cbkgphi4"); } void bu2kstarmumu_parameters::load_only_Bmass_param_values(std::string filename){ this->load_param(filename, "sigma_1"); this->load_param(filename, "alpha_1"); this->load_param(filename, "n_1"); this->load_param(filename, "sigma_2"); this->load_param(filename, "alpha_2"); this->load_param(filename, "n_2"); } void bu2kstarmumu_parameters::save_param_values(std::string filename){ std::ostringstream sout; spdlog::info("Parameter values are being saved to file "+ filename);; //write all parameters to oss for(UInt_t p = 0; p < this->nparameters(); p++){ sout << std::endl; sout << p; sout << "\t" << this->get_parameter(p)->get_name(); if (this->get_parameter(p)->get_error()==0) continue; //Print only not-fixed parameters sout << "\t" << this->get_parameter(p)->get_value(); sout << "\t" << this->get_parameter(p)->get_error(); if (TMath::Abs(this->get_parameter(p)->get_error()/this->get_parameter(p)->get_value()) > 0.5){ sout << "\tLARGE ERROR"; //c++s abs returned an int for whatever reason spdlog::warn("Par " + this->get_parameter(p)->get_name() + " has a large error:\t {0:f} +- {1:f}", this->get_parameter(p)->get_value() ,this->get_parameter(p)->get_error() ); } else{ spdlog::info("\tPar " + this->get_parameter(p)->get_name() + ":\t {0:f} +- {1:f}", this->get_parameter(p)->get_value() ,this->get_parameter(p)->get_error() ); } } //save oss to file std::ofstream file(filename.c_str()); file << sout.str(); file.close(); } void bu2kstarmumu_parameters::add_parameters(){ //physics parameters add_parameter(&Fl); add_parameter(&S1s); add_parameter(&S3); add_parameter(&S4); add_parameter(&S5); add_parameter(&Afb); add_parameter(&S6s); add_parameter(&S7); add_parameter(&S8); add_parameter(&S9); add_parameter(&P1); add_parameter(&P2); add_parameter(&P3); add_parameter(&P4); add_parameter(&P5); add_parameter(&P6); add_parameter(&P8); add_parameter(&FS); add_parameter(&SS1); add_parameter(&SS2); add_parameter(&SS3); add_parameter(&SS4); add_parameter(&SS5); //had this at the start //signal fraction add_parameter(&f_sig); add_parameter(&n_sig); add_parameter(&n_bkg); //mass parameters add_parameter(&m_b); add_parameter(&m_res_1); add_parameter(&m_sigma_1); add_parameter(&m_sigma_2); add_parameter(&m_scale); add_parameter(&alpha_1); add_parameter(&alpha_2); add_parameter(&n_1); add_parameter(&n_2); add_parameter(&fm_tau); add_parameter(&m_tau); add_parameter(&m_tau_2); add_parameter(&m_lambda); add_parameter(&m_lambda_2); add_parameter(&eff_q2); add_parameter(&asphase); add_parameter(&a); add_parameter(&r); add_parameter(&gammakstar); add_parameter(&mkstar); add_parameter(&gammakstarplus); add_parameter(&mkstarplus); add_parameter(&mf800); add_parameter(&gammaf800); add_parameter(&f800mag); add_parameter(&f800phase); add_parameter(&cbkgctl0); add_parameter(&cbkgctl1); add_parameter(&cbkgctl2); add_parameter(&cbkgctl3); add_parameter(&cbkgctl4); add_parameter(&cbkgctk0); add_parameter(&cbkgctk1); add_parameter(&cbkgctk2); add_parameter(&cbkgctk3); add_parameter(&cbkgctk4); add_parameter(&cbkgctk5); add_parameter(&cbkgctk6); add_parameter(&cbkgphi0); add_parameter(&cbkgphi1); add_parameter(&cbkgphi2); add_parameter(&cbkgphi3); add_parameter(&cbkgphi4); add_parameter(&cbkgmkpi0); add_parameter(&cbkgmkpi1); add_parameter(&cbkgmkpi2); add_parameter(&cbkgmkpi3); add_parameter(&cbkgmkpi4); add_parameter(&cswavemkpi0); add_parameter(&cswavemkpi1); add_parameter(&cswavemkpi2); add_parameter(&cswavemkpi3); add_parameter(&cswavemkpi4); add_parameter(&cbkgp20); add_parameter(&cbkgp21); add_parameter(&cbkgp22); add_parameter(&cbkgp23); add_parameter(&cbkgp24); add_parameter(&nthreshold); add_parameter(&R); } void bu2kstarmumu_parameters::init_mass_parameters(int PDF, int nBins, int bin, double defaultStepSize){ //Initialize the mass fit parameters based on the bin, as pi0 screws everyhting up std::vector> sMassPar = init_mass_params_MC(nBins,PDF); //Not the most efficient to always get the full vector with all bins, but oh well if(opts->twotailedcrystalball){ m_res_1.init(1.0, 0.0, 1.0, 0.0); m_sigma_1.init(sMassPar[0][bin],15.0, 50.0, defaultStepSize); } else{ m_res_1.init(0.5, 0.0, 1.0, defaultStepSize); m_sigma_1.init(sMassPar[0][bin],15.0, 40.0, defaultStepSize); m_sigma_2.init(sMassPar[1][bin],15.0, 40.0, defaultStepSize); } alpha_1.init(sMassPar[2][bin], 0.5, 3.0, defaultStepSize); alpha_2.init(sMassPar[3][bin], 0.5, 3.0, defaultStepSize); n_1.init(sMassPar[4][bin], 2.0, 10.0, defaultStepSize); n_2.init(sMassPar[5][bin], 2.0, 10.0, defaultStepSize); return; } void bu2kstarmumu_parameters::init_Bmass(std::string fileName, int PDF, double stepSize, fixConstr FC){ double massInit = get_param_value_from_rootfile(fileName,"m_b", PDF, 0); //fixing the Bmass outweights constraining it: if (FC.fix) m_b.init(massInit,B_MASS_LOW,B_MASS_HIGH, 0.0); else if (FC.constrain) m_b.init(massInit,B_MASS_LOW,B_MASS_HIGH, stepSize, 1.0, true); else m_b.init(massInit,B_MASS_LOW,B_MASS_HIGH, stepSize); return; } void bu2kstarmumu_parameters::init_angular_background_parameters(bool fitReference, double stepsize){ //Order of the polynomial is 0-6, each parameter represents x^n //TODO: CHECK THE FOLDINGS //fitReference is not used, but in case this needs to be different for signal/reference! //First set everything to be flat so one can only change the parameters that actually vary use_default_bkg(); std::vector init_values = init_bkg(opts->folding, opts->bkg_order_costhetal,opts->bkg_order_costhetak); for_indexed(auto name: PAR_BKG_STRING(opts->folding, opts->bkg_order_costhetal,opts->bkg_order_costhetak)){ std::vector range = GetParamRange(name); this->get_parameter(name)->init(init_values[i],range.front(), range.back(),stepsize); spdlog::trace("Initialized " + this->get_parameter(name)->get_name()); } return; } void bu2kstarmumu_parameters::init_mass_background_parameters(int nBins, int bin, bool useLambda){ std::vector f_lambda = init_f_lambda(nBins); if(useLambda){ m_lambda.init(f_lambda.at(bin), PAR_LAMBDA*PAR_LAMBDA_SCALE, PAR_LAMBDA/PAR_LAMBDA_SCALE, 1.0e-5); //Turn on/off second exponential possibly m_lambda_2.init(f_lambda.at(bin), PAR_LAMBDA*PAR_LAMBDA_SCALE, PAR_LAMBDA/PAR_LAMBDA_SCALE, FIX_FM ? 0.0 : 1.0e-5); m_tau.init_fixed(0.0); m_tau_2.init_fixed(0.0); } else{ //Not really used, so if someone ever needs this, modify yourselves!!! m_tau.init(-1.0/f_lambda.at(bin), 100, 100000, FIX_FM ? 0.0 : 10.0); //Turn on/off second exponential possibly m_tau_2.init(-1.0/f_lambda.at(bin), 100, 100000, FIX_FM ? 0.0 : 10.0); m_lambda.init_fixed(0.0); m_lambda_2.init_fixed(0.0); } return; } void bu2kstarmumu_parameters::init_mkpi_pWave_parameters(bool fitReference, double stepsize){ //fitReference is not used, but in case this needs to be different for signal/reference! gammakstar.init(0.065, 0.055, 0.07, stepsize); mkstar.init(PDGMASS_K_STAR_PLUS / 1000., 0.882, 0.902, 0.0); //PDG value R.init(1.6, 0.0, 10.0, 0.00); return; } void bu2kstarmumu_parameters::init_mkpi_sWave_parameters(bool fitReference, double stepsize){ //fitReference is not used, but in case this needs to be different for signal/reference! gammakstarplus.init(0.236, 0.1, 0.5, stepsize); //PDG value is 0.236 mkstarplus.init(1.41,1.2,1.6, 0.00); //PDG value is 1.41 asphase.init(TMath::Pi(), 0.0, 2.0*TMath::Pi(), 0.0); a.init(1.95, 0.0, 20.0, 0.0); r.init(1.78, 0.0, 10.0, 0.0); return; } void bu2kstarmumu_parameters::init_kpi_background_parameters(bool fitReference, double stepsize){ //fitReference is not used, but in case this needs to be different for signal/reference! cbkgmkpi1.init(-0.99, -1.25, 0.25, stepsize); //cbkgmkpi2.init(0.3, -1.0, 1.0, stepsize); return; } void bu2kstarmumu_parameters::init_angular_parameters(int nBins, int bin, double stepsize, double scale, bool blind){ //Scale sets the range //First, make sure everything is at the starting point use_default_observables(); //Initialize angular parameters from constants //s1s //s3 //s4 //s5 //s6s //s7 //s8 //s9 std::vector> sParameters; if (opts->initSM){ spdlog::debug("Loading angular parameters from flavio SM preditions"); sParameters = init_angular_params(nBins,false,false); } else{ spdlog::debug("Loading angular parameters from MC result file"); sParameters = init_angular_params_MC(nBins); } double blind_scale = 1.0; //Don't know what it does, but it is set to 1.0 everywhere if (!opts->fit_pprimes){ if(opts->fit_fl) Fl.init(1.0-4.0/3.0*sParameters.at(0).at(bin), 0.0, 2.0*scale, stepsize); else S1s.init(sParameters.at(0).at(bin), -scale, scale, stepsize); S3.init(sParameters.at(1).at(bin), -scale, scale, stepsize); S4.init(sParameters.at(2).at(bin), -scale, scale, (opts->full_angular || opts->folding == 1 ? stepsize : 0.0)); S5.init(sParameters.at(3).at(bin), -scale, scale, (opts->full_angular || opts->folding == 2 ? stepsize : 0.0)); if(opts->fit_afb) Afb.init(3.0/4.0*sParameters.at(4).at(bin), -0.75*scale, 0.75*scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); else S6s.init(sParameters.at(4).at(bin), -scale, scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); S7.init(sParameters.at(5).at(bin), -scale, scale, (opts->full_angular || opts->folding == 3 ? stepsize : 0.0)); S8.init(sParameters.at(6).at(bin), -scale, scale, (opts->full_angular || opts->folding == 4 ? stepsize : 0.0)); S9.init(sParameters.at(7).at(bin), -scale, scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); if(blind){ Fl.set_blinding(true, blind_scale, true); P1.set_blinding(true, blind_scale, true); P2.set_blinding(true, blind_scale, true); P3.set_blinding(true, blind_scale, true); P4.set_blinding(true, blind_scale, true); P5.set_blinding(true, blind_scale, true); P6.set_blinding(true, blind_scale, true); P8.set_blinding(true, blind_scale, true); } } else{ double fl = 1.0-4.0/3.0*sParameters.at(0).at(bin); Fl.init(fl, 0.0, 2.0*scale, stepsize); P1.init(2*sParameters.at(0).at(bin)/(1.-fl) , -scale, scale, stepsize); P2.init(sParameters.at(4).at(bin)/2/(1.-fl) , -scale, scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); P3.init(-sParameters.at(1).at(bin)/(1.-fl) , -scale, scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); P4.init(sParameters.at(2).at(bin)/sqrt(fl*(1.-fl)), -scale, scale, (opts->full_angular || opts->folding == 1 ? stepsize : 0.0)); P5.init(sParameters.at(3).at(bin)/sqrt(fl*(1.-fl)), -scale, scale, (opts->full_angular || opts->folding == 2 ? stepsize : 0.0)); P6.init(sParameters.at(5).at(bin)/sqrt(fl*(1.-fl)), -scale, scale, (opts->full_angular || opts->folding == 3 ? stepsize : 0.0)); P8.init(sParameters.at(6).at(bin)/sqrt(fl*(1.-fl)), -scale, scale, (opts->full_angular || opts->folding == 4 ? stepsize : 0.0)); if(blind){ if(opts->fit_fl) Fl.set_blinding(true, blind_scale, true); else S1s.set_blinding(true, blind_scale, true); S3.set_blinding(true, blind_scale, true); S4.set_blinding(true, blind_scale, true); S5.set_blinding(true, blind_scale, true); if(opts->fit_afb) Afb.set_blinding(true, blind_scale, true); else S6s.set_blinding(true, blind_scale, true); S7.set_blinding(true, blind_scale, true); S8.set_blinding(true, blind_scale, true); S9.set_blinding(true, blind_scale, true); } } return; } void bu2kstarmumu_parameters::init_ang_parameters_fromRefDavid(double stepsize, double scale, bool blind){ std::vector angPars = init_angular_params_RefFromDavid(); //Not the most efficient to always get the full vector, but oh well if (opts->fit_pprimes){ spdlog::critical("init_ang_parameters_fromRefDavid not implemented yet for Pprimes!"); assert(0); } if(opts->fit_fl) Fl.init(1.0-4.0/3.0*angPars.at(0), 0.0, 2.0*scale, stepsize); else S1s.init(angPars.at(0), -scale, scale, stepsize); S3.init(angPars.at(1), -scale, scale, stepsize); S4.init(angPars.at(2), -scale, scale, (opts->full_angular || opts->folding == 1 ? stepsize : 0.0)); S5.init(angPars.at(3), -scale, scale, (opts->full_angular || opts->folding == 2 ? stepsize : 0.0)); if(opts->fit_afb) Afb.init(3.0/4.0*angPars.at(4), -0.75*scale, 0.75*scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); else S6s.init(angPars.at(4), -scale, scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); S7.init(angPars.at(5), -scale, scale, (opts->full_angular || opts->folding == 3 ? stepsize : 0.0)); S8.init(angPars.at(6), -scale, scale, (opts->full_angular || opts->folding == 4 ? stepsize : 0.0)); S9.init(angPars.at(7), -scale, scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); int blind_scale = 1.0; //No clue what this is good for, but it is 1.0 everywhere, so if(blind){ if(opts->fit_fl) Fl.set_blinding(true, blind_scale, true); else S1s.set_blinding(true, blind_scale, true); S3.set_blinding(true, blind_scale, true); S4.set_blinding(true, blind_scale, true); S5.set_blinding(true, blind_scale, true); if(opts->fit_afb) Afb.set_blinding(true, blind_scale, true); else S6s.set_blinding(true, blind_scale, true); S7.set_blinding(true, blind_scale, true); S8.set_blinding(true, blind_scale, true); S9.set_blinding(true, blind_scale, true); } return; } void bu2kstarmumu_parameters::init_sWave_parameters(double stepsize){ //TODO: very basic for now double scale = 1.0; SS1.init( -0.153, -scale, scale, opts->full_angular || opts->folding != 4 ? stepsize : 0.0); SS2.init( 0.032, -scale, scale, opts->full_angular || opts->folding == 1 ? stepsize : 0.0); SS3.init( -0.001, -scale, scale, opts->full_angular || opts->folding == 2 ? stepsize : 0.0); SS4.init( 0.001, -scale, scale, opts->full_angular || opts->folding > 2 ? stepsize : 0.0); SS5.init( -0.070, -scale, scale, opts->full_angular ? stepsize : 0.0); return; } bu2kstarmumu_parameters::bu2kstarmumu_parameters(options* o): opts(o) { use_default(); add_parameters(); } double eventsInBin_fraction(int bin, int run, int nBins, bool fromRef){ //From the requested total number of events, get the number of events in the given bin for given pdf //Get the number of events from the dataFile and from the fraction of nSig/(nSig+nBkg) assert(bin >= 0 && bin < nBins); assert(run == 1 || run == 2 || run == 12); TChain * chain = new TChain("Events"); spdlog::trace("Run 1 data file ='" + get_theFCNCpath(0,1) + "'"); chain->Add(get_theFCNCpath(0,1).c_str()); spdlog::trace("Run 2 data file ='" + get_theFCNCpath(0,2) + "'"); chain->Add(get_theFCNCpath(0,2).c_str()); spdlog::debug("Chain entries: {0:d}", chain->GetEntries()); //cut on the q2 std::vector q2BinsMin = get_TheQ2binsmin(nBins, fromRef); //No need to have specifically 1 for Ref std::vector q2BinsMax = get_TheQ2binsmax(nBins, fromRef); //as if reference, always returns one bin std::string whichYear = ""; switch(run){ case 1: whichYear = "(year<2013) &&"; break; case 2: whichYear = "(year>2013) &&"; break; case 12: whichYear = "(year<2020) &&"; break; } std::string cutOnQ2 = " "; for (unsigned int b = 0; b < q2BinsMin.size(); b++){ cutOnQ2.append( "(" + std::to_string(q2BinsMin[b]) + " < q2 && q2 < "+ std::to_string(q2BinsMax[b]) +") || "); } cutOnQ2.erase(cutOnQ2.length()-3); spdlog::debug("Using cut: '" + cutOnQ2 + "'"); int n_all = chain->GetEntries(cutOnQ2.c_str()); //number of events in the rare q2 region if(n_all == -1) spdlog::debug("Getting number of all entries from TChain failed. Using hardcoded numbers."); spdlog::debug("All entries: {0:d}", n_all); cutOnQ2 = whichYear + std::to_string(q2BinsMin[bin]) + " < q2 && q2 < "+ std::to_string(q2BinsMax[bin]); spdlog::debug("Using cut: '" + cutOnQ2 + "'"); int n_bin = chain->GetEntries(cutOnQ2.c_str()); //number of events in the desired q2 bin if(n_bin == -1)spdlog::debug("Getting number of entries for bin {0:d} from TChain failed. Using hardcoded numbers.", bin); spdlog::debug("Entries in bin: {0:d}", n_bin); //Running on Condor does not allow usage of TTreePlayer, which is needed for the GetEntries with selection cut //In that case, -1 is returned. If so, use hardcoded fractions for the 4 or 5 q2 binning scheme. if(n_all == -1 || n_bin == -1){ spdlog::warn("Could not determine event fraction in bin={0:d} for run={1:d} from TChain. Use hardcoded numbers.", bin, run); if(nBins == 4 || nBins == 5){ std::vector > frac = fracs(nBins); if(run == 12)return frac.at(0).at(bin)+frac.at(1).at(bin); else return frac.at(run-1).at(bin); } spdlog::error("No hardcoded numbers available for {0:d} q2 bins.", nBins); return 0.0; } double fraction = double(n_bin)/double(n_all); spdlog::debug("Returning fraction of {0:f}", fraction); chain->Clear(); return fraction; } void EventNumbers(unsigned int bin, unsigned int pdf, double & fraction, unsigned int & eventnumbers, unsigned int TotalEvents, unsigned int bins, unsigned int pdfs){ bool use_unblinded_values = false;//TODO //return the fraction of nSig/(nSig+nBkg) *** in the requested q2bin *** //return the number of events (nSig+nBkg) *** in this q2bin *** and in this sub-set given a total number of events (all sub-sets and all q2bins) fraction = 0; eventnumbers = 0; std::vector f_signal = init_n_signal(bins); std::vector f_bckgnd = init_n_bckgnd(bins); std::vector f_subset = get_f_subset(pdfs); assert(f_signal.size() == bins); assert(f_bckgnd.size() == bins); assert(f_subset.size() == pdfs); //assign signal fraction fraction = f_signal.at(bin) / (f_signal.at(bin) + f_bckgnd.at(bin)); //get total event number in this bin and for this sub-set: double f_sig_norm = sum_vector(f_signal) + sum_vector(f_bckgnd); double f_event_norm = sum_vector(f_subset); for(auto sig: f_signal) sig /= f_sig_norm; for(auto bkg: f_bckgnd) bkg /= f_sig_norm; for(auto f_sub: f_subset) f_sub /= f_event_norm; eventnumbers = (unsigned int) (0.5 + TotalEvents * (f_signal.at(bin) + f_bckgnd.at(bin)) * f_subset.at(pdf)); if(use_unblinded_values){ //Number of signal and background events for each PDF //TODO: de-hardcode this one fraction = sig_unblinded.at(bin).at(pdf) / (sig_unblinded.at(bin).at(pdf) + bkg_unblinded.at(bin).at(pdf)); eventnumbers = (unsigned int) (0.5 + sig_unblinded.at(bin).at(pdf) + bkg_unblinded.at(bin).at(pdf)); } return; }