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.
 
 
 
 

5380 lines
251 KiB

//Renata Kopecna
#include <fstream>
#include "folder.hh"
#include <funcs.hh>
#include <constants.hh>
#include <bu2kstarmumu_pdf.hh>
#include <pdf.hh>
#include <options.hh>
#include <values.hh>
#include <design.hh>
#include <integrals.hh>
#include <event.hh>
#include <helpers.hh>
#include <paths.hh>
#include <TMinuit.h>
#include <spdlog.h>
#include <TROOT.h>
#include <TFile.h>
#include <TStyle.h>
//Helper function to create a polynomial for the background
std::vector<double> init_ch_ctl(const fcnc::bu2kstarmumu_parameters* params){
std::vector<double> bkg_ctl;
bkg_ctl.push_back(params->cbkgctl0());
bkg_ctl.push_back(params->cbkgctl1());
bkg_ctl.push_back(params->cbkgctl2());
bkg_ctl.push_back(params->cbkgctl3());
bkg_ctl.push_back(params->cbkgctl4());
return bkg_ctl;
}
std::vector<double> init_ch_ctk(const fcnc::bu2kstarmumu_parameters* params){
std::vector<double> bkg_ctk;
bkg_ctk.push_back(params->cbkgctk0());
bkg_ctk.push_back(params->cbkgctk1());
bkg_ctk.push_back(params->cbkgctk2());
bkg_ctk.push_back(params->cbkgctk3());
bkg_ctk.push_back(params->cbkgctk4());
bkg_ctk.push_back(params->cbkgctk5());
bkg_ctk.push_back(params->cbkgctk6());
return bkg_ctk;
}
std::vector<double> init_ch_phi(const fcnc::bu2kstarmumu_parameters* params){
std::vector<double> bkg_phi;
bkg_phi.push_back(params->cbkgphi0());
bkg_phi.push_back(params->cbkgphi1());
bkg_phi.push_back(params->cbkgphi2());
bkg_phi.push_back(params->cbkgphi3());
bkg_phi.push_back(params->cbkgphi4());
return bkg_phi;
}
//using namespace std;
using namespace fcnc;
//this is a wrapper for the complex error function
//which is needed for a gaussian convolution of exp*cos/sin
//this fortran implementation however is not thread safe!
extern "C" void wwerfwrap_(double *zr, double *zi, double *wr, double* wi);
//boost::mutex global_mutex_2;
std::mutex global_mutex_2;
bu2kstarmumu_pdf* bu2kstarmumu_pdf::current_pdf;
bu2kstarmumu_pdf::bu2kstarmumu_pdf(options* o, const bu2kstarmumu_parameters* params):
opts(o)
{
//vector of efficiency coefficients containing 1260 elements, coefficients stored in bu2kstarmumu_coefficients.cc
//coeffs_eff_4d = fcnc::coefficients_nominal;
//load_coeffs_eff_phsp_4d();
fldr = new fcnc::folder(opts);
};
bu2kstarmumu_pdf::~bu2kstarmumu_pdf()
{
};
void bu2kstarmumu_pdf::get_moments(std::vector<fcnc::event> events, std::vector<double>& moments, std::vector<double>& covariance) const
{
if(!opts->full_angular){
spdlog::error("No folding implemented for moments. Debug: 1");
assert(0);
}
std::vector<double> cov(NTERMS*NTERMS, 0.0);//the actual covariance matrix for the moments
std::vector<double> m(NTERMS, 0.0);//need to first calculate the mean
double nweight = 0.0; //sum of weights
double nweightsquared = 0.0; //sum of weights squared, not used anywhere
for (auto meas: events){
double weight = meas.weight*meas.sweight;
nweight += weight;
nweightsquared += weight*weight;
}
for (auto meas: events){
double weight = meas.weight*meas.sweight;
weight /= nweight;//nominal
//Calculate the angular terms for each parameter
double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0,
f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0;
fj(meas.costhetal, meas.costhetak, meas.phi,
f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12);
double ffs=0.0, fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0;
if(opts->swave){
swave_fj(meas.costhetal, meas.costhetak, meas.phi,
ffs, fs1, fs2, fs3, fs4, fs5);
}
//TODO when bored: this is very annoying and f_whatever should be a struct or so and one should loop
m.at(0) += f1*weight;
m.at(1) += f2*weight;
m.at(2) += f3*weight;
m.at(3) += f4*weight;
m.at(4) += f5*weight;
m.at(5) += f6*weight;
m.at(6) += f7*weight;
m.at(7) += f8*weight;
m.at(8) += f9*weight;
m.at(9) += f10*weight;
m.at(10) += f11*weight;
m.at(11) += f12*weight;
if(opts->swave){
m.at(12) += ffs*weight;
m.at(13) += fs1*weight;
m.at(14) += fs2*weight;
m.at(15) += fs3*weight;
m.at(16) += fs4*weight;
m.at(17) += fs5*weight;
}
}
//calculate rms
for (auto meas: events){
double weight = meas.weight*meas.sweight;//dangerous?
weight /= nweight;//nominal
double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0,
f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0;
fj(meas.costhetal, meas.costhetak, meas.phi,
f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12);
double ffs=0.0, fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0;
if(opts->swave){
swave_fj(meas.costhetal, meas.costhetak, meas.phi,
ffs, fs1, fs2, fs3, fs4, fs5);
}
std::vector<double> diff(NTERMS*NTERMS, 0.0);
diff.at(0) = f1 - m.at(0); //aaaaaaaarrrrggghhh
diff.at(1) = f2 - m.at(1);
diff.at(2) = f3 - m.at(2);
diff.at(3) = f4 - m.at(3);
diff.at(4) = f5 - m.at(4);
diff.at(5) = f6 - m.at(5);
diff.at(6) = f7 - m.at(6);
diff.at(7) = f8 - m.at(7);
diff.at(8) = f9 - m.at(8);
diff.at(9) = f10 - m.at(9);
diff.at(10) = f11 - m.at(10);
diff.at(11) = f12 - m.at(11);
if(opts->swave){
diff.at(12) = ffs - m.at(12);
diff.at(13) = fs1 - m.at(13);
diff.at(14) = fs2 - m.at(14);
diff.at(15) = fs3 - m.at(15);
diff.at(16) = fs4 - m.at(16);
diff.at(17) = fs5 - m.at(17);
}
//for swave==false, only loop over the first 12x12 elements
//the matrix however stays in the 18x18 format, with 0.0 for all j > 11 || k > 11
UInt_t mm = opts->swave ? NTERMS : NTERMS_P;
for (unsigned int j = 0; j<mm; j++){
for (unsigned int k = 0; k<mm; k++){
cov.at(j*NTERMS+k) += (diff.at(j))*(diff.at(k))*sqr(weight);
}
}
}
moments = m;
covariance = cov;
return;
};
double corr_from_obs(std::vector<double> obs, std::vector<double> obscov, int i, int k){
return obscov.at(i+NTERMS*k)/sqrt(obscov.at(k+NTERMS*k))/sqrt(obscov.at(i+NTERMS*i));
}
void bu2kstarmumu_pdf::save_moments_to_obs(bu2kstarmumu_parameters* params,
std::vector<double> obs,
std::vector<double> obscov) const
{
assert(obs.size() == NTERMS);
assert(obscov.size() == NTERMS*NTERMS);
//**** Fl ****//
params->Fl.set_value(1.0-4.0/3.0*obs.at(0));
params->Fl.set_error(4.0/3.0*sqrt(obscov.at(0+NTERMS*0)));
if(opts->fit_fl) params->Fl.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++){
if(i == 0) params->Fl.set_correlation(1.0, 0); //self correlation is one by definition
else if(i == 7 && opts->fit_afb){
//correlation to Afb is equal to correlation of S1s and S6s
params->Fl.set_correlation(corr_from_obs(obs,obscov,7,0), 7);
}
else{
params->Fl.set_correlation(corr_from_obs(obs,obscov,i,0)/sqrt(3.0/4.0), i);
}
}
//**** S1s ****//
params->S1s.set_value(obs.at(0));
params->S1s.set_error(sqrt(obscov.at(0+NTERMS*0)));
if(!opts->fit_fl) params->S1s.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++){
params->S1s.set_correlation(corr_from_obs(obs,obscov,i,0), i);
}
//**** S3 ****//
params->S3.set_value(obs.at(4));
params->S3.set_error(sqrt(obscov.at(4+NTERMS*4)));
params->S3.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++){
params->S3.set_correlation(corr_from_obs(obs,obscov,i,4), i);
}
//**** S4 ****//
params->S4.set_value(obs.at(5));
params->S4.set_error(sqrt(obscov.at(5+NTERMS*5)));
params->S4.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++)
params->S4.set_correlation(corr_from_obs(obs,obscov,i,5), i);
//**** S5 ****//
params->S5.set_value(obs.at(6));
params->S5.set_error(sqrt(obscov.at(6+NTERMS*6)));
params->S5.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++)
params->S5.set_correlation(corr_from_obs(obs,obscov,i,6), i);
//**** Afb ****//
params->Afb.set_value(3.0/4.0*obs.at(7));
params->Afb.set_error(3.0/4.0*sqrt(obscov.at(7+NTERMS*7)));
if(opts->fit_afb)
params->Afb.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++){
if(i == 7) params->Afb.set_correlation(1.0, 7);//self correlation is not scaled
else if(i == 0 && opts->fit_afb){
//correlation to Fl is equal to correlation of S1s and S6s
params->Afb.set_correlation(corr_from_obs(obs,obscov,0,7), 0);
}
else params->Afb.set_correlation(corr_from_obs(obs,obscov,i,7)/sqrt(4.0/3.0), i);
}
//**** S6s ****//
params->S6s.set_value(obs.at(7));
params->S6s.set_error(sqrt(obscov.at(7+NTERMS*7)));
if(!opts->fit_afb) params->S6s.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++) params->S6s.set_correlation(corr_from_obs(obs,obscov,i,7), i);
//**** S7 ****//
params->S7.set_value(obs.at(9));
params->S7.set_error(sqrt(obscov.at(9+NTERMS*9)));
params->S7.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++) params->S7.set_correlation(corr_from_obs(obs,obscov,i,9), i);
//**** S8 ****//
params->S8.set_value(obs.at(10));
params->S8.set_error(sqrt(obscov.at(10+NTERMS*10)));
params->S8.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++) params->S8.set_correlation(corr_from_obs(obs,obscov,i,10), i);
//**** S9 ****//
params->S9.set_value(obs.at(11));
params->S9.set_error(sqrt(obscov.at(11+NTERMS*11)));
params->S9.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++) params->S9.set_correlation(corr_from_obs(obs,obscov,i,11), i);
//**** FS ****//
params->FS.set_value(obs.at(12));
params->FS.set_error(sqrt(obscov.at(12+NTERMS*12)));
if(opts->swave) params->FS.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++) params->FS.set_correlation(corr_from_obs(obs,obscov,i,12), i);
//**** SS1 ****//
params->SS1.set_value(obs.at(13));
params->SS1.set_error(sqrt(obscov.at(13+NTERMS*13)));
if(opts->swave) params->SS1.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++) params->SS1.set_correlation(corr_from_obs(obs,obscov,i,13), i);
//**** SS2 ****//
params->SS2.set_value(obs.at(14));
params->SS2.set_error(sqrt(obscov.at(14+NTERMS*14)));
if(opts->swave) params->SS2.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++) params->SS2.set_correlation(corr_from_obs(obs,obscov,i,14), i);
//**** SS3 ****//
params->SS3.set_value(obs.at(15));
params->SS3.set_error(sqrt(obscov.at(15+NTERMS*15)));
if(opts->swave) params->SS3.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++) params->SS3.set_correlation(corr_from_obs(obs,obscov,i,15), i);
//**** SS4 ****//
params->SS4.set_value(obs.at(16));
params->SS4.set_error(sqrt(obscov.at(16+NTERMS*16)));
if(opts->swave)params->SS4.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++) params->SS4.set_correlation(corr_from_obs(obs,obscov,i,16), i);
//**** SS5 ****//
params->SS5.set_value(obs.at(17));
params->SS5.set_error(sqrt(obscov.at(17+NTERMS*17)));
if(opts->swave) params->SS5.set_step_size(0.0001);
for(unsigned int i = 0; i < NTERMS; i++) params->SS5.set_correlation(corr_from_obs(obs,obscov,i,17), i);
}
double bu2kstarmumu_pdf::prob(const bu2kstarmumu_parameters* params, const event& meas) const
{
//safety checks:
if(opts->fit_mkpi && opts->use_mkpi){
spdlog::critical("Do not use the direct fit of m(Kpi) and the included fit of m(Kpi) in the angular s-Wave at the same time!");
spdlog::critical("5D fit:\t'use_mkpi'");
spdlog::critical("4D+1D fit:\t'fit_mkpi'");
assert(0);
}
if(opts->only_mass2DFit && opts->only_Bmass){
spdlog::critical("Cannot fit m(Kpi) and m(B) with option 'only_Bmass'!");
assert(0);
}
if(opts->only_mass2DFit && !opts->fit_mkpi){
spdlog::critical("When using the 2D mass fit, enable 'fit_mkpi' as well!");
assert(0);
}
if(opts->only_mkpi && !opts->fit_mkpi){
spdlog::critical("When using the m(Kpi) mass fit, enable 'fit_mkpi' as well!");
assert(0);
}
if((opts->only_angles && opts->only_Bmass) || (opts->only_mkpi && opts->only_Bmass) || (opts->only_angles && opts->only_mkpi)){
spdlog::critical("Do not use two or more of 'only_Bmass', 'only_mkpi' and 'only_angles' at the same time!");
spdlog::critical("only_Bmass = " + boolToString(opts->only_Bmass));
spdlog::critical("only_mkpi = " + boolToString(opts->only_mkpi));
spdlog::critical("only_angles = " + boolToString(opts->only_angles));
assert(0);
}
if(opts->use_angular_acc && opts->weighted_fit){
spdlog::critical("Do not use 'use_angular_acc' and 'weighted_fit' at the same time!");
spdlog::critical("'use_angular_acc'\tConvolute acceptance function into fit pdf");
spdlog::critical("'weighted_fit'\tAssign per event weight according to acceptance");
assert(0);
}
if(opts->twotailedcrystalball && opts->crystalball){
spdlog::critical("Cannot use CB and two-tailed CB option. Choose only one and chose wisely:");
spdlog::critical("Either 'twotailedcrystalball' or 'crystalball'");
assert(0);
}
if(opts->full_angular && opts->folding > -1){
spdlog::critical("Cannot run full angular fit and folding at the same time");
assert(0);
}
//determine signal and background probability
double fsig = (opts->extended_ml ? params->n_sig()/(params->n_sig()+params->n_bkg()) : params->f_sig());
double sig_part = 0.0;
double bkg_part = 0.0;
if(fsig != 0.0)//signal part:
sig_part += fsig
* angular_sig_prob(params, meas)
* m_sig_prob(params, meas)
* mkpi_sig_prob(params, meas);
if(fsig != 1.0)//background part:
bkg_part += (1.0-fsig)
* angular_bkg_prob(params, meas)
* m_bkg_prob(params, meas)
* mkpi_bkg_prob(params, meas);
//force individual probabilities for signal and background to be positive
if(opts->individual_penalties){
if(sig_part < 0.0){
sig_part = 1.0e-12;
bkg_part = 0.0;
}
if(bkg_part < 0.0){
bkg_part = 1.0e-12;
sig_part = 0.0;
}
}
//add background and signal parts:
double result = sig_part + bkg_part;
//check final probability
if(result < 0.0){
std::lock_guard<std::mutex> lock(global_mutex_2);
spdlog::debug("Event has negative probability {0:e}", result);
spdlog::debug("Signal_part:\t{0:e}", sig_part);
spdlog::debug("m(B):\t\t{0:e}",m_sig_prob(params, meas)); //THIS one crashes and idk why
spdlog::debug("m(Kpi):\t{0:e}",mkpi_sig_prob(params, meas));
spdlog::debug("angles:\t{0:e}",angular_sig_prob(params, meas));
spdlog::debug("FS:\t\t{0:e}", params->FS.get_value());
spdlog::debug("Backgrnd_part:\t{0:e}", bkg_part);
if (fsig != 1.0){
spdlog::debug("m(B):\t{0:e}",m_bkg_prob(params, meas));
spdlog::debug("m(Kpi):\t{0:e}",mkpi_bkg_prob(params, meas));
spdlog::debug("angles:\t{0:e}",angular_bkg_prob(params, meas));
}
const bool variablepushback = false; //OMFG
if(variablepushback){
double baseline = 1.0e-12;
double absres = fabs(result) > 1.0e-6 ? fabs(result) : 1.0e-6;
double logres = log10(absres)+6.0;
double factor = pow(10.0, -logres);
result = baseline*factor;
}
else{
result = 1.0e-12;
}
}
else if(std::isinf(result) || std::isnan(result)){
std::lock_guard<std::mutex> lock(global_mutex_2);
params->print_parameters(false);
spdlog::error("Event has probability {0:f}", result);
spdlog::error("Signal_part:\t{0:f}", sig_part);
spdlog::error("fsig:\t\t{0:f}", fsig);
spdlog::error("m(B):\t\t{0:f}", m_sig_prob(params, meas));
spdlog::error("m(Kpi):\t{0:e}", mkpi_sig_prob(params, meas));
spdlog::error("angles:\t{0:e}",angular_sig_prob(params, meas));
spdlog::error("FS:\t\t{0:f}", params->FS.get_value());
spdlog::error("m(K*+) s-Wave NORM:\t{0:f}", mkpi_swave_2_norm);
spdlog::error("m(K*+) p-Wave NORM:\t{0:f}", mkpi_pwave_2_norm);
spdlog::error("Backgrnd_part:\t{0:f}", bkg_part);
assert(0);
}
return result;
};
void bu2kstarmumu_pdf::init(parameters* params) {
init(dynamic_cast<bu2kstarmumu_parameters*>(params));
//update_cached_normalization(params);
};
struct bin_edges{ //This could've been a class in case someone is bored in the future
//limits for all variable (range) (4D):
double q2min, q2max;
double ctkmin, ctkmax;
double ctlmin, ctlmax;
double phimin, phimax;
unsigned int nq2bins, nctlbins, nctkbins, nphibins;
//keep this as functions in case of modyfing the ranges during running the code!
//range of each dimension (4D):
double range_q2(){
return q2max - q2min;
}
double range_ctk(){
return ctkmax - ctkmin;
}
double range_ctl(){
return ctlmax - ctlmin;
}
double range_phi(){
return phimax - phimin;
}
//bin width for each variable
double binWidth_q2(){
return range_q2()/nq2bins;
}
double binWidth_ctl(){
return range_ctl()/nctlbins;
}
double binWidth_ctk(){
return range_ctk()/nctkbins;
}
double binWidth_phi(){
return range_phi()/nphibins;
}
//bin edges for each variable
std::vector<double> edges_q2(){
std::vector<double> tmp;
for (unsigned int h = 0; h<=nq2bins; h++){
tmp.push_back(q2min + h * binWidth_q2());
}
return tmp;
}
std::vector<double> edges_ctl(){
std::vector<double> tmp;
for (unsigned int h = 0; h<=nctlbins; h++){
tmp.push_back(ctlmin + h * binWidth_ctl());
}
return tmp;
}
std::vector<double> edges_ctk(){
std::vector<double> tmp;
for (unsigned int h = 0; h<=nctkbins; h++){
tmp.push_back(ctkmin + h * binWidth_ctk());
}
return tmp;
}
std::vector<double> edges_phi(){
std::vector<double> tmp;
for (unsigned int h = 0; h<=nphibins; h++){
tmp.push_back(phimin + h * binWidth_phi());
}
return tmp;
}
//Total number of bins in 4D
unsigned int getNbins(){
return nq2bins*nctlbins*nctkbins*nphibins;
}
//constructor
bin_edges(fcnc::options *opts, unsigned int nq2,unsigned int nctl,unsigned int nctk,unsigned int nphi){
//get the limits for all variables (4D):
q2min = opts->TheQ2binsmin.front(); q2max = opts->TheQ2binsmax.back();
ctkmin = opts->ctk_min; ctkmax = opts->ctk_max;
ctlmin = opts->ctl_min; ctlmax = opts->ctl_max;
phimin = opts->phi_min; phimax = opts->phi_max;
nq2bins = nq2;
nctlbins = nctl;
nctkbins = nctk;
nphibins = nphi;
}
};
unsigned int get_bin_in4D(int h, int i, int j, int k, bin_edges edges){
/// h = q2, i = ctl, j = ctk, k = phi
//Return the bin number for given event evt in 4D (q2, thetal, thetak, phi)
//Starting from 0!
unsigned int bin = edges.nctlbins*edges.nctkbins*edges.nphibins*h //q2
+edges.nctkbins*edges.nphibins*i //thetaL
+edges.nphibins*j //thetaK
+k; //phi
if (bin >= edges.getNbins()){
spdlog::critical("Bin {0:d} is larger than the dimension of {1:d}!",bin,edges.getNbins());
spdlog::error("h {0:d},\ti {1:d},\tj {2:d},\tk {3:d}", h, i, j, k);
spdlog::error("q2 {0:d},\tctl {1:d},\tctk {2:d},\tphi {3:d}",
edges.nq2bins, edges.nctlbins, edges.nctkbins, edges.nphibins);
assert(0);
}
else return bin;
}
unsigned int get_bin_in4D(event evt, bin_edges edges ){
//Return the bin number for given event evt in 4D (q2, thetal, thetak, phi)
//Starting from 0!
unsigned int h = (evt.q2 - edges.q2min ) / edges.binWidth_q2(); //division here truncates the result"chi
unsigned int i = (evt.costhetal - edges.ctlmin) / edges.binWidth_ctl();//eg 18/10 = 1
unsigned int j = (evt.costhetak - edges.ctkmin) / edges.binWidth_ctk();
unsigned int k = (evt.phi - edges.phimin) / edges.binWidth_phi();
return get_bin_in4D(h,i,j,k, edges);
}
unsigned int npolynom::get_bin_in4D(int h, int i, int j, int k){
/// h = q2, i = ctl, j = ctk, k = phi
//Return the bin number for given event evt in 4D (q2, thetal, thetak, phi)
//Starting from 0!
return ctl*ctk*phi*h //q2
+ctk*phi*i //thetaL
+phi*j //thetaK
+k; //phi
}
unsigned int get_bin_in3D(int i, int j, int k, npolynom npol){
/// h = q2, i = ctl, j = ctk, k = phi
//Return the bin number for given event evt in 4D (q2, thetal, thetak, phi)
//Starting from 0!
return npol.ctk*npol.phi*i //thetaL
+npol.phi*j //thetaK
+k; //phi
}
unsigned int get_bin_in3D(int i, int j, int k, bin_edges edges){
/// h = q2, i = ctl, j = ctk, k = phi
//Return the bin number for given event evt in 4D (q2, thetal, thetak, phi)
//Starting from 0!
return edges.nctkbins*edges.nphibins*i //thetaL
+edges.nphibins*j //thetaK
+k; //phi
}
void get_chi2(bin_edges edges, npolynom npol,
std::vector<event> eventsInQ2bin, std::vector<double> coeffs_moments,
values* globalvalues,
bool assumectleven, bool assumePhiEven, bool write_eps,
std::string subfolder, std::string appendix){
spdlog::info( "Starting chi2 calculation" );
std::vector<double> nsel_hist(edges.getNbins(), 0.0);
std::vector<double> nsel_hist_errsq(edges.getNbins(), 0.0);
//this is actually not the correct error here, due to the weights!
//should be sqrt(sum_i weights_i^2)
double nsel = 0.0;
int nEvents = eventsInQ2bin.size();
for (auto &meas: eventsInQ2bin) {
unsigned int bin = get_bin_in4D(meas,edges);
nsel_hist.at(bin) += meas.weight;
nsel += meas.weight;
nsel_hist_errsq.at(bin) += sqr(meas.weight);
}
//Set errors
for (auto err: nsel_hist_errsq){
if (err == 0.0) err = 1.0;
}
//compare with prediction
double neps = 0.0;
std::vector<double> neps_hist(edges.getNbins(), 0.0);
std::vector<double> q2_edges = edges.edges_q2();
std::vector<double> ctl_edges = edges.edges_ctl();
std::vector<double> ctk_edges = edges.edges_ctk();
std::vector<double> phi_edges = edges.edges_phi();
for (unsigned int h = 0; h<edges.nq2bins; h++){
for (unsigned int i = 0; i<edges.nctlbins; i++){
for (unsigned int j = 0; j<edges.nctkbins; j++){
for (unsigned int k = 0; k<edges.nphibins; k++){
double integral = 0.0;
for (unsigned int l = 0; l<npol.q2; l++){
for (unsigned int m = 0; m<npol.ctl; m++){
for (unsigned int n = 0; n<npol.ctk; n++){
for (unsigned int o = 0; o<npol.phi; o++){
double result = coeffs_moments.at(npol.get_bin_in4D(l,m,n,o))
*(pow(q2_edges[h+1],l+1) - pow(q2_edges[h],l+1))/(l+1.0)
*(pow(ctl_edges[i+1],m+1) - pow(ctl_edges[i],m+1))/(m+1.0)
*(pow(ctk_edges[j+1],n+1) - pow(ctk_edges[j],n+1))/(n+1.0)
*(pow(phi_edges[k+1],o+1) - pow(phi_edges[k],o+1))/(o+1.0);
integral += result;
}
}
}
}
neps_hist.at(get_bin_in4D(h,i,j,k,edges)) = integral;
neps += integral;
}
}
}
}
spdlog::debug( "nsel {0:f}\n\t nEvents {1:d}\n\t neps {2:f}\n\t nsel/neps {3:f} ", nsel, nEvents, neps, nsel/neps );
TH1D* hpull = new TH1D("hpull", ";(N_{sel}-N_{fit})/#sqrt{N_{sel}};",100, -5.0, +5.0);
TH1D* hnsel = new TH1D("hnsel", ";N_{sel};",100, 0.0, +25.0);
TH1D* hnfit = new TH1D("hnfit", ";N_{fit};",100, 0.0, +25.0);
//rescale fitted efficiency to MC statistics
//This would be nicer in a vector of vectors or so, but oh well
for (unsigned int h = 0; h<edges.nq2bins; h++)
for (unsigned int i = 0; i<edges.nctlbins; i++)
for (unsigned int j = 0; j<edges.nctkbins; j++)
for (unsigned int k = 0; k<edges.nphibins; k++)
neps_hist.at(get_bin_in4D(h,i,j,k, edges)) *= nsel/neps;
//calculate chi2 and perform "pull" plot
double chi2 = 0.0;
//double errorscale = 1.01;
for (unsigned int h = 0; h<edges.nq2bins; h++){
for (unsigned int i = 0; i<edges.nctlbins; i++){
for (unsigned int j = 0; j<edges.nctkbins; j++){
for (unsigned int k = 0; k<edges.nphibins; k++){
unsigned int bin = get_bin_in4D(h,i,j,k, edges);
//nominal
chi2 += sqr(nsel_hist.at(bin)-neps_hist.at(bin))/fabs(neps_hist.at(bin));
hpull->Fill((nsel_hist.at(bin)-neps_hist.at(bin))/sqrt(fabs(neps_hist.at(bin))));
spdlog::trace("nsel_hist.at({0:d})\t{1:f}",bin,nsel_hist.at(bin));
spdlog::trace("neps_hist.at({0:d})\t{1:f}",bin,neps_hist.at(bin));
hnsel->Fill(nsel_hist.at(bin));
hnfit->Fill(neps_hist.at(bin));
}
}
}
}
spdlog::debug( "chi2\t {0:f}", chi2 );
//Calculate the number of parameters
int nparams = npol.q2*npol.ctl*npol.ctk*npol.phi-1;
spdlog::debug( "Nparams\t {0:d}", nparams );
if (assumectleven && assumePhiEven){
nparams = npol.q2*((npol.ctl+1)/2)*npol.ctk*((npol.phi+1)/2)-1;
}
else{
if (assumectleven) nparams = npol.q2*((npol.ctl+1)/2)*npol.ctk*npol.phi-1;
if (assumePhiEven) nparams = npol.q2*npol.ctl*npol.ctk*((npol.phi+1)/2)-1;
}
spdlog::debug( "Nparams (accounting for even ctl and phi)\t {0:d}", nparams );
//Get degrees of freedom
int nbins = edges.getNbins();
spdlog::debug( "Nbins\t {0:d}", nbins);
int ndof = nbins - nparams - 1;
spdlog::debug( "ndof\t {0:d}", ndof );
spdlog::debug( "chi2/ndof (accounting for even ctl and phi)\t {0:f}",chi2/ndof );
spdlog::debug( "chi2/Nbins\t\t {0:f}",chi2/nbins );
spdlog::debug( "pvalue using ndof\t {0:f}",TMath::Prob(chi2, ndof) );
spdlog::debug( "pvalue using nbins\t {0:f}", TMath::Prob(chi2, nbins) );
//=========================================
//
// save chi2 to global values:
//
//=========================================
globalvalues->angacccorr_chi2 = chi2;
globalvalues->angacccorr_ndof = ndof;
//recount of nparams
int ncount = 0;
for (unsigned int l = 0; l<npol.q2; l++)
for (unsigned int m = 0; m<npol.ctl; m++)
for (unsigned int n = 0; n<npol.ctk; n++)
for (unsigned int o = 0; o<npol.phi; o++)
if (coeffs_moments.at(npol.get_bin_in4D(l,m,n,o)) != 0.0) ncount++;
spdlog::debug( "Recount of Nparams gives:\t {0:d}",ncount );
if(write_eps){
plotAndSave(hpull,"cpull",subfolder + "pull"+appendix, "eps");
plotAndSave(hnsel,"csel",subfolder + "nsel"+appendix, "eps");
plotAndSave(hnfit,"cfit",subfolder + "nfit"+appendix, "eps");
}
delete hpull;
delete hnsel;
delete hnfit;
return;
}
void get_legendre(bin_edges edges, npolynom npol,
std::vector<event> eventsInQ2bin, double nWeightedEvents,
std::vector<double> &poly_moments,
bool fejerkernel, bool assumectleven, bool assumePhiEven,
bool checkSignificance, bool calculateCovariance){
//use Legendre polynomials
spdlog::info("DOLEGENDRE start");
//should def use this:
//calculates all legendre polynomials up to including degree n
//void fcnc::legendre(double x, int n, std::vector<double>& results)
//this is not the best way to do things
//should rather
//loop over events
//determine, for every event the legendre polynomials order 0 to nq2/nctl/nctk/nphi
//loop over all orders
//add weight*leg_q2.at(h)*leg_ctl.at(i)*leg_ctk.at(j)*leg_phi.at(k) in correct bin
//optimized version
std::vector<double> chijk_moments = std::vector<double>(npol.getSize(), 0.0);
for (auto & meas: eventsInQ2bin){ //This is all computed then in the range of -1 to +1
double q2 = 2.0 * (meas.q2 - edges.q2min ) / edges.range_q2() - 1.0;
double ctl = 2.0 * (meas.costhetal - edges.ctlmin) / edges.range_ctl()- 1.0;
double ctk = 2.0 * (meas.costhetak - edges.ctkmin) / edges.range_ctk()- 1.0;
double phi = 2.0 * (meas.phi - edges.phimin) / edges.range_phi()- 1.0;
double weight = meas.weight;
//calculates all legendre polynomials up to including degree n
std::vector<double> leg_q2(npol.q2, 0.0);
fcnc::legendre(q2, npol.q2, leg_q2);
std::vector<double> leg_ctl(npol.ctl, 0.0);
fcnc::legendre(ctl, npol.ctl, leg_ctl);
std::vector<double> leg_ctk(npol.ctk, 0.0);
fcnc::legendre(ctk, npol.ctk, leg_ctk);
std::vector<double> leg_phi(npol.phi, 0.0);
fcnc::legendre(phi, npol.phi, leg_phi);
double result = 0.0;
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
unsigned int bin = npol.get_bin_in4D(h,i,j,k);
result = 0.0;
//result
if (assumectleven && i%2 != 0 ) result = 0.0;
else if (assumePhiEven && k%2 != 0) result = 0.0;
else{
result =
weight
*leg_q2.at(h)*(2.0*h+1.0)/2.0
*leg_ctl.at(i)*(2.0*i+1.0)/2.0
*leg_ctk.at(j)*(2.0*j+1.0)/2.0
*leg_phi.at(k)*(2.0*k+1.0)/2.0
/nWeightedEvents;
if (fejerkernel)
result *= (1.0 - h/double(npol.q2-1))
*(1.0 - i/double(npol.ctl-1))
*(1.0 - j/double(npol.ctk-1))
*(1.0 - k/double(npol.phi-1));
}
chijk_moments.at(bin) += result;
}
}
}
}
}
//check significance
//can be optimized as above
if (checkSignificance){
spdlog::info("starting CHECK SIGNIFICANT for LEGENDRE" );
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
unsigned int bin = npol.get_bin_in4D(h,i,j,k);
double result = chijk_moments.at(bin);
double sigma = 0.0;
for (unsigned int e=0; e<eventsInQ2bin.size(); e++){
const event & meas = eventsInQ2bin.at(e);
double q2 = 2.0 * (meas.q2 - edges.q2min ) / edges.range_q2() - 1.0;
double ctl = 2.0 * (meas.costhetal - edges.ctlmin ) / edges.range_ctl() - 1.0;
double ctk = 2.0 * (meas.costhetak - edges.ctkmin ) / edges.range_ctk() - 1.0;
double phi = 2.0 * (meas.phi - edges.phimin ) / edges.range_phi() - 1.0;
sigma += sqr(result - meas.weight // /nWeightedEvents
*fcnc::legendre(q2, h)*(2.0*h+1.0)/2.0
*fcnc::legendre(ctl, i)*(2.0*i+1.0)/2.0
*fcnc::legendre(ctk, j)*(2.0*j+1.0)/2.0
*fcnc::legendre(phi, k)*(2.0*k+1.0)/2.0
);// /eventsInQ2bin.size();
}
sigma = sqrt(sigma);
sigma /= nWeightedEvents;
if (fabs(result/sigma) < 1.0) chijk_moments.at(bin) = 0.0;
}
}
}
}
spdlog::info( "finished CHECK SIGNIFICANT for LEGENDRE" );
}
//Log
spdlog::debug( "//vector of legendre efficiency coefficients containing {0:d} elements", chijk_moments.size());
spdlog::trace( "legendre_coeffs_eff_4d = { " );
if (spdlog_trace()){
for (unsigned int i=0; i<chijk_moments.size(); i++){
std::cout<< std::setprecision(15) << std::scientific << chijk_moments.at(i) << (i<chijk_moments.size()-1 ? ", " : " ");
}
}
//calculate covariance
if (calculateCovariance){
const unsigned int nsize = npol.getSize();
spdlog::info( "Start COVARIANCE matrix for LEGENDRE polynoms" );
spdlog::debug( "calculating {0:d} by {1:d} convariance matrix ({2:d} doubles)" , nsize, nsize, nsize*nsize );
//optimized
std::vector<double> covariance(nsize*nsize, 0.0);
//startB = clock();
for (unsigned int e=0; e<eventsInQ2bin.size(); e++){
if (e % (eventsInQ2bin.size()/100) == 0)spdlog::debug( "{0:f}%", round(double(e*100)/eventsInQ2bin.size()));
const event & meas = eventsInQ2bin.at(e);
double q2 = 2.0 * (meas.q2 - edges.q2min ) / edges.range_q2() - 1.0;
double ctl = 2.0 * (meas.costhetal - edges.ctlmin) / edges.range_ctl()- 1.0;
double ctk = 2.0 * (meas.costhetak - edges.ctkmin) / edges.range_ctk()- 1.0;
double phi = 2.0 * (meas.phi - edges.phimin) / edges.range_phi()- 1.0;
double weight = meas.weight;
//calculates all legendre polynomials up to including degree n
std::vector<double> leg_q2(npol.q2, 0.0);
legendre(q2, npol.q2, leg_q2);
std::vector<double> leg_ctl(npol.ctl, 0.0);
legendre(ctl, npol.ctl, leg_ctl);
std::vector<double> leg_ctk(npol.ctk, 0.0);
legendre(ctk, npol.ctk, leg_ctk);
std::vector<double> leg_phi(npol.phi, 0.0);
legendre(phi, npol.phi, leg_phi);
double wfactor = weight*weight/(nWeightedEvents*nWeightedEvents);
double resulti=0.0, resultj=0.0, cov=0.0;
unsigned int bini=0, binj=0;
int hfactor=0, ifactor=0, jfactor=0, kfactor=0,
lfactor=0, mfactor=0, nfactor=0, ofactor=0,
hifactor=0, hijfactor=0, hijkfactor=0,
lmfactor=0, lmnfactor=0, lmnofactor=0;
double aq2=0.0,aq2ctl=0.0,aq2ctlctk=0.0,aq2ctlctkphi=0.0;
double bq2=0.0,bq2ctl=0.0,bq2ctlctk=0.0,bq2ctlctkphi=0.0;
for (unsigned int h = 0; h<npol.q2; h++){
hfactor = (2*h+1);
aq2 = 0.0625*leg_q2[h];
for (unsigned int i = 0; i<npol.ctl; i++){
ifactor = (2*i+1);
hifactor = hfactor*ifactor;
aq2ctl = aq2*leg_ctl[i];
for (unsigned int j = 0; j<npol.ctk; j++){
jfactor = (2*j+1);
hijfactor = hifactor*jfactor;
aq2ctlctk = aq2ctl*leg_ctk[j];
for (unsigned int k = 0; k<npol.phi; k++){
kfactor = (2*k+1);
hijkfactor = hijfactor*kfactor;
aq2ctlctkphi = aq2ctlctk*leg_phi[k];
bini = npol.get_bin_in4D(h,i,j,k);
resulti = chijk_moments[bini];
if (resulti != 0.0){
for (unsigned int l = 0; l<npol.q2; l++){
lfactor = (2*l+1);
bq2 = 0.0625*leg_q2[l];
for (unsigned int m = 0; m<npol.ctl; m++)
{
mfactor = (2*m+1);
lmfactor = lfactor*mfactor;
bq2ctl = bq2*leg_ctl[m];
for (unsigned int n = 0; n<npol.ctk; n++){
nfactor = (2*n+1);
lmnfactor = lmfactor*nfactor;
bq2ctlctk = bq2ctl*leg_ctk[n];
for (unsigned int o = 0; o<npol.phi; o++){
ofactor = (2*o+1);
lmnofactor = lmnfactor*ofactor;
bq2ctlctkphi = bq2ctlctk*leg_phi[o];
binj = npol.get_bin_in4D(l,m,n,o);
resultj = chijk_moments[binj];
if (binj <= bini && resultj != 0.0){
cov = (wfactor
*(resulti-hijkfactor*aq2ctlctkphi)
*(resultj-lmnofactor*bq2ctlctkphi)
);
covariance[nsize*bini+binj] += cov;
}
}
}
}
}
}
}
}
}
}
}
for (unsigned int bini = 0; bini<nsize; bini++){
for (unsigned int binj = 0; binj<nsize; binj++){
//covariance matrix is symmetric
if (binj < bini) covariance.at(nsize*binj+bini) = covariance.at(nsize*bini+binj);
}
}
//Print uncertanities in a matrix
spdlog::info("uncertainties[{0:0.8e}]", nsize);
for (unsigned int i =0; i<nsize; i++) std::cout << covariance.at(nsize*i+i) << (i < nsize-1 ? ", " : " };");
//Print covariance matrix
spdlog::info("Covariance matrix cov[{0:0.8e}]", nsize*nsize);
for (unsigned int i =0; i<nsize; i++){
for (unsigned int j =0; j<nsize; j++){
std::cout <<covariance.at(nsize*i+j) << ", ";
}
std::cout << std::endl;
}
std::cout << "};" << std::endl;//needs to be converted into correct range and translated to monomial coefficients? no, should do these transformations after every acceptance randomization
double correlation = 0.0;
for (unsigned int i =0; i<nsize; i++){
for (unsigned int j =0; j<nsize; j++){
double corr = covariance.at(nsize*i+j)/sqrt(covariance.at(nsize*i+i))/sqrt(covariance.at(nsize*j+j));
if (fabs(corr) > fabs(correlation) && i != j) correlation = corr;
}
}
spdlog::info("Largest correlation found is {0:f}", correlation );
}
spdlog::debug("start CONVERT legendre to monomial coefficients" );
//transform legendre coefficients to monomial coefficients
for (unsigned int h = 0; h<npol.q2; h++)
for (unsigned int i = 0; i<npol.ctl; i++)
for (unsigned int j = 0; j<npol.ctk; j++)
for (unsigned int k = 0; k<npol.phi; k++){
double tmp = chijk_moments.at(npol.get_bin_in4D(h,i,j,k));
std::vector<double> leg_coeffs_q2(npol.q2, 0.0);
std::vector<double> leg_coeffs_ctl(npol.ctl, 0.0);
std::vector<double> leg_coeffs_ctk(npol.ctk, 0.0);
std::vector<double> leg_coeffs_phi(npol.phi, 0.0);
std::vector<double> poly_coeffs_q2(npol.q2, 0.0);
std::vector<double> poly_coeffs_ctl(npol.ctl, 0.0);
std::vector<double> poly_coeffs_ctk(npol.ctk, 0.0);
std::vector<double> poly_coeffs_phi(npol.phi, 0.0);
leg_coeffs_q2.at(h) = 1.0;
leg_coeffs_ctl.at(i) = 1.0;
leg_coeffs_ctk.at(j) = 1.0;
leg_coeffs_phi.at(k) = 1.0;
legendre_to_poly(leg_coeffs_q2, poly_coeffs_q2);
legendre_to_poly(leg_coeffs_ctl, poly_coeffs_ctl);
legendre_to_poly(leg_coeffs_ctk, poly_coeffs_ctk);
legendre_to_poly(leg_coeffs_phi, poly_coeffs_phi);
for (unsigned int l = 0; l<=h; l++)
for (unsigned int m = 0; m<=i; m++)
for (unsigned int n = 0; n<=j; n++)
for (unsigned int o = 0; o<=k; o++){
unsigned int bin = npol.get_bin_in4D(l,m,n,o);
poly_moments.at(bin) += tmp*poly_coeffs_q2.at(l)*poly_coeffs_ctl.at(m)*poly_coeffs_ctk.at(n)*poly_coeffs_phi.at(o);
}
}//tested, works
spdlog::debug( "end CONVERT legendre to monomial coefficients" );
spdlog::debug( "poly_moments size: {0:d}", poly_moments.size() );
spdlog::info( "DOLEGENDRE end" );
}
void get_chebyschev(bin_edges edges, npolynom npol,
std::vector<event> eventsInQ2bin, double nWeightedEvents,
std::vector<double> &poly_moments,
bool fejerkernel, bool assumectleven, bool assumePhiEven,
bool checkSignificance, bool calculateCovariance
){
//use Legendre polynomials
spdlog::info("CHEBYSCHEV start");
std::vector<double> chijk_moments = std::vector<double>(npol.getSize(), 0.0);
for (unsigned int h = 0; h<npol.q2; h++)
for (unsigned int i = 0; i<npol.ctl; i++)
for (unsigned int j = 0; j<npol.ctk; j++)
for (unsigned int k = 0; k<npol.phi; k++){
double result = 0.0;
if (assumectleven && i%2 != 0)result = 0.0;
else if (assumePhiEven && k%2 != 0)result = 0.0;
else{
for (auto &meas: eventsInQ2bin){
double q2 = 2.0 * (meas.q2 - edges.q2min ) / edges.range_q2() - 1.0;
double ctl = 2.0 * (meas.costhetal - edges.ctlmin) / edges.range_ctl()- 1.0;
double ctk = 2.0 * (meas.costhetak - edges.ctkmin) / edges.range_ctk()- 1.0;
double phi = 2.0 * (meas.phi - edges.phimin) / edges.range_phi()- 1.0;
result += meas.weight
*fcnc::chebyshev(q2, h)/sqrt(1.0-q2*q2)*(h == 0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(ctl, i)/sqrt(1.0-ctl*ctl)*(i == 0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(ctk, j)/sqrt(1.0-ctk*ctk)*(j == 0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(phi, k)/sqrt(1.0-phi*phi)*(k == 0 ? 1.0/MY_PI : 2.0/MY_PI)
/nWeightedEvents;// /eventsInQ2bin.size();
}
if (fejerkernel){
result *= (1.0 - h/double(npol.q2-1))
*(1.0 - i/double(npol.ctl-1))
*(1.0 - j/double(npol.ctk-1))
*(1.0 - k/double(npol.phi-1));
}
}
//now have the "mean" in result
//mu = sum_i w_i/N
//sigma(mu) = sqrt(sum_i (w_i-mu)^2)/N
//else
chijk_moments.push_back(result);
}
//check significance
if (checkSignificance){
spdlog::info( "start CHECK SIGNIFICANCE for CHEBYSHEV polynoms" );
for (unsigned int h = 0; h<npol.q2; h++)
for (unsigned int i = 0; i<npol.ctl; i++)
for (unsigned int j = 0; j<npol.ctk; j++)
for (unsigned int k = 0; k<npol.phi; k++){
unsigned int bin = npol.get_bin_in4D(h,i,j,k);
double result = chijk_moments.at(bin);
double sigma = 0.0;
for (auto &meas : eventsInQ2bin){
double q2 = 2.0 * (meas.q2 - edges.q2min ) / edges.range_q2() - 1.0;
double ctl = 2.0 * (meas.costhetal - edges.ctlmin) / edges.range_ctl()- 1.0;
double ctk = 2.0 * (meas.costhetak - edges.ctkmin) / edges.range_ctk()- 1.0;
double phi = 2.0 * (meas.phi - edges.phimin) / edges.range_phi()- 1.0;
sigma += sqr(result - meas.weight // /nWeightedEvents
*fcnc::chebyshev(q2, h)/sqrt(1-q2*q2)*(h == 0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(ctl, i)/sqrt(1-ctl*ctl)*(i == 0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(ctk, j)/sqrt(1-ctk*ctk)*(j == 0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(phi, k)/sqrt(1-phi*phi)*(k == 0 ? 1.0/MY_PI : 2.0/MY_PI));// /eventsInQ2bin.size();
}
sigma = sqrt(sigma);
sigma /= nWeightedEvents;
if (fabs(result/sigma) < 1.0) chijk_moments.at(bin) = 0.0;
}
spdlog::info( "end CHECK SIGNIFICANCE for CHEBYSHEV polynoms" );
}
//printchebyshev
spdlog::debug( "//vector of chebyshev efficiency coefficients containing {0:d} elements",chijk_moments.size());
spdlog::trace( "chebyshev_coeffs_eff_4d = { " );
if (spdlog_trace()){
for (unsigned int i=0; i<chijk_moments.size(); i++){
std::cout<< std::setprecision(15) << std::scientific << chijk_moments.at(i) << (i<chijk_moments.size()-1 ? ", " : " ");
}
}
//calculate covariance
if (calculateCovariance){
spdlog::debug( "calculating {0:d} by {1:d} convariance matrix ({2:d} doubles)" , npol.getSize(), npol.getSize(), npol.getSize2() );
std::vector<double> covariance(npol.getSize2(), 0.0);
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
unsigned int bini = npol.get_bin_in4D(h,i,j,k);
double resulti = chijk_moments.at(bini);
if (resulti != 0.0){
for (unsigned int l = 0; l<npol.q2; l++){
for (unsigned int m = 0; m<npol.ctl; m++){
for (unsigned int n = 0; n<npol.ctk; n++){
for (unsigned int o = 0; o<npol.phi; o++){
unsigned int binj = npol.get_bin_in4D(l,m,n,o);
if (binj > bini) continue;//covariance matrix is symmetric
double resultj = chijk_moments.at(binj);
if (((bini*npol.getSize()+binj) * 100) % (npol.getSize2()) == 0)
spdlog::debug( "covariance matrix calculation {0:f}%", ((bini*npol.getSize()+binj) * 100) / (npol.getSize2()));
if (resultj != 0.0){
double cov = 0.0;
for (auto &meas : eventsInQ2bin){
double q2 = 2.0 * (meas.q2 - edges.q2min ) / edges.range_q2() - 1.0;
double ctl = 2.0 * (meas.costhetal - edges.ctlmin) / edges.range_ctl()- 1.0;
double ctk = 2.0 * (meas.costhetak - edges.ctkmin) / edges.range_ctk()- 1.0;
double phi = 2.0 * (meas.phi - edges.phimin) / edges.range_phi()- 1.0;
cov += ((resulti - meas.weight
*fcnc::chebyshev(q2, h)/sqrt(1-q2*q2)*(h == 0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(ctl, i)/sqrt(1-ctl*ctl)*(i == 0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(ctk, j)/sqrt(1-ctk*ctk)*(j == 0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(phi, k)/sqrt(1-phi*phi)*(k == 0 ? 1.0/MY_PI : 2.0/MY_PI))
*(resultj - meas.weight
*fcnc::chebyshev(q2, l)/sqrt(1-q2*q2)*(l == 0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(ctl, m)/sqrt(1-ctl*ctl)*(m == 0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(ctk, n)/sqrt(1-ctk*ctk)*(n == 0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(phi, o)/sqrt(1-phi*phi)*(o == 0 ? 1.0/MY_PI : 2.0/MY_PI))
);
}
//cov = sqrt(cov); //to get sigma on diagonal
cov /= sqr(nWeightedEvents);
covariance.at(npol.getSize()*bini+binj) = cov;
covariance.at(npol.getSize()*binj+bini) = cov;
}
}
}
}
}
}
}
}
}
}
spdlog::info("uncertainties[{0:0.8e}]", npol.getSize());
if (spdlog_info()){
for (unsigned int i =0; i<npol.getSize(); i++){
std::cout <<covariance.at(npol.getSize()*i+i) << (i < npol.getSize()-1 ? ", " : " };");
}
std::cout << std::endl;//needs to be converted into correct range and translated to monomial coefficients?
}
spdlog::info("Covariance matrix cov[{0:0.8e}]", npol.getSize2());
for (unsigned int i =0; i<npol.getSize(); i++){
for (unsigned int j =0; j<npol.getSize(); j++){
std::cout << covariance.at(npol.getSize()*i+j) << ", ";
}
std::cout << std::endl;
}
std::cout <<"};" << std::endl;//needs to be converted into correct range and translated to monomial coefficients? no, should do these transformations after every acceptance randomization
double correlation = 0.0;
for (unsigned int i =0; i<npol.getSize(); i++)
for (unsigned int j =0; j<npol.getSize(); j++)
{
double corr = covariance.at(npol.getSize()*i+j)/sqrt(covariance.at(npol.getSize()*i+i))/sqrt(covariance.at(npol.getSize()*j+j));
if (fabs(corr) > fabs(correlation) && i != j)
correlation = corr;
}
spdlog::info( "Largest correlation found is {0:f}", correlation );
}
//transform chebyshev coefficients to monomial coefficients
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
double c = chijk_moments.at(npol.get_bin_in4D(h,i,j,k));
std::vector<double> ch_coeffs_q2(npol.q2, 0.0);
std::vector<double> ch_coeffs_ctl(npol.ctl, 0.0);
std::vector<double> ch_coeffs_ctk(npol.ctk, 0.0);
std::vector<double> ch_coeffs_phi(npol.phi, 0.0);
std::vector<double> poly_coeffs_q2(npol.q2, 0.0);
std::vector<double> poly_coeffs_ctl(npol.ctl, 0.0);
std::vector<double> poly_coeffs_ctk(npol.ctk, 0.0);
std::vector<double> poly_coeffs_phi(npol.phi, 0.0);
ch_coeffs_q2.at(h) = 1.0;
ch_coeffs_ctl.at(i) = 1.0;
ch_coeffs_ctk.at(j) = 1.0;
ch_coeffs_phi.at(k) = 1.0;
chebyshev_to_poly(ch_coeffs_q2, poly_coeffs_q2);
chebyshev_to_poly(ch_coeffs_ctl, poly_coeffs_ctl);
chebyshev_to_poly(ch_coeffs_ctk, poly_coeffs_ctk);
chebyshev_to_poly(ch_coeffs_phi, poly_coeffs_phi);
for (unsigned int l = 0; l<=h; l++){
for (unsigned int m = 0; m<=i; m++){
for (unsigned int n = 0; n<=j; n++){
for (unsigned int o = 0; o<=k; o++){
unsigned int bin = npol.get_bin_in4D(l,m,n,o);
poly_moments.at(bin) += c*poly_coeffs_q2.at(l)*poly_coeffs_ctl.at(m)*poly_coeffs_ctk.at(n)*poly_coeffs_phi.at(o);
}
}
}
}
}
}
}
}
}
double integrate_4D(bin_edges edges, int h, int i, int j, int k){
return integrate_x_to_n(edges.q2min, edges.q2max,h)//careful with q2max
*integrate_x_to_n(edges.ctlmin, edges.ctlmax,i)
*integrate_x_to_n(edges.ctkmin, edges.ctkmax,j)
*integrate_x_to_n(edges.phimin, edges.phimax,k);
}
double integrate_3D(bin_edges edges, int i, int j, int k){
return integrate_x_to_n(edges.ctlmin, edges.ctlmax,i)
*integrate_x_to_n(edges.ctkmin, edges.ctkmax,j)
*integrate_x_to_n(edges.phimin, edges.phimax,k);
}
void fill_moments_hist_1D(TH1D *hist_moments, std::vector<double> coeffs_moments,
bin_edges edges, npolynom npol, double q2low, double q2high){
bool do_ctl = (std::string(hist_moments->GetName()).find("ctl") != std::string::npos);
bool do_ctk = (std::string(hist_moments->GetName()).find("ctk") != std::string::npos);
bool do_phi = (std::string(hist_moments->GetName()).find("phi") != std::string::npos);
bool do_q2 = (std::string(hist_moments->GetName()).find("q2") != std::string::npos);
for (int l=1; l<=hist_moments->GetNbinsX(); l++){
double a = hist_moments->GetBinLowEdge(l);
double b = hist_moments->GetBinLowEdge(l+1);
double integral = 0.0;
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
double result = coeffs_moments.at(npol.get_bin_in4D(h,i,j,k))
*(pow(do_q2 ? b : q2high ,h+1)/(h+1.0) - pow(do_q2 ? a : q2low ,h+1)/(h+1.0)) //Possibly replace by get_result;
*(pow(do_ctl ? b : edges.ctlmax,i+1)/(i+1.0) - pow(do_ctl ? a : edges.ctlmin,i+1)/(i+1.0))
*(pow(do_ctk ? b : edges.ctkmax,j+1)/(j+1.0) - pow(do_ctk ? a : edges.ctkmin,j+1)/(j+1.0))
*(pow(do_phi ? b : edges.phimax,k+1)/(k+1.0) - pow(do_phi ? a : edges.phimin,k+1)/(k+1.0));
integral += result;
}
}
}
}
hist_moments->SetBinContent(l, integral);
}
return;
}
void fill_moments_hist_2D(TH2D *hist_moments, std::vector<double> coeffs_moments,
bin_edges edges, npolynom npol, double q2low, double q2high){
bool do_ctl = (std::string(hist_moments->GetName()).find("ctl") != std::string::npos);
bool do_ctk = (std::string(hist_moments->GetName()).find("ctk") != std::string::npos);
bool do_phi = (std::string(hist_moments->GetName()).find("phi") != std::string::npos);
bool do_q2 = (std::string(hist_moments->GetName()).find("q2") != std::string::npos);
spdlog::trace("do_ctl\t"+boolToString(do_ctl));
spdlog::trace("do_ctk\t"+boolToString(do_ctk));
spdlog::trace("do_phi\t"+boolToString(do_phi));
spdlog::trace("do_q2\t"+boolToString(do_q2));
bool is_ctl_First = !do_q2; //ctl is second if q2
bool is_ctk_First = !(do_q2 || do_ctl); //ctk is second if ctl or q2
//phi is always second and q2 always first
spdlog::trace("is_ctl_First\t"+boolToString(is_ctl_First));
spdlog::trace("is_ctk_First\t"+boolToString(is_ctk_First));
for (int l=1; l<=hist_moments->GetNbinsX(); l++){
double a = hist_moments->GetXaxis()->GetBinLowEdge(l);
double b = hist_moments->GetXaxis()->GetBinLowEdge(l+1);
for (int m=1; m<=hist_moments->GetNbinsY(); m++){
double c = hist_moments->GetYaxis()->GetBinLowEdge(m);
double d = hist_moments->GetYaxis()->GetBinLowEdge(m+1);
double integral = 0.0;
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
double result = coeffs_moments.at(npol.get_bin_in4D(h,i,j,k))
*integrate_x_to_n(do_q2 ? a : q2low, do_q2 ? b : q2high ,h)
*integrate_x_to_n(do_ctl ? (is_ctl_First ? a : c) : edges.ctlmin,
do_ctl ? (is_ctl_First ? b : d) : edges.ctlmax,i)
*integrate_x_to_n(do_ctk ? (is_ctk_First ? a : c) : edges.ctkmin,
do_ctk ? (is_ctk_First ? b : d) : edges.ctkmax, j)
*integrate_x_to_n(do_phi ? c : edges.phimin,do_phi ? d : edges.phimax,k);
integral += result;
}
}
}
}
spdlog::trace("\t*** fill_moments_hist_2D: ***\t´");
spdlog::trace("l: {0:d}\tm: {1:d}\tint: {2:f}", l, m, integral);
hist_moments->SetBinContent(l, m, integral);
}
}
return;
}
int get_correct_index(std::string whichVar, int l, int m, int n, int o){
if (whichVar == "q2") return l;
if (whichVar == "ctl") return m;
if (whichVar == "ctk") return n;
if (whichVar == "phi") return o;
return -1;
}
int change_index(std::string whichVar, npolynom npol, int p, int l, int m, int n, int o){
if (whichVar == "q2") return npol.get_bin_in4D(p,m,n,o);
if (whichVar == "ctl") return npol.get_bin_in4D(l,p,n,o);
if (whichVar == "ctk") return npol.get_bin_in4D(l,m,p,o);
if (whichVar == "phi") return npol.get_bin_in4D(l,m,n,p);
return -1;
}
void correct_coefficients(npolynom npol, bin_edges edges, std::vector<double> &out_poly_moments, std::vector<double> in_poly_moments, std::string whichVar){
//Just rebin
unsigned int npol_var;
double intvar_min;
double intvar_max;
if (whichVar == "q2"){ //If this would be na efin array, my life would be orders of magnitute easier
npol_var = npol.q2;
intvar_min = edges.q2min;
intvar_max = edges.q2max;
}
else if (whichVar == "ctl") {
npol_var = npol.ctl;
intvar_min = edges.ctlmin;
intvar_max = edges.ctlmax;
}
else if (whichVar == "ctk") {
npol_var = npol.ctk;
intvar_min = edges.ctkmin;
intvar_max = edges.ctkmax;
}
else if (whichVar == "phi") {
npol_var = npol.phi;
intvar_min = edges.phimin;
intvar_max = edges.phimax;
}
else{
spdlog::error("Wrong index name! Either q2, ctl, ctk or phi!");
assert (0);
}
spdlog::debug("npol_var = {0:d}\tintvar_min = {1:f}\tintvar_max = {2:f}", npol_var, intvar_min, intvar_max);
for (unsigned int l = 0; l<npol.q2; l++){
for (unsigned int m = 0; m<npol.ctl; m++){
for (unsigned int n = 0; n<npol.ctk; n++){
for (unsigned int o = 0; o<npol.phi; o++){
unsigned int bin = npol.get_bin_in4D(l,m,n,o);
spdlog::trace("l={0:d}\tm={1:d}\tn={2:d}\to={3:d}\t bin ={4:d}",l,m,n,o,bin);
std::vector<double> poly(npol_var, 0.0);
poly.at(get_correct_index(whichVar,l,m,n,o)) = in_poly_moments.at(bin);
std::vector<double> correct(npol_var, 0.0);
correct_poly(poly, correct, intvar_min, intvar_max);
for (unsigned int p = 0; p<npol_var; p++){
unsigned int tobin = change_index(whichVar,npol,p,l,m,n,o);
spdlog::trace("p={0:d}\t tobin ={1:d}",p,tobin);
out_poly_moments.at(tobin) += correct.at(p);
}
}
}
}
}
return;
}
void bu2kstarmumu_pdf::parametrize_eff_phsp_4d(const std::vector<event>& events, values* globalvalues, int tagNumber, bool assumePhiEven, bool checkSignificance, bool runMinuit, bool checkFactorization, bool do3Dmoments){
spdlog::debug("----> start parametrization of angular acceptance correction coefficients with {0:d} events.", events.size());
const UInt_t nBinsQ2 = 40;
const UInt_t nBinsAngles = 40;
bool ignore_q2weights = false;
if (ignore_q2weights) spdlog::warn("Not using weights from genLvl PHSP to flatten the q2 distribution!!!");
//Get the pointer to this class of bu2kstarmumu_pdf
current_pdf = this;
std::vector<double> q2binsmin = opts->TheQ2binsmin; //Check TheQ2binsmax and q2binsmin
std::vector<double> q2binsmax = opts->TheQ2binsmax;
spdlog::debug("Vector q2binsmin:\t"+convert_vector_to_string(q2binsmin));
spdlog::debug("Vector q2binsmax:\t"+convert_vector_to_string(q2binsmax));
//name tag for all plots:
std::string appendix = "_"+DECAY_NAME
+ (opts->KS ? opts->DDLL+"_" : "_")
+ "Run" + std::to_string(opts->run)
+ ((opts->angacccorrperyear && opts->year != -1) ? "_"+std::to_string(opts->year) : "")
+ ((opts->folding != -1) ? "_folding"+std::to_string(opts->folding) : "")
+ ((opts->systematic == 3) ? "_"+std::to_string(opts->orderincrease)+"moreOrders" : "")
+ std::string(tagNumber != 0 ? "_"+std::to_string(tagNumber) : "");
std::string subfolder = "plots/angular/" + std::string(tagNumber != 0 ? "test/" : "");
spdlog::debug("Saving all plots into folder " + subfolder);
//Set orders of chebyshev/legendre polynomials
npolynom npol(opts); //Should be a const, but then all the future shuffling gets difficult
//fold the events if needed:
spdlog::debug("Init folder....");
//TODO remove fcnc::folder fldr(opts);
//only accept events inside q2min and q2max
std::vector<event> filtered_events;
//std::vector<event> fullrange_events;
unsigned int ee;
unsigned int N = events.size();
TRandom3 * rnd = new TRandom3(15*opts->job_id);
spdlog::debug("Filtering events...");
for (unsigned int e=0; e<N; e++){
//choose random events for bootstrapping
if (opts->systematic == 1) ee = int(rnd->Rndm() * N);
else ee = e; //or the correct, nominal order
fcnc::event evt = events.at(ee);
if (!isEvtInAngleRange(&(evt), opts)) continue;
filtered_events.push_back(evt);
if(!opts->full_angular) fldr->fold(&filtered_events.back());
}
if (!ignore_q2weights){
spdlog::debug("Getting q2 weights...");
//weight for all events, reweight from PHSP q2 model to flat q2 distribution using histogram
TFile* fphspweightq2 = new TFile(CONFIG_PHSP_WEIGHT.c_str());
TH1D* phspweightq2 = dynamic_cast<TH1D*>(fphspweightq2->Get(opts->IsFlatQ2 ? "flatq2weights" : "phspweightq2"));
bool keep_weights = opts->systematic != 2;
bool vary_weights = opts->systematic == 4;
//reweight filtered events
for (auto evt: filtered_events){
double q2 = evt.q2;
if(vary_weights){
evt.weight += evt.delta_weight * rnd->Gaus(0., 1.);
}
if (q2 < 0.2){
if(keep_weights) evt.weight *= phspweightq2->GetBinContent(2);//keep loaded totalweight!
else evt.weight = phspweightq2->GetBinContent(2);
}
else{
int bin = phspweightq2->FindFixBin(q2);
if (bin >=1 && bin <= phspweightq2->GetNbinsX()){
if(keep_weights) evt.weight *= phspweightq2->GetBinContent(bin);//keep loaded totalweight!
else evt.weight = phspweightq2->GetBinContent(bin);
}
}
}
delete phspweightq2;
fphspweightq2->Close();
delete fphspweightq2;
}
//for systematic 9: trigger weights, multiply existing weights by 1/L0Muon_eff
if(opts->systematic == 9){
spdlog::debug("Getting systematic 9");
//get years from current data-set:
std::vector<int> years; //empty vector
for (auto event: filtered_events){
bool year_found = false;
for(auto yr: years){
if(yr == event.year){
year_found = true;
break;
}
}
if(!year_found) years.push_back(event.year); //First event always gets filled
//Technically one should make an if to check it is all years, but given the size of the event sample this is okayish
}
assert(years.size());
std::sort(years.begin(), years.end());
//get L0Muon efficiency histo(s)
TFile * f_L0_w[years.size()];
TH1D * h_L0_w[years.size()];
for(unsigned int y = 0; y < years.size(); y++){
f_L0_w[y] = new TFile((std::string("config/")+(opts->KS?"KshortPiplus":"KplusPi0Resolved")+"_L0MuonEfficiency_"+std::to_string(years.at(y))+".root").c_str(), "READ");
if(!f_L0_w[y]->IsOpen()){
spdlog::critical( "Could not find file with L0Muon efficiencies: 'config/" + std::string(opts->KS ? "KshortPiplus" : "KplusPi0Resolved") + "_L0MuonEfficiency_{0:d}.root'", years.at(y) );
assert(0);
}
h_L0_w[y] = dynamic_cast<TH1D*>(f_L0_w[y]->Get("L0MuonEffRatioPHSP"));
spdlog::info("Succesfully loaded L0Muon efficiency reweighting histogram for year={0:d}", years.at(y));
}
for (unsigned int i=0; i<filtered_events.size(); i++){
double max_mu_pt = filtered_events.at(i).max_mu_pt;
unsigned int year_idx = 0;
for(unsigned int y = 0; y < years.size(); y++){
if(years.at(y) == filtered_events.at(i).year){
year_idx = y;
break;
}
}
if(max_mu_pt > 20000.){
filtered_events.at(i).weight *= h_L0_w[year_idx]->GetBinContent(h_L0_w[year_idx]->GetNbinsX());
}
else{
int bin = h_L0_w[year_idx]->FindFixBin(max_mu_pt);
filtered_events.at(i).weight *= h_L0_w[year_idx]->GetBinContent(bin);
}
}
for(unsigned int y = 0; y < years.size(); y++){
delete h_L0_w[y];
f_L0_w[y]->Close();
delete f_L0_w[y];
}
}
//set the pointer that is accessible from the minuit fcn
eff_events = filtered_events;
//make plot to check weight distribution if running a test
if(tagNumber >0){
spdlog::debug("Plotting weights");
TH1D* hweight = new TH1D("hweight", ";w;", 100, 0.0, 1.0/EFF_CUTOFF);
for (unsigned int i=0; i<filtered_events.size(); i++){
spdlog::trace("Weight of event {0:d}\t\t{1:f}", i , filtered_events.at(i).weight);
hweight->Fill(filtered_events.at(i).weight);
}
TCanvas * cweights = new TCanvas();
cweights->cd();
hweight->Draw("");
if(opts->write_eps)cweights->Print((subfolder + "weights"+appendix+".eps").c_str(), "eps");
if(opts->write_eps)cweights->Print((subfolder + "weights"+appendix+".root").c_str(), "root");
delete hweight;
delete cweights;
}
//---------------------------------------
//DETERMINATION FROM ACCEPTANCE HISTOGRAM
//---------------------------------------
unsigned int nq2bins = 18;
unsigned int nctlbins = 10;
unsigned int nctkbins = 10;
unsigned int nphibins = 5;
bool adapt_bins_to_folding = false;
if(adapt_bins_to_folding){
nphibins /= 2;
if(opts->folding > 0)nctlbins /= 2;
}
spdlog::debug("Options: ");
spdlog::debug("q2min={0:f}\tq2max={1:f}", opts->TheQ2binsmin.front(),opts->TheQ2binsmax.back());
spdlog::debug("ctkmin={0:f}\tctkmax={1:f}", opts->ctk_min, opts->ctk_max);
spdlog::debug("ctlmin={0:f}\tctlmax={1:f}", opts->ctl_min, opts->ctl_max);
spdlog::debug("phimin={0:f}\tphimax={1:f}", opts->phi_min, opts->phi_max);
bin_edges edges (opts, nq2bins, nctlbins, nctkbins, nphibins);
const std::vector<double> q2_edges = edges.edges_q2();
const std::vector<double> ctl_edges = edges.edges_ctl();
const std::vector<double> ctk_edges = edges.edges_ctk();
const std::vector<double> phi_edges = edges.edges_phi(); //This could've been a struct/class
spdlog::trace("q2 edges: " + convert_vector_to_string(q2_edges));
spdlog::trace("ctl edges: " + convert_vector_to_string(ctl_edges));
spdlog::trace("ctk edges: " + convert_vector_to_string(ctk_edges));
spdlog::trace("phi edges: " + convert_vector_to_string(phi_edges));
//should compare full 4D with
//3D in q2 bins
//3D factorizing in bins of q2
spdlog::debug("Getting number of weighted events...");
std::vector<double> eps_hist(edges.getNbins(), 0.0);
double nWeightedEvents = 0.0;
for (auto &meas: filtered_events){
unsigned int bin = get_bin_in4D(meas,edges);
eps_hist.at(bin) += meas.weight;
nWeightedEvents += meas.weight;
}
//rescale efficiency
spdlog::debug("Rescaling efficiency...");
for (unsigned int h = 0; h<edges.nq2bins; h++){
for (unsigned int i = 0; i<edges.nctlbins; i++){
for (unsigned int j = 0; j<edges.nctkbins; j++){
for (unsigned int k = 0; k<edges.nphibins; k++){
eps_hist.at(get_bin_in4D(h,i,j,k,edges)) *= edges.getNbins()/nWeightedEvents;
}
}
}
}
//determine xis in bins of q2
spdlog::debug("Getting xis in bins of q2...");
std::vector<TH1D*> hxi_hist;
for (auto angObs: get_angObser_withTeX_vec()){
hxi_hist.push_back(new TH1D(("hxi"+angObs[0]+"hist").c_str(), (";q^{2};"+angObs[1]).c_str(),
edges.nq2bins, edges.q2min, edges.q2max));
}
std::vector<int>int_xi(hxi_hist.size(),0);
for (unsigned int h = 0; h<edges.nq2bins; h++){
std::fill(int_xi.begin(), int_xi.end(), 0); //fill int_xi with zeroes
for (unsigned int i = 0; i<edges.nctlbins; i++)
for (unsigned int j = 0; j<edges.nctkbins; j++)
for (unsigned int k = 0; k<edges.nphibins; k++){
unsigned int bin = get_bin_in4D(h,i,j,k,edges);
double eps = eps_hist.at(bin);
double f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12;
if(opts->full_angular){
integrated_fj_noacc(ctl_edges[i], ctl_edges[i+1],
ctk_edges[j], ctk_edges[j+1],
phi_edges[k], phi_edges[k+1],
f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12);
}
else{
folded_integrated_fj_noacc(ctl_edges[i], ctl_edges[i+1],
ctk_edges[j], ctk_edges[j+1],
phi_edges[k], phi_edges[k+1],
f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12);
}
int_xi[0] += eps*f1; //KILL ME
int_xi[1] += eps*f2;
int_xi[2] += eps*f3;
int_xi[3] += eps*f4;
int_xi[4] += eps*f5;
int_xi[5] += eps*f6;
int_xi[6] += eps*f7;
int_xi[7] += eps*f8;
int_xi[8] += eps*f9;
int_xi[9] += eps*f10;
int_xi[10] += eps*f11;
int_xi[11] += eps*f12;
}
for_indexed(auto hist: hxi_hist) hist->SetBinContent(h+1,int_xi[i]);
}
//-----------------------------------
//DETERMINE XIS USING UNBINNED METHOD
//-----------------------------------
spdlog::debug("Getting xis using unbinned method...");
std::vector<TH1D*> hxi_ub;
for (auto angObs: get_angObser_withTeX_vec()){
hxi_ub.push_back(new TH1D(("hxi"+angObs[0]+"ub").c_str(), (";q^{2};"+angObs[1]).c_str(),
edges.nq2bins, edges.q2min, edges.q2max));
}
//make it pretty
for (auto hist: hxi_ub) hist->SetLineColor(4);
for (unsigned int h = 0; h<edges.nq2bins; h++){
std::fill(int_xi.begin(), int_xi.end(), 0); //fill int_xi with zeroes, no need to initialize (see line 961)
//double q2a = hxi_ub[0]->GetBinLowEdge(h); //check this is the same as q2_edges!!!!! should be, but to be sure
//double q2b = hxi_ub[0]->GetBinLowEdge(h+1);
for (auto &&meas: filtered_events){
if (meas.q2 < q2_edges[h] || meas.q2 > q2_edges[h]) continue;
double f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12;
if(opts->full_angular){
fj(meas.costhetal, meas.costhetak, meas.phi,
f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12);
}
else{
folded_fj(meas.costhetal, meas.costhetak, meas.phi,
f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12);
}
double weight = meas.weight/nWeightedEvents*edges.nq2bins*(edges.range_ctl()*edges.range_ctk()*edges.range_phi());
int_xi[0] += f1*weight; //KILL ME
int_xi[1] += f2*weight;
int_xi[2] += f3*weight;
int_xi[3] += f4*weight;
int_xi[4] += f5*weight;
int_xi[5] += f6*weight;
int_xi[6] += f7*weight;
int_xi[7] += f8*weight;
int_xi[8] += f9*weight;
int_xi[9] += f10*weight;
int_xi[10] += f11*weight;
int_xi[11] += f12*weight;
}
for_indexed(auto hist: hxi_ub) hist->SetBinContent(h,int_xi[i]);
}
//------------------------------------------------------
//DETERMINE POLYNOMIAL ACCEPTANCE WITH METHOD OF MOMENTS
//------------------------------------------------------
const bool calculateCovariance = false;
const bool assumectleven = opts->systematic == 2;
const bool fejerkernel = false; //see Alexander Weisse, Holger Feshke, Chebyshev expansion techniques
const bool doLegendre = true; //somehow, chebyshev is broken now, great job me
std::vector<double> poly_moments(npol.getSize(), 0.0);
if (doLegendre){
get_legendre(edges, npol,
filtered_events, nWeightedEvents,
poly_moments,
fejerkernel, assumectleven, assumePhiEven,
checkSignificance, calculateCovariance);
}
else{
get_chebyschev(edges, npol,
filtered_events, nWeightedEvents,
poly_moments,
fejerkernel, assumectleven, assumePhiEven,
checkSignificance, calculateCovariance);
}
spdlog::debug("Getting correct polynomial coefficients in cos(thetak) and cos(thetal)");
spdlog::debug("poly_moments size:{0:d}", poly_moments.size());
//correct coefficients from -1 +1 to ctlmin .. ctlmax for ctl, bit difficult, requires binomial coefficients
std::vector<double> poly_moments_ctl(npol.getSize(), 0.0);
std::vector<double> poly_moments_ctk(npol.getSize(), 0.0);
std::vector<double> poly_moments_phi(npol.getSize(), 0.0);
std::vector<double> poly_moments_q2(npol.getSize(), 0.0);
correct_coefficients(npol,edges,poly_moments_ctl,poly_moments, "ctl");
correct_coefficients(npol,edges,poly_moments_ctk,poly_moments_ctl, "ctk");
correct_coefficients(npol,edges,poly_moments_phi,poly_moments_ctk, "phi");
correct_coefficients(npol,edges,poly_moments_q2, poly_moments_phi, "q2");
spdlog::debug("Getting moments....");
std::vector<double> coeffs_moments(poly_moments_q2);
//calculate norm after full integration
double full_norm = 0.0;
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
full_norm += coeffs_moments.at(npol.get_bin_in4D(h,i,j,k))*integrate_4D(edges, h, i, j, k);
}
}
}
}
//assume a flat efficiency of 1.0 -> scale by edges.range_q2()*RANGE_3D()/full_norm
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
coeffs_moments.at(npol.get_bin_in4D(h,i,j,k)) *= edges.range_q2()*RANGE_3D()/full_norm;
}
}
}
}
//print to std::out
if (spdlog_trace()){
spdlog::trace( "//vector of efficiency coefficients containing {0:d} elements", coeffs_moments.size());
spdlog::trace( "coeffs_eff_4d = { " );
for (unsigned int i=0; i<coeffs_moments.size(); i++){
std::cout << std::setprecision(5) << std::scientific << coeffs_moments.at(i)<< (i<coeffs_moments.size()-1 ? ", " : " ");
}
}
//set this as default coefficients now
coeffs_eff_4d = coeffs_moments;
//calculate the integrated angular terms int f_i dOmega (q2) = xi(q2)
std::vector<TH1D*> hxi_moments;
for (auto &angObs: get_angObser_withTeX_vec()){
hxi_moments.push_back(new TH1D(("hxi"+angObs[0]+"_moments").c_str(), (";q^{2};"+angObs[1]).c_str(),
edges.nq2bins, edges.q2min, edges.q2max));
}
for (int l=1; l<=hxi_moments[0]->GetNbinsX(); l++) {
double a = hxi_moments[0]->GetXaxis()->GetBinLowEdge(l);
double b = hxi_moments[0]->GetXaxis()->GetBinLowEdge(l+1);
std::vector<double> integral_xi(hxi_moments.size(),0.0);
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
unsigned int bin =npol.get_bin_in4D(h, i, j, k);
double coeff = C_PWAVE*coeffs_moments.at(bin)*pow(0.5*(a+b), h);
//f1 = c * sinthetak2; //j1s
integral_xi[0] += coeff
* integrate_x_to_n(edges.ctlmin, edges.ctlmax, i)
*(integrate_x_to_n(edges.ctkmin, edges.ctkmax, j) - integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2))
* integrate_x_to_n(edges.phimin, edges.phimax,k);
//f2 = c * costhetak2; //j1c
integral_xi[1] += coeff
*integrate_x_to_n(edges.ctlmin, edges.ctlmax, i)
*integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2)
*integrate_x_to_n(edges.phimin, edges.phimax,k);
//f3 = c * sinthetak2*cos2thetal; //j2s
integral_xi[2] += coeff
*(2.0*integrate_x_to_n(edges.ctlmin, edges.ctlmax, i+2)-integrate_x_to_n(edges.ctlmin, edges.ctlmax, i))
*(integrate_x_to_n(edges.ctkmin, edges.ctkmax, j)-integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2))
*integrate_x_to_n(edges.phimin, edges.phimax,k);
//f4 = c * costhetak2*cos2thetal; //j2c
integral_xi[3] += coeff
*(2.0*integrate_x_to_n(edges.ctlmin, edges.ctlmax, i+2)-integrate_x_to_n(edges.ctlmin, edges.ctlmax, i))
*integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2)
*integrate_x_to_n(edges.phimin, edges.phimax,k);
//f5 = c * sinthetak2*sinthetal2*cos(2.0*phi); //j3
integral_xi[4] += coeff
*(integrate_x_to_n(edges.ctlmin, edges.ctlmax, i)-integrate_x_to_n(edges.ctlmin, edges.ctlmax, i+2))
*(integrate_x_to_n(edges.ctkmin, edges.ctkmax, j)-integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2))
*integrate_x_to_n_times_cos_2x(edges.phimin, edges.phimax,k);
//f6 = c * sin2thetak*sin2thetal*cos(phi); //j4
integral_xi[5] += coeff
*2.0*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctlmin, edges.ctlmax, i+1)
*2.0*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctkmin, edges.ctkmax, j+1)
*integrate_x_to_n_times_cos_x(edges.phimin, edges.phimax,k);
//f7 = c * sin2thetak*sinthetal*cos(phi); //j5
integral_xi[6] += coeff
*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctlmin, edges.ctlmax, i)
*2.0*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctkmin, edges.ctkmax, j+1)
*integrate_x_to_n_times_cos_x(edges.phimin, edges.phimax,k);
//f8 = c * sinthetak2*costhetal; //j6s
integral_xi[7] += coeff
*integrate_x_to_n(edges.ctlmin, edges.ctlmax, i+1)
*(integrate_x_to_n(edges.ctkmin, edges.ctkmax, j)-integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2))
*integrate_x_to_n(edges.phimin, edges.phimax,k);
//f9 = c * costhetak2*costhetal; //j6c
integral_xi[8] += coeff
*integrate_x_to_n(edges.ctlmin, edges.ctlmax, i+1)
*integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2)
*integrate_x_to_n(edges.phimin, edges.phimax,k);
//f10 = c * sin2thetak*sinthetal*sin(phi); //j7
integral_xi[9] += coeff
*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctlmin, edges.ctlmax, i)
*2.0*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctkmin, edges.ctkmax, j+1)
*integrate_x_to_n_times_sin_x(edges.phimin, edges.phimax,k);
//f11 = c * sin2thetak*sin2thetal*sin(phi); //j8
integral_xi[10] += coeff
*2.0*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctlmin, edges.ctlmax, i+1)
*2.0*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctkmin, edges.ctkmax, j+1)
*integrate_x_to_n_times_sin_x(edges.phimin, edges.phimax,k);
//f12 = c * sinthetak2*sinthetal2*sin(2.0*phi); //j9
integral_xi[11] += coeff
*(integrate_x_to_n(edges.ctlmin, edges.ctlmax, i) - integrate_x_to_n(edges.ctlmin, edges.ctlmax, i+2))
*(integrate_x_to_n(edges.ctkmin, edges.ctkmax, j) - integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2))
*integrate_x_to_n_times_sin_2x(edges.phimin, edges.phimax,k);
}
}
}
}
for_indexed(auto hist: hxi_moments) hist->SetBinContent(l, is_param_folded(i,opts) ? 0.0 : integral_xi[i]);
}
//-----------------------------------------------------
//DETERMINE POLYNOMIAL ACCEPTANCE USING UNBINNED ML FIT
//-----------------------------------------------------
std::vector<TH1D*> hxi_ml_hist;
for (auto &angObs: get_angObser_withTeX_vec()){
hxi_ml_hist.push_back(new TH1D(("hxi"+angObs[0]+"_ml").c_str(), (";q^{2};"+angObs[1]).c_str(),
nBinsQ2, edges.q2min, edges.q2max));
}
for (auto &hist: hxi_ml_hist){
hist->SetLineColor(3);
}
//possible TODO for when you're bored: move into it's own function
//Running minuit is expensive, use only if necesary!
if (runMinuit){
spdlog::info("Running Minuit....");
//setup minuit
TMinuit* minuit_eff = new TMinuit(10000);
int errorcode;
minuit_eff->SetFCN(&(eff_fcn_phsp_4d));
double strategy_list[1] = {2.0};
minuit_eff->mnexcm("SET STR", strategy_list, 1, errorcode);
minuit_eff->SetMaxIterations(1000000);
minuit_eff->SetErrorDef(1.0);
const bool second_run = false;
//define params (could also feed with starting values from method of moments)
unsigned int q2_limit = 6;
unsigned int ctl_limit = 3;
unsigned int ctk_limit = 4;
unsigned int phi_limit = 1;
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
std::ostringstream sout;
sout << "c" << h << i << j << k;
if (h==0 && i==0 && j==0 && k==0){
minuit_eff->DefineParameter(npol.get_bin_in4D(h,i,j,k), sout.str().c_str(), 1.0, 0.0, 0.0, 0.0);
}
else if (h >= q2_limit || i >= ctl_limit || j >= ctk_limit || k >= phi_limit){
//this is to be able to do higher orders with the moments method and lower ones with minuit
minuit_eff->DefineParameter(npol.get_bin_in4D(h,i,j,k), sout.str().c_str(), 0.0, 0.0, 0.0, 0.0);
}
else if ((second_run && i == 0 && k == 0)|| (!second_run && i % 2 == 0 && k % 2 == 0)){
minuit_eff->DefineParameter(npol.get_bin_in4D(h,i,j,k), sout.str().c_str(), 0.0, 0.001, 0.0, 0.0);
}
else{
minuit_eff->DefineParameter(npol.get_bin_in4D(h,i,j,k), sout.str().c_str(), 0.0, 0.0, 0.0, 0.0);
}
}
}
}
}
double migrad_options[2] = {100000000.0, 0.1}; //{max calls, tolerance}
spdlog::info( "Running Migrad to determine eff shape" );
minuit_eff->mnset();
minuit_eff->mnexcm("MIG", migrad_options, 2, errorcode);
if (second_run){
spdlog::info( "Running Migrad a second time releasing parameters" );
//second run releasing some parameters
for (unsigned int h = 0; h<npol.q2; h++)
for (unsigned int i = 0; i<npol.ctl; i++)
for (unsigned int j = 0; j<npol.ctk; j++)
for (unsigned int k = 0; k<npol.phi; k++){
std::ostringstream sout;
sout << "c" << h << i << j << k;
if ((i > 0 || k > 0) && i % 2 == 0 && k % 2 == 0
&& h < q2_limit && i < ctl_limit && j < ctk_limit && k < phi_limit
)// && (i+j+k)<=4)
minuit_eff->DefineParameter(npol.get_bin_in4D(h,i,j,k), sout.str().c_str(), 0.0, 0.001, 0.0, 0.0);
}
spdlog::info( "Running Migrad to determine eff shape" );
minuit_eff->mnexcm("MIG", migrad_options, 2, errorcode);
}
//extract fitted parameters
spdlog::debug("Extracting fitted parameters.");
std::vector<double> chijk_ml;
for (unsigned int h = 0; h<npol.q2; h++)
for (unsigned int i = 0; i<npol.ctl; i++)
for (unsigned int j = 0; j<npol.ctk; j++)
for (unsigned int k = 0; k<npol.phi; k++){
double v,e;
minuit_eff->GetParameter(npol.get_bin_in4D(h,i,j,k), v, e);
chijk_ml.push_back(v);
}
delete minuit_eff;
spdlog::info( "Minuit finished" );
//transform chebyshev coefficients to monomial coefficients
std::vector<double> poly_ml(npol.getSize(), 0.0);
for (unsigned int h = 0; h<npol.q2; h++)
for (unsigned int i = 0; i<npol.ctl; i++)
for (unsigned int j = 0; j<npol.ctk; j++)
for (unsigned int k = 0; k<npol.phi; k++){
double c = chijk_ml.at(npol.get_bin_in4D(h,i,j,k));
std::vector<double> ch_coeffs_q2(npol.q2, 0.0);
std::vector<double> ch_coeffs_ctl(npol.ctl, 0.0);
std::vector<double> ch_coeffs_ctk(npol.ctk, 0.0);
std::vector<double> ch_coeffs_phi(npol.phi,0.0);
ch_coeffs_q2.at(h) = 1.0;
ch_coeffs_ctl.at(i) = 1.0;
ch_coeffs_ctk.at(j) = 1.0;
ch_coeffs_phi.at(k) = 1.0;
std::vector<double> poly_coeffs_q2(npol.q2, 0.0);
std::vector<double> poly_coeffs_ctl(npol.ctl, 0.0);
std::vector<double> poly_coeffs_ctk(npol.ctk, 0.0);
std::vector<double> poly_coeffs_phi(npol.phi,0.0);
chebyshev_to_poly(ch_coeffs_q2, poly_coeffs_q2);
chebyshev_to_poly(ch_coeffs_ctl, poly_coeffs_ctl);
chebyshev_to_poly(ch_coeffs_ctk, poly_coeffs_ctk);
chebyshev_to_poly(ch_coeffs_phi, poly_coeffs_phi);
for (unsigned int l = 0; l<=h; l++)
for (unsigned int m = 0; m<=i; m++)
for (unsigned int n = 0; n<=j; n++)
for (unsigned int o = 0; o<=k; o++){
unsigned int bin = npol.get_bin_in4D(l,m,n,o);
poly_ml.at(bin) += c*poly_coeffs_q2.at(l)*poly_coeffs_ctl.at(m)*poly_coeffs_ctk.at(n)*poly_coeffs_phi.at(o);
}
}//tested, works
//correct coefficients from -1 +1 to ctlmin .. ctlmax for ctl, bit difficult, requires binomial coefficients
std::vector<double> poly_ml_ctl(npol.getSize(), 0.0);
std::vector<double> poly_ml_ctk(npol.getSize(), 0.0);
std::vector<double> poly_ml_phi(npol.getSize(), 0.0);
std::vector<double> poly_ml_q2(npol.getSize(), 0.0);
correct_coefficients(npol, edges, poly_ml_ctl, poly_ml, "ctl");
correct_coefficients(npol, edges, poly_ml_ctk, poly_ml_ctl, "ctk");
correct_coefficients(npol, edges, poly_ml_phi, poly_ml_ctk, "phi");
correct_coefficients(npol, edges, poly_ml_q2, poly_ml_phi, "q2");
std::vector<double> coeffs_ml(poly_ml_q2);
//calculate norm after full integration
double full_norm = 0.0;
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
full_norm += coeffs_ml.at(npol.get_bin_in4D(h,i,j,k))*integrate_4D(edges,h,i,j,k);
}
}
}
}
//assume a flat efficiency of 1.0 -> scale by edges.range_q2()*RANGE_3D()/full_norm
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
coeffs_ml.at(npol.get_bin_in4D(h,i,j,k)) *= edges.range_q2()*RANGE_3D()/full_norm;
// delta_q2*delta_ctl*delta_ctk*delta_phi/full_norm;
}
}
}
}
//calculate the integrated angular terms int f_i dOmega (q2) = xi(q2)
for (int l=1; l<=hxi_ml_hist[0]->GetNbinsX(); l++){
double a = hxi_ml_hist[0]->GetXaxis()->GetBinLowEdge(l);
double b = hxi_ml_hist[0]->GetXaxis()->GetBinLowEdge(l+1);
std::vector<double> integral_xi(hxi_ml_hist.size(), 0.0);
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
unsigned int bin = npol.get_bin_in4D(h,i,j,k);
double coeff = C_PWAVE*coeffs_ml.at(bin)*pow(0.5*(a+b), h);
//f1 = c * sinthetak2; //j1s
integral_xi[0] += coeff
*integrate_x_to_n(edges.ctlmin, edges.ctlmax, i)
*(integrate_x_to_n(edges.ctkmin, edges.ctkmax, j)-integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2))
*integrate_x_to_n(edges.phimin, edges.phimax,k);
//f2 = c * costhetak2; //j1c
integral_xi[1] += coeff
*integrate_x_to_n(edges.ctlmin, edges.ctlmax, i)
*integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2)
*integrate_x_to_n(edges.phimin, edges.phimax,k);
//f3 = c * sinthetak2*cos2thetal; //j2s
integral_xi[2] += coeff
*(2.0*integrate_x_to_n(edges.ctlmin, edges.ctlmax, i+2)-integrate_x_to_n(edges.ctlmin, edges.ctlmax, i))
*(integrate_x_to_n(edges.ctkmin, edges.ctkmax, j)-integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2))
*integrate_x_to_n(edges.phimin, edges.phimax,k);
//f4 = c * costhetak2*cos2thetal; //j2c
integral_xi[3] += coeff
*(2.0*integrate_x_to_n(edges.ctlmin, edges.ctlmax, i+2)-integrate_x_to_n(edges.ctlmin, edges.ctlmax, i))
*integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2)
*integrate_x_to_n(edges.phimin, edges.phimax,k);
//f5 = c * sinthetak2*sinthetal2*cos(2.0*phi); //j3
integral_xi[4] += coeff
*(integrate_x_to_n(edges.ctlmin, edges.ctlmax, i)-integrate_x_to_n(edges.ctlmin, edges.ctlmax, i+2))
*(integrate_x_to_n(edges.ctkmin, edges.ctkmax, j)-integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2))
*integrate_x_to_n_times_cos_2x(edges.phimin, edges.phimax,k);
//f6 = c * sin2thetak*sin2thetal*cos(phi); //j4
integral_xi[5] += coeff
*2.0*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctlmin, edges.ctlmax, i+1)
*2.0*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctkmin, edges.ctkmax, j+1)
*integrate_x_to_n_times_cos_x(edges.phimin, edges.phimax,k);
//f7 = c * sin2thetak*sinthetal*cos(phi); //j5
integral_xi[6] += coeff
*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctlmin, edges.ctlmax, i)
*2.0*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctkmin, edges.ctkmax, j+1)
*integrate_x_to_n_times_cos_x(edges.phimin, edges.phimax,k);
//f8 = c * sinthetak2*costhetal; //j6s
integral_xi[7] += coeff
*integrate_x_to_n(edges.ctlmin, edges.ctlmax, i+1)
*(integrate_x_to_n(edges.ctkmin, edges.ctkmax, j)-integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2))
*integrate_x_to_n(edges.phimin, edges.phimax,k);
//f9 = c * costhetak2*costhetal; //j6c
integral_xi[8] += coeff
*integrate_x_to_n(edges.ctlmin, edges.ctlmax, i+1)
*integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2)
*integrate_x_to_n(edges.phimin, edges.phimax,k);
//f10 = c * sin2thetak*sinthetal*sin(phi); //j7
integral_xi[9] += coeff
*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctlmin, edges.ctlmax, i)
*2.0*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctkmin, edges.ctkmax, j+1)
*integrate_x_to_n_times_sin_x(edges.phimin, edges.phimax,k);
//f11 = c * sin2thetak*sin2thetal*sin(phi); //j8
integral_xi[10] += coeff
*2.0*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctlmin, edges.ctlmax, i+1)
*2.0*integrate_x_to_n_times_sqrt_1_minus_x2(edges.ctkmin, edges.ctkmax, j+1)
*integrate_x_to_n_times_sin_x(edges.phimin, edges.phimax,k);
//f12 = c * sinthetak2*sinthetal2*sin(2.0*phi); //j9
integral_xi[11] += coeff
*(integrate_x_to_n(edges.ctlmin, edges.ctlmax, i) - integrate_x_to_n(edges.ctlmin, edges.ctlmax, i+2))
*(integrate_x_to_n(edges.ctkmin, edges.ctkmax, j) - integrate_x_to_n(edges.ctkmin, edges.ctkmax, j+2))
*integrate_x_to_n_times_sin_2x(edges.phimin, edges.phimax,k);
}
}
}
}
for_indexed(auto hist: hxi_ml_hist) hist->SetBinContent(l, is_param_folded(i,opts) ? 0.0 : integral_xi[i]);
}
}
//-----------------------
// Factorization in q2 bins
//-----------------------
//std::vector<double> nfact();
if (checkFactorization){ //possible TODO for when you're bored: move into it's own function
spdlog::info( "CHECKFACTORIZATION start " );
//fill histo for comparison
std::vector<double> nsel_hist(edges.getNbins(), 0.0);
std::vector<double> nsel_hist_errsq(edges.getNbins(), 0.0);
for (auto &meas: filtered_events){
unsigned int h = (meas.q2 - edges.q2min ) / edges.binWidth_q2();
unsigned int i = (meas.costhetal - edges.ctlmin ) / edges.binWidth_ctl();
unsigned int j = (meas.costhetak - edges.ctkmin ) / edges.binWidth_ctk();
unsigned int k = (meas.phi - edges.phimin ) / edges.binWidth_phi();
unsigned int bin = get_bin_in4D(h,i,j,k,edges);
nsel_hist.at(bin) += meas.weight;
nsel_hist_errsq.at(bin) += sqr(meas.weight);
}
for (unsigned int i=0; i<nsel_hist_errsq.size(); i++){
if (nsel_hist_errsq.at(i) == 0.0) nsel_hist_errsq.at(i) = 1.0;
}
//loop over all q2 bins
double chi2 = 0.0;
for (unsigned int h=0; h<q2_edges.size()-1; h++){
double q2a = q2_edges.at(h);
double q2b = q2_edges.at(h+1);
std::vector<double> ctl_moments(npol.ctl, 0.0);
std::vector<double> ctk_moments(npol.ctk, 0.0);
std::vector<double> phi_moments(npol.phi,0.0);
double nfactweighted = 0.0;
//determine weighted number of events in this bin and fill control histos
std::ostringstream sout;
sout << h;
sout << "_" << DECAY_NAME << (opts->KS ? opts->DDLL+"_" : "_")
<< "Run" << opts->run
<< ((opts->angacccorrperyear && opts->year != -1) ? "_"+std::to_string(opts->year) : "")
<< "_" << tagNumber;
TH1D* hctl = new TH1D("hctl", ";cos#Theta_{L};", nBinsAngles, edges.ctlmin, edges.ctlmax);
TH1D* hctk = new TH1D("hctk", ";cos#Theta_{K};", nBinsAngles, edges.ctkmin, edges.ctkmax);
TH1D* hphi = new TH1D("hphi", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax);
for (auto &meas : filtered_events){
if (meas.q2 > q2a && meas.q2 < q2b){
nfactweighted += meas.weight;
hctl->Fill(meas.costhetal, meas.weight);
hctk->Fill(meas.costhetak, meas.weight);
hphi->Fill(meas.phi, meas.weight);
}
}
//loop over events in this bin, determine factorizing moments
for (auto & meas: filtered_events){
if (meas.q2 > q2a && meas.q2 < q2b){
double weight = meas.weight;
double ctl = 2.0 * (meas.costhetal - edges.ctlmin ) / edges.range_ctl() - 1.0;
double ctk = 2.0 * (meas.costhetak - edges.ctkmin ) / edges.range_ctk() - 1.0;
double phi = 2.0 * (meas.phi - edges.phimin ) / edges.range_phi() - 1.0;
for (unsigned int i = 0; i<npol.ctl; i++){
if (assumectleven && i%2 != 0){
ctl_moments.at(i) = 0.0;
}
else{
//ctl_moments.at(i)+=weight*fcnc::chebyshev(ctl,i)/sqrt(1-ctl*ctl)*(i==0?1.0/pi:2.0/pi)/nfactweighted;
ctl_moments.at(i) += weight*fcnc::legendre(ctl, i)*(2.0*i+1.0)/2.0/nfactweighted;
}
}
for (unsigned int j = 0; j<npol.ctk; j++){
//ctk_moments.at(j) += weight*fcnc::chebyshev(ctk, j)/sqrt(1-ctk*ctk)*(j == 0 ? 1.0/pi : 2.0/pi)/nfactweighted;
ctk_moments.at(j) += weight*fcnc::legendre(ctk, j)*(2.0*j+1.0)/2.0/nfactweighted;
}
for (unsigned int k = 0; k<npol.phi; k++){
if (assumePhiEven && k%2 != 0){
phi_moments.at(k) = 0.0;
}
else{
//phi_moments.at(k) += weight*fcnc::chebyshev(phi, k)/sqrt(1-phi*phi)*(k == 0 ? 1.0/pi : 2.0/pi)/nfactweighted;
phi_moments.at(k) += weight*fcnc::legendre(phi, k)*(2.0*k+1.0)/2.0/nfactweighted;
}
}
}
}
//make polynomial
std::vector<double> ctl_polys(npol.ctl, 0.0);
std::vector<double> ctk_polys(npol.ctk, 0.0);
std::vector<double> phi_polys(npol.phi,0.0);
if (doLegendre){
legendre_to_poly(ctl_moments, ctl_polys);
legendre_to_poly(ctk_moments, ctk_polys);
legendre_to_poly(phi_moments, phi_polys);
}
else{
chebyshev_to_poly(ctl_moments, ctl_polys);
chebyshev_to_poly(ctk_moments, ctk_polys);
chebyshev_to_poly(phi_moments, phi_polys);
}
//transform angles from -1 +1 to angle_min angle_max
std::vector<double> ctl_correct(npol.ctl, 0.0);
std::vector<double> ctk_correct(npol.ctk, 0.0);
std::vector<double> phi_correct(npol.phi,0.0);
for (unsigned int i=0; i<ctk_polys.size(); i++) ctk_correct.at(i) = ctk_polys.at(i);
for (unsigned int i=0; i<ctl_polys.size(); i++) ctl_correct.at(i) = ctl_polys.at(i);
correct_poly(phi_polys, phi_correct, -TMath::Pi(), +TMath::Pi());
//determine chi2 in this bin
std::vector<double> neps_hist(nctlbins*nctkbins*nphibins, 0.0);
for (unsigned int i = 0; i<nctlbins; i++){
double ctla = edges.ctlmin + edges.range_ctl() * i /double(edges.nctlbins);
double ctlb = edges.ctlmin + edges.range_ctl() * (i+1.0) /double(edges.nctlbins);
for (unsigned int j = 0; j<nctkbins; j++){
double ctka = edges.ctkmin + edges.range_ctk() * j /double(edges.nctkbins);
double ctkb = edges.ctkmin + edges.range_ctk() * (j+1.0) /double(edges.nctkbins);
for (unsigned int k = 0; k<nphibins; k++){
double phi_a = edges.phimin + edges.range_phi() * k / double(edges.nphibins);
double phi_b = edges.phimin + edges.range_phi() * (k+1.0) / double(edges.nphibins);
double result_ctl = 0.0, result_ctk = 0.0, result_phi = 0.0;
for (unsigned int m = 0; m<npol.ctl; m++) result_ctl += ctl_correct.at(m)*integrate_x_to_n(ctla,ctlb,m);
for (unsigned int n = 0; n<npol.ctk; n++) result_ctk += ctk_correct.at(n)*integrate_x_to_n(ctka,ctkb,n);
for (unsigned int o = 0; o<npol.phi; o++) result_phi += phi_correct.at(o)*integrate_x_to_n(phi_a,phi_b,o);
neps_hist.at(get_bin_in3D(i,j,k,edges)) = result_ctl*result_ctk*result_phi;
}
}
}
//rescale to be sure
double nnorm_ctl = 0.0, nnorm_ctk = 0.0, nnorm_phi = 0.0;
for (unsigned int m = 0; m<npol.ctl; m++) nnorm_ctl += ctl_correct.at(m)*integrate_x_to_n(edges.ctlmin, edges.ctlmax, m);
for (unsigned int n = 0; n<npol.ctk; n++) nnorm_ctk += ctk_correct.at(n)*integrate_x_to_n(edges.ctkmin, edges.ctkmax, n);
for (unsigned int o = 0; o<npol.phi; o++) nnorm_phi += phi_correct.at(o)*integrate_x_to_n(edges.phimin, edges.phimax, o);
for (unsigned int i = 0; i<nctlbins; i++){
for (unsigned int j = 0; j<nctkbins; j++){
for (unsigned int k = 0; k<nphibins; k++){
neps_hist.at(get_bin_in3D(i,j,k,edges)) *= (nfactweighted/nnorm_ctl/nnorm_ctk/nnorm_phi);
}
}
}
//should scale nfactweighted/nfactfit
//determine chi2 //TODO: not working?
double curr_chi2 = 0.0;
TH1D* hpull = new TH1D("hpull", ";(N_{sel}-N_{fit})/#sqrt{N_{sel}};", 100, -5.0, 5.0);
for (unsigned int i = 0; i<nctlbins; i++){
for (unsigned int j = 0; j<nctkbins; j++){
for (unsigned int k = 0; k<nphibins; k++){
unsigned int bin = get_bin_in4D(h,i,j,k,edges);
curr_chi2 += sqr(nsel_hist.at(bin)-neps_hist.at(get_bin_in3D(i,j,k,edges)))/fabs(neps_hist.at(get_bin_in3D(i,j,k,edges))); //TODO: h is a wrong bin!
hpull->Fill((nsel_hist.at(bin)-neps_hist.at(get_bin_in3D(i,j,k,edges)))/sqrt(fabs(neps_hist.at(get_bin_in3D(i,j,k,edges)))));//TODO: h is a wrong bin!
}
}
}
//do plots
TH1D* ectl = new TH1D("ectl", ";cos#Theta_{L};", nBinsAngles, edges.ctlmin, edges.ctlmax);
TH1D* ectk = new TH1D("ectk", ";cos#Theta_{K};", nBinsAngles, edges.ctkmin, edges.ctkmax);
TH1D* ephi = new TH1D("ephi", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax);
for (int l=1; l<=ectl->GetNbinsX(); l++){
double integral = 0.0;
for (unsigned int i = 0; i<npol.ctl; i++){
integral += ctl_correct.at(i)*integrate_x_to_n(ectl->GetBinLowEdge(l),ectl->GetBinLowEdge(l+1),i);
}
ectl->SetBinContent(l, integral);
}
for (int l=1; l<=ectk->GetNbinsX(); l++){
double integral = 0.0;
for (unsigned int j = 0; j<npol.ctk; j++){
integral += ctk_correct.at(j)*integrate_x_to_n(ectl->GetBinLowEdge(l),ectl->GetBinLowEdge(l+1),j);
}
ectk->SetBinContent(l, integral);
}
for (int l=1; l<=ephi->GetNbinsX(); l++){
double integral = 0.0;
for (unsigned int k = 0; k<npol.phi; k++){
integral += phi_correct.at(k)*integrate_x_to_n(ectl->GetBinLowEdge(l),ectl->GetBinLowEdge(l+1),k);
}
ephi->SetBinContent(l, integral);
}
TLatex *tex = getPrettyTex(0.06,31);
std::ostringstream sregion;
sregion << std::fixed << std::setprecision(2) << q2a << "<q^{2}<" << q2b;
TCanvas* c_pull = new TCanvas("c_pull", "c_pull", 1600, 1200);
c_pull->cd();
hpull->Draw();
tex->DrawLatex(0.85, 0.15, sregion.str().c_str());
if(opts->write_eps)c_pull->Print((std::string(subfolder + "fact_pull")+sout.str()+std::string(".eps")).c_str(),"eps");
plotAngular(hctl,ectl,opts->write_eps,"fact_ctleff",sout.str(),sregion.str(),tex,subfolder);
plotAngular(hctk,ectk,opts->write_eps,"fact_ctkeff",sout.str(),sregion.str(),tex,subfolder);
plotAngular(hphi,ephi,opts->write_eps,"fact_phieff",sout.str(),sregion.str(),tex,subfolder);
delete hpull;
delete ectl;
delete ectk;
delete ephi;
delete hctl;
delete hctk;
delete hphi;
delete c_pull;
spdlog::debug( "fact chi2 in bin {0:d}: {1:f}", h, curr_chi2 );
chi2 += curr_chi2;
}
spdlog::info( "fact total chi2: {0:f}",chi2 );
spdlog::info( "uses {0:d}*{1:d}*{2:d}*{3:d}={4:d} bins",edges.nq2bins, edges.nctlbins, edges.nctkbins, edges.nphibins, edges.getNbins());
spdlog::info( "Chi2/Nbins = {0:f}", chi2/(edges.getNbins()) );
spdlog::info( "CHECKFACTORIZATION end " );
}
//-----------------------
// 3D MOMENTS in q2 bins
//-----------------------
if (do3Dmoments){
spdlog::info("DOTHREEDMOMENTS start ");
//fill histo for comparison
std::vector<double> nsel_hist(edges.getNbins(), 0.0);
std::vector<double> nsel_hist_errsq(edges.getNbins(), 0.0);
for (unsigned int e=0; e<filtered_events.size(); e++){
const event & meas = filtered_events.at(e);
unsigned int bin = get_bin_in4D(meas,edges);
nsel_hist.at(bin) += meas.weight;
nsel_hist_errsq.at(bin) += sqr(meas.weight);
}
for (unsigned int i=0; i<nsel_hist_errsq.size(); i++){
if (nsel_hist_errsq.at(i) == 0.0) nsel_hist_errsq.at(i) = 1.0;
}
//loop over all q2 bins
double chi2 = 0.0;
for (unsigned int h=0; h<q2_edges.size()-1; h++){
double q2a = q2_edges.at(h);
double q2b = q2_edges.at(h+1);
double nthreedweighted = 0.0;
//determine weighted number of events in this bin and fill control histos
std::ostringstream sout;
sout << h;
sout << "_" << DECAY_NAME << (opts->KS ? opts->DDLL+"_" : "_")
<< "Run" << opts->run
<< ((opts->angacccorrperyear && opts->year != -1) ? "_"+std::to_string(opts->year) : "");
TH1D* hctl = new TH1D("hctl", ";cos#Theta_{L};", nBinsAngles, edges.ctlmin, edges.ctlmax);
TH1D* hctk = new TH1D("hctk", ";cos#Theta_{K};", nBinsAngles, edges.ctkmin, edges.ctkmax);
TH1D* hphi = new TH1D("hphi", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax);
for (auto &meas: filtered_events){
if (meas.q2 > q2a && meas.q2 < q2b){
nthreedweighted += meas.weight;
hctl->Fill(meas.costhetal, meas.weight);
hctk->Fill(meas.costhetak, meas.weight);
hphi->Fill(meas.phi, meas.weight);
}
}
//loop over events in this bin, determine factorizing moments
spdlog::debug("Getting factorizing moments");
std::vector<double> threed_moments(npol.ctl*npol.ctk*npol.phi,0.0);
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
for (auto &meas: filtered_events){
if (meas.q2 > q2a && meas.q2 < q2b){
double weight = meas.weight;
double ctl = 2.0 * (meas.costhetal - edges.ctlmin ) / edges.range_ctl() - 1.0;
double ctk = 2.0 * (meas.costhetak - edges.ctkmin ) / edges.range_ctk() - 1.0;
double phi = 2.0 * (meas.phi - edges.phimin ) / edges.range_phi() - 1.0;
double result = 0.0;
if (assumectleven && i%2 != 0) result = 0.0;
else if (assumePhiEven && k%2 != 0) result = 0.0;
else {
if (doLegendre){
result = weight
*fcnc::legendre(ctl, i)*(2.0*i+1.0)/2.0
*fcnc::legendre(ctk, j)*(2.0*j+1.0)/2.0
*fcnc::legendre(phi, k)*(2.0*k+1.0)/2.0
/nthreedweighted;// /filtered_events.size();
}
else{
result = weight
*fcnc::chebyshev(ctl, i)/sqrt(1-ctl*ctl)*(i==0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(ctk, j)/sqrt(1-ctk*ctk)*(j==0 ? 1.0/MY_PI : 2.0/MY_PI)
*fcnc::chebyshev(phi, k)/sqrt(1-phi*phi)*(k==0 ? 1.0/MY_PI : 2.0/MY_PI)
/nthreedweighted;// /filtered_events.size();
}
}
threed_moments.at( get_bin_in3D(i,j,k,npol)) += result;
}
}
}
}
}
//make polynomial
//transform legendre coefficients to monomial coefficients
spdlog::debug("Transforming legendre coefficients to monomial coefficients....");
std::vector<double> threedpoly_moments(npol.ctl*npol.ctk*npol.phi,0.0);
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
double tmp = threed_moments.at(get_bin_in3D(i,j,k,npol));
std::vector<double> leg_coeffs_ctl(npol.ctl, 0.0);
std::vector<double> leg_coeffs_ctk(npol.ctk, 0.0);
std::vector<double> leg_coeffs_phi(npol.phi,0.0);
leg_coeffs_ctl.at(i) = 1.0;
leg_coeffs_ctk.at(j) = 1.0;
leg_coeffs_phi.at(k) = 1.0;
std::vector<double> poly_coeffs_ctl(npol.ctl, 0.0);
std::vector<double> poly_coeffs_ctk(npol.ctk, 0.0);
std::vector<double> poly_coeffs_phi(npol.phi,0.0);
legendre_to_poly(leg_coeffs_ctl, poly_coeffs_ctl);
legendre_to_poly(leg_coeffs_ctk, poly_coeffs_ctk);
legendre_to_poly(leg_coeffs_phi, poly_coeffs_phi);
for (unsigned int m = 0; m<=i; m++){
for (unsigned int n = 0; n<=j; n++){
for (unsigned int o = 0; o<=k; o++){
unsigned int bin = get_bin_in3D(m,n,o,npol);
threedpoly_moments.at(bin) += tmp*poly_coeffs_ctl.at(m)*poly_coeffs_ctk.at(n)*poly_coeffs_phi.at(o);
}
}
}
}
}
}
//correct coefficients from -1 +1 to -pi .. +pi for phi, this is easy
std::vector<double> threedpoly_moments_phi(threedpoly_moments);
for (unsigned int m = 0; m<npol.ctl; m++){
for (unsigned int n = 0; n<npol.ctk; n++){
for (unsigned int o = 0; o<npol.phi; o++){
threedpoly_moments_phi.at(get_bin_in3D(m,n,o,npol)) *= pow(1.0/MY_PI, o);
}
}
}
//calculate norm after full integration
double full_norm = 0.0;
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
double result = threedpoly_moments_phi.at(get_bin_in3D(i,j,k,npol))*integrate_3D(edges,i,j,k);
full_norm += result;
}
}
}
spdlog::debug("Rescaling...");
//rescale to be sure
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
threedpoly_moments_phi.at(get_bin_in3D(i,j,k,npol)) *= nthreedweighted/full_norm;
}
}
}
//determine nfit in this bin
std::vector<double> neps_hist(nctlbins*nctkbins*nphibins, 0.0);
for (unsigned int i = 0; i<nctlbins; i++){
double ctla = edges.ctlmin + i * edges.range_ctl();
double ctlb = edges.ctlmin + (i+1) * edges.range_ctl();
for (unsigned int j = 0; j<nctkbins; j++){
double ctka = edges.ctkmin + j * edges.range_ctk();
double ctkb = edges.ctkmin + (j+1) * edges.range_ctk();
for (unsigned int k = 0; k<nphibins; k++){
double phi_a = edges.phimin + k * edges.range_phi();
double phi_b = edges.phimin + (k+1) * edges.range_phi();
double result = 0.0;
for (unsigned int m = 0; m<npol.ctl; m++)
for (unsigned int n = 0; n<npol.ctk; n++)
for (unsigned int o = 0; o<npol.phi; o++)
result += threedpoly_moments_phi.at(get_bin_in3D(m,n,o,npol))
*(pow(ctlb,m+1)/(m+1.0) - pow(ctla, m+1)/(m+1.0))
*(pow(ctkb,n+1)/(n+1.0) - pow(ctka, n+1)/(n+1.0))
*(pow(phi_b,o+1)/(o+1.0) - pow(phi_a, o+1)/(o+1.0));
unsigned int bin = get_bin_in3D(i,j,k,edges);
neps_hist.at(bin) = result;
}
}
}
spdlog::debug("Getting chi2...");
//determine chi2
double curr_chi2 = 0.0;
TH1D* hpull = new TH1D("hpull", ";(N_{sel}-N_{fit})/#sqrt{N_{sel}};", 100, -5.0, 5.0);
for (unsigned int i = 0; i<nctlbins; i++)
for (unsigned int j = 0; j<nctkbins; j++)
for (unsigned int k = 0; k<nphibins; k++){
unsigned int bin =get_bin_in4D(h,i,j,k,edges);
curr_chi2 += sqr(nsel_hist.at(bin)-neps_hist.at(get_bin_in3D(i,j,k,edges)))/fabs(neps_hist.at(get_bin_in3D(i,j,k,edges)));
hpull->Fill((nsel_hist.at(bin)-neps_hist.at(get_bin_in3D(i,j,k,edges)))/sqrt(fabs(neps_hist.at(get_bin_in3D(i,j,k,edges)))));
}
//spdlog::debug( "ok" );
//do plots
TH1D* ectl = new TH1D("ectl", ";cos#Theta_{L};", nBinsAngles, edges.ctlmin, edges.ctlmax);
TH1D* ectk = new TH1D("ectk", ";cos#Theta_{K};", nBinsAngles, edges.ctkmin, edges.ctkmax);
TH1D* ephi = new TH1D("ephi", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax);
for (int l=1; l<=ectl->GetNbinsX(); l++){
double a = ectl->GetBinLowEdge(l);
double b = ectl->GetBinLowEdge(l+1);
double integral = 0.0;
for (unsigned int i = 0; i<npol.ctl; i++)
for (unsigned int j = 0; j<npol.ctk; j++)
for (unsigned int k = 0; k<npol.phi; k++){
double result = threedpoly_moments_phi.at(get_bin_in3D(i,j,k,npol))
*(pow(b ,i+1)/(i+1.0) - pow(a ,i+1)/(i+1.0))
*(pow(edges.ctkmax,j+1)/(j+1.0) - pow(edges.ctkmin,j+1)/(j+1.0))
*(pow(edges.phimax,k+1)/(k+1.0) - pow(edges.phimin,k+1)/(k+1.0));
integral += result;
}
ectl->SetBinContent(l, integral);
}
for (int l=1; l<=ectk->GetNbinsX(); l++){
double a = ectk->GetBinLowEdge(l);
double b = ectk->GetBinLowEdge(l+1);
double integral = 0.0;
for (unsigned int i = 0; i<npol.ctl; i++)
for (unsigned int j = 0; j<npol.ctk; j++)
for (unsigned int k = 0; k<npol.phi; k++){
double result = threedpoly_moments_phi.at(get_bin_in3D(i,j,k,npol))
*(pow(edges.ctlmax,i+1)/(i+1.0) - pow(edges.ctlmin,i+1)/(i+1.0))
*(pow(b ,j+1)/(j+1.0) - pow(a ,j+1)/(j+1.0))
*(pow(edges.phimax,k+1)/(k+1.0) - pow(edges.phimin,k+1)/(k+1.0));
integral += result;
}
ectk->SetBinContent(l, integral);
}
for (int l=1; l<=ephi->GetNbinsX(); l++){
double a = ephi->GetBinLowEdge(l);
double b = ephi->GetBinLowEdge(l+1);
double integral = 0.0;
for (unsigned int i = 0; i<npol.ctl; i++)
for (unsigned int j = 0; j<npol.ctk; j++)
for (unsigned int k = 0; k<npol.phi; k++){
double result = threedpoly_moments_phi.at(get_bin_in3D(i,j,k,npol))
*(pow(edges.ctlmax,i+1)/(i+1.0) - pow(edges.ctlmin,i+1)/(i+1.0))
*(pow(edges.ctkmax,j+1)/(j+1.0) - pow(edges.ctkmin,j+1)/(j+1.0))
*(pow(b ,k+1)/(k+1.0) - pow(a ,k+1)/(k+1.0));
integral += result;
}
ephi->SetBinContent(l, integral);
}
spdlog::debug("Plotting...");
TLatex *tex = getPrettyTex(0.06,31);
std::ostringstream sregion;
sregion << std::fixed << std::setprecision(2) << q2a << "<q^{2}<" << q2b;
TCanvas* c_zero = new TCanvas("c_zero", "c_zero", 1600, 1200);
c_zero->cd();
hpull->Draw();
tex->DrawLatex(0.85, 0.15, sregion.str().c_str());
if(opts->write_eps)c_zero->Print((std::string(subfolder + "3d_pull")+sout.str()+std::string(".eps")).c_str(),"eps");
plotAngular(hctl,ectl,opts->write_eps,"3d_ctleff", sout.str(), sregion.str(),tex,subfolder);
plotAngular(hctk,ectk,opts->write_eps,"3d_ctkeff", sout.str(), sregion.str(),tex,subfolder);
plotAngular(hphi,ephi,opts->write_eps,"3d_phieff", sout.str(), sregion.str(),tex,subfolder);
delete hpull;
delete ectl;
delete ectk;
delete ephi;
delete hctl;
delete hctk;
delete hphi;
delete c_zero;
spdlog::debug( "3d chi2 in bin {0:d}: {1:f}", h, curr_chi2 );
chi2 += curr_chi2;
}
spdlog::debug( "3d total chi2: {0:f}",chi2 );
spdlog::debug( "3d uses {0:d}*{1:d}*{2:d}*{3:d}={4_d} bins",edges.nq2bins, edges.nctlbins, edges.nctkbins, edges.nphibins, edges.getNbins());
spdlog::debug( "3d chi2/Nbins = {0:f}", chi2/(edges.getNbins()) );
spdlog::info( "DOTHREEDMOMENTS end " );
}
//-----------------------
// CHI2 TEST FOR MOMENTS
//-----------------------
bool dochi2test = true;
if(opts->only_4_1D_chi2)dochi2test = false;
spdlog::debug("dochi2: "+boolToString(dochi2test));
if (dochi2test) {
get_chi2(edges, npol, filtered_events, coeffs_moments, globalvalues,
assumectleven, assumePhiEven, opts->write_eps, subfolder, appendix);
}
//-----------------------
//MAKE NICE CONTROL PLOTS
//-----------------------
const bool do_plots = opts->write_eps || opts->only_4_1D_chi2;
if (do_plots){
spdlog::info( "Start PLOTS.." );
gROOT->SetStyle("Plain");
TPad foo;
const int NRGBs = 5;
const int NCont = 250;
double stops[NRGBs] = { 0.00, 0.34, 0.61, 0.84, 1.00 };
double red[NRGBs] = { 0.00, 0.00, 0.87, 1.00, 0.51 };
double green[NRGBs] = { 0.00, 0.81, 1.00, 0.20, 0.00 };
double blue[NRGBs] = { 0.51, 1.00, 0.12, 0.00, 0.00 };
TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont);
gStyle->SetNumberContours(NCont);
gStyle->SetLabelFont(132, "xyz");
gStyle->SetTitleFont(132, "xyz");
gStyle->SetLegendFont(132);
gStyle->SetStatFont(132);
//new histograms binned in q2
//compare the three angular projections for data and moments
for (unsigned int u=0; u<q2_edges.size()-1; u++){
std::ostringstream sout;
sout << u;
std::string binno = sout.str();
TH1D* hctl = new TH1D("hctl", ";cos#Theta_{L};", nBinsAngles, edges.ctlmin, edges.ctlmax);
TH1D* hctk = new TH1D("hctk", ";cos#Theta_{K};", nBinsAngles, edges.ctkmin, edges.ctkmax);
TH1D* hphi = new TH1D("hphi", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax);
TH2D* hctlctk = new TH2D("hctlctk", ";cos#Theta_{L};cos#Theta_{K}", nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.ctkmin, edges.ctkmax);
TH2D* hctlphi = new TH2D("hctlphi", ";cos#Theta_{L};#phi [rad]" , nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.phimin, edges.phimax);
TH2D* hctkphi = new TH2D("hctkphi", ";cos#Theta_{K};#phi [rad]" , nBinsAngles, edges.ctkmin, edges.ctkmax, nBinsAngles, edges.phimin, edges.phimax);
double q2a = q2_edges.at(u);
double q2b = q2_edges.at(u+1);
for (auto & meas: filtered_events){
if (meas.q2 > q2a && meas.q2 < q2b){
hctl->Fill(meas.costhetal, meas.weight);
hctk->Fill(meas.costhetak, meas.weight);
hphi->Fill(meas.phi, meas.weight);
hctlctk->Fill(meas.costhetal, meas.costhetak, meas.weight);
hctlphi->Fill(meas.costhetal, meas.phi, meas.weight);
hctkphi->Fill(meas.costhetak, meas.phi, meas.weight);
}
}
TH1D* hctl_moments = new TH1D("hctl_moments", ";cos#Theta_{L};", nBinsAngles, edges.ctlmin, edges.ctlmax);
TH1D* hctk_moments = new TH1D("hctk_moments", ";cos#Theta_{K};", nBinsAngles, edges.ctkmin, edges.ctkmax);
TH1D* hphi_moments = new TH1D("hphi_moments", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax);
TH2D* hctlctk_moments = new TH2D("hctlctk_moments", ";cos#Theta_{L};cos#Theta_{K}", nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.ctkmin, edges.ctkmax);
TH2D* hctlphi_moments = new TH2D("hctlphi_moments", ";cos#Theta_{L};#phi [rad]" , nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.phimin, edges.phimax);
TH2D* hctkphi_moments = new TH2D("hctkphi_moments", ";cos#Theta_{K};#phi [rad]" , nBinsAngles, edges.ctkmin, edges.ctkmax, nBinsAngles, edges.phimin, edges.phimax);
//1d plots
fill_moments_hist_1D(hctl_moments, coeffs_moments, edges, npol, q2a, q2b);
fill_moments_hist_1D(hctk_moments, coeffs_moments, edges, npol, q2a, q2b);
fill_moments_hist_1D(hphi_moments, coeffs_moments, edges, npol, q2a, q2b);
//2d plots
fill_moments_hist_2D(hctlctk_moments, coeffs_moments, edges, npol, q2a, q2b);
fill_moments_hist_2D(hctlphi_moments, coeffs_moments, edges, npol, q2a, q2b);
fill_moments_hist_2D(hctkphi_moments, coeffs_moments, edges, npol, q2a, q2b);
TLatex *tex = getPrettyTex(0.06,31);
std::ostringstream sregion;
sregion << std::fixed << std::setprecision(2) << q2a << "<q^{2}<" << q2b;
plotAngular(hctl,hctl_moments,opts->write_eps,"ctleff",binno+appendix,sregion.str(), tex, subfolder);
plotAngular(hctk,hctk_moments,opts->write_eps,"ctkeff",binno+appendix,sregion.str(), tex, subfolder);
plotAngular(hphi,hphi_moments,opts->write_eps,"phieff",binno+appendix,sregion.str(), tex, subfolder);
if (tagNumber < 0){ //Do not plot when testing quickly
plotAngular(hctlctk,hctlctk_moments,opts->write_eps,"ctlctkeff",binno+appendix,
sregion.str(), tex, subfolder);
plotAngular(hctlphi,hctlphi_moments,opts->write_eps,"ctlphieff",binno+appendix,
sregion.str(), tex, subfolder);
plotAngular(hctkphi,hctkphi_moments,opts->write_eps,"ctkphieff",binno+appendix,
sregion.str(), tex, subfolder);
}
delete hctl; delete hctl_moments;
delete hctk; delete hctk_moments;
delete hphi; delete hphi_moments;
delete hctlctk; delete hctlctk_moments;
delete hctkphi; delete hctkphi_moments;
delete hctlphi; delete hctlphi_moments;
}//end extra plots in bins of q2
//data histograms
TH1D* hq2 = new TH1D("hq2" , ";q^{2} [GeV^{2}];" , nBinsQ2 ,edges.q2min, edges.q2max);
TH1D* hctl = new TH1D("hctl", ";cos(#Theta_{L});", nBinsAngles, edges.ctlmin, edges.ctlmax);
TH1D* hctk = new TH1D("hctk", ";cos(#Theta_{K});", nBinsAngles, edges.ctkmin, edges.ctkmax);
TH1D* hphi = new TH1D("hphi", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax);
TH2D* hctlctk = new TH2D("hctlctk", ";cos#Theta_{L};cos#Theta_{K}", nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.ctkmin, edges.ctkmax);
TH2D* hctlphi = new TH2D("hctlphi", ";cos#Theta_{L};#phi [rad]" , nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.phimin, edges.phimax);
TH2D* hctkphi = new TH2D("hctkphi", ";cos#Theta_{K};#phi [rad]" , nBinsAngles, edges.ctkmin, edges.ctkmax, nBinsAngles, edges.phimin, edges.phimax);
TH2D* hq2ctl = new TH2D("hq2ctl", ";q^{2};cos#Theta_{L}", nBinsQ2, edges.q2min, edges.q2max, nBinsAngles, edges.ctlmin, edges.ctlmax);
TH2D* hq2ctk = new TH2D("hq2ctk", ";q^{2};cos#Theta_{K}", nBinsQ2, edges.q2min, edges.q2max, nBinsAngles, edges.ctkmin, edges.ctkmax);
TH2D* hq2phi = new TH2D("hq2phi", ";q^{2};#phi [rad]" , nBinsQ2, edges.q2min, edges.q2max, nBinsAngles, edges.phimin, edges.phimax);
hq2->Sumw2();
hctl->Sumw2();
hctk->Sumw2();
hphi->Sumw2();
for (unsigned int i=0; i<filtered_events.size(); i++){
const event& meas = filtered_events.at(i);
hq2->Fill(meas.q2, meas.weight);
hctl->Fill(meas.costhetal, meas.weight);
hctk->Fill(meas.costhetak, meas.weight);
hphi->Fill(meas.phi, meas.weight);
hctlctk->Fill(meas.costhetal, meas.costhetak, meas.weight);
hctlphi->Fill(meas.costhetal, meas.phi, meas.weight);
hctkphi->Fill(meas.costhetak, meas.phi, meas.weight);
hq2ctl->Fill(meas.q2, meas.costhetal, meas.weight);
hq2ctk->Fill(meas.q2, meas.costhetak, meas.weight);
hq2phi->Fill(meas.q2, meas.phi, meas.weight);
}
//fitted histograms, moments method
TH1D* hq2_moments = new TH1D("hq2_moments" , ";q^{2} [GeV^{2}];" , nBinsQ2, edges.q2min, edges.q2max);
TH1D* hctl_moments = new TH1D("hctl_moments", ";cos(#Theta_{L});", nBinsAngles, edges.ctlmin, edges.ctlmax);
TH1D* hctk_moments = new TH1D("hctk_moments", ";cos(#Theta_{K});", nBinsAngles, edges.ctkmin, edges.ctkmax);
TH1D* hphi_moments = new TH1D("hphi_moments", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax);
TH2D* hctlctk_moments = new TH2D("hctlctk_moments", ";cos#Theta_{L};cos#Theta_{K}", nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.ctkmin, edges.ctkmax);
TH2D* hctlphi_moments = new TH2D("hctlphi_moments", ";cos#Theta_{L};#phi [rad]" , nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.phimin, edges.phimax);
TH2D* hctkphi_moments = new TH2D("hctkphi_moments", ";cos#Theta_{K};#phi [rad]" , nBinsAngles, edges.ctkmin, edges.ctkmax, nBinsAngles, edges.phimin, edges.phimax);
TH2D* hq2ctl_moments = new TH2D("hq2ctl_moments", ";q^{2};cos#Theta_{L}", nBinsQ2, edges.q2min, edges.q2max, nBinsAngles, edges.ctlmin, edges.ctlmax);
TH2D* hq2ctk_moments = new TH2D("hq2ctk_moments", ";q^{2};cos#Theta_{K}", nBinsQ2, edges.q2min, edges.q2max, nBinsAngles, edges.ctkmin, edges.ctkmax);
TH2D* hq2phi_moments = new TH2D("hq2phi_moments", ";q^{2};#phi [rad]" , nBinsQ2, edges.q2min, edges.q2max, nBinsAngles, edges.phimin, edges.phimax);
//1d plots
fill_moments_hist_1D(hq2_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max);
fill_moments_hist_1D(hctl_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max);
fill_moments_hist_1D(hctk_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max);
fill_moments_hist_1D(hphi_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max);
//2d plots
fill_moments_hist_2D(hctlctk_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max);
fill_moments_hist_2D(hctlphi_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max);
fill_moments_hist_2D(hctkphi_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max);
fill_moments_hist_2D(hq2ctl_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max);
fill_moments_hist_2D(hq2ctk_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max);
fill_moments_hist_2D(hq2phi_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max);
if(opts->only_4_1D_chi2){
//reset globalvalues
globalvalues->chi2_4_1D = 0.0;
globalvalues->chi2_4_1D_ctk = 0.0;
globalvalues->chi2_4_1D_ctl = 0.0;
globalvalues->chi2_4_1D_phi = 0.0;
globalvalues->chi2_4_1D_q2 = 0.0;
globalvalues->ndof_4_1D = 0;
globalvalues->ndof_4_1D_ctk = 0;
globalvalues->ndof_4_1D_ctl = 0;
globalvalues->ndof_4_1D_phi = 0;
globalvalues->ndof_4_1D_q2 = 0;
//first scale moments to match integral of event histograms
hctk_moments->Scale(hctk->Integral()/hctk_moments->Integral());
hctl_moments->Scale(hctl->Integral()/hctl_moments->Integral());
hphi_moments->Scale(hphi->Integral()/hphi_moments->Integral());
hq2_moments ->Scale(hq2->Integral()/hq2_moments->Integral());
//get chi2 from all 4 variables
for(UInt_t b = 1; b <= nBinsAngles; b++){
globalvalues->chi2_4_1D_ctk += sqr((hctk->GetBinContent(b) - hctk_moments->GetBinContent(b))) / fabs(hctk_moments->GetBinContent(b));
globalvalues->chi2_4_1D_ctl += sqr((hctl->GetBinContent(b) - hctl_moments->GetBinContent(b))) / fabs(hctl_moments->GetBinContent(b));
globalvalues->chi2_4_1D_phi += sqr((hphi->GetBinContent(b) - hphi_moments->GetBinContent(b))) / fabs(hphi_moments->GetBinContent(b));
}
for(UInt_t b = 1; b <= nBinsQ2; b++){
globalvalues->chi2_4_1D_q2 += sqr((hq2->GetBinContent(b) - hq2_moments->GetBinContent(b))) / fabs(hq2_moments->GetBinContent(b));
}
//sum of all four 1D histograms
globalvalues->chi2_4_1D = globalvalues->chi2_4_1D_ctk + globalvalues->chi2_4_1D_ctl + globalvalues->chi2_4_1D_phi + globalvalues->chi2_4_1D_q2;
//determine ndof for all angles and q2
//NOT sure if these ndofs are 100% correct, but good enough for a relative measure
globalvalues->ndof_4_1D_ctk = nBinsAngles - (npol.ctk-1) - 1;
globalvalues->ndof_4_1D_ctl = nBinsAngles - (npol.ctl-1) - 1;
globalvalues->ndof_4_1D_phi = nBinsAngles - (npol.phi-1) - 1;
globalvalues->ndof_4_1D_q2 = nBinsQ2 - (npol.q2-1) - 1;
globalvalues->ndof_4_1D = 3*nBinsAngles + nBinsQ2 - 1 - (npol.ctk + npol.ctl + npol.phi + npol.q2 - 1);
}
//plot
plotAngular(hq2,hq2_moments,opts->write_eps,"q2eff",appendix, subfolder);
plotAngular(hctl,hctl_moments,opts->write_eps,"ctleff",appendix, subfolder);
plotAngular(hctk,hctk_moments,opts->write_eps,"ctkeff",appendix, subfolder);
plotAngular(hphi,hphi_moments,opts->write_eps,"phieff",appendix, subfolder);
if (tagNumber < 0){ //do not plot when testing
plotAngular(hctlctk,hctlctk_moments,opts->write_eps,"ctlctkeff",appendix, subfolder);
plotAngular(hctlphi,hctlphi_moments,opts->write_eps,"ctlphieff",appendix, subfolder);
plotAngular(hctkphi,hctkphi_moments,opts->write_eps,"ctkphieff",appendix, subfolder);
plotAngular(hq2ctl,hq2ctl_moments,opts->write_eps,"q2ctleff",appendix, subfolder);
plotAngular(hq2ctk,hq2ctk_moments,opts->write_eps,"q2ctkeff",appendix, subfolder);
plotAngular(hq2phi,hq2phi_moments,opts->write_eps,"q2phieff",appendix, subfolder);
}
delete hq2; delete hq2_moments;
delete hctl; delete hctl_moments;
delete hctk; delete hctk_moments;
delete hphi; delete hphi_moments;
delete hctlctk; delete hctlctk_moments;
delete hctkphi; delete hctkphi_moments;
delete hctlphi; delete hctlphi_moments;
delete hq2ctl; delete hq2ctl_moments;
delete hq2ctk; delete hq2ctk_moments;
delete hq2phi; delete hq2phi_moments;
hxi_moments[0]->SetMinimum(1.0); hxi_moments[0]->SetMaximum(+2.0);
hxi_moments[1]->SetMinimum(0.25); hxi_moments[1]->SetMaximum(+1.25);
hxi_moments[2]->SetMinimum(-1.0); hxi_moments[2]->SetMaximum(+0.0);
hxi_moments[3]->SetMinimum(-0.75); hxi_moments[3]->SetMaximum(+0.25);
for (int i = 4; i<12; i++){
hxi_moments[i]->SetMinimum(-0.5);
hxi_moments[i]->SetMaximum(+0.5);
}
for (auto hist: hxi_moments) hist->GetYaxis()->SetTitleOffset(1.4);
TCanvas* c10 = new TCanvas("c10", "c10", 1600, 1200);
c10->Divide(4,3);
plotAngularInOne(c10,1,hxi_moments[0],hxi_ub[0],hxi_hist[0],hxi_ml_hist[0],runMinuit,edges.q2min,edges.q2max,1.5,false);
plotAngularInOne(c10,2,hxi_moments[1],hxi_ub[1],hxi_hist[1],hxi_ml_hist[1],runMinuit,edges.q2min,edges.q2max,0.75,false);
plotAngularInOne(c10,3,hxi_moments[2],hxi_ub[2],hxi_hist[2],hxi_ml_hist[2],runMinuit,edges.q2min,edges.q2max,-0.5,false);
plotAngularInOne(c10,4,hxi_moments[3],hxi_ub[3],hxi_hist[3],hxi_ml_hist[3],runMinuit,edges.q2min,edges.q2max,-0.25,false);
for (int i = 4; i<12; i++){
plotAngularInOne(c10,i+1,hxi_moments[i],hxi_ub[i],hxi_hist[i],hxi_ml_hist[i],runMinuit,
edges.q2min,edges.q2max,0.0,is_param_folded(i,opts));
}
if(opts->write_eps)c10->Print((subfolder + "/xis"+appendix+".eps").c_str(),"eps");
delete c10;
spdlog::info( "end PLOTS" );
}//end make plots
//delete histograms
for (auto hist: hxi_moments) delete hist;
for (auto hist: hxi_ml_hist) delete hist;
for (auto hist: hxi_hist) delete hist;
for (auto hist: hxi_ub) delete hist;
}; //end parametrize_eff_phsp_4d()
double bu2kstarmumu_pdf::get_ang_eff(fcnc::options *opts,
double q2, double ctl, double ctk, double phi) const{
npolynom npol(opts);
assert(coeffs_eff_4d.size() == npol.getSize());
//Posibly can be faster, but with more memory consumption and unless I calculate this for like a million events it doesn't make a difference. This way the code is readable and usable at many places
double eff = 0.0;
for(unsigned int h = 0; h<npol.q2; h++){
for(unsigned int i = 0; i<npol.ctl; i++){
for(unsigned int j = 0; j<npol.ctk; j++){
for(unsigned int k = 0; k<npol.phi; k++){
eff += coeffs_eff_4d[npol.get_bin_in4D(h,i,j,k)]
*pow(q2,h)*pow(ctl,i)*pow(ctk,j)*pow(phi,k);
}
}
}
}
//spdlog::trace("ctl={0:f}\t ctk={1:f}\t phi={2:f}\t eff={3:f}", ctl, ctk, phi, eff);
return eff;
}
double bu2kstarmumu_pdf::get_ang_eff(fcnc::options *opts, fcnc::event evt, bool fa) const{
//fa=true meansusing the evt. _fa values
if (fa) return get_ang_eff(opts, evt.q2, evt.costhetal_fa, evt.costhetak_fa, evt.phi_fa);
else return get_ang_eff(opts, evt.q2, evt.costhetal, evt.costhetak, evt.phi);
}
void bu2kstarmumu_pdf::eff_fcn(Int_t &npar, Double_t *grad, Double_t &lh, Double_t *params, Int_t iflag)
{
//TODO full angular fit
npolynom npol(current_pdf->opts);
std::vector<double> chebyshev_costhetal(npol.ctl, 0.0);
std::vector<double> chebyshev_costhetak(npol.ctk, 0.0);
std::vector<double> chebyshev_phi(npol.phi, 0.0);
for (unsigned int j = 0; j<npol.ctl; j++) chebyshev_costhetal.at(j) = params[j];
for (unsigned int j = 0; j<npol.ctk; j++) chebyshev_costhetak.at(j) = params[npol.ctl+j];
for (unsigned int j = 0; j<npol.phi; j++) chebyshev_phi.at(j) = params[npol.ctl+npol.ctk+j];
std::vector<double> coeffs_costhetal(npol.ctl, 0.0);
std::vector<double> coeffs_costhetak(npol.ctk, 0.0);
std::vector<double> coeffs_phi(npol.phi, 0.0);
std::vector<double> temp_ctl(npol.ctl, 0.0);
std::vector<double> temp_ctk(npol.ctk, 0.0);
std::vector<double> temp_phi(npol.phi, 0.0);
chebyshev_to_poly(chebyshev_costhetal, temp_ctl);
chebyshev_to_poly(chebyshev_costhetak, temp_ctk);
chebyshev_to_poly(chebyshev_phi, temp_phi);
for (unsigned int i=0; i<coeffs_costhetak.size(); i++){
coeffs_costhetak.at(i) = temp_ctk.at(i);
}
for (unsigned int i=0; i<coeffs_costhetal.size(); i++){
coeffs_costhetal.at(i) = temp_ctl.at(i);
}
correct_poly(temp_phi, coeffs_phi, -TMath::Pi(), +TMath::Pi());
double cijk = 0.0;
double f1 = 0.0, f2 = 0.0, f3 = 0.0, f4 = 0.0, f5 = 0.0,
f6 = 0.0, f7 = 0.0, f8 = 0.0, f9 = 0.0, f10 = 0.0, f11 = 0.0, f12 = 0.0;
const double pi = MY_PI;
double c = C_PWAVE;
if(current_pdf->opts->full_angular)c *= 2.0; //folding in phi
if (current_pdf->opts->full_angular)
{
for (unsigned int i = 0; i<npol.ctl; i++)
for (unsigned int j = 0; j<npol.ctk; j++)
for (unsigned int k = 0; k<npol.phi; k++)
{
cijk = c*coeffs_costhetal.at(i)*coeffs_costhetak.at(j)*coeffs_phi.at(k);
f1 += cijk * (pow(-1,i)/(i+1.0)+1.0/(i+1.0))*(2.0*pow(-1,j)/(j*j+4.0*j+3.0)+2.0/(j*j+4.0*j+3.0))*(pow(-1,k)*pow(pi,k+1)/(k+1.0)+pow(pi,k+1)/(k+1.0));
f2 += cijk * (pow(-1,i)/(i+1.0)+1.0/(i+1.0))*(pow(-1,j)/(j+3.0)+1.0/(j+3.0))*(pow(-1,k)*pow(pi,k+1)/(k+1.0)+pow(pi,k+1)/(k+1.0));
f3 += cijk * (((i-1.0)*pow(-1,i)/(i*i+4.0*i+3.0)+(i-1.0)/(i*i+4.0*i+3.0))*(2.0*pow(-1,j)/(j*j+4.0*j+3.0)+2.0/(j*j+4.0*j+3.0))*(pow(-1,k)*pow(pi,k+1)/(k+1.0)+pow(pi,k+1)/(k+1.0)));
f4 += cijk * (((i-1.0)*pow(-1,i)/(i*i+4.0*i+3.0)+(i-1.0)/(i*i+4.0*i+3.0))*(pow(-1,j)/(j+3.0)+1/(j+3.0))*(pow(-1,k)*pow(pi,k+1.0)/(k+1.0)+pow(pi,k+1)/(k+1.0)));
f5 += cijk * (2.0*pow(-1,i)/(i*i+4.0*i+3.0)+2.0/(i*i+4.0*i+3.0))*(2.0*pow(-1,j)/(j*j+4.0*j+3.0)+2.0/(j*j+4.0*j+3.0))
*(integral_x_to_n_times_cos_2x(pi,k)-integral_x_to_n_times_cos_2x(-pi,k));
f6 += cijk * 4.0
*(integral_x_to_n_times_sqrt_1_minus_x2(1,j+1)-integral_x_to_n_times_sqrt_1_minus_x2(-1,j+1))
*(integral_x_to_n_times_sqrt_1_minus_x2(1,i+1)-integral_x_to_n_times_sqrt_1_minus_x2(-1,i+1))
*(integral_x_to_n_times_cos_x(pi,k)-integral_x_to_n_times_cos_x(-pi,k));
f7 += cijk * 2.0
*(integral_x_to_n_times_sqrt_1_minus_x2(1,j+1)-integral_x_to_n_times_sqrt_1_minus_x2(-1,j+1))
*(integral_x_to_n_times_sqrt_1_minus_x2(1,i)-integral_x_to_n_times_sqrt_1_minus_x2(-1,i))
*(integral_x_to_n_times_cos_x(pi,k)-integral_x_to_n_times_cos_x(-pi,k));
f8 += cijk * (1.0/(i+2.0)-pow(-1,i)/(i+2.0))*(2.0*pow(-1,j)/(j*j+4.0*j+3.0)+2.0/(j*j+4.0*j+3.0))*(pow(-1,k)*pow(pi,k+1)/(k+1.0)+pow(pi,k+1)/(k+1.0));
f9 += cijk * (1.0/(i+2.0)-pow(-1,i)/(i+2.0))*(pow(-1,j)/(j+3.0)+1.0/(j+3.0))*(pow(-1,k)*pow(pi,k+1)/(k+1.0)+pow(pi,k+1)/(k+1.0));
f10 += cijk * 2.0
*(integral_x_to_n_times_sqrt_1_minus_x2(1,j+1)-integral_x_to_n_times_sqrt_1_minus_x2(-1,j+1))
*(integral_x_to_n_times_sqrt_1_minus_x2(1,i)-integral_x_to_n_times_sqrt_1_minus_x2(-1,i))
*(integral_x_to_n_times_sin_x(pi,k)-integral_x_to_n_times_sin_x(-pi,k));
f11 += cijk * 4.0
*(integral_x_to_n_times_sqrt_1_minus_x2(1,j+1)-integral_x_to_n_times_sqrt_1_minus_x2(-1,j+1))
*(integral_x_to_n_times_sqrt_1_minus_x2(1,i+1)-integral_x_to_n_times_sqrt_1_minus_x2(-1,i+1))
*(integral_x_to_n_times_sin_x(pi,k)-integral_x_to_n_times_sin_x(-pi,k));
f12 += cijk * (2.0*pow(-1,i)/(i*i+4.0*i+3.0)+2.0/(i*i+4.0*i+3.0))*(2.0*pow(-1,j)/(j*j+4.0*j+3.0)+2.0/(j*j+4.0*j+3.0))
*(integral_x_to_n_times_sin_2x(pi,k)-integral_x_to_n_times_sin_2x(-pi,k));
}
}
else
{
for (unsigned int i = 0; i<npol.ctl; i++)
for (unsigned int j = 0; j<npol.ctk; j++)
for (unsigned int k = 0; k<npol.phi; k++)
{
cijk = c * coeffs_costhetal.at(i)*coeffs_costhetak.at(j)*coeffs_phi.at(k);
/*
f1 += cijk * 2.0*(2.0*pow(-1,i)/(i*i+4.0*i+3.0)+2.0/(i*i+4.0*i+3.0))*(pow(-1,j)/(j+3.0)+1.0/(j+3.0))*pow(MY_PI,k+1)/(k+1.0);
f2 += cijk * ((i+2.0)*pow(-1,i)/(i*i+4.0*i+3.0)+(i+2.0)/(i*i+4.0*i+3.0))*(2.0*pow(-1,j)/(j*j+4.0*j+3.0)+2.0/(j*j+4.0*j+3.0))*pow(MY_PI,k+1)/(k+1.0);
f3 += cijk * (2.0*pow(-1,i)/(i*i+4.0*i+3.0)+2.0/(i*i+4.0*i+3.0))*(2.0*pow(-1,j)/(j*j+4.0*j+3.0)+2.0/(j*j+4.0*j+3.0))
*(integral_x_to_n_times_cos_2x(MY_PI, k) - integral_x_to_n_times_cos_2x(0.0, k));
f4 += cijk * 4.0*(1.0/(i+2.0)-pow(-1,i)/(i+2.0))*(2.0*pow(-1,j)/(j*j+4.0*j+3.0)+2.0/(j*j+4.0*j+3.0))*pow(MY_PI,k+1)/(3.0*(k+1.0));
f5 += cijk * (2.0*pow(-1,i)/(i*i+4.0*i+3.0)+2.0/(i*i+4.0*i+3.0))*(2.0*pow(-1,j)/(j*j+4.0*j+3.0)+2.0/(j*j+4.0*j+3.0))
*(integral_x_to_n_times_sin_2x(MY_PI, k) - integral_x_to_n_times_sin_2x(0.0, k));
*/
//TODO add f1 to f12 for new folding!
spdlog::error("Function 'eff_fcn' not yet implemented for folding");
assert(0);
}
}
//calculate eps()
std::vector<double> ch_costhetal;
std::vector<double> ch_costhetak;
std::vector<double> ch_phi;
double lh_costhetal = 0.0;
double lh_costhetak = 0.0;
double lh_phi = 0.0;
unsigned int nsize = current_pdf->eff_events.size();
for (unsigned int i=0; i<nsize; i++)
{
event meas = current_pdf->eff_events.at(i);
chebyshev(meas.costhetal, npol.ctl, ch_costhetal);
chebyshev(meas.costhetak, npol.ctk, ch_costhetak);
if (current_pdf->opts->full_angular)
chebyshev(meas.phi/MY_PI, npol.phi, ch_phi);
else
chebyshev(2.0*meas.phi/MY_PI-1.0, npol.phi, ch_phi);
//double result = 0.0;
double result_costhetal = 0.0;
for (unsigned int j = 0; j<npol.ctl; j++){
result_costhetal += params[j]*ch_costhetal.at(j);// /norm_costhetal;
}
lh_costhetal += -2.0*TMath::Log(result_costhetal);
double result_costhetak = 0.0;
for (unsigned int j = 0; j<npol.ctk; j++){
result_costhetak += params[npol.ctl+j]*ch_costhetak.at(j);// /norm_costhetak;
}
lh_costhetak += -2.0*TMath::Log(result_costhetak);
double result_phi = 0.0;
for (unsigned int j = 0; j<npol.phi; j++){
result_phi += params[npol.ctl+npol.ctk+j]*ch_phi.at(j);// /norm_phi;
}
lh_phi += -2.0*TMath::Log(result_phi);
}
//multiply with the pdf
const double j1s = current_pdf->eff_params->J1s();
const double j1c = current_pdf->eff_params->J1c();
const double j2s = current_pdf->eff_params->J2s();
const double j2c = current_pdf->eff_params->J2c();
const double j3 = current_pdf->eff_params->J3();
const double j4 = current_pdf->eff_params->J4();
const double j5 = current_pdf->eff_params->J5();
const double j6s = current_pdf->eff_params->J6s();
const double j6c = current_pdf->eff_params->J6c();
const double j7 = current_pdf->eff_params->J7();
const double j8 = current_pdf->eff_params->J8();
const double j9 = current_pdf->eff_params->J9();
double sig_norm = 0.0;
sig_norm = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4
+ f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9);
double lh_sig = 0.0, prob = 0.0;
for (unsigned int i=0; i<nsize; i++)
{
event meas = current_pdf->eff_events.at(i);
if (current_pdf->opts->full_angular)
{
current_pdf->fj(meas.costhetal, meas.costhetak, meas.phi,
f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12);
prob = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4
+ f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9)/sig_norm;
}
else
{
current_pdf->folded_fj(meas.costhetal, meas.costhetak, meas.phi, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12);
/*
prob = 9.0/16.0/MY_PI * (fl * f1
+ft * f2
+s3 * f3
+afb * f4
+aim * f5
)/sig_norm;
*/
prob = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4
+ f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9)/sig_norm;
}
lh_sig += -2.0*TMath::Log(prob);
}
//is the integral correct here?
//need to do a nice integration over pdf_sig(costhetal,costhetak,phi)*eps(costhetal,costhetak,phi)
lh = lh_sig + lh_costhetal + lh_costhetak + lh_phi;
};
//this does not assume factorisation of the three dependencies, but assumes phsp MC in 3D
void bu2kstarmumu_pdf::eff_fcn_phsp(Int_t &npar, Double_t *grad, Double_t &lh, Double_t *params, Int_t iflag)
{
//TODO
unsigned int ncosthetal = 5;
unsigned int ncosthetak = 5;
unsigned int nphi = 5;
//make sure we are doing full angular acceptance, no phi folding
assert(current_pdf->opts->full_angular);
//need to account for the norm given the current parameters
double norm = 0.0;
for (unsigned int i = 0; i<ncosthetal; i++)
for (unsigned int j = 0; j<ncosthetak; j++)
for (unsigned int k = 0; k<nphi; k++)
{
double cijk = params[ncosthetak*nphi*i+nphi*j+k];
norm += cijk
*(integral_chebyshev(+1.0, i)-integral_chebyshev(-1.0, i)) //TODO: check the -1,+1
*(integral_chebyshev(+1.0, j)-integral_chebyshev(-1.0, j))
*(integral_chebyshev(+1.0, k)-integral_chebyshev(-1.0, k));//there surely is a more efficient way
}
//this gives Sum_events Log(eps(event))
lh = 0.0;
unsigned int nsize = current_pdf->eff_events.size();
//loop over all events
for (unsigned int l=0; l<nsize; l++) {
const event& meas = current_pdf->eff_events.at(l);
std::vector<double> ch_costhetal;
std::vector<double> ch_costhetak;
std::vector<double> ch_phi;
chebyshev(meas.costhetal, ncosthetal, ch_costhetal);
chebyshev(meas.costhetak, ncosthetak, ch_costhetak);
chebyshev(meas.phi/MY_PI, nphi, ch_phi);
double result = 0.0;
for (unsigned int i = 0; i<ncosthetal; i++)
for (unsigned int j = 0; j<ncosthetak; j++)
for (unsigned int k = 0; k<nphi; k++)
{
double cijk = params[ncosthetak*nphi*i+nphi*j+k];
result += cijk*ch_costhetal.at(i)*ch_costhetak.at(j)*ch_phi.at(k);
}
if (result > 0.0 && !std::isnan(result) && !std::isinf(result))
lh += -2.0*TMath::Log(result/norm) - (-2.0*TMath::Log(1.0/8.0));//can subtract
else
lh += (-100.0*2.0*TMath::Log(1.0/8.0));
}
spdlog::debug( "eff_fcn_phsp lh {0:f}\t npar {1:d}\tiflag {2:d}\tnorm {3:f}", lh, npar, iflag, norm);
};
void bu2kstarmumu_pdf::eff_fcn_phsp_4d(Int_t &npar, Double_t *grad, Double_t &lh, Double_t *params, Int_t iflag)
{
npolynom npol(current_pdf->opts);
double q2min = current_pdf->opts->TheQ2binsmin.front(), q2max = current_pdf->opts->TheQ2binsmax.back();
double ctkmin = current_pdf->opts->ctk_min, ctkmax = current_pdf->opts->ctk_max;
double ctlmin = current_pdf->opts->ctl_min, ctlmax = current_pdf->opts->ctl_max;
double phimin = current_pdf->opts->phi_min, phimax = current_pdf->opts->phi_max;
spdlog::warn("The TMinuit version was not yet tested for folded analysis!");
assert(current_pdf->opts->full_angular);
//need to account for the norm given the current parameters
double norm = 0.0;
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
double chijk = params[npol.get_bin_in4D(h,i,j,k)];
if (chijk == 0.0) continue;
norm += chijk
*(integral_chebyshev(+1.0, h)-integral_chebyshev(-1.0, h))
*(integral_chebyshev(+1.0, i)-integral_chebyshev(-1.0, i))
*(integral_chebyshev(+1.0, j)-integral_chebyshev(-1.0, j))
*(integral_chebyshev(+1.0, k)-integral_chebyshev(-1.0, k));//there surely is a more efficient way
}
}
}
}
//this gives Sum_events Log(eps(event))
lh = 0.0;
unsigned int nsize = current_pdf->eff_events.size();
//loop over all events
for (unsigned int l=0; l<nsize; l++){
const event& meas = current_pdf->eff_events.at(l);
if (meas.q2 < q2min || meas.q2 > q2max) continue;
std::vector<double> ch_q2;
std::vector<double> ch_costhetal;
std::vector<double> ch_costhetak;
std::vector<double> ch_phi;
chebyshev(2.0*(meas.q2 - q2min ) / (q2max - q2min ) - 1.0, npol.q2, ch_q2);
chebyshev(2.0*(meas.costhetal - ctlmin) / (ctlmax - ctlmin) - 1.0, npol.ctl, ch_costhetal);
chebyshev(2.0*(meas.costhetak - ctkmin) / (ctkmax - ctkmin) - 1.0, npol.ctk, ch_costhetak);
chebyshev(2.0*(meas.phi - phimin) / (phimax - phimin) - 1.0, npol.phi, ch_phi);
/*
chebyshev(meas.costhetal, ncosthetal, ch_costhetal);
chebyshev(meas.costhetak, ncosthetak, ch_costhetak);
chebyshev(meas.phi/pi, nphi, ch_phi);
*/
double result = 0.0;
for (unsigned int h = 0; h<npol.q2; h++)
for (unsigned int i = 0; i<npol.ctl; i++)
for (unsigned int j = 0; j<npol.ctk; j++)
for (unsigned int k = 0; k<npol.q2; k++)
{
double chijk = params[npol.get_bin_in4D(h,i,j,k)];
result += chijk*ch_q2.at(h)*ch_costhetal.at(i)*ch_costhetak.at(j)*ch_phi.at(k);
}
if (result > 0.0 && !std::isnan(result) && !std::isinf(result)){
lh += -2.0*meas.weight*TMath::Log(result/norm) - (-2.0*TMath::Log(1.0/16.0));
}
else{
lh += (-100.0*2.0*TMath::Log(1.0/8.0));
}
}
spdlog::debug( "eff_fcn_phsp_4d lh {0:f}\t npar {1:d}\tiflag {2:d}\tnorm {3:f}", lh, npar, iflag, norm);
};
void bu2kstarmumu_pdf::update_cached_normalization(const bu2kstarmumu_parameters* params)
{
spdlog::trace("updating cached normalisation");
//this caches the overall normalisation for both signal and background
double q2 = params->eff_q2();
//swave norm
if (opts->use_mkpi || opts->fit_mkpi){
double mkpi_min = opts->mkpi_min/1.0e+3;
double mkpi_max = opts->mkpi_max/1.0e+3;
//double q2 = params->eff_q2();
double asphase = params->asphase();
double a = params->a();
double r = params->r();
double gammakstar = params->gammakstar();
double mkstar = params->mkstar();
double gammakstarplus = params->gammakstarplus();
double mkstarplus = params->mkstarplus();
double R = params->R();
double gammaf800 = params->gammaf800();
double mf800 = params->mf800();
double f800mag = params->f800mag();
double f800phase = params->f800phase();
//integrate over mkpi2
const double mk = PDGMASS_KST_KAON/1.0e+3;
const double mpi = PDGMASS_KST_PION/1.0e+3;
const double mb = PDGMASS_B/1.0e+3;
const double from = opts->mkpi_full_range_norm ? (mk+mpi) : mkpi_min;
const double to = opts->mkpi_full_range_norm ? mb : mkpi_max;
std::complex<double> mkpi_swavepwave_norm;
if (opts->simple_mkpi){
mkpi_swave_2_norm = int_mkpi_simple_kstarzero_amp_squared(from, to, q2,
f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus);
mkpi_pwave_2_norm = int_mkpi_simple_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar);
mkpi_swavepwave_norm = int_mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(from, to, q2,
gammakstar, mkstar, asphase,
f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus);
mkpi_re_swavepwave_norm = mkpi_swavepwave_norm.real();
mkpi_im_swavepwave_norm = mkpi_swavepwave_norm.imag();
}
else if (opts->isobar){
mkpi_swave_2_norm = int_mkpi_kstarzero_isobar_amp_squared(from, to, q2,
f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R);
mkpi_pwave_2_norm = int_mkpi_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar, R);
mkpi_swavepwave_norm = int_mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(from, to, q2,
gammakstar, mkstar, asphase,
f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R);
mkpi_re_swavepwave_norm = mkpi_swavepwave_norm.real();
mkpi_im_swavepwave_norm = mkpi_swavepwave_norm.imag();
}
else{//nominal lass
mkpi_swave_2_norm = int_mkpi_kstarzero_lass_amp_squared(from, to, q2, asphase, a, r, gammakstarplus, mkstarplus, R);
mkpi_pwave_2_norm = int_mkpi_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar, R);
mkpi_swavepwave_norm = int_mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(from, to, q2,
gammakstar, mkstar,
asphase, a, r, gammakstarplus, mkstarplus, R);
mkpi_re_swavepwave_norm = mkpi_swavepwave_norm.real();
mkpi_im_swavepwave_norm = mkpi_swavepwave_norm.imag();
}
if (opts->use_p2){
//mkpi_bkg(
std::vector<double> ch_p2(5, 0.0);
ch_p2.at(0) = params->cbkgp20();
ch_p2.at(1) = params->cbkgp21();
ch_p2.at(2) = params->cbkgp22();
ch_p2.at(3) = params->cbkgp23();
ch_p2.at(4) = params->cbkgp24();
std::vector<double> poly_p2(ch_p2.size(), 0.0);
chebyshev_to_poly(ch_p2, poly_p2);
std::vector<double> poly_corr_p2(ch_p2.size(), 0.0);
correct_poly(poly_p2, poly_corr_p2, mkpi_min*mkpi_min, mkpi_max*mkpi_max);
mkpi_bkg_norm = 0.0;
for (unsigned int i=0; i<ch_p2.size(); i++)
mkpi_bkg_norm += poly_corr_p2.at(i)*(pow(mkpi_max*mkpi_max,i+1)-pow(mkpi_min*mkpi_min,i+1))/(i+1.0);
}
else{
std::vector<double> ch_mkpi(5, 0.0);
ch_mkpi.at(0) = params->cbkgmkpi0();
ch_mkpi.at(1) = params->cbkgmkpi1();
ch_mkpi.at(2) = params->cbkgmkpi2();
ch_mkpi.at(3) = params->cbkgmkpi3();
ch_mkpi.at(4) = params->cbkgmkpi4();
std::vector<double> poly_mkpi(ch_mkpi.size(), 0.0);
chebyshev_to_poly(ch_mkpi, poly_mkpi);
std::vector<double> poly_corr_mkpi(ch_mkpi.size(), 0.0);
correct_poly(poly_mkpi, poly_corr_mkpi, mkpi_min, mkpi_max);
mkpi_bkg_norm = 0.0;
if (opts->mkpi_threshold){
mkpi_bkg_norm = fcnc::int_threshold(mkpi_min, mkpi_max, 0.633, params->nthreshold());
}
else{
for(unsigned int i=0; i<poly_mkpi.size(); i++)
mkpi_bkg_norm += poly_corr_mkpi.at(i)*(pow(mkpi_max,i+1)-pow(mkpi_min,i+1))/(i+1.0);
}
}
}
double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0,
f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0;
double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0;
const double j1s = params->J1s();
const double j1c = params->J1c();
const double j2s = params->J2s();
const double j2c = params->J2c();
const double j3 = params->J3();
const double j4 = params->J4();
const double j5 = params->J5();
const double j6s = params->J6s();
const double j6c = params->J6c();
const double j7 = params->J7();
const double j8 = params->J8();
const double j9 = params->J9();
const double fs = params->FS();
const double js1 = params->SS1();
const double js2 = params->SS2();
const double js3 = params->SS3();
const double js4 = params->SS4();
const double js5 = params->SS5();
if(spdlog_trace()){ //print out the integrated angular moments. with and without weights, as well as their ratios
load_coeffs_eff_phsp_4d();
integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12, q2);
double pwave_weighted = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4
+ f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9);
integrated_fj_noacc(f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12);
double pwave_noweights = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4
+ f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9);
swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2);
swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6);
spdlog::trace("Integrated P-wave:");
spdlog::trace("P-wave no weights: {0:0.5f}",pwave_noweights);
spdlog::trace("P-wave weighted: {0:0.5f}",pwave_weighted);
spdlog::trace("P-wave ratio: {0:0.5f}\n",pwave_weighted / pwave_noweights);
if (opts->swave){
double swave_noweights = (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5);
double swave_weighted = (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5);
spdlog::trace("Integrated S-wave:");
spdlog::trace("S-wave weighted: {0:0.5f}{0:0.5f}",swave_weighted);
spdlog::trace("S-wave no weights: {0:0.5f}",swave_noweights);
spdlog::trace("S-wave ratio: {0:0.5f}\n",swave_weighted / swave_noweights);
spdlog::trace("Double ratio (s/p):{0:0.5f}",(swave_weighted / swave_noweights) / (pwave_weighted / pwave_noweights));
}
//assert(0);
}
if(opts->full_angular){
if(!opts->cache_fis){
if(opts->use_angular_acc){
integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12, q2);
}
else{//this is also what the weighted fit uses!
integrated_fj_noacc(f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12);
}
fbuffer_f1 = f1;
fbuffer_f2 = f2;
fbuffer_f3 = f3;
fbuffer_f4 = f4;
fbuffer_f5 = f5;
fbuffer_f6 = f6;
fbuffer_f7 = f7;
fbuffer_f8 = f8;
fbuffer_f9 = f9;
fbuffer_f10 = f10;
fbuffer_f11 = f11;
fbuffer_f12 = f12;
}
else{
f1 = fbuffer_f1;
f2 = fbuffer_f2;
f3 = fbuffer_f3;
f4 = fbuffer_f4;
f5 = fbuffer_f5;
f6 = fbuffer_f6;
f7 = fbuffer_f7;
f8 = fbuffer_f8;
f9 = fbuffer_f9;
f10 = fbuffer_f10;
f11 = fbuffer_f11;
f12 = fbuffer_f12;
}
fnorm_sig = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4
+ f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9);
if (opts->fit_asymmetries){
fnorm_sig = (f1*j1s + f2*j1c + f3*j2s + f4*j2c);
}
bool swave = opts->swave;
if (swave){
if (!opts->cache_fis){
if (opts->use_angular_acc){
swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2);
}
else{//weighted fit and fit without acceptance
swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6);
}
fbuffer_fs1 = fs1;
fbuffer_fs2 = fs2;
fbuffer_fs3 = fs3;
fbuffer_fs4 = fs4;
fbuffer_fs5 = fs5;
fbuffer_fs6 = fs6;
}
else{
fs1 = fbuffer_fs1;
fs2 = fbuffer_fs2;
fs3 = fbuffer_fs3;
fs4 = fbuffer_fs4;
fs5 = fbuffer_fs5;
fs6 = fbuffer_fs6;
}
fnorm_sig = (1.0-fs) * (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9)
+ (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5);
if (opts->fit_asymmetries){
fnorm_sig = (1.0-fs)*(f1*j1s + f2*j1c + f3*j2s + f4*j2c)
+ (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5);
}
}
spdlog::trace("Fnormsig (full_angular) {0:f}",fnorm_sig );
spdlog::trace("Normalization integrals P-wave");
spdlog::trace("\tj1s {0:0.4f}",f1/fnorm_sig);
spdlog::trace("\tj1c {0:0.4f}",f2/fnorm_sig);
spdlog::trace("\tj2s {0:0.4f}",f3/fnorm_sig);
spdlog::trace("\tj2c {0:0.4f}",f4/fnorm_sig);
spdlog::trace("\tj3 {0:0.4f}",f5/fnorm_sig);
spdlog::trace("\tj4 {0:0.4f}",f6/fnorm_sig);
spdlog::trace("\tj5 {0:0.4f}",f7/fnorm_sig);
spdlog::trace("\tj6s {0:0.4f}",f8/fnorm_sig);
spdlog::trace("\tj6c {0:0.4f}",f9/fnorm_sig);
spdlog::trace("\tj7 {0:0.4f}",f10/fnorm_sig);
spdlog::trace("\tj8 {0:0.4f}",f11/fnorm_sig);
spdlog::trace("\tj9 {0:0.4f}",f12/fnorm_sig);
if(opts->swave){
spdlog::trace("Normalization integrals S-wave");
spdlog::trace("fs {0:0.4f}",fs1/fnorm_sig);
spdlog::trace("\tas1 {0:0.4f}",fs2/fnorm_sig);
spdlog::trace("\tas2 {0:0.4f}",fs3/fnorm_sig);
spdlog::trace("\tas3 {0:0.4f}",fs4/fnorm_sig);
spdlog::trace("\tas4 {0:0.4f}",fs5/fnorm_sig);
spdlog::trace("\tas5 {0:0.4f}",fs6/fnorm_sig);
}
spdlog::trace("Angular amplitudes: ");
spdlog::trace("\tj1s {0:0.4f}",j1s);
spdlog::trace("\tj1c {0:0.4f}",j1c);
spdlog::trace("\tj2s {0:0.4f}",j2s);
spdlog::trace("\tj2c {0:0.4f}",j2c);
spdlog::trace("\tj3 {0:0.4f}",j3);
spdlog::trace("\tj4 {0:0.4f}",j4);
spdlog::trace("\tj5 {0:0.4f}",j5);
spdlog::trace("\tj6s {0:0.4f}",j6s);
spdlog::trace("\tj6c {0:0.4f}",j6c);
spdlog::trace("\tj7 {0:0.4f}",j7);
spdlog::trace("\tj8 {0:0.4f}",j8);
spdlog::trace("\tj9 {0:0.4f}",j9);
}
else //folded normalization!
{
if (!opts->cache_fis) {
if (opts->use_angular_acc){
folded_integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12, q2);
}
else{//this is also what the weighted fit uses!
folded_integrated_fj_noacc(f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12);
}
fbuffer_f1 = f1;
fbuffer_f2 = f2;
fbuffer_f3 = f3;
fbuffer_f4 = f4;
fbuffer_f5 = f5;
fbuffer_f6 = f6;
fbuffer_f7 = f7;
fbuffer_f8 = f8;
fbuffer_f9 = f9;
fbuffer_f10 = f10;
fbuffer_f11 = f11;
fbuffer_f12 = f12;
}
else{
f1 = fbuffer_f1;
f2 = fbuffer_f2;
f3 = fbuffer_f3;
f4 = fbuffer_f4;
f5 = fbuffer_f5;
f6 = fbuffer_f6;
f7 = fbuffer_f7;
f8 = fbuffer_f8;
f9 = fbuffer_f9;
f10 = fbuffer_f10;
f11 = fbuffer_f11;
f12 = fbuffer_f12;
}
fnorm_sig = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4
+ f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9);
if (opts->fit_asymmetries){
fnorm_sig = (f1*j1s + f2*j1c + f3*j2s + f4*j2c);
}
bool swave = opts->swave;
if (swave){
if (!opts->cache_fis) {
if (opts->use_angular_acc ){
folded_swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2);
}
else{//weighted fit and fit without acceptance
folded_swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6);
}
fbuffer_fs1 = fs1;
fbuffer_fs2 = fs2;
fbuffer_fs3 = fs3;
fbuffer_fs4 = fs4;
fbuffer_fs5 = fs5;
fbuffer_fs6 = fs6;
}
else {
fs1 = fbuffer_fs1;
fs2 = fbuffer_fs2;
fs3 = fbuffer_fs3;
fs4 = fbuffer_fs4;
fs5 = fbuffer_fs5;
fs6 = fbuffer_fs6;
}
fnorm_sig = (1-fs) * (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9)
+ (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5);
if (opts->fit_asymmetries)
fnorm_sig = (1-fs)*(f1*j1s + f2*j1c + f3*j2s + f4*j2c)
+(fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5);
}
spdlog::trace("Fnormsig (folding {0:d}) {1:f}", opts->folding, fnorm_sig );
spdlog::trace("Normalization integrals P-wave");
spdlog::trace("\tj1s {0:0.4f}",f1/fnorm_sig);
spdlog::trace("\tj1c {0:0.4f}",f2/fnorm_sig);
spdlog::trace("\tj2s {0:0.4f}",f3/fnorm_sig);
spdlog::trace("\tj2c {0:0.4f}",f4/fnorm_sig);
spdlog::trace("\tj3 {0:0.4f}",f5/fnorm_sig);
spdlog::trace("\tj4 {0:0.4f}",f6/fnorm_sig);
spdlog::trace("\tj5 {0:0.4f}",f7/fnorm_sig);
spdlog::trace("\tj6s {0:0.4f}",f8/fnorm_sig);
spdlog::trace("\tj6c {0:0.4f}",f9/fnorm_sig);
spdlog::trace("\tj7 {0:0.4f}",f10/fnorm_sig);
spdlog::trace("\tj8 {0:0.4f}",f11/fnorm_sig);
spdlog::trace("\tj9 {0:0.4f}",f12/fnorm_sig);
if(opts->swave){
spdlog::trace("Normalization integrals S-wave");
spdlog::trace("fs {0:0.4f}",fs1/fnorm_sig);
spdlog::trace("\tas1 {0:0.4f}",fs2/fnorm_sig);
spdlog::trace("\tas2 {0:0.4f}",fs3/fnorm_sig);
spdlog::trace("\tas3 {0:0.4f}",fs4/fnorm_sig);
spdlog::trace("\tas4 {0:0.4f}",fs5/fnorm_sig);
spdlog::trace("\tas5 {0:0.4f}",fs6/fnorm_sig);
}
spdlog::trace("Angular amplitudes: ");
spdlog::trace("\tj1s {0:0.4f}",j1s);
spdlog::trace("\tj1c {0:0.4f}",j1c);
spdlog::trace("\tj2s {0:0.4f}",j2s);
spdlog::trace("\tj2c {0:0.4f}",j2c);
spdlog::trace("\tj3 {0:0.4f}",j3);
spdlog::trace("\tj4 {0:0.4f}",j4);
spdlog::trace("\tj5 {0:0.4f}",j5);
spdlog::trace("\tj6s {0:0.4f}",j6s);
spdlog::trace("\tj6c {0:0.4f}",j6c);
spdlog::trace("\tj7 {0:0.4f}",j7);
spdlog::trace("\tj8 {0:0.4f}",j8);
spdlog::trace("\tj9 {0:0.4f}",j9);
}
//bkg norm
//this is used to convolute the acceptance into the pdf
if(opts->use_angular_acc && opts->use_weighted_bkg){ //weighted background pdf
if (opts->full_angular){
fnorm_bkg = integral_bkg_chebyshev(params, CTL_MIN, CTL_MAX, CTK_MIN, CTK_MAX, PHI_MIN, PHI_MAX, q2);
}
else if(opts->fit_full_angular_bkg){
fnorm_bkg = integral_bkg_chebyshev(params, CTL_MIN, CTL_MAX, opts->ctk_min, opts->ctk_max, PHI_MIN, PHI_MAX, q2); //TODO: check here whether this makes any sense (https://gitlab.cern.ch/LHCb-RD/ewp-Bplus2Kstmumu-AngAna/-/merge_requests/21)
}
else{
fnorm_bkg = integral_bkg_chebyshev(params, opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max, q2);
}
}
else{ //non weighted background pdf
if (opts->full_angular){
if (opts->flat_bkg) fnorm_bkg = RANGE_3D();
else fnorm_bkg = integral_bkg(params, opts->ctl_min, opts->ctl_max,
opts->ctk_min, opts->ctk_max,
opts->phi_min, opts->phi_max);
}
else{ //folded angles
if (opts->flat_bkg){
fnorm_bkg = (opts->ctk_max - opts->ctk_min) * (opts->ctl_max - opts->ctl_min) * (opts->phi_max - opts->phi_min);
}
else{
if(opts->fit_full_angular_bkg){
fnorm_bkg = integral_bkg(params, CTL_MIN, CTL_MAX, CTK_MIN, CTK_MAX, PHI_MIN, PHI_MAX);
}
else{
fnorm_bkg = integral_bkg(params, opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max);
}
}
}
}
}
void bu2kstarmumu_pdf::update_cached_integrated_fis(const bu2kstarmumu_parameters* params)
{
if(opts->cache_fis){
double q2 = params->eff_q2();
if(opts->full_angular){
if(opts->use_angular_acc){
integrated_fj_chebyshev(fbuffer_f1, fbuffer_f2, fbuffer_f3, fbuffer_f4, fbuffer_f5, fbuffer_f6,
fbuffer_f7, fbuffer_f8, fbuffer_f9, fbuffer_f10, fbuffer_f11, fbuffer_f12, q2);
swave_integrated_fj_chebyshev(fbuffer_fs1, fbuffer_fs2, fbuffer_fs3, fbuffer_fs4, fbuffer_fs5, fbuffer_fs6, q2);
}
else{//this is also what the weighted fit uses!
integrated_fj_noacc(fbuffer_f1, fbuffer_f2, fbuffer_f3, fbuffer_f4, fbuffer_f5, fbuffer_f6,
fbuffer_f7, fbuffer_f8, fbuffer_f9, fbuffer_f10, fbuffer_f11, fbuffer_f12);
swave_integrated_fj_noacc(fbuffer_fs1, fbuffer_fs2, fbuffer_fs3, fbuffer_fs4, fbuffer_fs5, fbuffer_fs6);
}
}
else{ //folded
if(opts->use_angular_acc){
folded_integrated_fj_chebyshev(fbuffer_f1, fbuffer_f2, fbuffer_f3, fbuffer_f4, fbuffer_f5, fbuffer_f6,
fbuffer_f7, fbuffer_f8, fbuffer_f9, fbuffer_f10, fbuffer_f11, fbuffer_f12, q2);
folded_swave_integrated_fj_chebyshev(fbuffer_fs1, fbuffer_fs2, fbuffer_fs3, fbuffer_fs4, fbuffer_fs5, fbuffer_fs6, q2);
}
else{//this is also what the weighted fit uses!
folded_integrated_fj_noacc(fbuffer_f1, fbuffer_f2, fbuffer_f3, fbuffer_f4, fbuffer_f5, fbuffer_f6,
fbuffer_f7, fbuffer_f8, fbuffer_f9, fbuffer_f10, fbuffer_f11, fbuffer_f12);
folded_swave_integrated_fj_noacc(fbuffer_fs1, fbuffer_fs2, fbuffer_fs3, fbuffer_fs4, fbuffer_fs5, fbuffer_fs6);
}
}
}
}
double bu2kstarmumu_pdf::mkpi_pwave_2(const bu2kstarmumu_parameters* params, const event& meas) const
{
double mkpi = meas.mkpi/1.0e+3;
double q2 = params->eff_q2();
//if (opts->weighted_fit) TODO
// q2 = meas.q2;
double gammakstar = params->gammakstar();
double mkstar = params->mkstar();
double R = params->R();
if (opts->simple_mkpi) return mkpi_simple_bw_kstar_amp_squared(mkpi, q2, gammakstar, mkstar);
else return mkpi_bw_kstar_amp_squared(mkpi, q2, gammakstar, mkstar, R);
}
double bu2kstarmumu_pdf::mkpi_swave_2(const bu2kstarmumu_parameters* params, const event& meas) const
{
double mkpi = meas.mkpi/1.0e+3;
double q2 = params->eff_q2();
//if (opts->weighted_fit) TODO
// q2 = meas.q2;
double asphase = params->asphase();
double a = params->a();
double r = params->r();
double R = params->R();
double gammakstarplus = params->gammakstarplus();
double mkstarplus = params->mkstarplus();
double gammaf800 = params->gammaf800();
double mf800 = params->mf800();
double f800mag = params->f800mag();
double f800phase = params->f800phase();
if (opts->simple_mkpi){
return mkpi_simple_kstarzero_amp_squared(mkpi, q2,
f800mag, f800phase, gammaf800, mf800,
gammakstarplus, mkstarplus);
}
else if (opts->isobar){
return mkpi_kstarzero_isobar_amp_squared(mkpi, q2,
f800mag, f800phase, gammaf800, mf800,
gammakstarplus, mkstarplus, R);
}
else{//LASS
return mkpi_kstarzero_lass_amp_squared(mkpi, q2, asphase, a, r, gammakstarplus, mkstarplus, R);
}
}
double bu2kstarmumu_pdf::mkpi_re_swavepwave(const bu2kstarmumu_parameters* params, const event& meas) const
{
double mkpi = meas.mkpi/1.0e+3;
double q2 = params->eff_q2();
// if (opts->weighted_fit) //TODO
// q2 = meas.q2;
double gammakstar = params->gammakstar();
double mkstar = params->mkstar();
double asphase = params->asphase();
double a = params->a();
double r = params->r();
double gammakstarplus = params->gammakstarplus();
double mkstarplus = params->mkstarplus();
double R = params->R();
double gammaf800 = params->gammaf800();
double mf800 = params->mf800();
double f800mag = params->f800mag();
double f800phase = params->f800phase();
std::complex<double> swavepwave;
if (opts->simple_mkpi){
swavepwave = mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(mkpi, q2,
gammakstar, mkstar, asphase,
f800mag, f800phase, gammaf800, mf800,
gammakstarplus, mkstarplus);
}
else if (opts->isobar){
swavepwave = mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(mkpi, q2,
gammakstar, mkstar, asphase,
f800mag, f800phase, gammaf800, mf800,
gammakstarplus, mkstarplus, R);
}
else{//LASS
swavepwave = mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(mkpi, q2, gammakstar, mkstar, asphase,
a, r, gammakstarplus, mkstarplus, R);
}
return swavepwave.real();
}
double bu2kstarmumu_pdf::mkpi_im_swavepwave(const bu2kstarmumu_parameters* params, const event& meas) const
{
double mkpi = meas.mkpi/1.0e+3;
double q2 = params->eff_q2();
//if (opts->weighted_fit) //TODO
// q2 = meas.q2;
double gammakstar = params->gammakstar();
double mkstar = params->mkstar();
double asphase = params->asphase();
double a = params->a();
double r = params->r();
double gammakstarplus = params->gammakstarplus();
double mkstarplus = params->mkstarplus();
double R = params->R();
double gammaf800 = params->gammaf800();
double mf800 = params->mf800();
double f800mag = params->f800mag();
double f800phase = params->f800phase();
std::complex<double> swavepwave;
if (opts->simple_mkpi){
swavepwave = mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(mkpi, q2,
gammakstar, mkstar, asphase,
f800mag, f800phase, gammaf800, mf800,
gammakstarplus, mkstarplus);
}
else if (opts->isobar){
swavepwave = mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(mkpi, q2,
gammakstar, mkstar, asphase,
f800mag, f800phase, gammaf800, mf800,
gammakstarplus, mkstarplus, R);
}
else{//LASS
swavepwave = mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(mkpi, q2, gammakstar, mkstar, asphase,
a, r, gammakstarplus, mkstarplus, R);
}
return swavepwave.imag();
}
double bu2kstarmumu_pdf::mkpi_bkg(const bu2kstarmumu_parameters* params, const event& meas) const
{
double mkpi = meas.mkpi/1.0e+3;
double mkpi_min = opts->mkpi_min/1.0e+3;
double mkpi_max = opts->mkpi_max/1.0e+3;
double probbkg = 0.0;
if (opts->use_p2) {
std::vector<double> ch_p2(5, 0.0);
ch_p2.at(0) = params->cbkgp20();
ch_p2.at(1) = params->cbkgp21();
ch_p2.at(2) = params->cbkgp22();
ch_p2.at(3) = params->cbkgp23();
ch_p2.at(4) = params->cbkgp24();
std::vector<double> poly_p2(ch_p2.size(), 0.0);
chebyshev_to_poly(ch_p2, poly_p2);
std::vector<double> poly_corr_p2(ch_p2.size(), 0.0);
correct_poly(poly_p2, poly_corr_p2, mkpi_min*mkpi_min, mkpi_max*mkpi_max);
for (unsigned int i=0; i<ch_p2.size(); i++)
probbkg += poly_corr_p2.at(i)*pow(mkpi*mkpi,i);
}
else
{
std::vector<double> ch_mkpi(5, 0.0);
ch_mkpi.at(0) = params->cbkgmkpi0();
ch_mkpi.at(1) = params->cbkgmkpi1();
ch_mkpi.at(2) = params->cbkgmkpi2();
ch_mkpi.at(3) = params->cbkgmkpi3();
ch_mkpi.at(4) = params->cbkgmkpi4();
std::vector<double> poly_mkpi(ch_mkpi.size(), 0.0);
chebyshev_to_poly(ch_mkpi, poly_mkpi);
std::vector<double> poly_corr_mkpi(ch_mkpi.size(), 0.0);
correct_poly(poly_mkpi, poly_corr_mkpi, mkpi_min, mkpi_max);
if (opts->mkpi_threshold){
//threshold(double x, double thr, double n);
probbkg = fcnc::threshold(mkpi, 0.633, params->nthreshold());
}
else{
for (unsigned int i=0; i<ch_mkpi.size(); i++) probbkg += poly_corr_mkpi.at(i)*pow(mkpi,i);
}
}
return probbkg;
}
void bu2kstarmumu_pdf::update_cached_xis(const bu2kstarmumu_parameters* params, std::vector<event>* events)
{
spdlog::info("Updating cached xis");
//this is used if per_event_norm is on
//it stores the 18 xis for every event
//otherwise using a different norm per event is computationally not possible
//double q2 = params->eff_q2();
assert(opts->use_event_norm);
/*
for (unsigned int e=0; e<events->size(); e++)
{
if ((e*100) % events->size() == 0)
std::cout << (e*100)/events->size() << "% " << std::endl;
event& meas = events->at(e);D
double q2 = meas.q2;
double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0,
f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0;
integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12, q2);
meas.xis[0] = f1;
meas.xis[1] = f2;
meas.xis[2] = f3;
meas.xis[3] = f4;
meas.xis[4] = f5;
meas.xis[5] = f6;
meas.xis[6] = f7;
meas.xis[7] = f8;
meas.xis[8] = f9;
meas.xis[9] = f10;
meas.xis[10] = f11;
meas.xis[11] = f12;
bool swave = opts->swave;
if (swave)
{
double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0;
swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2);
meas.xis[12] = fs1;
meas.xis[13] = fs2;
meas.xis[14] = fs3;
meas.xis[15] = fs4;
meas.xis[16] = fs5;
meas.xis[17] = fs6;
}
}
*/
/*
for (unsigned int e=0; e<events->size(); e++)
{
event& meas = events->at(e);
std::cout << meas.xis[0] << " "
<< meas.xis[1] << " "
<< meas.xis[2] << " "
<< meas.xis[3] << " "
<< meas.xis[4] << " "
<< meas.xis[5] << " "
<< meas.xis[6] << " "
<< meas.xis[7] << " "
<< meas.xis[8] << " "
<< meas.xis[9] << " "
<< meas.xis[10] << " "
<< meas.xis[11] << " "
<< meas.xis[12] << " "
<< meas.xis[13] << " "
<< meas.xis[14] << " "
<< meas.xis[15] << " "
<< meas.xis[16] << " "
<< meas.xis[17] << " q2 " << meas.q2 << std::endl;
}
*/
//std::cout << std::endl;
}
void bu2kstarmumu_pdf::update_cached_normalization(const parameters* params){
update_cached_normalization(static_cast<const bu2kstarmumu_parameters*>(params));
}
void bu2kstarmumu_pdf::update_cached_integrated_fis(const parameters* params){
update_cached_integrated_fis(static_cast<const bu2kstarmumu_parameters*>(params));
}
void bu2kstarmumu_pdf::update_cached_efficiencies(const parameters* params, std::vector<event>* events)
{
update_cached_efficiencies(static_cast<const bu2kstarmumu_parameters*>(params), events);
}
void bu2kstarmumu_pdf::update_cached_xis(const parameters* params, std::vector<event>* events)
{
update_cached_xis(static_cast<const bu2kstarmumu_parameters*>(params), events);
}
double bu2kstarmumu_pdf::m_sig_prob(const bu2kstarmumu_parameters* params, const event& meas) const{
if (opts->only_angles || opts->only_mkpi) return 1.0;
double mmin=params->m_b.get_min();
double mmax=params->m_b.get_max();
if(meas.m > mmax || meas.m < mmin){
spdlog::error("m(B) outside of allowed range: mmin={0:f}, mmax={1:f} m={2:f}", mmin, mmax, meas.m);
assert(0);
}
double result = 0.0;
if(opts->crystalball){
result = params->m_res_1()
* crystalball(meas.m, params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->n_1())
/ integrate_crystalball(params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->n_1(), mmin, mmax);
if(params->m_res_1() != 1.0)
result += (1.0-params->m_res_1())
* crystalball(meas.m, params->m_b(), params->m_scale()*params->m_sigma_2(), params->alpha_2(), params->n_2())
/ integrate_crystalball(params->m_b(), params->m_scale()*params->m_sigma_2(), params->alpha_2(), params->n_2(), mmin, mmax);
}
else if(opts->twotailedcrystalball){
result = twotailedcrystalball(meas.m, params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->alpha_2(), params->n_1(), params->n_2())
/ integrate_twotailedcrystalball(params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->alpha_2(), params->n_1(), params->n_2(), mmin, mmax);
}
else{
result = params->m_res_1()
* normed_gauss(meas.m, params->m_scale()*params->m_sigma_1(), params->m_b(), mmin, mmax);
if(params->m_res_1() != 1.0)
result += (1.0-params->m_res_1())
* normed_gauss(meas.m, params->m_scale()*params->m_sigma_2(), params->m_b(), mmin, mmax);
}
return result;
};
double bu2kstarmumu_pdf::mkpi_sig_prob(const bu2kstarmumu_parameters* params, const event& meas) const
{
if(!opts->fit_mkpi || opts->only_angles || opts->only_Bmass) return 1.0;
assert(meas.mkpi <= opts->mkpi_max);
assert(meas.mkpi >= opts->mkpi_min);
double result = 0.0;
double prob_mkpi_pwave = mkpi_pwave_2(params, meas);
double prob_mkpi_swave = mkpi_swave_2(params, meas);
double prob_mkpi_pwaveswave_re = mkpi_re_swavepwave(params, meas);
double prob_mkpi_pwaveswave_im = mkpi_im_swavepwave(params, meas);
double fs = params->FS();
//only m(B) and m(K*+) fitted
if(opts->only_mass2DFit){
if(opts->swave){
result = (1.0-fs)
* prob_mkpi_pwave/mkpi_pwave_2_norm
+ fs
* prob_mkpi_swave/mkpi_swave_2_norm;
}
else{
result = prob_mkpi_pwave/mkpi_pwave_2_norm;
}
}//end only m(B) and m(K*+)
else{//angular dimensions included in the fit
double q2 = meas.q2;
//integrated S_i
double xi1, xi2, xi3, xi4, xi5, xi6, xi7, xi8, xi9, xi10, xi11, xi12;
if(opts->use_angular_acc) integrated_fj_chebyshev(xi1, xi2, xi3, xi4, xi5, xi6, xi7, xi8, xi9, xi10, xi11, xi12, q2);
else integrated_fj_noacc(xi1, xi2, xi3, xi4, xi5, xi6, xi7, xi8, xi9, xi10, xi11, xi12);
//integrated SS_i
double sxi1, sxi2, sxi3, sxi4, sxi5, sxi6;
if(opts->use_angular_acc) swave_integrated_fj_chebyshev(sxi1, sxi2, sxi3, sxi4, sxi5, sxi6, q2);
else swave_integrated_fj_noacc(sxi1, sxi2, sxi3, sxi4, sxi5, sxi6);
//load values for required parameters:
const double s1s = params->S1s();
const double s2s = s1s/3.0;
const double s1c = 1.0 - 4.0/3.0 * s1s;
const double s2c = -s1c;
const double s3 = params->S3();
const double s4 = params->S4();
const double s5 = params->S5();
const double s6s = params->S6s();
const double s6c = 0.;
const double s7 = params->S7();
const double s8 = params->S8();
const double s9 = params->S9();
const double ss1 = params->SS1();
const double ss2 = params->SS2();
const double ss3 = params->SS3();
const double ss4 = params->SS4();
const double ss5 = params->SS5();
double norm = (1 - fs) * (xi1*s1s + xi2*s1c + xi3*s2s + xi4*s2c + xi5*s3 + xi6*s4
+ xi7*s5 + xi8*s6s + xi9*s6c + xi10*s7 + xi11*s8 + xi12*s9)
+ (sxi1*fs)
+ (sxi2*ss1 + sxi3*ss2 + sxi4*ss3)
+ (sxi5*ss4 + sxi6*ss5);
double A = (xi1*s1s + xi2*s1c + xi3*s2s + xi4*s2c + xi5*s3 + xi6*s4
+ xi7*s5 + xi8*s6s + xi9*s6c + xi10*s7 + xi11*s8 + xi12*s9)/norm;
double B = sxi1/norm;
double C = (sxi2*ss1 + sxi3*ss2 + sxi4*ss3)/norm;
double D = (sxi5*ss4 + sxi6*ss5)/norm;
result = (1.0-fs) * A * prob_mkpi_pwave/mkpi_pwave_2_norm
+ fs * B * prob_mkpi_swave/mkpi_swave_2_norm
+ C * prob_mkpi_pwaveswave_re/mkpi_re_swavepwave_norm
+ D * prob_mkpi_pwaveswave_im/mkpi_im_swavepwave_norm;
}//end of prob with angular parts included
return result;
};
double bu2kstarmumu_pdf::integral_m_sig_prob(const bu2kstarmumu_parameters* params, double ma, double mb) const
{
double result = 0.0;
if (opts->crystalball){
double mmin=params->m_b.get_min(), mmax=params->m_b.get_max();
result = params->m_res_1()*integrate_crystalball(params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->n_1(), ma, mb)
/ integrate_crystalball(params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->n_1(), mmin, mmax);
if (params->m_res_1() != 1.0)
result += (1.0-params->m_res_1()) * integrate_crystalball(params->m_b(), params->m_scale()*params->m_sigma_2(), params->alpha_2(), params->n_2(), ma, mb)
/ integrate_crystalball(params->m_b(), params->m_scale()*params->m_sigma_2(), params->alpha_2(), params->n_2(), mmin, mmax);
}
else if(opts->twotailedcrystalball){
double mmin=params->m_b.get_min(), mmax=params->m_b.get_max();
result = integrate_twotailedcrystalball(params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->alpha_2(), params->n_1(), params->n_2(), ma, mb)
/ integrate_twotailedcrystalball(params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->alpha_2(), params->n_1(), params->n_2(), mmin, mmax);
}
else{
double mean = params->m_b();
double min = params->m_b.get_min();
double max = params->m_b.get_max();
double sigma1 = params->m_scale()*params->m_sigma_1();
double sigma2 = params->m_scale()*params->m_sigma_2();
double fres = params->m_res_1();
double fullrange = (fres)*1.0/2.0*(TMath::Erf((max-mean)/(sqrt(2.0)*sigma1))-TMath::Erf((min-mean)/(sqrt(2.0)*sigma1)));
if (params->m_res_1() != 1.0)
fullrange += (1.0-fres)*1.0/2.0*(TMath::Erf((max-mean)/(sqrt(2.0)*sigma2))-TMath::Erf((min-mean)/(sqrt(2.0)*sigma2)));
double integral = (fres)*1.0/2.0*(TMath::Erf((mb-mean)/(sqrt(2.0)*sigma1))-TMath::Erf((ma-mean)/(sqrt(2.0)*sigma1)));
if (params->m_res_1() != 1.0)
integral += (1.0-fres)*1.0/2.0*(TMath::Erf((mb-mean)/(sqrt(2.0)*sigma2))-TMath::Erf((ma-mean)/(sqrt(2.0)*sigma2)));
result = integral/fullrange;
}
return result;
};
double bu2kstarmumu_pdf::m_bkg_prob(const bu2kstarmumu_parameters* params, const event& meas) const
{
if (opts->only_angles || opts->only_mkpi) return 1.0;
double mmin=params->m_b.get_min(), mmax=params->m_b.get_max();
assert(meas.m <= mmax);
assert(meas.m >= mmin);
if(opts->cutsignalwindow){
assert(meas.m <= opts->m_min || meas.m >= opts->m_max);
}
double fm1 = params->fm_tau();
double tau1 = params->m_tau();
double tau2 = params->m_tau_2();
double lambda1 = params->m_lambda();
double lambda2 = params->m_lambda_2();
double result = 0.;
if(opts->fit_lambda){
if(lambda1 == 0.0) return 1.0;
double norm1 = 1.0/lambda1*(exp(mmax*lambda1) - exp(mmin*lambda1));
if(opts->cutsignalwindow){
norm1 -= 1.0/lambda1*(exp(opts->m_max*lambda1) - exp(opts->m_min*lambda1));
}
result = exp(meas.m*lambda1)/norm1;
if (fm1 != 1.0){
if(lambda2 == 0.0) return result;
result *= fm1;
double norm2 = 1.0/lambda2*(exp(mmax*lambda2) - exp(mmin*lambda2));
if(opts->cutsignalwindow)
norm2 -= 1.0/lambda2*(exp(opts->m_max*lambda2) - exp(opts->m_min*lambda2));
result += (1.0-fm1)*exp(meas.m*lambda2)/norm2;
}
}
else{
double norm1 = tau1*(exp(-mmin/tau1) - exp(-mmax/tau1));
if(opts->cutsignalwindow)
norm1 -= tau1*(exp(-opts->m_min/tau1) - exp(-opts->m_max/tau1));
result = exp(-meas.m/tau1)/norm1;
if (fm1 != 1.0){
result *= fm1;
double norm2 = tau2*(exp(-mmin/tau2) - exp(-mmax/tau2));
if(opts->cutsignalwindow)
norm2 -= tau2*(exp(-opts->m_min/tau2) - exp(-opts->m_max/tau2));
result += (1.0-fm1)*exp(-meas.m/tau2)/norm2;
}
}
return result;
};
double bu2kstarmumu_pdf::mkpi_bkg_prob(const bu2kstarmumu_parameters* params, const event& meas) const
{
if(!(opts->fit_mkpi || opts->use_mkpi) || opts->only_angles || opts->only_Bmass)
return 1.0;
assert(meas.mkpi <= opts->mkpi_max);
assert(meas.mkpi >= opts->mkpi_min);
double result = 0.0;
double mkpi_min = opts->mkpi_min/1.0e+3;
double mkpi_max = opts->mkpi_max/1.0e+3;
double mkpi = meas.mkpi/1.0e+3;
double normbkg=0.0;
std::vector<double> ch_mkpi(5, 0.0);
ch_mkpi.at(0) = params->cbkgmkpi0();
ch_mkpi.at(1) = params->cbkgmkpi1();
ch_mkpi.at(2) = params->cbkgmkpi2();
ch_mkpi.at(3) = params->cbkgmkpi3();
ch_mkpi.at(4) = params->cbkgmkpi4();
std::vector<double> poly_mkpi(ch_mkpi.size(), 0.0);
chebyshev_to_poly(ch_mkpi, poly_mkpi);
std::vector<double> poly_corr_mkpi(ch_mkpi.size(), 0.0);
correct_poly(poly_mkpi, poly_corr_mkpi, mkpi_min, mkpi_max);
for(unsigned int i=0; i<poly_mkpi.size(); i++)
normbkg += poly_corr_mkpi.at(i)*(pow(mkpi_max,i+1)-pow(mkpi_min,i+1))/(i+1.0);
double probbkg = 0.0;
for (unsigned int i=0; i<ch_mkpi.size(); i++)
probbkg += poly_corr_mkpi.at(i)*pow(mkpi,i);
result = probbkg/normbkg;
return result;
};
double bu2kstarmumu_pdf::integral_m_bkg_prob(const bu2kstarmumu_parameters* params, double ma, double mb) const
{
double mmin=params->m_b.get_min(), mmax=params->m_b.get_max();
double bkg_frac = params->fm_tau();
double tau1 = params->m_tau();
double tau2 = params->m_tau_2();
double lambda1 = params->m_lambda();
double lambda2 = params->m_lambda_2();
double result = 0.0;
if(opts->fit_lambda){
assert(lambda1 <= 0.);
double fullrange1 = 1.0/lambda1*(exp(mmax*lambda1) - exp(mmin*lambda1));
if(opts->cutsignalwindow){
fullrange1 -= 1.0/lambda1*(exp(opts->m_max*lambda1) - exp(opts->m_min*lambda1));
}
double integral1 = 1.0/lambda1*(exp(mb*lambda1) - exp(ma*lambda1));
result = integral1/fullrange1;
if (bkg_frac != 1.0){
assert(lambda2 <= 0.);
result *= bkg_frac;
double fullrange2 = 1.0/lambda2*(exp(mmax*lambda2) - exp(mmin*lambda2));
if(opts->cutsignalwindow){
fullrange2 -= 1.0/lambda2*(exp(opts->m_max*lambda2) - exp(opts->m_min*lambda2));
}
double integral2 = 1.0/lambda2*(exp(mb*lambda2) - exp(ma*lambda2));
result += (1.0-bkg_frac)*integral2/fullrange2;
}
}
else{
double fullrange1 = tau1*(exp(-mmin/tau1) - exp(-mmax/tau1));
if(opts->cutsignalwindow){
fullrange1 -= tau1*(exp(opts->m_max/tau1) - exp(opts->m_min/tau1));
}
double integral1 = tau1*(exp(-ma/tau1) - exp(-mb/tau1));
result = integral1/fullrange1;
if (bkg_frac != 1.0){
result *= bkg_frac;
double fullrange2 = tau2*(exp(-mmin/tau2) - exp(-mmax/tau2));
if(opts->cutsignalwindow){
fullrange2 -= tau2*(exp(opts->m_max/tau2) - exp(opts->m_min/tau2));
}
double integral2 = tau2*(exp(-ma/tau2) - exp(-mb/tau2));
result += (1.0-bkg_frac)*integral2/fullrange2;
}
}
return result;
};
double bu2kstarmumu_pdf::angular_sig_prob(const bu2kstarmumu_parameters* params, const event& meas) const
{
//Don't when only fitting the mass
if (opts->only_Bmass || opts->only_mass2DFit || opts->only_mkpi) return 1.0;
double ctl = meas.costhetal;
double ctk = meas.costhetak;
double phi = meas.phi;
double result_swave = 0.0, result_pwave = 0.0;
double result = 0.0;
double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0,
f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0;
const double j1s = params->J1s();
const double j1c = params->J1c();
const double j2s = params->J2s();
const double j2c = params->J2c();
const double j3 = params->J3();
const double j4 = params->J4();
const double j5 = params->J5();
const double j6s = params->J6s();
const double j6c = params->J6c();
const double j7 = params->J7();
const double j8 = params->J8();
const double j9 = params->J9();
if (opts->full_angular) fj(ctl, ctk, phi, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12);
else folded_fj(ctl, ctk, phi, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12);
if (opts->fit_asymmetries && meas.cp_conjugate){
result_pwave += (f1*j1s + f2*j1c + f3*j2s + f4*j2c - f5*j3 - f6*j4
- f7*j5 - f8*j6s - f9*j6c - f10*j7 - f11*j8 - f12*j9);
}
else{
result_pwave += (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4
+ f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9);
}
if (opts->swave){
double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0;
if(opts->full_angular) swave_fj(ctl, ctk, phi, f1, f2, f3, f4, f5, f6);
else folded_swave_fj(ctl, ctk, phi, f1, f2, f3, f4, f5, f6);
const double fs = params->FS();
const double js1 = params->SS1();
const double js2 = params->SS2();
const double js3 = params->SS3();
const double js4 = params->SS4();
const double js5 = params->SS5();
result_pwave *= (1.0 - fs);
result_swave += (fs*f1 + js1*f2 + js2*f3 + js3*f4 + js4*f5 + js5*f6);
if (opts->use_mkpi){
double prob_mkpi_pwave = mkpi_pwave_2(params, meas);
double prob_mkpi_swave = mkpi_swave_2(params, meas);
double prob_mkpi_re_swavepwave = mkpi_re_swavepwave(params, meas);
double prob_mkpi_im_swavepwave = mkpi_im_swavepwave(params, meas);
result_pwave *= prob_mkpi_pwave/mkpi_pwave_2_norm;
if (std::isnan(result_pwave)) spdlog::warn("prob_mkpi_pwave {0:f}",prob_mkpi_pwave );
result_swave = (fs*f1*prob_mkpi_swave/mkpi_swave_2_norm
+ (js1*f2 + js2*f3 + js3*f4)*prob_mkpi_re_swavepwave/mkpi_re_swavepwave_norm
+ (js4*f5 + js5*f6)*prob_mkpi_im_swavepwave/mkpi_im_swavepwave_norm);
}
if (std::isnan(result_swave) || std::isinf(result_swave)){
spdlog::warn("\tresult_swave {0:0.6f}",result_swave);
spdlog::warn("\t mkpi_swave_2_norm {0:0.6f}",mkpi_swave_2_norm);
spdlog::warn("\t mkpi_pwave_2_norm {0:0.6f}",mkpi_pwave_2_norm);
spdlog::warn("\t prob_mkpi_swave {0:0.6f}",mkpi_swave_2(params, meas));
spdlog::warn("\t prob_mkpi_re_swavepwave {0:0.6f}",mkpi_re_swavepwave(params, meas));
spdlog::warn("\t prob_mkpi_im_swavepwave {0:0.6f}",mkpi_im_swavepwave(params, meas));
result_swave = 1.0e-12;
}
}
result = result_pwave + result_swave;
if(std::isnan(result) || std::isinf(result)){
spdlog::error("result={0:0f}",result );
spdlog::error("pwave={0:0f}",result_pwave );
spdlog::error("swave={0:0f}",result_swave );
assert(0);
}
//spdlog::trace("result={0:0f}",result );
//spdlog::trace("pwave={0:0f}",result_pwave );
//spdlog::trace("swave={0:0f}",result_swave );
double eff = 1.0;
if (opts->use_angular_acc){
//for fixed effq2 the efficiency should have been calculated beforehand
//for floating q2 should recalculate as done below
//for event_norm, the efficiency should also have been calculated before
bool q2fixed = (params->eff_q2.get_step_size() == 0.0);
if ((q2fixed || opts->use_event_norm) && (!opts->mcweight)) { //use event norm is only used when convoluting the acceptance into the pdf
if (meas.weight > 0.0) eff = 1.0/meas.weight;
spdlog::trace("eff={0:f}",eff);
}
else{
double q2 = params->eff_q2();
eff = this->get_ang_eff(opts,q2,meas.costhetal_fa, meas.costhetal_fa,meas.phi_fa);
spdlog::trace("eff={0:f}",eff);
spdlog::trace("q2={0:f}",q2);
}
}
if(std::isnan(eff) || std::isinf(eff)){
spdlog::error("eff={0:f}",eff );
assert(0);
}
if(eff/fnorm_sig < 0.0){
spdlog::info("negative acc corr and/or normalizing");
spdlog::info("eff={0:f}",eff );
spdlog::info("norm={0:f}",fnorm_sig );
assert(eff > 0.0);
assert(fnorm_sig > 0.0);
}
//spdlog::trace("eff={0:f},\t fnorm_sig={1:f}",eff, fnorm_sig);
result *= eff/fnorm_sig;
return result;
};
double bu2kstarmumu_pdf::angular_bkg_prob(const bu2kstarmumu_parameters* params, const event& meas) const{
//Don't when only fitting the mass
if (opts->only_Bmass || opts->only_mass2DFit || opts->only_mkpi) return 1.0;
//calculate bkg prob for all 2(4) possible inversed folding angles:
if(opts->fit_full_angular_bkg && !opts->flat_bkg && !opts->full_angular){
fcnc::event e[3];
fldr->invers_fold(&meas, &e[0], &e[1], &e[2]);
double p1, p2, p3, p4;
p1 = simple_angular_bkg_prob(params, meas);
p4 = simple_angular_bkg_prob(params, e[2]);
if(opts->folding > 0){
p2 = simple_angular_bkg_prob(params, e[0]);
p3 = simple_angular_bkg_prob(params, e[1]);
return p1+p2+p3+p4;
}
else{
return p1+p4;
}
}
else{
return simple_angular_bkg_prob(params, meas);
}
}
double bu2kstarmumu_pdf::simple_angular_bkg_prob(const bu2kstarmumu_parameters* params, const event& meas) const{
if (opts->only_Bmass) return 1.0;
if (opts->only_mass2DFit) return 1.0; //Don't when fitting only mass
double result = 1.0;
double costhetal = meas.costhetal;
double costhetak = meas.costhetak;
double phi = meas.phi;
npolynom npol(opts);
assert(coeffs_eff_4d.size() == npol.getSize());
//determine weight/efficiency for this event
double eff = 1.0;
if(opts->use_angular_acc && opts->use_weighted_bkg){
//for fixed effq2 the efficiency should have been calculated beforehand
//for floating q2 should recalculate as done below
//for event_norm, the efficiency should also have been calculated before
bool q2fixed = (params->eff_q2.get_step_size() == 0.0);
if ((q2fixed || opts->use_event_norm) && (!opts->mcweight)){//use event norm is only used when convoluting the acceptance into the pdf
if (meas.weight > 0.0) eff = 1.0/meas.weight;
}
else eff = this->get_ang_eff(opts,meas,true);
}
if (opts->flat_bkg){ //for a flat background, only - if at all - the angular acceptance correction is needed
result *= eff/fnorm_bkg;
}
else{ //Chebyshev background
//read angular bkg coefficients from parameter object
std::vector<double> ch_ctl = init_ch_ctl(params);
std::vector<double> ch_ctk = init_ch_ctk(params);
std::vector<double> ch_phi = init_ch_phi(params);
//reserve vectors for the (non-)Chebyshev polynomial coefficients
std::vector<double> poly_ctl(ch_ctl.size(), 0.0);
std::vector<double> poly_ctk(ch_ctk.size(), 0.0);
std::vector<double> poly_phi(ch_phi.size(), 0.0);
//these temporary coefficients are defined in the range from -1 to +1
std::vector<double> temp_ctl(ch_ctl.size(), 0.0);
std::vector<double> temp_ctk(ch_ctk.size(), 0.0);
std::vector<double> temp_phi(ch_phi.size(), 0.0);
//transform chebyshev polynomial coefficients to Standard Form polynomials
chebyshev_to_poly(ch_ctl, temp_ctl);
chebyshev_to_poly(ch_ctk, temp_ctk);
chebyshev_to_poly(ch_phi, temp_phi);
//stretch or squeeze the definition of the polynomials in phi
//for (unsigned int i=0; i<poly_ctk.size(); i++) poly_ctk.at(i) = temp_ctk.at(i);
for (unsigned int i=0; i<poly_ctk.size(); i++) poly_ctk.at(i) = temp_ctk.at(i);
for (unsigned int i=0; i<poly_ctl.size(); i++) poly_ctl.at(i) = temp_ctl.at(i);
correct_poly(temp_phi, poly_phi, -TMath::Pi(), +TMath::Pi());
//add up all power terms of the polynomials
double p_costhetal = 0.0;
for (unsigned int i=0; i<ch_ctl.size(); i++) p_costhetal += poly_ctl.at(i)*pow(costhetal,i);
double p_costhetak = 0.0;
for (unsigned int i=0; i<ch_ctk.size(); i++) p_costhetak += poly_ctk.at(i)*pow(costhetak,i);
double p_phi = 0.0;
for (unsigned int i=0; i<ch_phi.size(); i++) p_phi += poly_phi.at(i)*pow(phi,i);
//multiply the indidivual angular dimensions. divide by the normalisation to obtain the angular background probability
result = p_costhetal*p_costhetak*p_phi*eff/fnorm_bkg;
}
return result;
};
double bu2kstarmumu_pdf::integral_bkg(const bu2kstarmumu_parameters* params, double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b) const
{
if (opts->flat_bkg){
return (ctl_b-ctl_a)*(ctk_b-ctk_a)*(phi_b-phi_a); // RANGE_3D() for non-folded
}
else{
std::vector<double> ch_ctl = init_ch_ctl(params);
std::vector<double> ch_ctk = init_ch_ctk(params);
std::vector<double> ch_phi = init_ch_phi(params);
std::vector<double> poly_ctl(ch_ctl.size(), 0.0);
std::vector<double> poly_ctk(ch_ctk.size(), 0.0);
std::vector<double> poly_phi(ch_phi.size(), 0.0);
std::vector<double> temp_ctl(ch_ctl.size(), 0.0);
std::vector<double> temp_ctk(ch_ctk.size(), 0.0);
std::vector<double> temp_phi(ch_phi.size(), 0.0);
chebyshev_to_poly(ch_ctl, temp_ctl);
chebyshev_to_poly(ch_ctk, temp_ctk);
chebyshev_to_poly(ch_phi, temp_phi);
for (unsigned int i=0; i<poly_ctk.size(); i++) poly_ctk.at(i) = temp_ctk.at(i);
for (unsigned int i=0; i<poly_ctl.size(); i++)poly_ctl.at(i) = temp_ctl.at(i);
correct_poly(temp_phi, poly_phi, -TMath::Pi(), +TMath::Pi());
double norm_costhetal = 0.0;
for (unsigned int i=0; i<poly_ctl.size(); i++)norm_costhetal += poly_ctl.at(i)*(pow(ctl_b,i+1)-pow(ctl_a,i+1))/(i+1.0);
double norm_costhetak = 0.0;
for (unsigned int i=0; i<poly_ctk.size(); i++)norm_costhetak += poly_ctk.at(i)*(pow(ctk_b,i+1)-pow(ctk_a,i+1))/(i+1.0);
double norm_phi = 0.0;
for (unsigned int i=0; i<poly_phi.size(); i++)norm_phi += poly_phi.at(i)*(pow(phi_b,i+1)-pow(phi_a,i+1))/(i+1.0);
return norm_costhetal*norm_costhetak*norm_phi;
}
}
double bu2kstarmumu_pdf::integral_bkg_chebyshev(const bu2kstarmumu_parameters* params, double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, double q2) const{
double result = 0.0;
if (opts->flat_bkg){
double c = 1.0;
//new improved non-factorizing acceptance
npolynom npol = npolynom(opts);
assert(coeffs_eff_4d.size() == npol.getSize());
double chijk = 0.0;
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
const unsigned int bin = npol.get_bin_in4D(h,i,j,k);
chijk = c*pow(q2, h)*coeffs_eff_4d.at(bin);
result += chijk
* (pow(ctl_b, i+1)/(i+1.0) - pow(ctl_a, i+1)/(i+1.0))
* (pow(ctk_b, j+1)/(j+1.0) - pow(ctk_a, j+1)/(j+1.0))
* (pow(phi_b, k+1)/(k+1.0) - pow(phi_a, k+1)/(k+1.0));
}
}
}
}
}
else{
//calculate integral of background with efficiency correction
std::vector<double> ch_ctl = init_ch_ctl(params);
std::vector<double> ch_ctk = init_ch_ctk(params);
std::vector<double> ch_phi = init_ch_phi(params);
std::vector<double> poly_ctl(ch_ctl.size(), 0.0);
std::vector<double> poly_ctk(ch_ctk.size(), 0.0);
std::vector<double> poly_phi(ch_phi.size(), 0.0);
std::vector<double> temp_ctl(ch_ctl.size(), 0.0);
std::vector<double> temp_ctk(ch_ctk.size(), 0.0);
std::vector<double> temp_phi(ch_phi.size(), 0.0);
chebyshev_to_poly(ch_ctl, temp_ctl);
chebyshev_to_poly(ch_ctk, temp_ctk);
chebyshev_to_poly(ch_phi, temp_phi);
for (unsigned int i=0; i<poly_ctk.size(); i++) poly_ctk.at(i) = temp_ctk.at(i);
for (unsigned int i=0; i<poly_ctl.size(); i++) poly_ctl.at(i) = temp_ctl.at(i);
correct_poly(temp_phi, poly_phi, -TMath::Pi(), +TMath::Pi());
double c = 1.0;
//new improved non-factorizing acceptance
//double q2 = params->eff_q2();
npolynom npol(opts);
assert(coeffs_eff_4d.size() == npol.getSize());
double chijk = 0.0;
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
const unsigned int bin = npol.get_bin_in4D(h,i,j,k);
chijk = c*pow(q2, h)*coeffs_eff_4d.at(bin);
for (unsigned int l=0; l<poly_ctl.size(); l++){
for (unsigned int m=0; m<poly_ctk.size(); m++){
for (unsigned int n=0; n<poly_phi.size(); n++){
result += chijk * poly_ctl.at(l) * poly_ctk.at(m) * poly_phi.at(n)
* (pow(ctl_b, i+l+1) - pow(ctl_a, i+l+1)) / (i+l+1.0)
* (pow(ctk_b, j+m+1) - pow(ctk_a, j+m+1)) / (j+m+1.0)
* (pow(phi_b, k+n+1) - pow(phi_a, k+n+1)) / (k+n+1.0);
}
}
}
}
}
}
}
}
return result;
}
double bu2kstarmumu_pdf::angular_bkg_norm(const bu2kstarmumu_parameters* params, bool weighted){
npolynom npol(opts);
assert(coeffs_eff_4d.size() == npol.getSize());
//bkg norm
if(weighted){ //weighted background pdf
double q2 = params->eff_q2();
if (opts->full_angular){
if (opts->flat_bkg){
double integral = 0.0;
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
integral += pow(q2, h)*coeffs_eff_4d.at(npol.get_bin_in4D(h,i,j,k))
* integrate_x_to_n(CTL_MIN,CTL_MAX,i)
* integrate_x_to_n(CTK_MIN,CTK_MAX,j)
* integrate_x_to_n(PHI_MIN,PHI_MAX,k);
}
}
}
}
return integral;
}
else{
return integral_bkg_chebyshev(params, CTL_MIN, CTL_MAX, CTK_MIN, CTK_MAX, PHI_MIN, PHI_MAX, q2);
}
}
else{ //folded angles
if (opts->flat_bkg){
double integral = 0.0;
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
integral += pow(q2, h)*coeffs_eff_4d.at(npol.get_bin_in4D(h,i,j,k))
* integrate_x_to_n(opts->ctl_min,opts->ctl_max,i)
* integrate_x_to_n(opts->ctk_min,opts->ctk_max,j)
* integrate_x_to_n(opts->phi_min,opts->phi_max,k);
}
}
}
}
return integral;
}
else{
if(opts->fit_full_angular_bkg){
return integral_bkg_chebyshev(params, CTL_MIN, CTL_MAX, opts->ctk_min, opts->ctk_max, PHI_MIN, PHI_MAX, q2); //TODO: check if that makes sense (https://gitlab.cern.ch/LHCb-RD/ewp-Bplus2Kstmumu-AngAna/-/merge_requests/21)
}
else{
return integral_bkg_chebyshev(params, opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max, q2);
}
}
}
}
else{ //non weighted background pdf
if (opts->full_angular){
if (opts->flat_bkg) return RANGE_3D();
else return integral_bkg(params, CTL_MIN, CTL_MAX, CTK_MIN, CTK_MAX, PHI_MIN, PHI_MAX);
}
else{ //folded angles
if (opts->flat_bkg){
return (opts->ctk_max - opts->ctk_min) * (opts->ctl_max - opts->ctl_min) * (opts->phi_max - opts->phi_min);
}
else{
if(opts->fit_full_angular_bkg){
return integral_bkg(params, CTL_MIN, CTL_MAX, CTK_MIN, CTK_MAX, PHI_MIN, PHI_MAX);
}
else{
return integral_bkg(params, opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max);
}
}
}
}
}
double bu2kstarmumu_pdf::angular_sig_norm(const bu2kstarmumu_parameters* params, bool weighted){
double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0,
f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0;
double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0;
const double j1s = params->J1s();
const double j1c = params->J1c();
const double j2s = params->J2s();
const double j2c = params->J2c();
const double j3 = params->J3();
const double j4 = params->J4();
const double j5 = params->J5();
const double j6s = params->J6s();
const double j6c = params->J6c();
const double j7 = params->J7();
const double j8 = params->J8();
const double j9 = params->J9();
const double fs = params->FS();
const double js1 = params->SS1();
const double js2 = params->SS2();
const double js3 = params->SS3();
const double js4 = params->SS4();
const double js5 = params->SS5();
//sig norm
double q2 = params->eff_q2();
if (opts->full_angular){
//get signal pdf
if (weighted) integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, q2);
else integrated_fj_noacc(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12);
//swave
if(opts->swave){
if (weighted) swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2);
else swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6);
}
//if asymmetries are fitted:
if(opts->fit_asymmetries){
if(opts->swave) return (1.0-fs) * (f1*j1s + f2*j1c + f3*j2s + f4*j2c) + (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5);
else return f1*j1s + f2*j1c + f3*j2s + f4*j2c;
}
if (opts->swave){
return (1.0-fs) * (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9)
+ (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5);
}
//signal pdf without swave, without asymmetries and without m(Kpi)
return f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9;
}
else{ //folded angles
if (weighted) folded_integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, q2);
else folded_integrated_fj_noacc(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12);
if(opts->swave){
if (weighted) folded_swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2);
else folded_swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6);
}
if(opts->fit_asymmetries){
if(opts->swave) return (1-fs) * (f1*j1s + f2*j1c + f3*j2s + f4*j2c) + (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5);
else return (f1*j1s + f2*j1c + f3*j2s + f4*j2c);
}
if(opts->swave){
return (1-fs) * (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9)
+ (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5);
}
//signal pdf without swave, without asymmetries and without m(Kpi)
return f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9;
}
}
double bu2kstarmumu_pdf::angular_swave_norm(const bu2kstarmumu_parameters* params, bool weighted){
double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0;
const double fs = params->FS();
//sig norm
double q2 = params->eff_q2();
if (opts->full_angular){
if (weighted) swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2);
else swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6);
}
else{ //folded angles
if (weighted) folded_swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2);
else folded_swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6);
}
return fs1*fs;
}
double bu2kstarmumu_pdf::angular_pwave_norm(const bu2kstarmumu_parameters* params, bool weighted){
double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0,
f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0;
const double j1s = params->J1s();
const double j1c = params->J1c();
const double j2s = params->J2s();
const double j2c = params->J2c();
const double j3 = params->J3();
const double j4 = params->J4();
const double j5 = params->J5();
const double j6s = params->J6s();
const double j6c = params->J6c();
const double j7 = params->J7();
const double j8 = params->J8();
const double j9 = params->J9();
//sig norm
double q2 = params->eff_q2();
if (opts->full_angular){
if (weighted) integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, q2);
else integrated_fj_noacc(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12);
}
else{ //folded angles
if (weighted) folded_integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, q2);
else folded_integrated_fj_noacc(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12);
}
//if asymmetries are fitted:
if(opts->fit_asymmetries)return f1*j1s + f2*j1c + f3*j2s + f4*j2c;
else return f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9;
}
double bu2kstarmumu_pdf::angular_pswave_norm(const bu2kstarmumu_parameters* params, bool weighted){
double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0;
const double js1 = params->SS1();
const double js2 = params->SS2();
const double js3 = params->SS3();
const double js4 = params->SS4();
const double js5 = params->SS5();
//sig norm
double q2 = params->eff_q2();
if (opts->full_angular){
if (weighted) swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2);
else swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6);
}
else{ //folded angles
if (weighted) folded_swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2);
else folded_swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6);
}
return fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5;
}
void bu2kstarmumu_pdf::update_cached_efficiencies(const bu2kstarmumu_parameters* params, std::vector<event>* events)
{
if (opts->update_efficiencies){
spdlog::info("Updating cached efficiencies");
//assert(0);
//three ways this is usefull
//-q2_eff is fixed and you want to avoid recalculating this every time
//-weighted fit to determine the event weight that needs to be used
//-when using per event norm this can also be cached
npolynom npol(opts);
assert(coeffs_eff_4d.size() == npol.getSize());
double q2 = params->eff_q2();
unsigned int N = events->size();
for (unsigned int e=0; e<N; e++){
double eff = 0.0;
event& meas = events->at(e);
if (opts->weighted_fit || (opts->use_angular_acc && opts->use_event_norm)){
q2 = meas.q2;
}
eff = this->get_ang_eff(opts,q2, meas.costhetal_fa, meas.costhetak_fa, meas.phi_fa);
if (eff > EFF_CUTOFF){
if (opts->multiply_eff) meas.weight *= 1.0/eff;
else meas.weight = 1.0/eff;
}
else{
spdlog::warn("Event with too low efficiency: {0:f}", eff);
spdlog::warn("\t q2: {0:f} \tq2_eff {1:f} \tctl: {2:f} \tctk: {3:f} \tphi: {4:f} ",
meas.q2, q2, meas.costhetal_fa, meas.costhetak_fa , meas.phi_fa);
if (opts->multiply_eff) meas.weight *= 1.0;
else meas.weight = 1.0;
}
}
return;
}
else return;
}
////////////////////////
/// Full angular ///
////////////////////////
//--------------------//
// S-wave
//--------------------//
void bu2kstarmumu_pdf::swave_fj(double ctl, double ctk, double phi,
double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const{
f1 = C_SWAVE * sintheta2(ctl);
f2 = C_SWAVE * sintheta2(ctl)*ctk;
f3 = C_SWAVE * sin2theta(ctl)*sintheta_abs(ctk)*cos(phi);
f4 = C_SWAVE * sintheta_abs(ctl)*sintheta_abs(ctk)*cos(phi);
f5 = C_SWAVE * sintheta_abs(ctl)*sintheta_abs(ctk)*sin(phi);
f6 = C_SWAVE * sin2theta(ctl)*sintheta_abs(ctk)*sin(phi);
}
void bu2kstarmumu_pdf::swave_integrated_fj_noacc(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const{
f1 = 1.0;
f2 = 0.0;
f3 = 0.0;
f4 = 0.0;
f5 = 0.0;
f6 = 0.0;
swave_integrated_fj_noacc(opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max,
f1, f2, f3, f4, f5, f6);
}
void bu2kstarmumu_pdf::swave_integrated_fj_noacc(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b,
double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const{
f1 = C_SWAVE * integrate_s_f1(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f2 = C_SWAVE * integrate_s_f2(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f3 = C_SWAVE * integrate_s_f3(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f4 = C_SWAVE * integrate_s_f4(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f5 = C_SWAVE * integrate_s_f5(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f6 = C_SWAVE * integrate_s_f6(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
return;
}
void bu2kstarmumu_pdf::swave_integrated_fj_chebyshev(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b,
double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double q2) const //TODO: modify this according to the normDebug branch
{
f1 = 0.0; f2 = 0.0; f3 = 0.0; f4 = 0.0; f5 = 0.0; f6 = 0.0;
npolynom npol(opts);
assert(coeffs_eff_4d.size() == npol.getSize());
double chijk = 0.0;
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
const unsigned int bin = npol.get_bin_in4D(h,i,j,k);
chijk = C_SWAVE*pow(q2, h)*coeffs_eff_4d.at(bin);
f1 += chijk * integrate_s_f1(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f2 += chijk * integrate_s_f2(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f3 += chijk * integrate_s_f3(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f4 += chijk * integrate_s_f4(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f5 += chijk * integrate_s_f5(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f6 += chijk * integrate_s_f6(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
}
}
}
}
return;
};
void bu2kstarmumu_pdf::swave_integrated_fj_chebyshev(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double q2) const{
f1 = 0.0; f2 = 0.0; f3 = 0.0; f4 = 0.0; f5 = 0.0; f6 = 0.0;
swave_integrated_fj_chebyshev(CTL_MIN, CTL_MAX, CTK_MIN, CTK_MAX, PHI_MIN, PHI_MAX,
f1, f2, f3, f4, f5, f6, q2);
return;
};
//--------------------//
// P-wave
//--------------------//
void bu2kstarmumu_pdf::fj(double ctl, double ctk, double phi,
double& f1, double& f2, double& f3, double& f4, double& f5, double& f6,
double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const{
f1 = C_PWAVE * sintheta2(ctk); //j1s = 3/4*(1-FL)
f2 = C_PWAVE * costheta2(ctk); //j1c = FL
f3 = C_PWAVE * sintheta2(ctk)*cos2theta(ctl); //j2s = 1/4*(1-FL)
f4 = C_PWAVE * costheta2(ctk)*cos2theta(ctl); //j2c = -FL
f5 = C_PWAVE * sintheta2(ctk)*sintheta2(ctl)*cos(2.0*phi); //j3
f6 = C_PWAVE * sin2theta(ctk)*sin2theta(ctl)*cos(phi); //j4
f7 = C_PWAVE * sin2theta(ctk)*sintheta_abs(ctl)*cos(phi); //j5
f8 = C_PWAVE * sintheta2(ctk)*ctl; //j6s
f9 = C_PWAVE * costheta2(ctk)*ctl; //j6c
f10 = C_PWAVE * sin2theta(ctk)*sintheta_abs(ctl)*sin(phi); //j7
f11 = C_PWAVE * sin2theta(ctk)*sin2theta(ctl)*sin(phi); //j8
f12 = C_PWAVE * sintheta2(ctk)*sintheta2(ctl)*sin(2.0*phi); //j9
};
void bu2kstarmumu_pdf::integrated_fj_noacc(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6,
double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const{
//Normalization of the p-wave in principle
f1 = 0.0; f2 = 0.0; f3 = 0.0; f4 = 0.0; f5 = 0.0; f6 = 0.0;
f7 = 0.0; f8 = 0.0; f9 = 0.0; f10 = 0.0; f11 = 0.0; f12 = 0.0;
integrated_fj_noacc(CTL_MIN, CTL_MAX, CTK_MIN, CTK_MAX, PHI_MIN, PHI_MAX,
f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12);
return;
};
void bu2kstarmumu_pdf::integrated_fj_noacc(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b,
double& f1, double& f2, double& f3, double& f4, double& f5, double& f6,
double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const{
f1 = C_PWAVE * integrate_f1(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f2 = C_PWAVE * integrate_f2(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f3 = C_PWAVE * integrate_f3(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f4 = C_PWAVE * integrate_f4(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f5 = C_PWAVE * integrate_f5(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f6 = C_PWAVE * integrate_f6(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f7 = C_PWAVE * integrate_f7(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f8 = C_PWAVE * integrate_f8(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f9 = C_PWAVE * integrate_f9(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f10 = C_PWAVE * integrate_f10(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f11 = C_PWAVE * integrate_f11(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f12 = C_PWAVE * integrate_f12(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
return;
};
void bu2kstarmumu_pdf::integrated_fj_chebyshev(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b,
double& f1, double& f2, double& f3, double& f4, double& f5, double& f6,
double& f7, double& f8, double& f9, double& f10, double& f11, double& f12, double q2) const{
f1 = 0.0;
f2 = 0.0;
f3 = 0.0;
f4 = 0.0;
f5 = 0.0;
f6 = 0.0;
f7 = 0.0;
f8 = 0.0;
f9 = 0.0;
f10 = 0.0;
f11 = 0.0;
f12 = 0.0;
//new improved non-factorizing acceptance
npolynom npol = npolynom(opts);
assert(coeffs_eff_4d.size() == npol.getSize());
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
const unsigned int bin = npol.get_bin_in4D(h,i,j,k);
double chijk = C_PWAVE*coeffs_eff_4d.at(bin)*pow(q2, h); //9/32pi * angCorr(bin) * q2^h (not integrating over q2)
f1 += chijk * integrate_f1(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f2 += chijk * integrate_f2(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f3 += chijk * integrate_f3(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f4 += chijk * integrate_f4(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f5 += chijk * integrate_f5(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f6 += chijk * integrate_f6(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f7 += chijk * integrate_f7(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f8 += chijk * integrate_f8(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f9 += chijk * integrate_f9(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f10 += chijk * integrate_f10(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f11 += chijk * integrate_f11(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f12 += chijk * integrate_f12(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
}
}
}
}
}
void bu2kstarmumu_pdf::integrated_fj_chebyshev(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6,
double& f7, double& f8, double& f9, double& f10, double& f11, double& f12, double q2) const{
f1 = 0.0; f2 = 0.0; f3 = 0.0; f4 = 0.0; f5 = 0.0; f6 = 0.0;
f7 = 0.0; f8 = 0.0; f9 = 0.0; f10 = 0.0; f11 = 0.0; f12 = 0.0;
integrated_fj_chebyshev(CTL_MIN, CTL_MAX, CTK_MIN, CTK_MAX, PHI_MIN, PHI_MAX,
f1, f2, f3, f4, f5, f6,
f7, f8, f9, f10, f11, f12, q2);
return;
};
/////////////////////
///Angular folding///
/////////////////////
//S-wave
void bu2kstarmumu_pdf::folded_swave_fj(double ctl, double ctk, double phi,
double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const
{
double c = C_SWAVE*2.0; // folding in phi
if(opts->folding > 0) c *= 2.0; //folding in cos(thetaL)
f2 = 0.0; f3 = 0.0; f4 = 0.0; f5 = 0.0; f6 = 0.0;
f1 = c * sintheta2(ctl);
if(opts->folding != 4) f2 = c * sintheta2(ctl)*(ctk);
if(opts->folding == 1) f3 = c * sintheta_abs(ctk)*sin2theta(ctl)*cos(phi);
if(opts->folding == 2) f4 = c * sintheta_abs(ctk)*sintheta_abs(ctl)*cos(phi);
if(opts->folding > 2) f5 = c * sintheta_abs(ctk)*sintheta_abs(ctl)*sin(phi);
//f6 always zero no matter what folding
}
void bu2kstarmumu_pdf::folded_swave_integrated_fj_noacc(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const
{
f1 = 1.0;
f2 = 0.0;
f3 = 0.0;
f4 = 0.0;
f5 = 0.0;
f6 = 0.0;
folded_swave_integrated_fj_noacc(opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max,
f1, f2, f3, f4, f5, f6);
}
void bu2kstarmumu_pdf::folded_swave_integrated_fj_noacc(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b,
double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const{
double c = C_SWAVE*2.0; // folding in phi
if(opts->folding > 0) c *= 2.0; //folding in cos(thetaL)
f2 = 0.0; f3 = 0.0; f4 = 0.0; f5 = 0.0;
f1 = c * integrate_s_f1(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
if(opts->folding != 4) f2 = c * integrate_s_f2(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
if(opts->folding == 1) f3 = c * integrate_s_f3(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
if(opts->folding == 2) f4 = c * integrate_s_f4(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
if(opts->folding > 2) f5 = c * integrate_s_f5(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f6 = 0.0;
return;
}
void bu2kstarmumu_pdf::folded_swave_integrated_fj_chebyshev(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b,
double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double q2) const{
double c = C_SWAVE*2.0; // folding in phi
if(opts->folding > 0) c *= 2.0; //folding in cos(thetaL)
f1 = 0.0; f2 = 0.0; f3 = 0.0; f4 = 0.0; f5 = 0.0; f6 = 0.0;
npolynom npol = npolynom(opts);
assert(coeffs_eff_4d.size() == npol.getSize());
double chijk = 0.0;
for (unsigned int h = 0; h<npol.q2; h++){
for (unsigned int i = 0; i<npol.ctl; i++){
for (unsigned int j = 0; j<npol.ctk; j++){
for (unsigned int k = 0; k<npol.phi; k++){
const unsigned int bin = npol.get_bin_in4D(h,i,j,k);
chijk = c*pow(q2, h)*coeffs_eff_4d.at(bin);
f1 += chijk * integrate_s_f1(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
if(opts->folding != 4) f2 += chijk * integrate_s_f2(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
if(opts->folding == 1) f3 += chijk * integrate_s_f3(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
if(opts->folding == 2) f4 += chijk * integrate_s_f4(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
if(opts->folding > 2) f5 += chijk * integrate_s_f5(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f6 = 0.0;
}
}
}
}
}
void bu2kstarmumu_pdf::folded_swave_integrated_fj_chebyshev(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double q2) const{
folded_swave_integrated_fj_chebyshev(opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max,
f1, f2, f3, f4, f5, f6, q2);
return;
}
//P-wave
void bu2kstarmumu_pdf::folded_fj(double ctl, double ctk, double phi, double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const
{
//reset all coefficients that might not be calculated due to folding!
f6 = 0.;
f7 = 0.;
f8 = 0.;
f9 = 0.;
f10 = 0.;
f11 = 0.;
f12 = 0.;
//constant coefficient
double c = 2.0*C_PWAVE; //multiply by 2 due to folding in phi
if(opts->folding > 0) c *= 2.0; //folding in cos(thetaL)
f1 = c * sintheta2(ctk); //j1s = 3/4*(1-FL)
f2 = c * costheta2(ctk); //j1c = FL
f3 = c * sintheta2(ctk)*cos2theta(ctl); //j2s = 1/4*(1-FL)
f4 = c * costheta2(ctk)*cos2theta(ctl); //j2c = -FL
f5 = c * sintheta2(ctk)*sintheta2(ctl)*cos(2.0*phi); //j3
if(opts->folding == 1) f6 = c * sin2theta(ctk)*sin2theta(ctl)*cos(phi); //j4
if(opts->folding == 2) f7 = c * sin2theta(ctk)*sintheta_abs(ctl)*cos(phi); //j5
if(opts->folding == 0){
f8 = c * sintheta2(ctk)*ctl; //j6s
f9 = c * costheta2(ctk)*ctl; //j6c
}
if(opts->folding == 3) f10 = c * sin2theta(ctk)*sintheta_abs(ctl)*sin(phi); //j7
if(opts->folding == 4) f11 = c * sin2theta(ctk)*sin2theta(ctl)*sin(phi); //j8
if(opts->folding == 0) f12 = c * sintheta2(ctk)*sintheta2(ctl)*sin(2.0*phi); //j9
};
void bu2kstarmumu_pdf::folded_integrated_fj_noacc(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const
{
folded_integrated_fj_noacc(opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max,
f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12);
};
void bu2kstarmumu_pdf::folded_integrated_fj_noacc(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b,
double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const
{
if(opts->full_angular){
spdlog::error("Cannot use folded integrals for full angular fit");
assert(0);
}
f1 = 0.0;
f2 = 0.0;
f3 = 0.0;
f4 = 0.0;
f5 = 0.0;
f6 = 0.0;
f7 = 0.0;
f8 = 0.0;
f9 = 0.0;
f10 = 0.0;
f11 = 0.0;
f12 = 0.0;
//copied from full angular integral:
double c = C_PWAVE*2.; //folding in phi
if(opts->folding > 0)c *= 2.; //folding in cos(theta_L)
f1 = c * integrate_f1(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f2 = c * integrate_f2(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f3 = c * integrate_f3(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f4 = c * integrate_f4(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f5 = c * integrate_f5(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
if(opts->folding == 0){
f8 = c * integrate_f8(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f9 = c * integrate_f9(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
f12 = c * integrate_f12(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
}
else if(opts->folding == 1) f6 = c * integrate_f6(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
else if(opts->folding == 2) f7 = c * integrate_f7(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
else if(opts->folding == 3) f10 = c * integrate_f10(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
else if(opts->folding == 4) f11 = c * integrate_f11(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0);
return;
};
void bu2kstarmumu_pdf::folded_integrated_fj_chebyshev(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b,
double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12, double q2) const{
if(opts->full_angular){
spdlog::error("Cannot use folded integrals for full angular fit");
assert(0);
}
double c = C_PWAVE* 2.; //folding in phi
if(opts->folding > 0)c *= 2.; //folding in cos(theta_L)
f1 = 0.0;
f2 = 0.0;
f3 = 0.0;
f4 = 0.0;
f5 = 0.0;
f6 = 0.0;
f7 = 0.0;
f8 = 0.0;
f9 = 0.0;
f10 = 0.0;
f11 = 0.0;
f12 = 0.0;
//new improved non-factorizing acceptance
npolynom npol = npolynom(opts);
assert(coeffs_eff_4d.size() == npol.getSize());
double chijk = 0.0;
for (unsigned int h = 0; h<npol.q2; h++)
for (unsigned int i = 0; i<npol.ctl; i++)
for (unsigned int j = 0; j<npol.ctk; j++)
for (unsigned int k = 0; k<npol.phi; k++)
{
const unsigned int bin = npol.get_bin_in4D(h,i,j,k);
chijk = c*pow(q2, h)*coeffs_eff_4d.at(bin);
f1 += chijk*integrate_f1(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f2 += chijk*integrate_f2(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f3 += chijk*integrate_f3(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f4 += chijk*integrate_f4(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f5 += chijk*integrate_f5(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
if(opts->folding == 0){
f8 += chijk*integrate_f8(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f9 += chijk*integrate_f9(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
f12 += chijk*integrate_f12(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
}
else if(opts->folding == 1) f6 += chijk*integrate_f6(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
else if(opts->folding == 2) f7 += chijk*integrate_f7(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
else if(opts->folding == 3) f10 += chijk*integrate_f10(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
else if(opts->folding == 4) f11 += chijk*integrate_f11(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k);
}
};
void bu2kstarmumu_pdf::folded_integrated_fj_chebyshev(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12, double q2) const{
folded_integrated_fj_chebyshev(opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max,
f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, q2);
return;
};
void bu2kstarmumu_pdf::calculate_sweights(const bu2kstarmumu_parameters* parms, std::vector<event>* ev) const
{
assert(opts->extended_ml);
parameter* psig = parms->get_parameter("n_sig");
parameter* pbkg = parms->get_parameter("n_bkg");
if (psig != 0 && pbkg != 0){
double nsig = psig->get_value();
double nbkg = pbkg->get_value();
double sweight = 0.0, prob_sig_m = 0.0, prob_bkg_m = 0.0;
//obtain inverse variant matrix (V_{nj}^{-1})
double inv_cov_matrix[2*2] = {0.0, 0.0, 0.0, 0.0};
for (unsigned int i = 0; i<ev->size(); i++){
const event& meas = ev->at(i);
prob_sig_m = m_sig_prob(parms, meas);
prob_bkg_m = m_bkg_prob(parms, meas);
inv_cov_matrix[0] += prob_sig_m*prob_sig_m/sqr(nsig*prob_sig_m + nbkg*prob_bkg_m);
inv_cov_matrix[1] += prob_sig_m*prob_bkg_m/sqr(nsig*prob_sig_m + nbkg*prob_bkg_m);
inv_cov_matrix[2] += prob_bkg_m*prob_sig_m/sqr(nsig*prob_sig_m + nbkg*prob_bkg_m);
inv_cov_matrix[3] += prob_bkg_m*prob_bkg_m/sqr(nsig*prob_sig_m + nbkg*prob_bkg_m);
}
spdlog::info("Inverse covariance matrix");
spdlog::info("{0:0.8f} {1:.8f}", inv_cov_matrix[0],inv_cov_matrix[1] );
spdlog::info("{0:0.8f} {1:.8f}", inv_cov_matrix[2],inv_cov_matrix[3] );
//invert inserve matrix to get V_{nj}
double cov_matrix[2*2] = {0.0, 0.0, 0.0, 0.0};
cov_matrix[0] = +inv_cov_matrix[3]/(inv_cov_matrix[0]*inv_cov_matrix[3]-inv_cov_matrix[1]*inv_cov_matrix[2]);
cov_matrix[1] = -inv_cov_matrix[1]/(inv_cov_matrix[0]*inv_cov_matrix[3]-inv_cov_matrix[1]*inv_cov_matrix[2]);
cov_matrix[2] = -inv_cov_matrix[2]/(inv_cov_matrix[0]*inv_cov_matrix[3]-inv_cov_matrix[1]*inv_cov_matrix[2]);
cov_matrix[3] = +inv_cov_matrix[0]/(inv_cov_matrix[0]*inv_cov_matrix[3]-inv_cov_matrix[1]*inv_cov_matrix[2]);
spdlog::info("Covariance matrix");
spdlog::info("{0:0.8f} {1:.8f}", cov_matrix[0], cov_matrix[1] );
spdlog::info("{0:0.8f} {1:.8f}", cov_matrix[2], cov_matrix[3] );
//get sWeights for all events
for (unsigned int i = 0; i<ev->size(); i++){
const event& meas = ev->at(i);
prob_sig_m = m_sig_prob(parms, meas);
prob_bkg_m = m_bkg_prob(parms, meas);
sweight = (prob_sig_m * cov_matrix[0] + prob_bkg_m * cov_matrix[1]) / ( prob_sig_m * nsig + prob_bkg_m * nbkg );
ev->at(i).sweight = sweight;
}
}
};
void bu2kstarmumu_pdf::save_coeffs_eff_phsp_4d(){
std::ofstream ostr(coeffs_eff_phsp_4D(opts));
for(unsigned int c = 0; c < this->coeffs_eff_4d.size(); c++){
ostr << std::setprecision(15) << std::scientific << this->coeffs_eff_4d.at(c) << "\n";
}
spdlog::info("[SAVE]\t\tSaved a total of {0:d} angular acceptance correction coefficients",this->coeffs_eff_4d.size());
}
std::vector<double> bu2kstarmumu_pdf::read_coeffs_eff_phsp_4d(){
unsigned int nCoeffs = opts->eff_order_q2 * opts->eff_order_costhetal * opts->eff_order_costhetak * opts->eff_order_phi;
std::string filename = coeffs_eff_phsp_4D(opts);
std::ifstream file(filename);
if(!file.is_open())spdlog::error("File " + filename + " not found to load coefficients!");
else spdlog::info("Loading a total of {0:d} coefficients from file " + filename + ".",nCoeffs);
std::string line;
double coeff;
std::vector<double>coeffs;
assert(file.is_open());
while(1){
getline(file, line);
if(file.eof())break;
std::istringstream istr(line);
istr >> coeff;
coeffs.push_back(coeff);
}
if(coeffs.size() != nCoeffs){
spdlog::critical("Number of coefficients loaded from file ({0:d}) does not match the number of configurated coefficients ({1:d}). Abort", coeffs.size(), nCoeffs);
assert(0);
}
return coeffs;
}
void bu2kstarmumu_pdf::load_coeffs_eff_phsp_4d(){
this->coeffs_eff_4d = read_coeffs_eff_phsp_4d();
}