Top

flavio.physics.bdecays.bxll module

Functions for inclusive $B\to X_q\ell^+\ell^-$ decays.

See arXiv:1503.04849.

r"""Functions for inclusive $B\to X_q\ell^+\ell^-$ decays.

See arXiv:1503.04849."""

import flavio
import numpy as np
from math import pi, log, sqrt
from flavio.math.functions import li2
from flavio.classes import Observable, Prediction
import warnings
from .bxll_qed import wem

def bxll_parameters(par, lep):
    # return lepton and b mass and alpha_s,e at the appropriate scale
    ml = par['m_'+lep]
    scale = flavio.config['renormalization scale']['bxll']
    mb = flavio.physics.running.running.get_mb_pole(par)
    mc = flavio.physics.running.running.get_mc_pole(par)
    alpha = flavio.physics.running.running.get_alpha(par, scale)
    alpha_s = alpha['alpha_s']
    alpha_e = alpha['alpha_e']
    return ml, mb, alpha_s, alpha_e, mc

def bxll_br_prefactor(par, q, lep):
    # prefactor for the branching ratio normalized to B->X_c enu
    ml, mb, alpha_s, alpha_e, mc = bxll_parameters(par, lep)
    bq = 'b' + q
    xi_t = flavio.physics.ckm.xi('t',bq)(par)
    Vcb = flavio.physics.ckm.get_ckm(par)[1,2]
    C = par['C_BXlnu']
    BRSL = par['BR(B->Xcenu)_exp']
    return alpha_e**2/4./pi**2 / mb**2 * BRSL/C * abs(xi_t)**2/abs(Vcb)**2

def inclusive_wc(q2, wc_obj, par, q, lep, mb):
    r"""Returns a dictionary of "inclusive" Wilson coefficients (including
    SM contributions) where universal bremsstrahlung and virtual corrections
    have been absorbed, as well as the dictionary with the Wilson
    coefficients without these corrections."""
    scale = flavio.config['renormalization scale']['bxll']
    alphas = flavio.physics.running.running.get_alpha(par, scale)['alpha_s']
    # the "usual" WCs
    wc = flavio.physics.bdecays.wilsoncoefficients.wctot_dict(wc_obj, 'b' + q + lep + lep, scale, par, nf_out=5)
    xi_u = flavio.physics.ckm.xi('u','b'+q)(par)
    xi_t = flavio.physics.ckm.xi('t','b'+q)(par)
    # virtual corrections
    Yq2 =flavio.physics.bdecays. matrixelements.Y(q2, wc, par, scale, 'b'+q) + (xi_u/xi_t)*flavio.physics.bdecays.matrixelements.Yu(q2, wc, par, scale, 'b'+q)
    delta_C7 = flavio.physics.bdecays.matrixelements.delta_C7(par=par, wc=wc, q2=q2, scale=scale, qiqj='b'+q)
    delta_C9 = flavio.physics.bdecays.matrixelements.delta_C9(par=par, wc=wc, q2=q2, scale=scale, qiqj='b'+q)
    mb_MSbar = flavio.physics.running.running.get_mb(par, scale)
    ll = lep + lep
    wc_eff = {}
    # add the universal bremsstrahlung corrections to the effective WCs
    brems_7 = 1 + alphas/pi * sigma7(q2/mb**2, scale, mb)
    brems_9 = 1 + alphas/pi * sigma9(q2/mb**2)
    wc_eff['7']  = wc['C7eff_b'+q]  * brems_7      + delta_C7
    wc_eff['7p'] = wc['C7effp_b'+q] * brems_7
    wc_eff['v']  = wc['C9_b'+q+ll]  * brems_9      + delta_C9 + Yq2
    wc_eff['vp'] = wc['C9p_b'+q+ll] * brems_9
    wc_eff['a']  = wc['C10_b'+q+ll] * brems_9
    wc_eff['ap'] = wc['C10p_b'+q+ll]* brems_9
    wc_eff['s']  = mb_MSbar * wc['CS_b'+q+ll]
    wc_eff['sp'] = mb_MSbar * wc['CSp_b'+q+ll]
    wc_eff['p']  = mb_MSbar * wc['CP_b'+q+ll]
    wc_eff['pp'] = mb_MSbar * wc['CPp_b'+q+ll]
    wc_eff['t']  = 0
    wc_eff['tp'] = 0
    return {'wc_eff': wc_eff, 'wc': wc}

def _bxll_dbrdq2_unnorm(q2, wc_obj, par, q, lep, include_qed=True, include_pc=True):
    # unnormalized PhiLL
    # see below: _bxll_dbrdq2
    ml, mb, alpha_s, alpha_e, mc = bxll_parameters(par, lep)
    if q2 < 4*ml**2 or q2 > mb**2:
        return 0
    wc_dict = inclusive_wc(q2, wc_obj, par, q, lep, mb)
    wc_eff = wc_dict['wc_eff']
    wc = wc_dict['wc']
    sh = q2/mb**2
    mlh = ml/mb
    # LO contributions + bremsstrahlung
    Phi_ll  = f_ll(sh, mlh, alpha_s, wc_eff['7'], wc_eff['v'], wc_eff['a'], wc_eff['s'], wc_eff['p'])
    # for ms=0, rate is simply the sum of C_i and C_i' contributions
    Phi_ll += f_ll(sh, mlh, alpha_s, wc_eff['7p'], wc_eff['vp'], wc_eff['ap'], wc_eff['sp'], wc_eff['pp'])
    if include_qed:
        # log-enhanced QED corrections: BR ~ H_L + H_T
        Phi_ll += Phill_logqed('BR', sh, mb, ml, alpha_s, alpha_e, wc, q, lep, mc)
    if include_pc:
        # 1/mb^2 power correction: BR ~ H_L + H_T
        Phi_ll += Phill_pc_mb2('L', sh, par['lambda_1'], par['lambda_2'], mb, wc, q, lep)
        Phi_ll += Phill_pc_mb2('T', sh, par['lambda_1'], par['lambda_2'], mb, wc, q, lep)
    return Phi_ll

def _bxll_dbrdq2(q2, wc_obj, par, q, lep, include_qed=True, include_pc=True):
    # see below: bxll_dbrdq2()
    ml, mb, alpha_s, alpha_e, mc = bxll_parameters(par, lep)
    if q2 < 4*ml**2 or q2 > mb**2:
        return 0
    N = bxll_br_prefactor(par, q, lep)
    Phi_ll  = _bxll_dbrdq2_unnorm(q2, wc_obj, par, q, lep, include_qed=include_qed, include_pc=include_pc)
    # denominator of the normalisation to the B->X_u lnu rate
    Phi_u = f_u(alpha_e, alpha_s, par['alpha_s'], mb, par['lambda_1'], par['lambda_2'])
    # fudge factor to account for remaining uncertainty
    if q2 < 12:
        if lep == 'tau':
            unc = 1 # for the tau, there is now low q^2 anyway
        else:
            unc = 1 + par['delta_BX'+q+lep+lep+' low']
    else:
        unc = 1 + par['delta_BX'+q+lep+lep+' high']
    return N * Phi_ll / Phi_u * unc

