def prediction(): try: obsname = request.query.obs obs = flavio.Observable.get_instance(obsname) if obs.arguments is not None: args = json.loads(request.query.args) # transform strings of numbers to numbers def tofloat(s): try: f = float(s) except: return s return f args = {key: tofloat(val) for key, val in args.items()} except: return {} if obs.arguments is None: cen = flavio.sm_prediction(obsname) else: cen = flavio.sm_prediction(obsname, **args) if request.query.unc == 'true': if obs.arguments is None: unc = flavio.sm_uncertainty(obsname) else: unc = flavio.sm_uncertainty(obsname, **args) return {'prediction': pretty_prediction(cen, unc), 'central': cen, 'uncertainty': unc} else: return {'prediction': pretty_prediction(cen), 'central': cen}
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_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 test_ae_SM(self): self.assertAlmostEqual(flavio.sm_prediction('a_e') / ae_SM, 1) pd = flavio.combine_measurements('a_e') ae_exp = pd.central_value ae_err_exp = pd.error_left np.random.seed(17) ae_err_sm = flavio.sm_uncertainty('a_e') # check that there is a -2.3 sigma tension, see 1804.07409 p. 13 self.assertAlmostEqual((ae_exp - ae_SM) / sqrt(ae_err_sm**2 + ae_err_exp**2), -2.3, delta=0.5)
def save_observables(filename): obslist = [] for j in all_measurements: meas1 = flavio.Measurement[j].get_central_all() for k in meas1.keys(): if k in observables: exp = meas1[k] err_exp = flavio.Measurement[j].get_1d_errors_random()[k] if isinstance(k, tuple): err_th = flavio.sm_uncertainty(k[0], q2min=k[1], q2max=k[2]) else: err_th = flavio.sm_uncertainty(k) err = sqrt(err_th**2 + err_exp**2) obslist.append({'obs': k, 'central': exp, 'error': err}) f = open(filename, 'w') yaml.dump(obslist, f) f.close()
def test_ae_SM(self): self.assertAlmostEqual(flavio.sm_prediction('a_e') / ae_SM, 1) pd = flavio.combine_measurements('a_e') ae_exp = pd.central_value ae_err_exp = pd.error_left np.random.seed(17) ae_err_sm = flavio.sm_uncertainty('a_e') # check that there is a -2.3 sigma tension, see 1804.07409 p. 13 self.assertAlmostEqual( (ae_exp - ae_SM) / sqrt(ae_err_sm**2 + ae_err_exp**2), -2.3, delta=0.5)
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 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 calc_obs(): "Re-obtain the experimental values and their uncertainties within the SM" exp = [] uncExp = [] expD = {} uncExpD = {} unc = [] uncTot = [] measurements = ['LHCb Bs->mumu 2017', 'CMS Bs->mumu 2013', 'LHCb RK* 2017', 'LHCb B->Kee 2014', 'LHCb B->K*mumu 2015 P 1.1-6', 'ATLAS B->K*mumu 2017 P4p', 'ATLAS B->K*mumu 2017 P5p', 'HFAG osc summer 2015', 'SLAC HFLAV 2018'] for m in measurements: expD.update(flavio.Measurement[m].get_central_all()) uncExpD.update(flavio.Measurement[m].get_1d_errors_random()) for obs in observables: unc += [flavio.sm_uncertainty(*obs)] if len(obs)==1: obs = obs[0] exp += [expD[obs]] uncExp += [uncExpD[obs]] uncTot += [sqrt(unc[-1]**2 + uncExpD[obs]**2) ]
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, scale_factor=1): 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' - `scale_factor` (optional): factor by which all values will be multiplied. Defaults to 1. 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, scale_factor * np.asarray(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, scale_factor * np.asarray(obs_arr - obs_err_arr_int), scale_factor * np.asarray(obs_arr + obs_err_arr_int), **fill_args)
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)
# w_c input at the EW scale, and standard basis w = Wilson( { 'CVL_bctaunutau': 0.17, 'CVL_bctaunumu': 0.32, 'CVL_bcmunutau': 1e-3, 'CVL_bcmunumu': 1.7e-3 }, scale=4.8, eft='WET', basis='flavio') #the prediction for RD* RD_star_np = flavio.np_prediction('Rtaul(B->D*lnu)', w) RD_star_np_uncertainty = flavio.np_uncertainty('Rtaul(B->D*lnu)', w) RD_star_sm = flavio.sm_prediction('Rtaul(B->D*lnu)') RD_star_sm_uncertainty = flavio.sm_uncertainty('Rtaul(B->D*lnu)') #LHCb result RD_star_obs = 0.366 RD_star_obs_sys = 0.030 RD_star_obs_stat = 0.027 ## values = [ RD_star_np, RD_star_np_uncertainty, RD_star_sm, RD_star_sm_uncertainty, RD_star_obs, np.sqrt(RD_star_obs_sys**2 + RD_star_obs_stat**2) ] ## sigma deviation sigma_np_obs = (np.abs(values[0] - values[4])) / (np.sqrt(values[1]**2 + values[5]**2)) print(values)
def q2_plot_th_diff_err(obs_name, q2min, q2max, wc=None, q2steps=100, q2steps_err=5, N=100, threads=1, plot_args=None, fill_args=None): r"""Plot the theory prediction of a $q^2$-dependent observable with uncertainties 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 for the computation of the central value. Defaults to 100. Less is faster but less precise. - `q2steps_err` (optional): number of $q^2$ 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 `q2steps_err` option. By default, the uncertainty is only computed at 10 steps in $q^2$ and is interpolated in between. This can be enough if the uncertainty does not vary strongly with $q^2$. 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 obs.arguments != ['q2']: raise ValueError(r"Only observables that depend on $q^2$ (and nothing else) are allowed") step = (q2max-q2min)/(q2steps-1) q2_arr = np.arange(q2min, q2max+step, step) step = (q2max-q2min)/(q2steps_err-1) q2_err_arr = np.arange(q2min, q2max+step, step) # fix to avoid bounds_error in interp1d due to lack of numerical precision q2_err_arr[-1] = q2_arr[-1] if wc is None: wc = flavio.physics.eft._wc_sm # SM Wilson coefficients obs_err_arr = [flavio.sm_uncertainty(obs_name, q2, threads=threads) for q2 in q2_err_arr] obs_arr = [flavio.sm_prediction(obs_name, q2) for q2 in q2_arr] else: obs_err_arr = [flavio.np_uncertainty(obs_name, wc_obj=wc, q2=q2, threads=threads) for q2 in q2_err_arr] obs_arr = [flavio.np_prediction(obs_name, wc, q2) for q2 in q2_arr] ax = plt.gca() plot_args = plot_args or {} fill_args = fill_args or {} if 'alpha' not in fill_args: fill_args['alpha'] = 0.5 ax.plot(q2_arr, obs_arr, **plot_args) interp_err = scipy.interpolate.interp1d(q2_err_arr, obs_err_arr, kind='quadratic') obs_err_arr_int = interp_err(q2_arr) ax.fill_between(q2_arr, obs_arr - obs_err_arr_int, obs_arr + obs_err_arr_int, **fill_args)