def test_np(self): # Bd CVSM = flavio.physics.mesonmixing.wilsoncoefficient.cvll_d(par, 'B0', scale=80)[0] w = Wilson({'CVRR_bdbd': CVSM}, 80, 'WET', 'flavio') self.assertAlmostEqual( flavio.np_prediction('DeltaM_d', w) / flavio.sm_prediction('DeltaM_d'), 2, delta=0.15) # difference due to NNLO evolution of SM contribution # Bs CVSM = flavio.physics.mesonmixing.wilsoncoefficient.cvll_d(par, 'Bs', scale=80)[0] w = Wilson({'CVRR_bsbs': CVSM}, 80, 'WET', 'flavio') self.assertAlmostEqual( flavio.np_prediction('DeltaM_s', w) / flavio.sm_prediction('DeltaM_s'), 2, delta=0.15) # difference due to NNLO evolution of SM contribution # K0 CVSM = flavio.physics.mesonmixing.wilsoncoefficient.cvll_d(par, 'K0', scale=80)[0] w = Wilson({'CVRR_sdsd': CVSM}, 80, 'WET', 'flavio') self.assertAlmostEqual( flavio.np_prediction('eps_K', w) / flavio.sm_prediction('eps_K'), 2, delta=0.15 ) # difference due to NNLO evolution of SM contribution + charm contribution
def test_obs_np_ff(self): w = wilson.Wilson({'ephi_33': 1e-8}, 125, 'SMEFT', 'Warsaw') mu_tau = flavio.np_prediction('mu_gg(h->tautau)', w) mu_mu = flavio.np_prediction('mu_gg(h->mumu)', w) # mu_mu is not exactly =1 since it modifies the Higgs total width self.assertAlmostEqual(mu_mu, 1, delta=0.02) self.assertNotAlmostEqual(mu_tau, 1, delta=0.02)
def chi2(wc=None): chi = 0 chiM = 0 chiACP = 0 for i in range(0, nobs): if isinstance(obslist[i]['obs'], tuple): if wc is None: th = flavio.sm_prediction(obslist[i]['obs'][0], q2min=obslist[i]['obs'][1], q2max=obslist[i]['obs'][2]) else: th = flavio.np_prediction(obslist[i]['obs'][0], wc_obj=wc, q2min=obslist[i]['obs'][1], q2max=obslist[i]['obs'][2]) else: if wc is None: th = flavio.sm_prediction(obslist[i]['obs']) else: th = flavio.np_prediction(obslist[i]['obs'], wc_obj=wc) chiterm = (th - obslist[i]['central'])**2 / obslist[i]['error']**2 chi += chiterm if obslist[i]['obs'] == 'DMs': chiM += chiterm if obslist[i]['obs'] == 'S_psiphi': chiACP += chiterm return (chi - chiM - chiACP, chiM, chiACP, chi)
def _setInitVal(dictParams, pred, lepton, _q2min, _q2max): channel = "B0->K*ee" if (lepton): channel = "B0->K*mumu" for key, par in dictParams.items(): if (pred == 'NP'): wc = flavio.WilsonCoefficients() if (key == 'AT2'): par.set_value( flavio.np_prediction('<P1>(' + channel + ')', wc, q2min=float(_q2min), q2max=float(_q2max))) else: par.set_value( flavio.np_prediction('<' + key + '>(' + channel + ')', wc, q2min=float(_q2min), q2max=float(_q2max))) else: if (key == 'AT2'): par.set_value( flavio.sm_prediction('<P1>(' + channel + ')', q2min=float(_q2min), q2max=float(_q2max))) else: par.set_value( flavio.sm_prediction('<' + key + '>(' + channel + ')', q2min=float(_q2min), q2max=float(_q2max)))
def test_taulnunu_np2(self): w = Wilson({ 'CVLL_numunuetaue': 2e-2, 'CVLL_numunuetaumu': 1e-2 }, 80, 'WET', 'flavio') BR1 = flavio.np_prediction('BR(tau->enunu)', w) BR2 = flavio.np_prediction('BR(tau->mununu)', w) self.assertAlmostEqual(BR1 / BR2, 4, delta=0.2)
def test_taulnunu_np3(self): CLSM = -4 * par['GF'] / sqrt(2) w = Wilson({'CVLL_numunueemu': CLSM}, 80, 'WET', 'flavio') BRSM = flavio.sm_prediction('BR(tau->enunu)') BRNP = flavio.np_prediction('BR(tau->enunu)', w) self.assertEqual(BRNP / BRSM, 0.25) w = Wilson({'CVLL_numunueemu': -0.5 * CLSM}, 80, 'WET', 'flavio') BRSM = flavio.sm_prediction('BR(tau->enunu)') BRNP = flavio.np_prediction('BR(tau->enunu)', w) self.assertEqual(BRNP / BRSM, 4)
def values(l, M, wc, ps=True): "Values of the observables in a NP scenario. Now in Markdown style" wcObj = Wilson(wc(l, M), scale=M, eft='WET', basis='flavio') print('|C9_bsmumu\t|' + str(wc(l, M)['C9_bsmumu']) + '|') print('|CVLL_bsbs\t|' + str(wc(l, M)['CVLL_bsbs']) + '|') for o in range(0, len(observables)): if o == len(observables) - 2 and ps: print('|' + observables[o][0] + '\t|' + str(roundC(flavio.np_prediction(observables[o][0], wcObj, *observables[o][1:])/flavio.sm_prediction('DeltaM_s')*20.01 ) ) + '|') else: print('|' + observables[o][0] + '\t|' + str(roundC(flavio.np_prediction(observables[o][0], wcObj, *observables[o][1:])) ) + '|')
def test_np(self): wc = flavio.WilsonCoefficients() for l in ['e', 'mu', 'tau']: wc.set_initial({'CSL_bc' + l + 'nu' + l: 1}, 4.8) self.assertTrue(par['tau_Bc_SM'] / flavio.np_prediction('tau_Bc', wc) > 1.1) self.assertAlmostEqual(par['tau_Bc_SM'] / flavio.np_prediction('tau_Bc', wc), 1 + flavio.np_prediction('BR(Bc->' + l + 'nu)', wc) - flavio.sm_prediction('BR(Bc->' + l + 'nu)'), delta=0.05, msg="Failed for {}".format(l))
def predmodel(wc, l0, M): chi = lambda lr, li: chi2( Wilson(wc(lr + li * 1j, M * 1000), scale=M * 1000, eft='WET', basis='flavio'))[-1] m = Minuit(chi, lr=l0[0], li=l0[1], error_lr=0.001, error_li=0.001, errordef=1, print_level=0) m.migrad() cont = [(l0[0] + m.errors[0], l0[1]), (l0[0] - m.errors[0], l0[1]), (l0[0], l0[1] + m.errors[1]), (l0[0], l0[1] - m.errors[1])] #obs0 = [('<Rmue>(B+->Kll)', 1.0, 6.0), ('<Rmue>(B0->K*ll)', 0.045, 1.1), ('<Rmue>(B0->K*ll)', 1.1, 6.0), ('DMs',), ('S_psiphi',)] obs0 = [('S_psiphi', )] for ob in obs0: lim = [] if isinstance(ob, tuple): centr = flavio.np_prediction( ob[0], Wilson(wc(l0[0] + l0[1] * 1j, M * 1000), scale=M * 1000, eft='WET', basis='flavio'), *ob[1:]) for p in cont: lim.append( flavio.np_prediction( ob[0], Wilson(wc(p[0] + p[1] * 1j, M * 1000), scale=M * 1000, eft='WET', basis='flavio'), *ob[1:])) else: centr = flavio.np_prediction( ob, Wilson(wc(l0[0] + l0[1] * 1j, M * 1000), scale=M * 1000, eft='WET', basis='flavio')) for p in cont: lim.append( flavio.np_prediction( ob, Wilson(wc(p[0] + p[1] * 1j, M * 1000), scale=M * 1000, eft='WET', basis='flavio'))) errorsup = max(lim) - centr errorinf = centr - min(lim) print(ob, ':\t', centr, ' + ', errorsup, ' - ', errorinf)
def test_ee_ww_GF(self): """Check that the NP contribution from phil3_22 and ll_1221 differs by a factor -2, since they only enter through the modified Fermi constant.""" np1 = wilson.Wilson({'phil3_22': 1e-6}, 91.1876, 'SMEFT', 'Warsaw') np2 = wilson.Wilson({'ll_1221': 1e-6}, 91.1876, 'SMEFT', 'Warsaw') for E in Es: R1 = np_prediction('R(ee->WW)', E=E, wc_obj=np1) R2 = np_prediction('R(ee->WW)', E=E, wc_obj=np2) self.assertAlmostEqual((R1 - 1) / (R2 - 1), -2, delta=0.2, msg="Failed for {}".format(E))
def test_bsll_lfv(self): # test for errors self.assertEqual(flavio.sm_prediction('BR(B0->emu)'), 0) self.assertEqual(flavio.sm_prediction('BR(Bs->taumu)'), 0) self.assertEqual(flavio.sm_prediction('BR(B0->emu,mue)'), 0) self.assertEqual(flavio.sm_prediction('BR(Bs->mutau,taumu)'), 0) wc = flavio.WilsonCoefficients() wc.set_initial({'C10_bdemu': 1, 'C10_bdmue': 2}, scale=4.8) self.assertAlmostEqual(flavio.np_prediction('BR(B0->mue)', wc) /flavio.np_prediction('BR(B0->emu)', wc), 4) self.assertAlmostEqual(flavio.np_prediction('BR(B0->emu,mue)', wc) /flavio.np_prediction('BR(B0->emu)', wc), 5)
def test_bsll_lfv(self): # test for errors self.assertEqual(flavio.sm_prediction('BR(B0->emu)'), 0) self.assertEqual(flavio.sm_prediction('BR(Bs->taumu)'), 0) self.assertEqual(flavio.sm_prediction('BR(B0->emu,mue)'), 0) self.assertEqual(flavio.sm_prediction('BR(Bs->mutau,taumu)'), 0) wc = flavio.WilsonCoefficients() wc.set_initial({'C10_bdemu': 1, 'C10_bdmue': 2}, scale=4.8) self.assertEqual(flavio.np_prediction('BR(B0->mue)', wc) /flavio.np_prediction('BR(B0->emu)', wc), 4) self.assertEqual(flavio.np_prediction('BR(B0->emu,mue)', wc) /flavio.np_prediction('BR(B0->emu)', wc), 5)
def test_trident_np_2(self): # mimic the SM but with taus or electrons to increase the rate 2x w = Wilson({ 'll_1222': pre * (1 - 1 / 2 + s2w), 'le_1222': pre * s2w }, 91.1876, 'SMEFT', 'Warsaw') self.assertAlmostEqual(flavio.np_prediction('R_trident', w), 2, delta=0.015) w = Wilson({ 'll_2223': pre * (1 - 1 / 2 + s2w), 'le_2322': pre * s2w }, 91.1876, 'SMEFT', 'Warsaw') self.assertAlmostEqual(flavio.np_prediction('R_trident', w), 2, delta=0.015)
def q2_plot_th_bin(obs_name, bin_list, wc=None, divide_binwidth=False, N=50, **kwargs): r"""Plot the binned theory prediction with uncertainties of a $q^2$-dependent observable as a function of $q^2$ (in the form of coloured boxes).""" obs = flavio.classes.Observable.get_instance(obs_name) if obs.arguments != ['q2min', 'q2max']: raise ValueError(r"Only observables that depend on q2min and q2max (and nothing else) are allowed") if wc is None: wc = flavio.WilsonCoefficients() # SM Wilson coefficients obs_dict = {bin_: flavio.sm_prediction(obs_name, *bin_) for bin_ in bin_list} obs_err_dict = {bin_: flavio.sm_uncertainty(obs_name, *bin_, N=N) for bin_ in bin_list} else: wc = flavio.WilsonCoefficients() # SM Wilson coefficients obs_dict = {bin_:flavio.np_prediction(obs_name, wc, *bin_) for bin_ in bin_list} ax = plt.gca() for bin_, central_ in obs_dict.items(): q2min, q2max = bin_ err = obs_err_dict[bin_] if divide_binwidth: err = err/(q2max-q2min) central = central_/(q2max-q2min) else: central = central_ if 'fc' not in kwargs and 'facecolor' not in kwargs: kwargs['fc'] = flavio.plots.colors.pastel[3] if 'linewidth' not in kwargs and 'lw' not in kwargs: kwargs['lw'] = 0 ax.add_patch(patches.Rectangle((q2min, central-err), q2max-q2min, 2*err,**kwargs))
def chicalcRK(l , M, wc): "Chi-squared statistic for the fit to RK(*)-related observables" wcObj = Wilson(wc(l, M), scale=M, eft='WET', basis='flavio') chi2 = 0 for o in range(0, len(observables)-2): chi2 += ((flavio.np_prediction(observables[o][0], wcObj, *observables[o][1:]) - exp[o] ))**2/(uncTot[o]**2 ) return chi2
def q2_plot_th_diff(obs_name, q2min, q2max, wc=None, q2steps=100, **kwargs): r"""Plot the central theory prediction of a $q^2$-dependent observable as a function of $q^2$. Parameters: - `q2min`, `q2max`: minimum and maximum $q^2$ values in GeV^2 - `wc` (optional): `WilsonCoefficient` instance to define beyond-the-SM Wilson coefficients - `q2steps` (optional): number of $q^2$ steps. Defaults to 100. Less is faster but less precise. Additional keyword arguments are passed to the matplotlib plot function, e.g. 'c' for colour. """ obs = flavio.classes.Observable.get_instance(obs_name) if obs.arguments != ['q2']: raise ValueError(r"Only observables that depend on $q^2$ (and nothing else) are allowed") q2_arr = np.arange(q2min, q2max, (q2max-q2min)/(q2steps-1)) if wc is None: wc = flavio.WilsonCoefficients() # SM Wilson coefficients obs_arr = [flavio.sm_prediction(obs_name, q2) for q2 in q2_arr] else: obs_arr = [flavio.np_prediction(obs_name, wc, q2) for q2 in q2_arr] ax = plt.gca() if 'c' not in kwargs and 'color' not in kwargs: kwargs['c'] = 'k' ax.plot(q2_arr, obs_arr, **kwargs)
def chicalcBs(l , M, wc): "Chi-squared statistic for the fit to Bs-mixing-related observables" wcObj = Wilson(wc(l, M), scale=M, eft='WET', basis='flavio') chi2 = 0 for o in (-2,-1): chi2 += ((flavio.np_prediction(observables[o][0], wcObj, *observables[o][1:]) - exp[o] ))**2/(uncTot[o]**2 ) return chi2
def diff_plot_th(obs_name, x_min, x_max, wc=None, steps=100, **kwargs): r"""Plot the central theory prediction of an observable dependending on a continuous parameter, e.g. $q^2$. Parameters: - `x_min`, `x_max`: minimum and maximum values of the parameter - `wc` (optional): `WilsonCoefficient` instance to define beyond-the-SM Wilson coefficients - `steps` (optional): number of steps in x. Defaults to 100. Less is faster but less precise. Additional keyword arguments are passed to the matplotlib plot function, e.g. 'c' for colour. """ obs = flavio.classes.Observable[obs_name] if not obs.arguments or len(obs.arguments) != 1: raise ValueError( r"Only observables that depend on a single parameter are allowed") x_arr = np.arange(x_min, x_max, (x_max - x_min) / (steps - 1)) if wc is None: wc = flavio.physics.eft._wc_sm # SM Wilson coefficients obs_arr = [flavio.sm_prediction(obs_name, x) for x in x_arr] else: obs_arr = [flavio.np_prediction(obs_name, wc, x) for x in x_arr] ax = plt.gca() if 'c' not in kwargs and 'color' not in kwargs: kwargs['c'] = 'k' ax.plot(x_arr, obs_arr, **kwargs)
def diff_plot_th(obs_name, x_min, x_max, wc=None, steps=100, **kwargs): r"""Plot the central theory prediction of an observable dependending on a continuous parameter, e.g. $q^2$. Parameters: - `x_min`, `x_max`: minimum and maximum values of the parameter - `wc` (optional): `WilsonCoefficient` instance to define beyond-the-SM Wilson coefficients - `steps` (optional): number of steps in x. Defaults to 100. Less is faster but less precise. Additional keyword arguments are passed to the matplotlib plot function, e.g. 'c' for colour. """ obs = flavio.classes.Observable[obs_name] if not obs.arguments or len(obs.arguments) != 1: raise ValueError(r"Only observables that depend on a single parameter are allowed") x_arr = np.arange(x_min, x_max, (x_max-x_min)/(steps-1)) if wc is None: wc = flavio.physics.eft._wc_sm # SM Wilson coefficients obs_arr = [flavio.sm_prediction(obs_name, x) for x in x_arr] else: obs_arr = [flavio.np_prediction(obs_name, wc, x) for x in x_arr] ax = plt.gca() if 'c' not in kwargs and 'color' not in kwargs: kwargs['c'] = 'k' ax.plot(x_arr, obs_arr, **kwargs)
def test_trident_zprime(self): # reproduce eq. (11) in arXiv:1406.2332 vp = 1000 CV = -pre * v**2 / vp**2 w = Wilson({'ll_2222': -CV / 2 / 2, 'le_2222': -CV / 2}, 91.1876, 'SMEFT', 'Warsaw') R = (1 + (1 + 4 * s2w + 2 * v**2 / vp**2)**2) / (1 + (1 + 4 * s2w)**2) self.assertAlmostEqual(flavio.np_prediction('R_trident', w), R, delta=0.005)
def q2_plot_th_diff(obs_name, q2min, q2max, wc=None, q2steps=100, **kwargs): r"""Plot the central theory prediction of a $q^2$-dependent observable as a function of $q^2$. Parameters: - `q2min`, `q2max`: minimum and maximum $q^2$ values in GeV^2 - `wc` (optional): `WilsonCoefficient` instance to define beyond-the-SM Wilson coefficients - `q2steps` (optional): number of $q^2$ steps. Defaults to 100. Less is faster but less precise. Additional keyword arguments are passed to the matplotlib plot function, e.g. 'c' for colour. """ obs = flavio.classes.Observable[obs_name] if obs.arguments != ['q2']: raise ValueError(r"Only observables that depend on $q^2$ (and nothing else) are allowed") q2_arr = np.arange(q2min, q2max, (q2max-q2min)/(q2steps-1)) if wc is None: wc = flavio.physics.eft._wc_sm # SM Wilson coefficients obs_arr = [flavio.sm_prediction(obs_name, q2) for q2 in q2_arr] else: obs_arr = [flavio.np_prediction(obs_name, wc, q2) for q2 in q2_arr] ax = plt.gca() if 'c' not in kwargs and 'color' not in kwargs: kwargs['c'] = 'k' ax.plot(q2_arr, obs_arr, **kwargs)
def predictions(filename): f = open(filename, 'at', buffering=1) chiSM = chi2() obscalc = [('<Rmue>(B+->Kll)', 1.0, 6.0), ('<Rmue>(B0->K*ll)', 0.045, 1.1), ('<Rmue>(B0->K*ll)', 1.1, 6.0)] for w in wcs: f.write(w.__name__ + '\n=================\n') chi = lambda cr, ci: chi2(w(cr, ci)) m = Minuit(chi, cr=0, ci=0, error_cr=0.01, error_ci=0.01, errordef=1, print_level=0) m.migrad() f.write('\tBest fit: ' + str(m.values[0]) + ' + ' + str(m.values[1]) + 'i\n') chibf = m.fval f.write('\tPull (sqrt): ' + str(sqrt(chiSM - chibf)) + '\n') f.write('\tPull (sigma): ' + str(pull(chiSM - chibf, 2)) + r' \sigma' + '\n') f.write('\tChi2/dof: ' + str(chibf / (nobs - 2)) + '\n') #m.minos() xr_centr = m.values[0] xi_centr = m.values[1] wcObj = w(xr_centr, xi_centr) cont = m.mncontour('cr', 'ci', numpoints=40)[2] for o in range(0, len(obscalc)): obs_centr = flavio.np_prediction(obscalc[o][0], wcObj, *obscalc[o][1:]) obs_max = obs_min = obs_centr for i in range(0, len(cont)): wcObj = w(*cont[i]) obs_max = max( obs_max, flavio.np_prediction(obscalc[o][0], wcObj, *obscalc[o][1:])) obs_min = min( obs_min, flavio.np_prediction(obscalc[o][0], wcObj, *obscalc[o][1:])) f.write('\t' + str(obscalc[o]) + ': ' + str(obs_centr) + ' + ' + str(obs_max - obs_centr) + ' - ' + str(obs_centr - obs_min) + '\n') f.write('\n\n') f.close()
def chiM(wc, l, M): wcobj = Wilson(wc(l, M * 1000), scale=M * 1000, eft='WET', basis='flavio') chiM = 0 for i in range(0, nobs): if obslist[i]['obs'] in ['DMs', 'S_psiphi']: th = flavio.np_prediction(obslist[i]['obs'], wcobj) chiM += (th - obslist[i]['central'])**2 / obslist[i]['error']**2 return chiM
def test_taulnunu_np4(self): CLSM = -4 * par['GF'] / sqrt(2) w = Wilson({'CVLL_numunueemu': -0.5 * CLSM, 'CVLL_nutaunueetau': CLSM}, 80, 'WET', 'flavio') BR1 = flavio.sm_prediction('BR(tau->enunu)') BR2 = flavio.np_prediction('BR(tau->enunu)', w) self.assertEqual(BR2 / BR1, 9)
def test_taulnunu_np4(self): CLSM = -4 * par['GF'] / sqrt(2) w = Wilson({ 'CVLL_numunueemu': -0.5 * CLSM, 'CVLL_nutaunueetau': CLSM }, 80, 'WET', 'flavio') BR1 = flavio.sm_prediction('BR(tau->enunu)') BR2 = flavio.np_prediction('BR(tau->enunu)', w) self.assertEqual(BR2 / BR1, 9)
def test_amu_NP(self): w = Wilson({'C7_mumu': 1e-3}, 1.0, 'WET-3', 'flavio') e = sqrt(4 * pi * par['alpha_e']) m = par['m_mu'] p = 4 * par['GF'] / sqrt(2) * e / 16 / pi**2 * m pre = p * 4 * m / e a = pre * 1e-3 self.assertAlmostEqual(flavio.np_prediction('a_mu', w) - amu_SM, a, delta=0.01 * abs(a))
def test_trident_np_1(self): # mimic the SM to increase the rate 4x w = Wilson( { 'll_2222': pre * (1 - 1 / 2 + s2w) / 2, 'le_2222': pre * s2w }, 91.1876, 'SMEFT', 'Warsaw') self.assertAlmostEqual(flavio.np_prediction('R_trident', w), 4, delta=0.03)
def chi2_budget(wc=None): chi = [] for i in range(0, nobs): if isinstance(obslist[i]['obs'], tuple): if wc is None: th = flavio.sm_prediction(obslist[i]['obs'][0], q2min=obslist[i]['obs'][1], q2max=obslist[i]['obs'][2]) else: th = flavio.np_prediction(obslist[i]['obs'][0], wc_obj=wc, q2min=obslist[i]['obs'][1], q2max=obslist[i]['obs'][2]) else: if wc is None: th = flavio.sm_prediction(obslist[i]['obs']) else: th = flavio.np_prediction(obslist[i]['obs'], wc_obj=wc) chi.append((th - obslist[i]['central'])**2 / obslist[i]['error']**2) return chi
def test_trident_zprime(self): # reproduce eq. (11) in arXiv:1406.2332 vp = 1000 CV = -pre * v**2 / vp**2 w = Wilson({ 'll_2222': -CV / 2 / 2, 'le_2222': -CV / 2 }, 91.1876, 'SMEFT', 'Warsaw') R = (1 + (1 + 4 * s2w + 2 * v**2 / vp**2)**2) / (1 + (1 + 4 * s2w)**2) self.assertAlmostEqual(flavio.np_prediction('R_trident', w), R, delta=0.005)
def test_diff_ee_ww_NP(self): coeffs = ['phiWB', 'phiD', 'phil3_11', 'phil3_22', 'll_1221', 'phil1_11', 'phie_11'] for coeff in coeffs: for E in [182.66, 189.09, 198.38, 205.92]: _E = Es.flat[np.abs(Es - E).argmin()] dsigma = [] dsigma_sm = [] for i in range(10): args = (E, np.round(i * 0.2 - 1, 1), np.round((i + 1) * 0.2 - 1, 1)) w = wilson.Wilson({coeff: 0.1 / 246.22**2}, 91.1876, 'SMEFT', 'Warsaw') dsigma.append(np_prediction('<dR/dtheta>(ee->WW)', w, *args)) dsigma_sm.append(sm_prediction('<dR/dtheta>(ee->WW)', *args)) r_tot = np_prediction('R(ee->WW)', w, _E) sigma_tot_sm = sum(dsigma_sm) sigma_tot = sum(dsigma) self.assertAlmostEqual(sigma_tot / sigma_tot_sm, r_tot, delta=0.25, msg="Failed for E={}, C_{}".format(E, coeff))
def q2_plot_th_bin(obs_name, bin_list, wc=None, divide_binwidth=False, N=50, **kwargs): r"""Plot the binned theory prediction with uncertainties of a $q^2$-dependent observable as a function of $q^2$ (in the form of coloured boxes). Parameters: - `bin_list`: a list of tuples containing bin boundaries - `wc` (optional): `WilsonCoefficient` instance to define beyond-the-SM Wilson coefficients - `divide_binwidth` (optional): this should be set to True when comparing integrated branching ratios from experiments with different bin widths or to theory predictions for a differential branching ratio. It will divide all values and uncertainties by the bin width (i.e. dimensionless integrated BRs will be converted to integrated differential BRs with dimensions of GeV$^{-2}$). Defaults to False. - `N` (optional): number of random draws to determine the uncertainty. Defaults to 50. Larger is slower but more precise. The relative error of the theory uncertainty scales as $1/\sqrt{2N}$. Additional keyword arguments are passed to the matplotlib add_patch function, e.g. 'fc' for face colour. """ obs = flavio.classes.Observable[obs_name] if obs.arguments != ['q2min', 'q2max']: raise ValueError(r"Only observables that depend on q2min and q2max (and nothing else) are allowed") if wc is None: wc = flavio.physics.eft._wc_sm # SM Wilson coefficients obs_dict = {bin_: flavio.sm_prediction(obs_name, *bin_) for bin_ in bin_list} obs_err_dict = {bin_: flavio.sm_uncertainty(obs_name, *bin_, N=N) for bin_ in bin_list} else: obs_dict = {bin_:flavio.np_prediction(obs_name, wc, *bin_) for bin_ in bin_list} obs_err_dict = {bin_: flavio.np_uncertainty(obs_name, wc, *bin_, N=N) for bin_ in bin_list} ax = plt.gca() for _i, (bin_, central_) in enumerate(obs_dict.items()): q2min, q2max = bin_ err = obs_err_dict[bin_] if divide_binwidth: err = err/(q2max-q2min) central = central_/(q2max-q2min) else: central = central_ if 'fc' not in kwargs and 'facecolor' not in kwargs: kwargs['fc'] = flavio.plots.colors.pastel[3] if 'linewidth' not in kwargs and 'lw' not in kwargs: kwargs['lw'] = 0 if _i > 0: # the label should only be set for one (i.e. the first) # of the boxes, otherwise it will appear multiply in the legend kwargs.pop('label', None) ax.add_patch(patches.Rectangle((q2min, central-err), q2max-q2min, 2*err,**kwargs))
def bin_plot_th(obs_name, bin_list, wc=None, divide_binwidth=False, N=50, threads=1, **kwargs): r"""Plot the binned theory prediction with uncertainties of an observable dependending on a continuous parameter, e.g. $q^2$ (in the form of coloured boxes). Parameters: - `bin_list`: a list of tuples containing bin boundaries - `wc` (optional): `WilsonCoefficient` instance to define beyond-the-SM Wilson coefficients - `divide_binwidth` (optional): this should be set to True when comparing integrated branching ratios from experiments with different bin widths or to theory predictions for a differential branching ratio. It will divide all values and uncertainties by the bin width (i.e. dimensionless integrated BRs will be converted to $q^2$-integrated differential BRs with dimensions of GeV$^{-2}$). Defaults to False. - `N` (optional): number of random draws to determine the uncertainty. Defaults to 50. Larger is slower but more precise. The relative error of the theory uncertainty scales as $1/\sqrt{2N}$. Additional keyword arguments are passed to the matplotlib add_patch function, e.g. 'fc' for face colour. """ obs = flavio.classes.Observable[obs_name] if not obs.arguments or len(obs.arguments) != 2: raise ValueError(r"Only observables that depend on the two bin boundaries (and nothing else) are allowed") if wc is None: wc = flavio.physics.eft._wc_sm # SM Wilson coefficients obs_dict = {bin_: flavio.sm_prediction(obs_name, *bin_) for bin_ in bin_list} obs_err_dict = {bin_: flavio.sm_uncertainty(obs_name, *bin_, N=N, threads=threads) for bin_ in bin_list} else: obs_dict = {bin_:flavio.np_prediction(obs_name, wc, *bin_) for bin_ in bin_list} obs_err_dict = {bin_: flavio.np_uncertainty(obs_name, wc, *bin_, N=N, threads=threads) for bin_ in bin_list} ax = plt.gca() for _i, (bin_, central_) in enumerate(obs_dict.items()): xmin, xmax = bin_ err = obs_err_dict[bin_] if divide_binwidth: err = err/(xmax-xmin) central = central_/(xmax-xmin) else: central = central_ if 'fc' not in kwargs and 'facecolor' not in kwargs: kwargs['fc'] = flavio.plots.colors.pastel[3] if 'linewidth' not in kwargs and 'lw' not in kwargs: kwargs['lw'] = 0 if _i > 0: # the label should only be set for one (i.e. the first) # of the boxes, otherwise it will appear multiply in the legend kwargs.pop('label', None) ax.add_patch(patches.Rectangle((xmin, central-err), xmax-xmin, 2*err,**kwargs))
def test_functions(self): o = Observable('test_obs') o.arguments = ['x'] def f(wc_obj, par_dict, x): return x pr = Prediction('test_obs', f ) wc_obj = None self.assertEqual(flavio.sm_prediction('test_obs', 7), 7) self.assertEqual(flavio.np_prediction('test_obs', x=7, wc_obj=wc_obj), 7) self.assertEqual(flavio.sm_uncertainty('test_obs', 7), 0) self.assertEqual(flavio.np_uncertainty('test_obs', x=7, wc_obj=wc_obj), 0) self.assertEqual(flavio.sm_uncertainty('test_obs', 7, threads=2), 0) self.assertEqual(flavio.np_uncertainty('test_obs', x=7, wc_obj=wc_obj, threads=2), 0) # delete dummy instance Observable.del_instance('test_obs')
def q2_plot_th_diff(obs_name, q2min, q2max, wc=None, q2steps=100, **kwargs): r"""Plot the central theory prediction of a $q^2$-dependent observable as a function of $q^2$.""" obs = flavio.classes.Observable.get_instance(obs_name) if obs.arguments != ['q2']: raise ValueError(r"Only observables that depend on $q^2$ (and nothing else) are allowed") q2_arr = np.arange(q2min, q2max, (q2max-q2min)/(q2steps-1)) if wc is None: wc = flavio.WilsonCoefficients() # SM Wilson coefficients obs_arr = [flavio.sm_prediction(obs_name, q2) for q2 in q2_arr] else: obs_arr = [flavio.np_prediction(obs_name, wc, q2) for q2 in q2_arr] ax = plt.gca() if 'c' not in kwargs and 'color' not in kwargs: kwargs['c'] = 'k' ax.plot(q2_arr, obs_arr, **kwargs)
def BR(c10, c10p, cS, cSp, cP, cPp): list_wc = {'C10_bsmumu' : c10, 'C10p_bsmumu': c10p, 'CS_bsmumu' : cS, 'CSp_bsmumu' : cSp, 'CP_bsmumu' : cP, 'CPp_bsmumu' : cPp, 'C9_bsmumu' : 0., 'C9p_bsmumu' : 0.} wc = flavio.WilsonCoefficients() wc.set_initial(list_wc, scale=160 ) BR_flavio = flavio.np_prediction('BR(Bs->mumu)', wc) BR_Amsterdam = BR_Amsterdam_Bs_mumu(par, list_wc) return {'flavio': BR_flavio, 'Amsterdam': BR_Amsterdam}
def test_tauegamma_implementation(self): input_dict_list=[{ 'Cgamma_taue':np.random.random()*1e-8*exp(1j*2*pi*np.random.random()), 'Cgamma_etau':np.random.random()*1e-8*exp(1j*2*pi*np.random.random()), } for i in range(10)] BRs = np.array([ flavio.np_prediction( 'BR(tau->egamma)', Wilson(input_dict, 100, 'WET', 'flavio') ) for input_dict in input_dict_list ]) compare_BRs = np.array([ compare_BR( Wilson(input_dict, 100, 'WET', 'flavio'), 'tau', 'e', ) for input_dict in input_dict_list ]) self.assertAlmostEqual(np.max(np.abs(1-BRs/compare_BRs)), 0, delta=0.002)
def test_np(self): v = 246.22 from wilson import Wilson w = Wilson({'phil3_11': -0.5 / v**2}, 91.1876, 'SMEFT', 'Warsaw') self.assertAlmostEqual(flavio.np_prediction('BR(W->enu)', w), 10.83e-2 / 2, delta=0.15e-2)
def test_taulnunu_np2(self): w = Wilson({'CVLL_numunuetaue': 2e-2, 'CVLL_numunuetaumu': 1e-2}, 80, 'WET', 'flavio') BR1 = flavio.np_prediction('BR(tau->enunu)', w) BR2 = flavio.np_prediction('BR(tau->mununu)', w) self.assertAlmostEqual(BR1 / BR2, 4, delta=0.2)
def test_trident_np_1(self): # mimic the SM to increase the rate 4x w = Wilson({'ll_2222': pre * (1 - 1 / 2 + s2w) / 2, 'le_2222': pre * s2w}, 91.1876, 'SMEFT', 'Warsaw') self.assertAlmostEqual(flavio.np_prediction('R_trident', w), 4, delta=0.03)
def diff_plot_th_err(obs_name, x_min, x_max, wc=None, steps=100, steps_err=5, N=100, threads=1, label=None, plot_args=None, fill_args=None): r"""Plot the theory prediction of an observable dependending on a continuous parameter, e.g. $q^2$, with uncertainties as a function of this parameter. Parameters: - `x_min`, `x_max`: minimum and maximum values of the parameter - `wc` (optional): `WilsonCoefficient` instance to define beyond-the-SM Wilson coefficients - `steps` (optional): number of steps for the computation of the central value. Defaults to 100. Less is faster but less precise. - `steps_err` (optional): number of steps for the computation of the uncertainty. Defaults to 5 and should be at least 3. Larger is slower but more precise. See caveat below. - `N` (optional): number of random evaluations to determine the uncertainty. Defaults to 100. Less is faster but less precise. - `threads` (optional): if bigger than 1, number of threads to use for parallel computation of uncertainties - `plot_args` (optional): dictionary with keyword arguments to be passed to the matplotlib plot function, e.g. 'c' for colour. - `fill_args` (optional): dictionary with keyword arguments to be passed to the matplotlib fill_between function, e.g. 'facecolor' A word of caution regarding the `steps_err` option. By default, the uncertainty is only computed at 10 steps and is interpolated in between. This can be enough if the uncertainty does not vary strongly with the parameter. However, when the starting point or end point of the plot range is outside the physical phase space, the uncertainty will vanish at that point and the interpolation might be inaccurate. """ obs = flavio.classes.Observable[obs_name] if not obs.arguments or len(obs.arguments) != 1: raise ValueError(r"Only observables that depend on a single parameter are allowed") step = (x_max-x_min)/(steps-1) x_arr = np.arange(x_min, x_max+step, step) step = (x_max-x_min)/(steps_err-1) x_err_arr = np.arange(x_min, x_max+step, step) # fix to avoid bounds_error in interp1d due to lack of numerical precision x_err_arr[-1] = x_arr[-1] if wc is None: wc = flavio.physics.eft._wc_sm # SM Wilson coefficients obs_err_arr = [flavio.sm_uncertainty(obs_name, x, threads=threads) for x in x_err_arr] obs_arr = [flavio.sm_prediction(obs_name, x) for x in x_arr] else: obs_err_arr = [flavio.np_uncertainty(obs_name, wc, x, threads=threads) for x in x_err_arr] obs_arr = [flavio.np_prediction(obs_name, wc, x) for x in x_arr] ax = plt.gca() plot_args = plot_args or {} fill_args = fill_args or {} if label is not None: plot_args['label'] = label if 'alpha' not in fill_args: fill_args['alpha'] = 0.5 ax.plot(x_arr, obs_arr, **plot_args) interp_err = scipy.interpolate.interp1d(x_err_arr, obs_err_arr, kind='quadratic') obs_err_arr_int = interp_err(x_arr) ax.fill_between(x_arr, obs_arr - obs_err_arr_int, obs_arr + obs_err_arr_int, **fill_args)
def test_trident_np_2(self): # mimic the SM but with taus or electrons to increase the rate 2x w = Wilson({'ll_1222': pre * (1 - 1 / 2 + s2w), 'le_1222': pre * s2w}, 91.1876, 'SMEFT', 'Warsaw') self.assertAlmostEqual(flavio.np_prediction('R_trident', w), 2, delta=0.015) w = Wilson({'ll_2223': pre * (1 - 1 / 2 + s2w), 'le_2322': pre * s2w}, 91.1876, 'SMEFT', 'Warsaw') self.assertAlmostEqual(flavio.np_prediction('R_trident', w), 2, delta=0.015)