def bxll_dbrdq2(q2, wc_obj, par, q, lep):
    r"""Inclusive $B\to  X_q\ell^+\ell^-$ differential branching ratio
    normalized to $B\to X_c\ell\nu$ taken from experiment."""
    if q2 > 8 and q2 < 14:
        warnings.warn("The predictions in the region of narrow charmonium resonances are not meaningful")
    if lep == 'l':
        # average of e and mu!
        return (_bxll_dbrdq2(q2, wc_obj, par, q, 'e') + _bxll_dbrdq2(q2, wc_obj, par, q, 'mu'))/2.
    else:
        return _bxll_dbrdq2(q2, wc_obj, par, q, lep)

def _bxll_afb_num(q2, wc_obj, par, q, lep, include_qed=True, include_pc=True):
    # see below: bxll_afb()
    ml, mb, alpha_s, alpha_e, mc = bxll_parameters(par, lep)
    if q2 < 4*ml**2 or q2 > mb**2:
        return 0
    wc_dict = inclusive_wc(q2, wc_obj, par, q, lep, mb)
    wc_eff = wc_dict['wc_eff']
    wc = wc_dict['wc']
    sh = q2/mb**2
    mlh = ml/mb
    # LO contributions + bremsstrahlung
    Phi_ll  = f_ll_ha(sh, mlh, alpha_s, wc_eff)
    if include_qed and q2 < 14: # log-enhanced QED corrections to AFB only known for low q2!
        # log-enhanced QED corrections: BR ~ H_L + H_T
        Phi_ll += Phill_logqed('A', sh, mb, ml, alpha_s, alpha_e, wc, q, lep, mc)
    if include_pc:
        # 1/mb^2 power correction: BR ~ H_L + H_T
        Phi_ll += Phill_pc_mb2('A', sh, par['lambda_1'], par['lambda_2'], mb, wc, q, lep)
    # fudge factor to account for remaining uncertainty
    if q2 < 12:
        if lep == 'tau':
            unc = 1 # for the tau, there is now low q^2 anyway
        else:
            unc = 1 + par['delta_BX'+q+lep+lep+' low']
    else:
        unc = 1 + par['delta_BX'+q+lep+lep+' high']
    return 3/4. * Phi_ll * unc

def bxll_afb_num(q2, wc_obj, par, q, lep, **kwargs):
    r"""Inclusive $B\to  X_q\ell^+\ell^-$ normalized differential
    forward-backward asymmetry."""
    if q2 > 8 and q2 < 14:
        warnings.warn("The predictions in the region of narrow charmonium resonances are not meaningful")
    if lep == 'l':
        # average of e and mu!
        return (_bxll_afb_num(q2, wc_obj, par, q, 'e', **kwargs) + _bxll_afb_num(q2, wc_obj, par, q, 'mu', **kwargs))/2.
    else:
        return _bxll_afb_num(q2, wc_obj, par, q, lep, **kwargs)

def bxll_afb_den(q2, wc_obj, par, q, lep, **kwargs):
    # auxiliary function needed for q2-integrated AFB defined below
    if q2 > 8 and q2 < 14:
        warnings.warn("The predictions in the region of narrow charmonium resonances are not meaningful")
    if q2 > 14:
        include_qed = False  # log-enhanced QED corrections to AFB only known for low q2!
        kwargs.pop('include_qed', None)
    else:
        if 'include_qed' in kwargs:
            include_qed = kwargs.pop('include_qed')
        else:
            include_qed = True
    if lep == 'l':
        # average of e and mu!
         return (_bxll_dbrdq2_unnorm(q2, wc_obj, par, q, 'e', include_qed=include_qed, **kwargs)
               + _bxll_dbrdq2_unnorm(q2, wc_obj, par, q, 'mu', include_qed=include_qed, **kwargs))/2.
    else:
        return _bxll_dbrdq2_unnorm(q2, wc_obj, par, q, lep, include_qed=include_qed, **kwargs)

def bxll_afb(q2, wc_obj, par, q, lep, **kwargs):
    num = bxll_afb_num(q2, wc_obj, par, q, lep, **kwargs)
    denom = bxll_afb_den(q2, wc_obj, par, q, lep, **kwargs)
    if denom == 0:
        return 0.
    else:
        return num/denom

def f_ll(sh, mlh, alpha_s, C7t, C9t, C10t, CS, CP):
    # The function of Wilson coefficients and kinematical quantities entering
    # the inclusive $B\to Xll$ rate.
    # NB: CS and CP are defined to be dimensionless!
    return (1-sh)**2 * sqrt(1-4*mlh**2/sh) * (
        # SM-like terms for m_l->0: here we add non-univ. bremsstrahlung corrections
        4*abs(C7t)**2*(1+2/sh) * (1+2*mlh**2/sh) * (1 + alpha_s/pi * tau77(sh))
        + 12*(C7t*C9t.conjugate()).real * (1+2*mlh**2/sh) * (1 + alpha_s/pi * tau79(sh))
        + (abs(C9t)**2 + abs(C10t)**2) * (1 + 2*sh + 2*mlh**2*(1-sh)/sh) * (1 + alpha_s/pi * tau99(sh))
        # scalar/pseudoscalar operators
        + 3/2. * sh * ((1-4*mlh**2/sh) * abs(CS)**2 + abs(CP)**2)
        # O(m_l) terms
        + 6*mlh**2 * (abs(C9t)**2 - abs(C10t)**2)
        + 6 * mlh * (CP * C10t.conjugate()).real )

def f_ll_ha(sh, mlh, alpha_s, wc_eff):
    # The function of Wilson coefficients and kinematical quantities entering
    # the inclusive $B\to Xll$ forward-backward asymmetry
    # NB: lepton mass is neglected here
    C7 = wc_eff['7']
    C9 = wc_eff['v']
    C10 = wc_eff['a']
    C7p = wc_eff['7p']
    C9p = wc_eff['vp']
    C10p = wc_eff['ap']
    return -4*(1-sh)**2 * (
        # here we add non-univ. bremsstrahlung corrections
        + sh*(C9*C10.conjugate()).real *  (1 + alpha_s/pi * tau910(sh))
        +  2*(C7*C10.conjugate()).real *  (1 + alpha_s/pi * tau710(sh))
        # primed operators - assume same bremsstrahlung as for unprimed
        - sh*(C9p*C10p.conjugate()).real *(1 + alpha_s/pi * tau910(sh))
        -  2*(C7p*C10p.conjugate()).real *(1 + alpha_s/pi * tau710(sh))
        )

# Functions needed for bremsstrahlung corrections to rate
def sigma9(s):
    return sigma(s) + 3/2
def sigma7(s, scale, mb):
    return sigma(s) + 1/6 - 8/3 * log(scale/mb)
def sigma(s):
    return - 4/3 * li2(s) - 2/3 * log(s) * log(1-s) -2/9 * pi**2 -log(1-s)-2/9 * (1-s) * log(1-s)
def tau77(s):
    return - 2/(9 * (2+s)) * (2 * (1-s)**2 * log(1-s) +(6 * s * (2-2 * s-s**2))/((1-s)**2) * log(s) +(11-7 * s-10 * s**2)/(1-s) )
def tau99(s):
    return -4/(9 * (1+2 * s)) * (2 * (1-s)**2 * log(1-s) +(3 * s * (1+s) * (1-2 * s))/((1-s)**2) * log(s)+(3 * (1-3 * s**2))/(1-s) )
def tau79(s):
    return - (4 * (1-s)**2)/(9 * s) * log(1-s)-(4 * s * (3-2 * s))/(9 * (1-s)**2) * log(s) -(2 * (5-3 * s))/(9 * (1-s))
def tau710(s):
	return -5/2 + 1/(3 * (1-3*s)) - 1/3 * (s * (6-7 * s) * log(s))/((1-s)**2)- 1/9 * ((3-7 * s + 4 * s**2) * log(1-s))/(s) + (f7(s))/3
def tau910(s) :
	return -5/2 + 1/(3 * (1-s)) - 1/3 * (s * (6-7*s) * log(s))/(((1-s)**2)) - 2/9 * ((3-5 * s + 2 * s**2) * log(1-s))/(s) + (f9(s))/3
def f7(s):
	return 1/(6 * (s-1)**2 ) * ( 24 * (1+13*s -4*s**2) * li2( sqrt(s)) + 12 * (1-17*s+6*s**2) * li2(s) +6*s * (6-7*s) * log(s) +24 * (1-s)**2*log(s) * log(1-s) + 12 * (-13+16*s-3*s**2) * (log(1- sqrt(s))-log(1-s)) +39 -2*pi**2 +252*s -26*pi**2*s +21*s**2+8*pi**2*s**2 -180 * sqrt(s) -132*s * sqrt(s) )
def f9(s):
	return -1/(6 * (s-1)**2 ) * ( 48 * s * (-5+ 2*s) * li2( sqrt(s)) + 24 * (-1+7*s-3*s**2) * li2(s) + 6*s * (-6+7*s) * log(s) -24 * (1-s)**2 * log(s) * log(1-s) +24 * (5-7*s+2*s**2) * (log(1- sqrt(s))-log(1-s)) -21-156*s+20*pi**2*s +9*s**2-8*pi**2*s**2+120 * sqrt(s)+48*s * sqrt(s) )

def Phill_pc_mb2(I, sh, l1, l2, mb, wc, q, lep):
    # 1/mb^2 power correction to Phi_ll
    bq = 'b'+q
    bqll = bq + lep + lep
    coeffs = ['C1_'+bq, 'C2_'+bq, 'C3_'+bq, 'C4_'+bq, 'C5_'+bq, 'C6_'+bq, 'C7eff_'+bq, 'C8eff_'+bq, 'C9_'+bqll, 'C10_'+bqll]
    wc1_10 = np.array([0] + [wc[name] for name in coeffs]) # first entry 0 to shift index by 1
    chi1 = np.zeros((11, 11))
    chi2 = np.zeros((11, 11))
    if I == 'T':
        chi1[7, 7] = 4/(3*sh) * (1-sh) * (5 * sh+3)
        chi1[7, 9] = 4 * (1-sh)**2
        chi1[9, 9] = -sh/3 * (1-sh) * (3 * sh+5)
        chi2[7, 7] = 4/sh * (3 * sh**2+2 * sh-9)
        chi2[7, 9] = 4 * (9 * sh**2-6 * sh-7)
        chi2[9, 9] = sh * (15 * sh**2-14 * sh-5)
    elif I == 'L':
        chi1[7, 7] = 2/3 * (sh-1) * (3 * sh+13)
        chi1[7, 9] = 2 * (1-sh)**2
        chi1[9, 9] = 1/6 * (1-sh) * (13 * sh+3)
        chi2[7, 7] = 2 * (15 * sh**2-6 * sh-13)
        chi2[7, 9] = 2 * (3 * sh**2-6 * sh-1)
        chi2[9, 9] = 1/2 * (-17 * sh**2+10 * sh+3)
    elif I == 'A':
        chi1[7, 10] = -4/3 * (3 * sh**2+2 * sh+3)
        chi1[9, 10] = -2/3 * sh * (3 * sh**2+2 * sh+3)
        chi2[7, 10] = -4 * (9 * sh**2-10 * sh-7)
        chi2[9, 10] = -2 * sh * (15 * sh**2-14 * sh-9)
    else:
        raise ValueError("I should be 'T', 'L', or 'A'")
    return ( l1/mb**2 * np.dot(wc1_10, np.dot(chi1, wc1_10.conj()))
           + l2/mb**2 * np.dot(wc1_10, np.dot(chi2, wc1_10.conj())) ).real

def Phill_logqed(I, sh, mb, ml, alpha_s, alpha_e, wc, q, lep, mc):
    # log-enhanced QED corrections to Phi_ll
    bq = 'b'+q
    bqll = bq + lep + lep
    ast = alpha_s/(4*pi)
    k = alpha_e/alpha_s
    coeffs = ['C1_'+bq, 'C2_'+bq, 'C3_'+bq, 'C4_'+bq, 'C5_'+bq, 'C6_'+bq, 'C7eff_'+bq, 'C8eff_'+bq, 'C9_'+bqll, 'C10_'+bqll]
    wc1_10 = np.array([0] + [wc[name] for name in coeffs]) # first entry 0 to shift index by 1
    scale = flavio.config['renormalization scale']['bxll']
    # (4.19) of 1503.04849
    # Note the different powers of ast (\tilde\alpha_s) and k (\kappa) due to
    # the different normalisation of 1) C9 and C10 and 2) the overall
    # normalisation of phi_ll
    flavio.citations.register("Huber:2015sra")
    e = np.zeros((11, 11), dtype=complex) # from 0 to 10
    if I == 'T' or I == 'L' or I == 'BR':
        e[7,7] = 8 * ast    * k    * sigmaij_I(I, 7, 7, sh)*wem(I, 7, 7, sh, mb, ml, scale, mc)
        e[7,9] = 8 * ast    * k    * sigmaij_I(I, 7, 9, sh)*wem(I, 7, 9, sh, mb, ml, scale, mc)
        e[9,9] = 8 * ast    * k    * sigmaij_I(I, 9, 9, sh)*wem(I, 9, 9, sh, mb, ml, scale, mc)
        e[2,9] = 8 * ast    * k    * sigmaij_I(I, 9, 9, sh)*wem(I, 2, 9, sh, mb, ml, scale, mc)
        e[2,2] = 8 * ast    * k    * sigmaij_I(I, 9, 9, sh)*wem(I, 2, 2, sh, mb, ml, scale, mc)
        e[1,1] = 16/9. * e[2,2]
        e[10,10] = e[9,9]
        e[1,2] = 8/3. * e[2,2]
        e[1,7] = 4/3. * e[2,7]
        e[1,9] = 4/3. * e[2,9]
        e[2,7] = 8 * ast    * k    * sigmaij_I(I, 7, 9, sh)*wem(I, 2, 7, sh, mb, ml, scale, mc)
    elif I == 'A':
        e[7,10] = 8 * ast    * k    * sigmaij_I(I, 7, 10, sh)*wem(I, 7, 10, sh, mb, ml, scale, mc)
        e[9,10] = 8 * ast    * k    * sigmaij_I(I, 9, 10, sh)*wem(I, 9, 10, sh, mb, ml, scale, mc)
        e[2,10] = 8 * ast    * k    * sigmaij_I(I, 9, 10, sh)*wem(I, 2, 10, sh, mb, ml, scale, mc)
        e[1,10] = 4/3. *  e[2,10]
    else:
        raise ValueError("I should be 'T', 'L', 'BR', or 'A'")
    return np.dot(wc1_10, np.dot(e, wc1_10.conj())).real

# kinematical prefactors
def sigma77_T(sh):
    return 8*(1-sh)**2/sh
def sigma79_T(sh):
    return 8*(1-sh)**2
def sigma99_T(sh):
    return 2*sh*(1-sh)**2
def sigma77_L(sh):
    return 4*(1-sh)**2
def sigma79_L(sh):
    return 4*(1-sh)**2
def sigma99_L(sh):
    return (1-sh)**2
def sigma710_A(sh):
    return -8*(1-sh)**2
def sigma910_A(sh):
    return -4*sh*(1-sh)**2
def sigmaij_I(I, i, j, sh):
    if I=='T' and i==7 and j==7:
        return sigma77_T(sh)
    elif I=='T' and i==7 and j==9:
        return sigma79_T(sh)
    elif I=='T' and i==9 and j==9:
        return sigma99_T(sh)
    elif I=='L' and i==7 and j==7:
        return sigma77_L(sh)
    elif I=='L' and i==7 and j==9:
        return sigma79_L(sh)
    elif I=='L' and i==9 and j==9:
        return sigma99_L(sh)
    elif I=='BR' and i==7 and j==7:
        return sigma77_L(sh) +  sigma77_T(sh)
    elif I=='BR' and i==7 and j==9:
        return sigma79_L(sh) + sigma79_T(sh)
    elif I=='BR' and i==9 and j==9:
        return sigma99_L(sh) + sigma99_T(sh)
    elif I=='A' and i==7 and j==10:
        return sigma710_A(sh)
    elif I=='A' and i==9 and j==10:
        return sigma910_A(sh)
    else:
        raise ValueError("Function sigmaij_I not defined for I, i, j = " +  str((I,i,j)))

def f_u(alpha_e, alpha_s, alpha_s_mu0, mb, l1, l2):
    # semileptonic phase space factor for B->Xulnu
    # see (4.8) of 1503.04849
    # NB the O(\tilde alpha_s^2) term is omitted on purpose as including it
    # would mean including terms of O(\tilde \alpha_s^4) in the dominant
    # contribution to the branching ratio, as C9 and C10 are formally of
    # O(\tilde \alpha_s \kappa). This is a numerically relevant choice (around
    # 15% change of the low-q^2 BR).
    flavio.citations.register("Huber:2015sra")
    ast = alpha_s/4./pi
    k = alpha_e/alpha_s
    eta = alpha_s_mu0/alpha_s
    scale = flavio.config['renormalization scale']['bxll']
    phi1 = (50/3. - 8*pi**2/3.)
    return ( 1 + ast * phi1 + k*(12/23.*(1-1/eta))
               + l1/(2*mb**2) - 9*l2/(2*mb**2))

# functions for observables

def bxll_br_int(q2min, q2max, wc_obj, par, q, lep):
    def obs(q2):
        return bxll_dbrdq2(q2, wc_obj, par, q, lep)
    return flavio.math.integrate.nintegrate(obs, q2min, q2max)

def bxll_br_int_func(q, lep):
    def fct(wc_obj, par, q2min, q2max):
        return bxll_br_int(q2min, q2max, wc_obj, par, q, lep)
    return fct

def bxll_br_int_ratio_func(q, lnum, lden):
    def fct(wc_obj, par, q2min, q2max):
        num = bxll_br_int(q2min, q2max, wc_obj, par, q, lnum)
        if num == 0:
            return 0
        den = bxll_br_int(q2min, q2max, wc_obj, par, q, lden)
        return num/den
    return fct

def bxll_dbrdq2_func(q, lep):
    def fct(wc_obj, par, q2):
        return bxll_dbrdq2(q2, wc_obj, par, q, lep)
    return fct

def bxll_afb_num_int(q2min, q2max, wc_obj, par, q, lep, **kwargs):
    def obs(q2):
        return bxll_afb_num(q2, wc_obj, par, q, lep, **kwargs)
    return flavio.math.integrate.nintegrate(obs, q2min, q2max)

def bxll_afb_den_int(q2min, q2max, wc_obj, par, q, lep, **kwargs):
    def obs(q2):
        return bxll_afb_den(q2, wc_obj, par, q, lep, **kwargs)
    return flavio.math.integrate.nintegrate(obs, q2min, q2max)


def bxll_afb_int_func(q, lep):
    def fct(wc_obj, par, q2min, q2max):
        num = bxll_afb_num_int(q2min, q2max, wc_obj, par, q, lep)
        if num == 0:
            return 0
        den = bxll_afb_den_int(q2min, q2max, wc_obj, par, q, lep)
        return num/den
    return fct

def bxll_afb_func(q, lep):
    def fct(wc_obj, par, q2):
        return bxll_afb(q2, wc_obj, par, q, lep)
    return fct


# Observable instances

_tex = {'e': 'e', 'mu': '\mu', 'tau': r'\tau', 'l': r'\ell'}
for l in ['e', 'mu', 'tau', 'l']:
    for q in ['s', 'd']:

        _process_tex =  r"B\to X_" + q +_tex[l]+r"^+"+_tex[l]+r"^-"
        _process_taxonomy = r'Process :: $b$ hadron decays :: FCNC decays :: $B\to X\ell^+\ell^-$ :: $' + _process_tex + r"$"

        # binned branching ratio
        _obs_name = "<BR>(B->X"+q+l+l+")"
        _obs = Observable(name=_obs_name, arguments=['q2min', 'q2max'])
        _obs.set_description(r"Binned branching ratio of $" + _process_tex + r"$")
        _obs.tex = r"$\langle \text{BR} \rangle(" + _process_tex + r")$"
        _obs.add_taxonomy(_process_taxonomy)
        Prediction(_obs_name, bxll_br_int_func(q, l))

        # differential branching ratio
        _obs_name = "dBR/dq2(B->X"+q+l+l+")"
        _obs = Observable(name=_obs_name, arguments=['q2'])
        _obs.set_description(r"Differential branching ratio of $" + _process_tex + r"$")
        _obs.tex = r"$\frac{d\text{BR}}{dq^2}(" + _process_tex + r")$"
        _obs.add_taxonomy(_process_taxonomy)
        Prediction(_obs_name, bxll_dbrdq2_func(q, l))

        if l != 'tau': # AFB not yet implemented for tau! (ml=0)

            # binned AFB
            _obs_name = "<AFB>(B->X"+q+l+l+")"
            _obs = Observable(name=_obs_name, arguments=['q2min', 'q2max'])
            _obs.set_description(r"Binned normalized forward-backward asymmetry of $" + _process_tex + r"$")
            _obs.tex = r"$\langle A_\text{FB} \rangle(" + _process_tex + r")$"
            _obs.add_taxonomy(_process_taxonomy)
            Prediction(_obs_name, bxll_afb_int_func(q, l))

            # differential AFB
            _obs_name = "AFB(B->X"+q+l+l+")"
            _obs = Observable(name=_obs_name, arguments=['q2'])
            _obs.set_description(r"Normalized forward-backward asymmetry of $" + _process_tex + r"$")
            _obs.tex = r"$A_\text{FB}(" + _process_tex + r")$"
            _obs.add_taxonomy(_process_taxonomy)
            Prediction(_obs_name, bxll_afb_func(q, l))


for l in [('mu','e'), ('tau','mu'),]:
    for q in ['s', 'd']:
        _process_taxonomy = r'Process :: $b$ hadron decays :: FCNC decays :: $B\to X\ell^+\ell^-$ :: $'

        # binned branching ratio
        _obs_name = "<R"+l[0]+l[1]+">(B->X"+q+"ll)"
        _obs = Observable(name=_obs_name, arguments=['q2min', 'q2max'])
        _obs.set_description(r"Ratio of partial branching ratios of $B\to X_" + q +_tex[l[0]]+r"^+"+_tex[l[0]]+r"^-$" + " and " + r"$B\to X_" + q +_tex[l[1]]+r"^+"+_tex[l[1]]+r"^-$")
        _obs.tex = r"$\langle R_{" + _tex[l[0]] + ' ' + _tex[l[1]] + r"} \rangle(B\to X_" + q + r"\ell^+\ell^-)$"
        for  li in l:
            # add taxonomy for both lepton flavours
            _obs.add_taxonomy(_process_taxonomy + r"B\to X_" + q +_tex[li]+r"^+"+_tex[li]+r"^-$")
        Prediction(_obs_name, bxll_br_int_ratio_func(q, l[0], l[1]))

Module variables

var l

var li

var pi

var q

Functions

def Phill_logqed(

I, sh, mb, ml, alpha_s, alpha_e, wc, q, lep, mc)

def Phill_logqed(I, sh, mb, ml, alpha_s, alpha_e, wc, q, lep, mc):
    # log-enhanced QED corrections to Phi_ll
    bq = 'b'+q
    bqll = bq + lep + lep
    ast = alpha_s/(4*pi)
    k = alpha_e/alpha_s
    coeffs = ['C1_'+bq, 'C2_'+bq, 'C3_'+bq, 'C4_'+bq, 'C5_'+bq, 'C6_'+bq, 'C7eff_'+bq, 'C8eff_'+bq, 'C9_'+bqll, 'C10_'+bqll]
    wc1_10 = np.array([0] + [wc[name] for name in coeffs]) # first entry 0 to shift index by 1
    scale = flavio.config['renormalization scale']['bxll']
    # (4.19) of 1503.04849
    # Note the different powers of ast (\tilde\alpha_s) and k (\kappa) due to
    # the different normalisation of 1) C9 and C10 and 2) the overall
    # normalisation of phi_ll
    flavio.citations.register("Huber:2015sra")
    e = np.zeros((11, 11), dtype=complex) # from 0 to 10
    if I == 'T' or I == 'L' or I == 'BR':
        e[7,7] = 8 * ast    * k    * sigmaij_I(I, 7, 7, sh)*wem(I, 7, 7, sh, mb, ml, scale, mc)
        e[7,9] = 8 * ast    * k    * sigmaij_I(I, 7, 9, sh)*wem(I, 7, 9, sh, mb, ml, scale, mc)
        e[9,9] = 8 * ast    * k    * sigmaij_I(I, 9, 9, sh)*wem(I, 9, 9, sh, mb, ml, scale, mc)
        e[2,9] = 8 * ast    * k    * sigmaij_I(I, 9, 9, sh)*wem(I, 2, 9, sh, mb, ml, scale, mc)
        e[2,2] = 8 * ast    * k    * sigmaij_I(I, 9, 9, sh)*wem(I, 2, 2, sh, mb, ml, scale, mc)
        e[1,1] = 16/9. * e[2,2]
        e[10,10] = e[9,9]
        e[1,2] = 8/3. * e[2,2]
        e[1,7] = 4/3. * e[2,7]
        e[1,9] = 4/3. * e[2,9]
        e[2,7] = 8 * ast    * k    * sigmaij_I(I, 7, 9, sh)*wem(I, 2, 7, sh, mb, ml, scale, mc)
    elif I == 'A':
        e[7,10] = 8 * ast    * k    * sigmaij_I(I, 7, 10, sh)*wem(I, 7, 10, sh, mb, ml, scale, mc)
        e[9,10] = 8 * ast    * k    * sigmaij_I(I, 9, 10, sh)*wem(I, 9, 10, sh, mb, ml, scale, mc)
        e[2,10] = 8 * ast    * k    * sigmaij_I(I, 9, 10, sh)*wem(I, 2, 10, sh, mb, ml, scale, mc)
        e[1,10] = 4/3. *  e[2,10]
    else:
        raise ValueError("I should be 'T', 'L', 'BR', or 'A'")
    return np.dot(wc1_10, np.dot(e, wc1_10.conj())).real

def Phill_pc_mb2(

I, sh, l1, l2, mb, wc, q, lep)

def Phill_pc_mb2(I, sh, l1, l2, mb, wc, q, lep):
    # 1/mb^2 power correction to Phi_ll
    bq = 'b'+q
    bqll = bq + lep + lep
    coeffs = ['C1_'+bq, 'C2_'+bq, 'C3_'+bq, 'C4_'+bq, 'C5_'+bq, 'C6_'+bq, 'C7eff_'+bq, 'C8eff_'+bq, 'C9_'+bqll, 'C10_'+bqll]
    wc1_10 = np.array([0] + [wc[name] for name in coeffs]) # first entry 0 to shift index by 1
    chi1 = np.zeros((11, 11))
    chi2 = np.zeros((11, 11))
    if I == 'T':
        chi1[7, 7] = 4/(3*sh) * (1-sh) * (5 * sh+3)
        chi1[7, 9] = 4 * (1-sh)**2
        chi1[9, 9] = -sh/3 * (1-sh) * (3 * sh+5)
        chi2[7, 7] = 4/sh * (3 * sh**2+2 * sh-9)
        chi2[7, 9] = 4 * (9 * sh**2-6 * sh-7)
        chi2[9, 9] = sh * (15 * sh**2-14 * sh-5)
    elif I == 'L':
        chi1[7, 7] = 2/3 * (sh-1) * (3 * sh+13)
        chi1[7, 9] = 2 * (1-sh)**2
        chi1[9, 9] = 1/6 * (1-sh) * (13 * sh+3)
        chi2[7, 7] = 2 * (15 * sh**2-6 * sh-13)
        chi2[7, 9] = 2 * (3 * sh**2-6 * sh-1)
        chi2[9, 9] = 1/2 * (-17 * sh**2+10 * sh+3)
    elif I == 'A':
        chi1[7, 10] = -4/3 * (3 * sh**2+2 * sh+3)
        chi1[9, 10] = -2/3 * sh * (3 * sh**2+2 * sh+3)
        chi2[7, 10] = -4 * (9 * sh**2-10 * sh-7)
        chi2[9, 10] = -2 * sh * (15 * sh**2-14 * sh-9)
    else:
        raise ValueError("I should be 'T', 'L', or 'A'")
    return ( l1/mb**2 * np.dot(wc1_10, np.dot(chi1, wc1_10.conj()))
           + l2/mb**2 * np.dot(wc1_10, np.dot(chi2, wc1_10.conj())) ).real

def bxll_afb(

q2, wc_obj, par, q, lep, **kwargs)

def bxll_afb(q2, wc_obj, par, q, lep, **kwargs):
    num = bxll_afb_num(q2, wc_obj, par, q, lep, **kwargs)
    denom = bxll_afb_den(q2, wc_obj, par, q, lep, **kwargs)
    if denom == 0:
        return 0.
    else:
        return num/denom

def bxll_afb_den(

q2, wc_obj, par, q, lep, **kwargs)

def bxll_afb_den(q2, wc_obj, par, q, lep, **kwargs):
    # auxiliary function needed for q2-integrated AFB defined below
    if q2 > 8 and q2 < 14:
        warnings.warn("The predictions in the region of narrow charmonium resonances are not meaningful")
    if q2 > 14:
        include_qed = False  # log-enhanced QED corrections to AFB only known for low q2!
        kwargs.pop('include_qed', None)
    else:
        if 'include_qed' in kwargs:
            include_qed = kwargs.pop('include_qed')
        else:
            include_qed = True
    if lep == 'l':
        # average of e and mu!
         return (_bxll_dbrdq2_unnorm(q2, wc_obj, par, q, 'e', include_qed=include_qed, **kwargs)
               + _bxll_dbrdq2_unnorm(q2, wc_obj, par, q, 'mu', include_qed=include_qed, **kwargs))/2.
    else:
        return _bxll_dbrdq2_unnorm(q2, wc_obj, par, q, lep, include_qed=include_qed, **kwargs)

def bxll_afb_den_int(

q2min, q2max, wc_obj, par, q, lep, **kwargs)

def bxll_afb_den_int(q2min, q2max, wc_obj, par, q, lep, **kwargs):
    def obs(q2):
        return bxll_afb_den(q2, wc_obj, par, q, lep, **kwargs)
    return flavio.math.integrate.nintegrate(obs, q2min, q2max)

def bxll_afb_func(

q, lep)

def bxll_afb_func(q, lep):
    def fct(wc_obj, par, q2):
        return bxll_afb(q2, wc_obj, par, q, lep)
    return fct

def bxll_afb_int_func(

q, lep)

def bxll_afb_int_func(q, lep):
    def fct(wc_obj, par, q2min, q2max):
        num = bxll_afb_num_int(q2min, q2max, wc_obj, par, q, lep)
        if num == 0:
            return 0
        den = bxll_afb_den_int(q2min, q2max, wc_obj, par, q, lep)
        return num/den
    return fct

def bxll_afb_num(

q2, wc_obj, par, q, lep, **kwargs)

Inclusive $B\to X_q\ell^+\ell^-$ normalized differential forward-backward asymmetry.

def bxll_afb_num(q2, wc_obj, par, q, lep, **kwargs):
    r"""Inclusive $B\to  X_q\ell^+\ell^-$ normalized differential
    forward-backward asymmetry."""
    if q2 > 8 and q2 < 14:
        warnings.warn("The predictions in the region of narrow charmonium resonances are not meaningful")
    if lep == 'l':
        # average of e and mu!
        return (_bxll_afb_num(q2, wc_obj, par, q, 'e', **kwargs) + _bxll_afb_num(q2, wc_obj, par, q, 'mu', **kwargs))/2.
    else:
        return _bxll_afb_num(q2, wc_obj, par, q, lep, **kwargs)

def bxll_afb_num_int(

q2min, q2max, wc_obj, par, q, lep, **kwargs)

def bxll_afb_num_int(q2min, q2max, wc_obj, par, q, lep, **kwargs):
    def obs(q2):
        return bxll_afb_num(q2, wc_obj, par, q, lep, **kwargs)
    return flavio.math.integrate.nintegrate(obs, q2min, q2max)

def bxll_br_int(

q2min, q2max, wc_obj, par, q, lep)

def bxll_br_int(q2min, q2max, wc_obj, par, q, lep):
    def obs(q2):
        return bxll_dbrdq2(q2, wc_obj, par, q, lep)
    return flavio.math.integrate.nintegrate(obs, q2min, q2max)

def bxll_br_int_func(

q, lep)

def bxll_br_int_func(q, lep):
    def fct(wc_obj, par, q2min, q2max):
        return bxll_br_int(q2min, q2max, wc_obj, par, q, lep)
    return fct

def bxll_br_int_ratio_func(

q, lnum, lden)

def bxll_br_int_ratio_func(q, lnum, lden):
    def fct(wc_obj, par, q2min, q2max):
        num = bxll_br_int(q2min, q2max, wc_obj, par, q, lnum)
        if num == 0:
            return 0
        den = bxll_br_int(q2min, q2max, wc_obj, par, q, lden)
        return num/den
    return fct

def bxll_br_prefactor(

par, q, lep)

def bxll_br_prefactor(par, q, lep):
    # prefactor for the branching ratio normalized to B->X_c enu
    ml, mb, alpha_s, alpha_e, mc = bxll_parameters(par, lep)
    bq = 'b' + q
    xi_t = flavio.physics.ckm.xi('t',bq)(par)
    Vcb = flavio.physics.ckm.get_ckm(par)[1,2]
    C = par['C_BXlnu']
    BRSL = par['BR(B->Xcenu)_exp']
    return alpha_e**2/4./pi**2 / mb**2 * BRSL/C * abs(xi_t)**2/abs(Vcb)**2

def bxll_dbrdq2(

q2, wc_obj, par, q, lep)

Inclusive $B\to X_q\ell^+\ell^-$ differential branching ratio normalized to $B\to X_c\ell\nu$ taken from experiment.

def bxll_dbrdq2(q2, wc_obj, par, q, lep):
    r"""Inclusive $B\to  X_q\ell^+\ell^-$ differential branching ratio
    normalized to $B\to X_c\ell\nu$ taken from experiment."""
    if q2 > 8 and q2 < 14:
        warnings.warn("The predictions in the region of narrow charmonium resonances are not meaningful")
    if lep == 'l':
        # average of e and mu!
        return (_bxll_dbrdq2(q2, wc_obj, par, q, 'e') + _bxll_dbrdq2(q2, wc_obj, par, q, 'mu'))/2.
    else:
        return _bxll_dbrdq2(q2, wc_obj, par, q, lep)

def bxll_dbrdq2_func(

q, lep)

def bxll_dbrdq2_func(q, lep):
    def fct(wc_obj, par, q2):
        return bxll_dbrdq2(q2, wc_obj, par, q, lep)
    return fct

def bxll_parameters(

par, lep)

def bxll_parameters(par, lep):
    # return lepton and b mass and alpha_s,e at the appropriate scale
    ml = par['m_'+lep]
    scale = flavio.config['renormalization scale']['bxll']
    mb = flavio.physics.running.running.get_mb_pole(par)
    mc = flavio.physics.running.running.get_mc_pole(par)
    alpha = flavio.physics.running.running.get_alpha(par, scale)
    alpha_s = alpha['alpha_s']
    alpha_e = alpha['alpha_e']
    return ml, mb, alpha_s, alpha_e, mc

def f7(

s)

def f7(s):
	return 1/(6 * (s-1)**2 ) * ( 24 * (1+13*s -4*s**2) * li2( sqrt(s)) + 12 * (1-17*s+6*s**2) * li2(s) +6*s * (6-7*s) * log(s) +24 * (1-s)**2*log(s) * log(1-s) + 12 * (-13+16*s-3*s**2) * (log(1- sqrt(s))-log(1-s)) +39 -2*pi**2 +252*s -26*pi**2*s +21*s**2+8*pi**2*s**2 -180 * sqrt(s) -132*s * sqrt(s) )

def f9(

s)

def f9(s):
	return -1/(6 * (s-1)**2 ) * ( 48 * s * (-5+ 2*s) * li2( sqrt(s)) + 24 * (-1+7*s-3*s**2) * li2(s) + 6*s * (-6+7*s) * log(s) -24 * (1-s)**2 * log(s) * log(1-s) +24 * (5-7*s+2*s**2) * (log(1- sqrt(s))-log(1-s)) -21-156*s+20*pi**2*s +9*s**2-8*pi**2*s**2+120 * sqrt(s)+48*s * sqrt(s) )

def f_ll(

sh, mlh, alpha_s, C7t, C9t, C10t, CS, CP)

def f_ll(sh, mlh, alpha_s, C7t, C9t, C10t, CS, CP):
    # The function of Wilson coefficients and kinematical quantities entering
    # the inclusive $B\to Xll$ rate.
    # NB: CS and CP are defined to be dimensionless!
    return (1-sh)**2 * sqrt(1-4*mlh**2/sh) * (
        # SM-like terms for m_l->0: here we add non-univ. bremsstrahlung corrections
        4*abs(C7t)**2*(1+2/sh) * (1+2*mlh**2/sh) * (1 + alpha_s/pi * tau77(sh))
        + 12*(C7t*C9t.conjugate()).real * (1+2*mlh**2/sh) * (1 + alpha_s/pi * tau79(sh))
        + (abs(C9t)**2 + abs(C10t)**2) * (1 + 2*sh + 2*mlh**2*(1-sh)/sh) * (1 + alpha_s/pi * tau99(sh))
        # scalar/pseudoscalar operators
        + 3/2. * sh * ((1-4*mlh**2/sh) * abs(CS)**2 + abs(CP)**2)
        # O(m_l) terms
        + 6*mlh**2 * (abs(C9t)**2 - abs(C10t)**2)
        + 6 * mlh * (CP * C10t.conjugate()).real )

def f_ll_ha(

sh, mlh, alpha_s, wc_eff)

def f_ll_ha(sh, mlh, alpha_s, wc_eff):
    # The function of Wilson coefficients and kinematical quantities entering
    # the inclusive $B\to Xll$ forward-backward asymmetry
    # NB: lepton mass is neglected here
    C7 = wc_eff['7']
    C9 = wc_eff['v']
    C10 = wc_eff['a']
    C7p = wc_eff['7p']
    C9p = wc_eff['vp']
    C10p = wc_eff['ap']
    return -4*(1-sh)**2 * (
        # here we add non-univ. bremsstrahlung corrections
        + sh*(C9*C10.conjugate()).real *  (1 + alpha_s/pi * tau910(sh))
        +  2*(C7*C10.conjugate()).real *  (1 + alpha_s/pi * tau710(sh))
        # primed operators - assume same bremsstrahlung as for unprimed
        - sh*(C9p*C10p.conjugate()).real *(1 + alpha_s/pi * tau910(sh))
        -  2*(C7p*C10p.conjugate()).real *(1 + alpha_s/pi * tau710(sh))
        )

def f_u(

alpha_e, alpha_s, alpha_s_mu0, mb, l1, l2)

def f_u(alpha_e, alpha_s, alpha_s_mu0, mb, l1, l2):
    # semileptonic phase space factor for B->Xulnu
    # see (4.8) of 1503.04849
    # NB the O(\tilde alpha_s^2) term is omitted on purpose as including it
    # would mean including terms of O(\tilde \alpha_s^4) in the dominant
    # contribution to the branching ratio, as C9 and C10 are formally of
    # O(\tilde \alpha_s \kappa). This is a numerically relevant choice (around
    # 15% change of the low-q^2 BR).
    flavio.citations.register("Huber:2015sra")
    ast = alpha_s/4./pi
    k = alpha_e/alpha_s
    eta = alpha_s_mu0/alpha_s
    scale = flavio.config['renormalization scale']['bxll']
    phi1 = (50/3. - 8*pi**2/3.)
    return ( 1 + ast * phi1 + k*(12/23.*(1-1/eta))
               + l1/(2*mb**2) - 9*l2/(2*mb**2))

def inclusive_wc(

q2, wc_obj, par, q, lep, mb)

Returns a dictionary of "inclusive" Wilson coefficients (including SM contributions) where universal bremsstrahlung and virtual corrections have been absorbed, as well as the dictionary with the Wilson coefficients without these corrections.

def inclusive_wc(q2, wc_obj, par, q, lep, mb):
    r"""Returns a dictionary of "inclusive" Wilson coefficients (including
    SM contributions) where universal bremsstrahlung and virtual corrections
    have been absorbed, as well as the dictionary with the Wilson
    coefficients without these corrections."""
    scale = flavio.config['renormalization scale']['bxll']
    alphas = flavio.physics.running.running.get_alpha(par, scale)['alpha_s']
    # the "usual" WCs
    wc = flavio.physics.bdecays.wilsoncoefficients.wctot_dict(wc_obj, 'b' + q + lep + lep, scale, par, nf_out=5)
    xi_u = flavio.physics.ckm.xi('u','b'+q)(par)
    xi_t = flavio.physics.ckm.xi('t','b'+q)(par)
    # virtual corrections
    Yq2 =flavio.physics.bdecays. matrixelements.Y(q2, wc, par, scale, 'b'+q) + (xi_u/xi_t)*flavio.physics.bdecays.matrixelements.Yu(q2, wc, par, scale, 'b'+q)
    delta_C7 = flavio.physics.bdecays.matrixelements.delta_C7(par=par, wc=wc, q2=q2, scale=scale, qiqj='b'+q)
    delta_C9 = flavio.physics.bdecays.matrixelements.delta_C9(par=par, wc=wc, q2=q2, scale=scale, qiqj='b'+q)
    mb_MSbar = flavio.physics.running.running.get_mb(par, scale)
    ll = lep + lep
    wc_eff = {}
    # add the universal bremsstrahlung corrections to the effective WCs
    brems_7 = 1 + alphas/pi * sigma7(q2/mb**2, scale, mb)
    brems_9 = 1 + alphas/pi * sigma9(q2/mb**2)
    wc_eff['7']  = wc['C7eff_b'+q]  * brems_7      + delta_C7
    wc_eff['7p'] = wc['C7effp_b'+q] * brems_7
    wc_eff['v']  = wc['C9_b'+q+ll]  * brems_9      + delta_C9 + Yq2
    wc_eff['vp'] = wc['C9p_b'+q+ll] * brems_9
    wc_eff['a']  = wc['C10_b'+q+ll] * brems_9
    wc_eff['ap'] = wc['C10p_b'+q+ll]* brems_9
    wc_eff['s']  = mb_MSbar * wc['CS_b'+q+ll]
    wc_eff['sp'] = mb_MSbar * wc['CSp_b'+q+ll]
    wc_eff['p']  = mb_MSbar * wc['CP_b'+q+ll]
    wc_eff['pp'] = mb_MSbar * wc['CPp_b'+q+ll]
    wc_eff['t']  = 0
    wc_eff['tp'] = 0
    return {'wc_eff': wc_eff, 'wc': wc}

def sigma(

s)

def sigma(s):
    return - 4/3 * li2(s) - 2/3 * log(s) * log(1-s) -2/9 * pi**2 -log(1-s)-2/9 * (1-s) * log(1-s)

def sigma7(

s, scale, mb)

def sigma7(s, scale, mb):
    return sigma(s) + 1/6 - 8/3 * log(scale/mb)

def sigma710_A(

sh)

def sigma710_A(sh):
    return -8*(1-sh)**2

def sigma77_L(

sh)

def sigma77_L(sh):
    return 4*(1-sh)**2

def sigma77_T(

sh)

def sigma77_T(sh):
    return 8*(1-sh)**2/sh

def sigma79_L(

sh)

def sigma79_L(sh):
    return 4*(1-sh)**2

def sigma79_T(

sh)

def sigma79_T(sh):
    return 8*(1-sh)**2

def sigma9(

s)

def sigma9(s):
    return sigma(s) + 3/2

def sigma910_A(

sh)

def sigma910_A(sh):
    return -4*sh*(1-sh)**2

def sigma99_L(

sh)

def sigma99_L(sh):
    return (1-sh)**2

def sigma99_T(

sh)

def sigma99_T(sh):
    return 2*sh*(1-sh)**2

def sigmaij_I(

I, i, j, sh)

def sigmaij_I(I, i, j, sh):
    if I=='T' and i==7 and j==7:
        return sigma77_T(sh)
    elif I=='T' and i==7 and j==9:
        return sigma79_T(sh)
    elif I=='T' and i==9 and j==9:
        return sigma99_T(sh)
    elif I=='L' and i==7 and j==7:
        return sigma77_L(sh)
    elif I=='L' and i==7 and j==9:
        return sigma79_L(sh)
    elif I=='L' and i==9 and j==9:
        return sigma99_L(sh)
    elif I=='BR' and i==7 and j==7:
        return sigma77_L(sh) +  sigma77_T(sh)
    elif I=='BR' and i==7 and j==9:
        return sigma79_L(sh) + sigma79_T(sh)
    elif I=='BR' and i==9 and j==9:
        return sigma99_L(sh) + sigma99_T(sh)
    elif I=='A' and i==7 and j==10:
        return sigma710_A(sh)
    elif I=='A' and i==9 and j==10:
        return sigma910_A(sh)
    else:
        raise ValueError("Function sigmaij_I not defined for I, i, j = " +  str((I,i,j)))

def tau710(

s)

def tau710(s):
	return -5/2 + 1/(3 * (1-3*s)) - 1/3 * (s * (6-7 * s) * log(s))/((1-s)**2)- 1/9 * ((3-7 * s + 4 * s**2) * log(1-s))/(s) + (f7(s))/3

def tau77(

s)

def tau77(s):
    return - 2/(9 * (2+s)) * (2 * (1-s)**2 * log(1-s) +(6 * s * (2-2 * s-s**2))/((1-s)**2) * log(s) +(11-7 * s-10 * s**2)/(1-s) )

def tau79(

s)

def tau79(s):
    return - (4 * (1-s)**2)/(9 * s) * log(1-s)-(4 * s * (3-2 * s))/(9 * (1-s)**2) * log(s) -(2 * (5-3 * s))/(9 * (1-s))

def tau910(

s)

def tau910(s) :
	return -5/2 + 1/(3 * (1-s)) - 1/3 * (s * (6-7*s) * log(s))/(((1-s)**2)) - 2/9 * ((3-5 * s + 2 * s**2) * log(1-s))/(s) + (f9(s))/3

def tau99(

s)

def tau99(s):
    return -4/(9 * (1+2 * s)) * (2 * (1-s)**2 * log(1-s) +(3 * s * (1+s) * (1-2 * s))/((1-s)**2) * log(s)+(3 * (1-3 * s**2))/(1-s) )