From cfa4410ffa4c8cc501c05071a911cf1aed391d2a Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 7 Feb 2022 11:37:20 +0100 Subject: [PATCH 01/74] init rewriting scale variations --- benchmarks/apfel_bench.py | 46 ++-- src/eko/evolution_operator/__init__.py | 55 +++-- src/eko/evolution_operator/grid.py | 15 ++ src/eko/scale_variations/__init__.py | 4 + src/eko/scale_variations/scheme_B.py | 280 +++++++++++++++++++++++++ 5 files changed, 361 insertions(+), 39 deletions(-) create mode 100644 src/eko/scale_variations/__init__.py create mode 100644 src/eko/scale_variations/scheme_B.py diff --git a/benchmarks/apfel_bench.py b/benchmarks/apfel_bench.py index 928b9c708..c92623293 100644 --- a/benchmarks/apfel_bench.py +++ b/benchmarks/apfel_bench.py @@ -5,7 +5,7 @@ import numpy as np from banana.data import cartesian_product -from ekomark.banana_cfg import register +from ekomark import register from ekomark.benchmark.runner import Runner from ekomark.data import operators @@ -65,11 +65,19 @@ def benchmark_plain(self, pto): cartesian_product(th), operators.build(operators.apfel_config), ["ToyLH"] ) - def benchmark_sv(self, pto): + def benchmark_sv(self, pto, scheme): """Scale Variation""" th = self.vfns_theory.copy() - th.update({"PTO": [pto], "XIR": [0.7071067811865475, 1.4142135623730951]}) + th.update( + { + "PTO": [pto], + "XIR": [np.sqrt(0.5)], + "fact_to_ren_scale_ratio": [np.sqrt(2.0)], + "SV_scheme": [scheme], + "EScaleVar": [0], + } + ) self.run( cartesian_product(th), operators.build(operators.apfel_config), ["ToyLH"] ) @@ -126,8 +134,8 @@ class BenchmarkFFNS(ApfelBenchmark): "FNS": "FFNS", "ModEv": [ "EXA", - "EXP", - "TRN", + # "EXP", + # "TRN", ], "NfFF": 4, "kcThr": 0.0, @@ -146,7 +154,7 @@ def benchmark_plain(self, pto): cartesian_product(th), operators.build(operators.apfel_config), ["ToyLH"] ) - def benchmark_sv(self, pto): + def benchmark_sv(self, pto, scheme): """Scale Variation""" ts = [] @@ -156,18 +164,22 @@ def benchmark_sv(self, pto): "PTO": [pto], "XIR": [np.sqrt(0.5)], "fact_to_ren_scale_ratio": [np.sqrt(2.0)], + "SV_scheme": [scheme], + "EScaleVar": [0], } ) ts.extend(cartesian_product(th)) - th = self.ffns_theory.copy() - th.update( - { - "PTO": [pto], - "XIR": [np.sqrt(2.0)], - "fact_to_ren_scale_ratio": [np.sqrt(0.5)], - } - ) - ts.extend(cartesian_product(th)) + # th = self.ffns_theory.copy() + # th.update( + # { + # "PTO": [pto], + # "XIR": [np.sqrt(2.0)], + # "fact_to_ren_scale_ratio": [np.sqrt(0.5)], + # "SV_scheme": [scheme], + # "EScaleVar": [0], + # } + # ) + # ts.extend(cartesian_product(th)) self.run(ts, operators.build(operators.apfel_config), ["ToyLH"]) @@ -177,6 +189,6 @@ def benchmark_sv(self, pto): # obj = BenchmarkFFNS() # obj.benchmark_plain(1) - # obj.benchmark_sv(1) + obj.benchmark_sv(1, "A") # obj.benchmark_kthr(2) - obj.benchmark_msbar(2) + # obj.benchmark_msbar(2) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index cbf4b3d91..3f17e4bc1 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -21,9 +21,10 @@ logger = logging.getLogger(__name__) +# TODO: move the scale var A to a proper module -@nb.njit("c16[:](u1,string,c16,u1,f8)", cache=True) -def gamma_ns_fact(order, mode, n, nf, L): +@nb.njit("c16[:](u1,string,c16,u1,f8,string)", cache=True) +def gamma_ns_fact(order, mode, n, nf, L, sv_scheme): """ Adjust the anomalous dimensions with the scale variations. @@ -39,6 +40,8 @@ def gamma_ns_fact(order, mode, n, nf, L): number of active flavors L : float logarithmic ratio of factorization and renormalization scale + sv_scheme : string + scale variation scheme Returns ------- @@ -48,18 +51,19 @@ def gamma_ns_fact(order, mode, n, nf, L): gamma_ns = ad.gamma_ns(order, mode[-1], n, nf) # since we are modifying *in-place* be carefull, that the order matters! # and indeed, we need to adjust the high elements first - if order >= 2: - gamma_ns[2] -= ( - 2 * beta.beta(0, nf) * gamma_ns[1] * L - + (beta.beta(1, nf) * L - beta.beta(0, nf) ** 2 * L ** 2) * gamma_ns[0] - ) - if order >= 1: - gamma_ns[1] -= beta.beta(0, nf) * gamma_ns[0] * L + if sv_scheme == "A": + if order >= 2: + gamma_ns[2] -= ( + 2 * beta.beta(0, nf) * gamma_ns[1] * L + + (beta.beta(1, nf) * L - beta.beta(0, nf) ** 2 * L ** 2) * gamma_ns[0] + ) + if order >= 1: + gamma_ns[1] -= beta.beta(0, nf) * gamma_ns[0] * L return gamma_ns -@nb.njit("c16[:,:,:](u1,c16,u1,f8)", cache=True) -def gamma_singlet_fact(order, n, nf, L): +@nb.njit("c16[:,:,:](u1,c16,u1,f8,string)", cache=True) +def gamma_singlet_fact(order, n, nf, L, sv_scheme): """ Adjust the anomalous dimensions with the scale variations. @@ -75,6 +79,8 @@ def gamma_singlet_fact(order, n, nf, L): number of active flavors L : float logarithmic ratio of factorization and renormalization scale + sv_scheme : string + scale variation scheme Returns ------- @@ -87,17 +93,18 @@ def gamma_singlet_fact(order, n, nf, L): nf, ) # concerning order: see comment at gamma_ns_fact - if order >= 2: - gamma_singlet[2] -= ( - 2 * beta.beta(0, nf) * gamma_singlet[1] * L - + (beta.beta(1, nf) * L - beta.beta(0, nf) ** 2 * L ** 2) * gamma_singlet[0] - ) - if order >= 1: - gamma_singlet[1] -= beta.beta(0, nf) * gamma_singlet[0] * L + if sv_scheme == "A": + if order >= 2: + gamma_singlet[2] -= ( + 2 * beta.beta(0, nf) * gamma_singlet[1] * L + + (beta.beta(1, nf) * L - beta.beta(0, nf) ** 2 * L ** 2) * gamma_singlet[0] + ) + if order >= 1: + gamma_singlet[1] -= beta.beta(0, nf) * gamma_singlet[0] * L return gamma_singlet -@nb.njit("f8(f8,u1,string,string,b1,f8,f8[:,:],f8,f8,f8,f8,u4,u1)", cache=True) +@nb.njit("f8(f8,u1,string,string,b1,f8,f8[:,:],f8,f8,f8,f8,u4,u1,string)", cache=True) def quad_ker( u, order, @@ -112,6 +119,7 @@ def quad_ker( L, ev_op_iterations, ev_op_max_order, + sv_scheme ): """ Raw kernel inside quad. @@ -144,6 +152,8 @@ def quad_ker( number of evolution steps ev_op_max_order : int perturbative expansion order of U + sv_scheme : string + scale variation scheme Returns ------- @@ -170,7 +180,7 @@ def quad_ker( return 0.0 # compute the actual evolution kernel if is_singlet: - gamma_singlet = gamma_singlet_fact(order, n, nf, L) + gamma_singlet = gamma_singlet_fact(order, n, nf, L, sv_scheme) ker = s.dispatcher( order, method, gamma_singlet, a1, a0, nf, ev_op_iterations, ev_op_max_order ) @@ -179,7 +189,7 @@ def quad_ker( l = 0 if mode[3] == "q" else 1 ker = ker[k, l] else: - gamma_ns = gamma_ns_fact(order, mode, n, nf, L) + gamma_ns = gamma_ns_fact(order, mode, n, nf, L, sv_scheme) ker = ns.dispatcher( order, method, @@ -216,7 +226,7 @@ class Operator: cut to the upper limit in the mellin inversion """ - def __init__(self, config, managers, nf, q2_from, q2_to, mellin_cut=5e-2): + def __init__(self, config, managers, nf, q2_from, q2_to=None, mellin_cut=5e-2): self.config = config self.managers = managers self.nf = nf @@ -329,6 +339,7 @@ def compute(self): np.log(fact_to_ren), self.config["ev_op_iterations"], self.config["ev_op_max_order"], + self.config["SV_scheme"] ), epsabs=1e-12, epsrel=1e-5, diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py index db5843556..145626c3f 100644 --- a/src/eko/evolution_operator/grid.py +++ b/src/eko/evolution_operator/grid.py @@ -15,6 +15,7 @@ from eko.evolution_operator import flavors from ..matching_conditions.operator_matrix_element import OperatorMatrixElement +from ..scale_variations.scheme_B import ScaleVariationOperator from . import Operator, physical logger = logging.getLogger(__name__) @@ -126,6 +127,7 @@ def from_dict( config["debug_skip_singlet"] = operators_card["debug_skip_singlet"] config["debug_skip_non_singlet"] = operators_card["debug_skip_non_singlet"] config["HQ"] = theory_card["HQ"] + config["SV_scheme"] = theory_card["SV_scheme"] q2_grid = np.array(operators_card["Q2grid"], np.float_) intrinsic_range = [] if int(theory_card["IC"]) == 1: @@ -276,6 +278,19 @@ def generate(self, q2): ) final_op = final_op @ rot @ matching @ phys_op + # Compute scale variation scheme B + if self.config["SV_scheme"] == "B": + scale_var = ScaleVariationOperator( + self.config, self.managers, path[-1].nf, final_op.q2_final + ) + scale_var.compute() + scale_var_op = physical.PhysicalOperator.ad_to_evol_map( + scale_var.op_members, + scale_var.nf, + scale_var.q2_to, + intrinsic_range, + ) + final_op = scale_var_op @ final_op values, errors = final_op.to_flavor_basis_tensor() fact_to_ren = self.config["fact_to_ren"] return { diff --git a/src/eko/scale_variations/__init__.py b/src/eko/scale_variations/__init__.py new file mode 100644 index 000000000..23a8fbaa6 --- /dev/null +++ b/src/eko/scale_variations/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +""" +This module contain the possible scale variations integrals. +""" diff --git a/src/eko/scale_variations/scheme_B.py b/src/eko/scale_variations/scheme_B.py new file mode 100644 index 000000000..890f31f6b --- /dev/null +++ b/src/eko/scale_variations/scheme_B.py @@ -0,0 +1,280 @@ +# -*- coding: utf-8 -*- +r""" +This module contains the scale varion operator in scheme B +""" + +import logging +import time + +import numba as nb +import numpy as np +from scipy import integrate + +from ..evolution_operator import Operator +from .. import anomalous_dimensions as ad +from .. import beta, interpolation, mellin +from ..basis_rotation import full_labels +from ..member import OpMember + +logger = logging.getLogger(__name__) + + +@nb.njit("c16(c16[:],f8,u1,u1,f8)", cache=True) +def non_singlet_dispatcher(gamma, a_s, order, nf, L): + """ + Scale Variation non singlet dispatcher + + Parameters + ---------- + gamma : numpy.ndarray + anomalous dimensions + a_s : float + target coupling value + order : int + perturbation order + nf : int + number of active flavors + L : float + logarithmic ratio of factorization and renormalization scale + + Returns + ------- + sv_ker : numpy.ndarray + scale varion kernel + """ + sv_ker = 1.0 + if order >= 1: + sv_ker -= a_s * L * gamma[0] + if order >= 2: + sv_ker += a_s ** 2 * ( + -gamma[1] * L + + 1 / 2 * (beta.beta_0(nf) * gamma[0] + gamma[0] * gamma[0]) * L ** 2 + ) + return sv_ker + + +@nb.njit("c16[:,:](c16[:,:,:],f8,u1,u1,f8)", cache=True) +def singlet_dispatcher(gamma, a_s, order, nf, L): + """ + Scale Variation singlet dispatcher + + Parameters + ---------- + gamma : numpy.ndarray + anomalous dimensions + a_s : float + target coupling value + order : int + perturbation order + nf : int + number of active flavors + L : float + logarithmic ratio of factorization and renormalization scale + + Returns + ------- + sv_ker : numpy.ndarray + scale varion kernel + """ + sv_ker = np.eye(2, dtype=np.complex_) + if order >= 1: + sv_ker -= a_s * L * gamma[0] + if order >= 2: + sv_ker += a_s ** 2 * ( + -gamma[1] * L + + 1 + / 2 + * ( + beta.beta_0(nf) * gamma[0] + + np.ascontiguousarray(gamma[0]) @ np.ascontiguousarray(gamma[0]) + ) + * L ** 2 + ) + return sv_ker + + +@nb.njit("f8(f8,u1,string,b1,f8,f8[:,:],f8,u1,f8)", cache=True) +def quad_ker( + u, + order, + mode, + is_log, + logx, + areas, + a_s, + nf, + L, +): + """ + Raw kernel inside quad. + + Parameters + ---------- + u : float + quad argument + order : int + perturbation order + mode : str + sector element + is_log : boolean + is a logarithmic interpolation + logx : float + Mellin inversion point + areas : tuple + basis function configuration + a_s : float + target coupling value + nf : int + number of active flavors + L : float + logarithm of the squared ratio of factorization and renormalization scale + + Returns + ------- + ker : float + evaluated scale variation kernel + """ + # TODO: this code is reperated twice or 3 times + is_singlet = mode[0] == "S" + # get transformation to N integral + if logx == 0.0: + return 0.0 + r = 0.4 * 16.0 / (-logx) + if is_singlet: + o = 1.0 + else: + o = 0.0 + n = mellin.Talbot_path(u, r, o) + jac = mellin.Talbot_jac(u, r, o) + # check PDF is active + if is_log: + pj = interpolation.log_evaluate_Nx(n, logx, areas) + else: + pj = interpolation.evaluate_Nx(n, logx, areas) + if pj == 0.0: + return 0.0 + + # compute the actual scale variation kernel + if is_singlet: + gamma_singlet = ad.gamma_singlet(order, n, nf) + ker = singlet_dispatcher(gamma_singlet, a_s, order, nf, L) + # select element of matrix + k = 0 if mode[2] == "q" else 1 + l = 0 if mode[3] == "q" else 1 + ker = ker[k, l] + else: + gamma_ns = ad.gamma_ns(order, mode[-1], n, nf) + ker = non_singlet_dispatcher(gamma_ns, a_s, order, nf, L) + + # recombine everthing + mellin_prefactor = complex(0.0, -1.0 / np.pi) + return np.real(mellin_prefactor * ker * pj * jac) + + +class ScaleVariationOperator(Operator): + """ + Internal representation of a Scale Variation operator. + + The actual matrices are computed upon calling :meth:`compute`. + + Parameters + ---------- + config : dict + configuration + managers : dict + managers + nf : int + number of active flavors + q2 : float + evolution scale + """ + + def __init__(self, config, managers, nf, q2): + super().__init__(config, managers, nf, q2) + + def compute(self): + """compute the actual operators (i.e. run the integrations)""" + # TODO: here there are a lot of repetitions, you need to generalize + # the evolution operator + # Generic parameters + int_disp = self.managers["interpol_dispatcher"] + grid_size = len(int_disp.xgrid) + + # init all ops with identity or zeros if we skip them + labels = self.labels() + eye = OpMember(np.eye(grid_size), np.zeros((grid_size, grid_size))) + zero = OpMember(*[np.zeros((grid_size, grid_size))] * 2) + for n in full_labels: + if n in labels: + # off diag singlet are zero + if n in ["S_qg", "S_gq"]: + self.op_members[n] = zero.copy() + else: + self.op_members[n] = eye.copy() + else: + self.op_members[n] = zero.copy() + + # At LO you don't need anything else + if self.config["order"] == 0: + logger.info("Scale Variation: no need to compute scale variations at LO") + self.copy_ns_ops() + return + + tot_start_time = time.perf_counter() + # setup ingredients + sc = self.managers["strong_coupling"] + fact_to_ren = self.config["fact_to_ren"] + a_s = sc.a_s(self.q2_from / fact_to_ren, fact_scale=self.q2_from, nf_to=self.nf) + logger.info( + "Scale Variation: (µ_F/µ_R)^2 = %e, Q^2 = %e, nf=%d", + fact_to_ren, + self.q2_from, + self.nf, + ) + logger.info("Scale Variation: computing operators - 0/%d", grid_size) + # iterate output grid + for k, logx in enumerate(np.log(int_disp.xgrid_raw)): + start_time = time.perf_counter() + # iterate basis functions + for l, bf in enumerate(int_disp): + if k == l and l == grid_size - 1: + continue + # iterate sectors + for label in labels: + # compute and set + res = integrate.quad( + quad_ker, + 0.5, + 1.0 - self._mellin_cut, + args=( + self.config["order"], + label, + int_disp.log, + logx, + bf.areas_representation, + a_s, + self.nf, + np.log(fact_to_ren), + ), + epsabs=1e-12, + epsrel=1e-5, + limit=100, + full_output=1, + ) + val, err = res[:2] + self.op_members[label].value[k][l] = val + self.op_members[label].error[k][l] = err + + logger.info( + "Scale Variation: computing operators - %d/%d took: %f s", + k + 1, + grid_size, + time.perf_counter() - start_time, + ) + + # closing comment + logger.info( + "Scale Variation: Total time %f s", time.perf_counter() - tot_start_time + ) + # copy non-singlet kernels, if necessary + self.copy_ns_ops() From a1acc58697d99a5ef95d4da82cf9ef73e92b9f64 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 7 Feb 2022 19:15:06 +0100 Subject: [PATCH 02/74] Add some sv scheme B tests --- tests/benchmark_evol_to_unity.py | 1 + tests/test_ev_op_grid.py | 21 ++++ tests/test_ev_operator.py | 1 + tests/test_interpolation.py | 8 +- tests/test_ome.py | 1 + tests/test_runner.py | 1 + tests/test_strong_coupling.py | 1 + tests/test_sv_scheme_B.py | 167 +++++++++++++++++++++++++++++++ 8 files changed, 197 insertions(+), 4 deletions(-) create mode 100644 tests/test_sv_scheme_B.py diff --git a/tests/benchmark_evol_to_unity.py b/tests/benchmark_evol_to_unity.py index e9f33fbe7..3ce7c91a8 100644 --- a/tests/benchmark_evol_to_unity.py +++ b/tests/benchmark_evol_to_unity.py @@ -33,6 +33,7 @@ class TestBackwardForward: "MaxNfPdf": 6, "MaxNfAs": 6, "HQ": "POLE", + "SV_scheme": None, } operators_card = { "Q2grid": [10], diff --git a/tests/test_ev_op_grid.py b/tests/test_ev_op_grid.py index 938d8d030..8ab47a33e 100644 --- a/tests/test_ev_op_grid.py +++ b/tests/test_ev_op_grid.py @@ -36,6 +36,7 @@ def _get_setup(self, use_FFNS): "MaxNfPdf": 6, "MaxNfAs": 6, "HQ": "POLE", + "SV_scheme": None, } operators_card = { "Q2grid": [1, 100 ** 2], @@ -134,3 +135,23 @@ def test_alphas(self): ) sv_opg = sv_opgrid.compute(3) assert opg[3]["alphas"] < sv_opg[3]["alphas"] + + def test_scheme_B(self): + opgrid = self._get_operator_grid( + theory_update={ + "PTO": 1, + "SV_scheme": "B", + } + ) + opg = opgrid.compute(3) + sv_opgrid = self._get_operator_grid( + theory_update={ + "fact_to_ren_scale_ratio": 1.0 + 1e-3, + "PTO": 1, + "SV_scheme": "B", + } + ) + sv_opg = sv_opgrid.compute(3) + np.testing.assert_allclose( + opg[3]["operators"], sv_opg[3]["operators"], atol=1e-4 + ) diff --git a/tests/test_ev_operator.py b/tests/test_ev_operator.py index 4a657e575..ac479b8a9 100644 --- a/tests/test_ev_operator.py +++ b/tests/test_ev_operator.py @@ -165,6 +165,7 @@ def test_compute(self, monkeypatch): "MaxNfPdf": 6, "MaxNfAs": 6, "HQ": "POLE", + "SV_scheme": None, } operators_card = { "Q2grid": [1, 10], diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index c4e06b7b6..a58c5e60d 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -240,11 +240,11 @@ def test_log_eval_N(self): assert_almost_equal(act_c, res_c) # Full -> \tilde p_0(N) = exp(-N)(exp(N)-1-N)/N^2 # MMa: Integrate[x^(n-1) (-Log[x]),{x,1/E,1}] - p0Nref_full = lambda N, lnx: ((np.exp(N) - 1 - N) / N**2) * np.exp( + p0Nref_full = lambda N, lnx: ((np.exp(N) - 1 - N) / N ** 2) * np.exp( -N * (lnx + 1) ) # partial = lower bound is neglected; - p0Nref_partial = lambda N, lnx: (1 / N**2) * np.exp(-N * lnx) + p0Nref_partial = lambda N, lnx: (1 / N ** 2) * np.exp(-N * lnx) p1N = inter_N[1] assert len(p1N.areas) == 1 p1_cs_ref = [1, 1] @@ -252,8 +252,8 @@ def test_log_eval_N(self): assert_almost_equal(act_c, res_c) # p_1(x) = 1+\ln(x) -> \tilde p_1(N) = (exp(-N)-1+N)/N^2 # MMa: Integrate[x^(n-1) (1+Log[x]),{x,1/E,1}] - p1Nref_full = lambda N, lnx: ((np.exp(-N) - 1 + N) / N**2) * np.exp(-N * lnx) - p1Nref_partial = lambda N, lnx: (1 / N - 1 / N**2) * np.exp(-N * lnx) + p1Nref_full = lambda N, lnx: ((np.exp(-N) - 1 + N) / N ** 2) * np.exp(-N * lnx) + p1Nref_partial = lambda N, lnx: (1 / N - 1 / N ** 2) * np.exp(-N * lnx) # iterate configurations for N in [1.0, 2.0, complex(1.0, 1.0)]: # check skip diff --git a/tests/test_ome.py b/tests/test_ome.py index 9cd9c2105..f286cebc6 100644 --- a/tests/test_ome.py +++ b/tests/test_ome.py @@ -220,6 +220,7 @@ class TestOperatorMatrixElement: "MaxNfPdf": 6, "MaxNfAs": 6, "HQ": "POLE", + "SV_scheme": None, } def test_labels(self): diff --git a/tests/test_runner.py b/tests/test_runner.py index b31f88331..e02a45b1b 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -30,6 +30,7 @@ "Qmc": 1.0, "Qmb": 4.75, "Qmt": 173.0, + "SV_scheme": None, } operators_card = { "Q2grid": [10, 100], diff --git a/tests/test_strong_coupling.py b/tests/test_strong_coupling.py index 20ef41af8..028e5adbc 100644 --- a/tests/test_strong_coupling.py +++ b/tests/test_strong_coupling.py @@ -28,6 +28,7 @@ def test_from_dict(self): "ktThr": 1.0, "MaxNfAs": 6, "HQ": "POLE", + "SV_scheme": None, } sc = StrongCoupling.from_dict(d) assert sc.a_s(d["Qref"] ** 2) == d["alphas"] / (4.0 * np.pi) diff --git a/tests/test_sv_scheme_B.py b/tests/test_sv_scheme_B.py new file mode 100644 index 000000000..f01490218 --- /dev/null +++ b/tests/test_sv_scheme_B.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- + +import numpy as np +import scipy.integrate + +from eko import interpolation, mellin +from eko.evolution_operator.grid import OperatorGrid +from eko.interpolation import InterpolatorDispatcher +from eko.kernels import non_singlet as ns +from eko.kernels import singlet as s +from eko.scale_variations import scheme_B +from eko.strong_coupling import StrongCoupling +from eko.thresholds import ThresholdsAtlas + + +def test_ns_sv_dispacher(): + """Test to identity""" + order = 2 + gamma_ns = np.random.random((order + 1, 2, 2)) + L = 0 + nf = 5 + a_s = 0.35 + np.testing.assert_allclose( + scheme_B.non_singlet_dispatcher(gamma_ns, a_s, order, nf, L), 1 + ) + + +def test_singlet_sv_dispacher(): + """Test to identity""" + order = 2 + gamma_singlet = np.random.random((order + 1, 2, 2)) + L = 0 + nf = 5 + a_s = 0.35 + np.testing.assert_allclose( + scheme_B.singlet_dispatcher(gamma_singlet, a_s, order, nf, L), np.eye(2) + ) + + +def test_quad_ker(monkeypatch): + monkeypatch.setattr( + mellin, "Talbot_path", lambda *args: 2 + ) # N=2 is a safe evaluation point + monkeypatch.setattr( + mellin, "Talbot_jac", lambda *args: complex(0, np.pi) + ) # negate mellin prefactor + monkeypatch.setattr(interpolation, "log_evaluate_Nx", lambda *args: 1) + monkeypatch.setattr(interpolation, "evaluate_Nx", lambda *args: 1) + monkeypatch.setattr(ns, "dispatcher", lambda *args: 1.0) + monkeypatch.setattr(s, "dispatcher", lambda *args: np.identity(2)) + for is_log in [True, False]: + res_ns = scheme_B.quad_ker( + u=0, + order=2, + mode="NS_p", + is_log=is_log, + logx=1.0, + areas=np.zeros(3), + a_s=1, + nf=3, + L=0, + ) + np.testing.assert_allclose(res_ns, 1.0) + res_s = scheme_B.quad_ker( + u=0, + order=2, + mode="S_qq", + is_log=is_log, + logx=1.0, + areas=np.zeros(3), + a_s=1, + nf=3, + L=0, + ) + np.testing.assert_allclose(res_s, 1.0) + res_s = scheme_B.quad_ker( + u=0, + order=2, + mode="S_qg", + is_log=is_log, + logx=1.0, + areas=np.zeros(3), + a_s=1, + nf=3, + L=0, + ) + np.testing.assert_allclose(res_s, 0.0) + res_logx = scheme_B.quad_ker( + u=0, + order=2, + mode="S_qq", + is_log=is_log, + logx=0.0, + areas=np.zeros(3), + a_s=1, + nf=3, + L=10, + ) + np.testing.assert_allclose(res_logx, 0.0) + + +class TestOperator: + def test_compute(self, monkeypatch): + # setup objs + theory_card = { + "alphas": 0.35, + "PTO": 0, + "ModEv": "TRN", + "fact_to_ren_scale_ratio": np.sqrt(2), + "Qref": np.sqrt(2), + "nfref": None, + "Q0": np.sqrt(2), + "nf0": 3, + "FNS": "FFNS", + "NfFF": 3, + "IC": 0, + "IB": 0, + "mc": 1.0, + "mb": 4.75, + "mt": 173.0, + "kcThr": np.inf, + "kbThr": np.inf, + "ktThr": np.inf, + "MaxNfPdf": 6, + "MaxNfAs": 6, + "HQ": "POLE", + "SV_scheme": "B", + } + operators_card = { + "Q2grid": [1, 10], + "interpolation_xgrid": [0.1, 1.0], + "interpolation_polynomial_degree": 1, + "interpolation_is_log": True, + "debug_skip_singlet": False, + "debug_skip_non_singlet": False, + "ev_op_max_order": 1, + "ev_op_iterations": 1, + "backward_inversion": "exact", + } + g = OperatorGrid.from_dict( + theory_card, + operators_card, + ThresholdsAtlas.from_dict(theory_card), + StrongCoupling.from_dict(theory_card), + InterpolatorDispatcher.from_dict(operators_card), + ) + o = scheme_B.ScaleVariationOperator(g.config, g.managers, nf=3, q2=2) + # fake quad + monkeypatch.setattr( + scipy.integrate, "quad", lambda *args, **kwargs: np.random.rand(2) + ) + # LO + o.compute() + assert "NS_m" in o.op_members + np.testing.assert_allclose( + o.op_members["NS_m"].value, o.op_members["NS_p"].value + ) + np.testing.assert_allclose( + o.op_members["NS_v"].value, o.op_members["NS_p"].value + ) + # NLO + o.config["order"] = 1 + o.compute() + assert not np.allclose(o.op_members["NS_p"].value, o.op_members["NS_m"].value) + np.testing.assert_allclose( + o.op_members["NS_v"].value, o.op_members["NS_m"].value + ) From 277591e7c35dd6977704b008070f85d8a5516b6e Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 7 Feb 2022 19:28:51 +0100 Subject: [PATCH 03/74] Update benchmarks runners --- benchmarks/lha_paper_bench.py | 9 +++++++-- benchmarks/pegasus_bench.py | 12 ++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/benchmarks/lha_paper_bench.py b/benchmarks/lha_paper_bench.py index 9ef572229..03887f238 100644 --- a/benchmarks/lha_paper_bench.py +++ b/benchmarks/lha_paper_bench.py @@ -4,8 +4,11 @@ """ import numpy as np +from ekomark import register from ekomark.benchmark.runner import Runner +register(__file__) + base_theory = { "ModEv": "EXA", "Q0": np.sqrt( @@ -75,9 +78,11 @@ def sv_theories(self, pto): low = self.theory.copy() low["PTO"] = pto low["fact_to_ren_scale_ratio"] = np.sqrt(1.0 / 2.0) + low["SV_scheme"] = "A" high = self.theory.copy() high["PTO"] = pto high["fact_to_ren_scale_ratio"] = np.sqrt(2.0) + high["SV_scheme"] = "A" return [high, low] @staticmethod @@ -173,5 +178,5 @@ def skip_pdfs(theory): obj = BenchmarkVFNS() # obj = BenchmarkFFNS() - obj.benchmark_plain(2) - # obj.benchmark_sv(1) + # obj.benchmark_plain(2) + obj.benchmark_sv(1) diff --git a/benchmarks/pegasus_bench.py b/benchmarks/pegasus_bench.py index 36fcc3a9f..e8e4a3ffd 100644 --- a/benchmarks/pegasus_bench.py +++ b/benchmarks/pegasus_bench.py @@ -5,9 +5,11 @@ import numpy as np from banana.data import cartesian_product +from ekomark import register from ekomark.benchmark.runner import Runner from ekomark.data import operators +register(__file__) def tolist(input_dict): output_dict = input_dict.copy() @@ -70,7 +72,7 @@ def benchmark_plain(self, pto): cartesian_product(th), operators.build(operators.pegasus_config), ["ToyLH"] ) - def benchmark_sv(self, pto): + def benchmark_sv(self, pto, scheme): """Scale Variation""" th = self.zm_theory.copy() @@ -78,6 +80,7 @@ def benchmark_sv(self, pto): { "PTO": [pto], "fact_to_ren_scale_ratio": [np.sqrt(0.5), np.sqrt(2.0)], + "SV_scheme": [scheme] } ) self.run( @@ -118,7 +121,7 @@ def benchmark_plain(self, pto): cartesian_product(th), operators.build(operators.pegasus_config), ["ToyLH"] ) - def benchmark_sv(self, pto): + def benchmark_sv(self, pto, scheme): """Scale Variation""" th = self.ffns_theory.copy() @@ -126,6 +129,7 @@ def benchmark_sv(self, pto): { "PTO": [pto], "fact_to_ren_scale_ratio": [np.sqrt(0.5), np.sqrt(2.0)], + "SV_scheme": [scheme], } ) self.run( @@ -137,7 +141,7 @@ def benchmark_sv(self, pto): obj = BenchmarkVFNS() # obj = BenchmarkFFNS() - obj.benchmark_plain(1) + # obj.benchmark_plain(1) - # obj.benchmark_sv(1) + obj.benchmark_sv(1, "A") # vfns.benchmark_sv() From 57870280f944872bded50a5bb0408f98b66929fb Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 7 Feb 2022 20:30:37 +0100 Subject: [PATCH 04/74] Small hack in pagasus runner --- benchmarks/pegasus_bench.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/benchmarks/pegasus_bench.py b/benchmarks/pegasus_bench.py index e8e4a3ffd..5bf1d5892 100644 --- a/benchmarks/pegasus_bench.py +++ b/benchmarks/pegasus_bench.py @@ -79,7 +79,8 @@ def benchmark_sv(self, pto, scheme): th.update( { "PTO": [pto], - "fact_to_ren_scale_ratio": [np.sqrt(0.5), np.sqrt(2.0)], + # TODO: why do we need this epsilon to have a good match ?? + "fact_to_ren_scale_ratio": [np.sqrt(0.5),np.sqrt(2.0-1e-8)], "SV_scheme": [scheme] } ) @@ -143,5 +144,5 @@ def benchmark_sv(self, pto, scheme): # obj = BenchmarkFFNS() # obj.benchmark_plain(1) - obj.benchmark_sv(1, "A") + obj.benchmark_sv(2, "A") # vfns.benchmark_sv() From 4558ef57772e4f56984423d15e708ed32fdba0ef Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 7 Feb 2022 20:31:42 +0100 Subject: [PATCH 05/74] Move scale var A to a module --- src/eko/evolution_operator/__init__.py | 97 +++----------------------- src/eko/scale_variations/scheme_A.py | 74 ++++++++++++++++++++ 2 files changed, 84 insertions(+), 87 deletions(-) create mode 100644 src/eko/scale_variations/scheme_A.py diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 3f17e4bc1..59218d0ae 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -13,96 +13,15 @@ from scipy import integrate from .. import anomalous_dimensions as ad -from .. import beta, interpolation, mellin +from .. import interpolation, mellin from ..basis_rotation import full_labels, singlet_labels from ..kernels import non_singlet as ns from ..kernels import singlet as s from ..member import OpMember +from ..scale_variations.scheme_A import gamma_ns_fact, gamma_singlet_fact logger = logging.getLogger(__name__) -# TODO: move the scale var A to a proper module - -@nb.njit("c16[:](u1,string,c16,u1,f8,string)", cache=True) -def gamma_ns_fact(order, mode, n, nf, L, sv_scheme): - """ - Adjust the anomalous dimensions with the scale variations. - - Parameters - ---------- - order : int - perturbation order - mode : str - sector element - n : complex - Melling moment - nf : int - number of active flavors - L : float - logarithmic ratio of factorization and renormalization scale - sv_scheme : string - scale variation scheme - - Returns - ------- - gamma_ns : numpy.ndarray - adjusted non-singlet anomalous dimensions - """ - gamma_ns = ad.gamma_ns(order, mode[-1], n, nf) - # since we are modifying *in-place* be carefull, that the order matters! - # and indeed, we need to adjust the high elements first - if sv_scheme == "A": - if order >= 2: - gamma_ns[2] -= ( - 2 * beta.beta(0, nf) * gamma_ns[1] * L - + (beta.beta(1, nf) * L - beta.beta(0, nf) ** 2 * L ** 2) * gamma_ns[0] - ) - if order >= 1: - gamma_ns[1] -= beta.beta(0, nf) * gamma_ns[0] * L - return gamma_ns - - -@nb.njit("c16[:,:,:](u1,c16,u1,f8,string)", cache=True) -def gamma_singlet_fact(order, n, nf, L, sv_scheme): - """ - Adjust the anomalous dimensions with the scale variations. - - Parameters - ---------- - order : int - perturbation order - mode : str - sector element - n : complex - Melling moment - nf : int - number of active flavors - L : float - logarithmic ratio of factorization and renormalization scale - sv_scheme : string - scale variation scheme - - Returns - ------- - gamma_singlet : numpy.ndarray - adjusted singlet anomalous dimensions - """ - gamma_singlet = ad.gamma_singlet( - order, - n, - nf, - ) - # concerning order: see comment at gamma_ns_fact - if sv_scheme == "A": - if order >= 2: - gamma_singlet[2] -= ( - 2 * beta.beta(0, nf) * gamma_singlet[1] * L - + (beta.beta(1, nf) * L - beta.beta(0, nf) ** 2 * L ** 2) * gamma_singlet[0] - ) - if order >= 1: - gamma_singlet[1] -= beta.beta(0, nf) * gamma_singlet[0] * L - return gamma_singlet - @nb.njit("f8(f8,u1,string,string,b1,f8,f8[:,:],f8,f8,f8,f8,u4,u1,string)", cache=True) def quad_ker( @@ -119,7 +38,7 @@ def quad_ker( L, ev_op_iterations, ev_op_max_order, - sv_scheme + sv_scheme, ): """ Raw kernel inside quad. @@ -180,7 +99,9 @@ def quad_ker( return 0.0 # compute the actual evolution kernel if is_singlet: - gamma_singlet = gamma_singlet_fact(order, n, nf, L, sv_scheme) + gamma_singlet = ad.gamma_singlet(order, n, nf) + if sv_scheme == "A": + gamma_singlet = gamma_singlet_fact(gamma_singlet, order, nf, L) ker = s.dispatcher( order, method, gamma_singlet, a1, a0, nf, ev_op_iterations, ev_op_max_order ) @@ -189,7 +110,9 @@ def quad_ker( l = 0 if mode[3] == "q" else 1 ker = ker[k, l] else: - gamma_ns = gamma_ns_fact(order, mode, n, nf, L, sv_scheme) + gamma_ns = ad.gamma_ns(order, mode[-1], n, nf) + if sv_scheme == "A": + gamma_ns = gamma_ns_fact(gamma_ns, order, nf, L) ker = ns.dispatcher( order, method, @@ -339,7 +262,7 @@ def compute(self): np.log(fact_to_ren), self.config["ev_op_iterations"], self.config["ev_op_max_order"], - self.config["SV_scheme"] + self.config["SV_scheme"], ), epsabs=1e-12, epsrel=1e-5, diff --git a/src/eko/scale_variations/scheme_A.py b/src/eko/scale_variations/scheme_A.py new file mode 100644 index 000000000..94bea7b97 --- /dev/null +++ b/src/eko/scale_variations/scheme_A.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +r""" +This module contains the scale varion operator in scheme A +""" +import numba as nb + +from .. import beta + +# TODO: if possible to unify this two functions, +# they differ only for the numba decorator + +@nb.njit("c16[:](c16[:],u1,u1,f8)", cache=True) +def gamma_ns_fact(gamma,order, nf, L): + """ + Adjust the anomalous dimensions with the scale variations. + + Parameters + ---------- + gamma : numpy.ndarray + anomalous dimensions + order : int + perturbation order + nf : int + number of active flavors + L : float + logarithmic ratio of factorization and renormalization scale + + Returns + ------- + gamma_ns : numpy.ndarray + adjusted non-singlet anomalous dimensions + """ + # since we are modifying *in-place* be carefull, that the order matters! + # and indeed, we need to adjust the high elements first + if order >= 2: + gamma[2] -= ( + 2 * beta.beta(0, nf) * gamma[1] * L + + (beta.beta(1, nf) * L - beta.beta(0, nf) ** 2 * L ** 2) * gamma[0] + ) + if order >= 1: + gamma[1] -= beta.beta(0, nf) * gamma[0] * L + return gamma + + +@nb.njit("c16[:,:,:](c16[:,:,:],u1,u1,f8)", cache=True) +def gamma_singlet_fact(gamma, order, nf, L): + """ + Adjust the anomalous dimensions with the scale variations. + + Parameters + ---------- + gamma : numpy.ndarray + anomalous dimensions + order : int + perturbation order + nf : int + number of active flavors + L : float + logarithmic ratio of factorization and renormalization scale + + Returns + ------- + gamma_singlet : numpy.ndarray + adjusted singlet anomalous dimensions + """ + # concerning order: see comment at gamma_ns_fact + if order >= 2: + gamma[2] -= ( + 2 * beta.beta(0, nf) * gamma[1] * L + + (beta.beta(1, nf) * L - beta.beta(0, nf) ** 2 * L ** 2) * gamma[0] + ) + if order >= 1: + gamma[1] -= beta.beta(0, nf) * gamma[0] * L + return gamma From ce00e3d69c05ec14a268998fd8514fa20e86d333 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 7 Feb 2022 20:33:08 +0100 Subject: [PATCH 06/74] Restore tests --- tests/test_ev_operator.py | 56 +++++++++++++++++++++------------------ tests/test_sv_scheme_A.py | 30 +++++++++++++++++++++ 2 files changed, 60 insertions(+), 26 deletions(-) create mode 100644 tests/test_sv_scheme_A.py diff --git a/tests/test_ev_operator.py b/tests/test_ev_operator.py index ac479b8a9..49ec19b02 100644 --- a/tests/test_ev_operator.py +++ b/tests/test_ev_operator.py @@ -6,7 +6,7 @@ from eko import anomalous_dimensions as ad from eko import basis_rotation as br from eko import interpolation, mellin -from eko.evolution_operator import Operator, gamma_ns_fact, gamma_singlet_fact, quad_ker +from eko.evolution_operator import Operator, quad_ker from eko.evolution_operator.grid import OperatorGrid from eko.interpolation import InterpolatorDispatcher from eko.kernels import non_singlet as ns @@ -14,31 +14,30 @@ from eko.strong_coupling import StrongCoupling from eko.thresholds import ThresholdsAtlas +# def test_gamma_ns_fact(monkeypatch): +# gamma_ns = np.array([1.0, 0.5, 0.25]) +# monkeypatch.setattr(ad, "gamma_ns", lambda *args: gamma_ns.copy()) +# gamma_ns_LO_0 = gamma_ns_fact(0, "NS_p", 1, 3, 0) +# np.testing.assert_allclose(gamma_ns_LO_0, gamma_ns) +# gamma_ns_LO_1 = gamma_ns_fact(0, "NS_p", 1, 3, 1) +# np.testing.assert_allclose(gamma_ns_LO_1, gamma_ns) +# gamma_ns_NLO_1 = gamma_ns_fact(1, "NS_p", 1, 3, 1) +# assert gamma_ns_NLO_1[1] < gamma_ns[1] +# gamma_ns_NNLO_1 = gamma_ns_fact(2, "NS_p", 1, 3, 1) +# assert gamma_ns_NNLO_1[2] - gamma_ns[2] == 8.0 -def test_gamma_ns_fact(monkeypatch): - gamma_ns = np.array([1.0, 0.5, 0.25]) - monkeypatch.setattr(ad, "gamma_ns", lambda *args: gamma_ns.copy()) - gamma_ns_LO_0 = gamma_ns_fact(0, "NS_p", 1, 3, 0) - np.testing.assert_allclose(gamma_ns_LO_0, gamma_ns) - gamma_ns_LO_1 = gamma_ns_fact(0, "NS_p", 1, 3, 1) - np.testing.assert_allclose(gamma_ns_LO_1, gamma_ns) - gamma_ns_NLO_1 = gamma_ns_fact(1, "NS_p", 1, 3, 1) - assert gamma_ns_NLO_1[1] < gamma_ns[1] - gamma_ns_NNLO_1 = gamma_ns_fact(2, "NS_p", 1, 3, 1) - assert gamma_ns_NNLO_1[2] - gamma_ns[2] == 8.0 - -def test_gamma_singlet_fact(monkeypatch): - gamma_s = np.array([1.0, 0.5, 0.25]) - monkeypatch.setattr(ad, "gamma_singlet", lambda *args: gamma_s.copy()) - gamma_s_LO_0 = gamma_singlet_fact(0, 1, 3, 0) - np.testing.assert_allclose(gamma_s_LO_0, gamma_s) - gamma_s_LO_1 = gamma_singlet_fact(0, 1, 3, 1) - np.testing.assert_allclose(gamma_s_LO_1, gamma_s) - gamma_s_NLO_1 = gamma_singlet_fact(1, 1, 3, 1) - assert gamma_s_NLO_1[1] < gamma_s[1] - gamma_s_NNLO_1 = gamma_singlet_fact(2, 1, 3, 1) - assert gamma_s_NNLO_1[2] - gamma_s[2] == 8.0 +# def test_gamma_singlet_fact(monkeypatch): +# gamma_s = np.array([1.0, 0.5, 0.25]) +# monkeypatch.setattr(ad, "gamma_singlet", lambda *args: gamma_s.copy()) +# gamma_s_LO_0 = gamma_singlet_fact(0, 1, 3, 0) +# np.testing.assert_allclose(gamma_s_LO_0, gamma_s) +# gamma_s_LO_1 = gamma_singlet_fact(0, 1, 3, 1) +# np.testing.assert_allclose(gamma_s_LO_1, gamma_s) +# gamma_s_NLO_1 = gamma_singlet_fact(1, 1, 3, 1) +# assert gamma_s_NLO_1[1] < gamma_s[1] +# gamma_s_NNLO_1 = gamma_singlet_fact(2, 1, 3, 1) +# assert gamma_s_NNLO_1[2] - gamma_s[2] == 8.0 def test_quad_ker(monkeypatch): @@ -67,6 +66,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, + sv_scheme=None, ) np.testing.assert_allclose(res_ns, 0.0) res_s = quad_ker( @@ -83,6 +83,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, + sv_scheme=None, ) np.testing.assert_allclose(res_s, 1.0) res_s = quad_ker( @@ -99,6 +100,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, + sv_scheme=None, ) np.testing.assert_allclose(res_s, 0.0) monkeypatch.setattr(interpolation, "log_evaluate_Nx", lambda *args: 0) @@ -116,6 +118,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, + sv_scheme=None, ) np.testing.assert_allclose(res_ns, 0.0) @@ -225,7 +228,7 @@ def quad_ker_pegasus( phi = 3 / 4 * np.pi c = 1.9 n = complex(c + u * np.exp(1j * phi)) - gamma_ns = gamma_ns_fact(order, mode, n, nf, L) + gamma_ns = ad.gamma_ns(order, mode[-1], n, nf) ker = ns.dispatcher( order, method, @@ -238,7 +241,7 @@ def quad_ker_pegasus( pj = interpolation.log_evaluate_Nx(n, logx, areas) return np.imag(np.exp(1j * phi) / np.pi * pj * ker) - # It might be useful to test with a different fuction + # It might be useful to test with a different function # monkeypatch.setattr(ns, "dispatcher", lambda x, *args: np.exp( - x ** 2 ) ) xgrid = np.geomspace(1e-7, 1, 10) int_disp = InterpolatorDispatcher(xgrid, 1, True) @@ -270,6 +273,7 @@ def quad_ker_pegasus( L, ev_op_iterations, 10, + None, ), epsabs=1e-12, epsrel=1e-5, diff --git a/tests/test_sv_scheme_A.py b/tests/test_sv_scheme_A.py new file mode 100644 index 000000000..c287e246c --- /dev/null +++ b/tests/test_sv_scheme_A.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- + +import numpy as np + +from eko import anomalous_dimensions as ad +from eko.scale_variations.scheme_A import gamma_ns_fact, gamma_singlet_fact + + +def test_gamma_ns_fact(): + gamma_ns = np.array([1.0, 0.5, 0.25]) + gamma_ns_LO_0 = gamma_ns_fact(gamma_ns.copy(), 0, 3, 0) + np.testing.assert_allclose(gamma_ns_LO_0, gamma_ns) + gamma_ns_LO_1 = gamma_ns_fact(gamma_ns.copy(), 0, 3, 1) + np.testing.assert_allclose(gamma_ns_LO_1, gamma_ns) + gamma_ns_NLO_1 = gamma_ns_fact(gamma_ns.copy(), 1, 3, 1) + assert gamma_ns_NLO_1[1] < gamma_ns[1] + gamma_ns_NNLO_1 = gamma_ns_fact(gamma_ns.copy(), 2, 3, 1) + assert gamma_ns_NNLO_1[2] - gamma_ns[2] == 8.0 + + +def test_gamma_singlet_fact(): + gamma_s = np.array([1.0, 0.5, 0.25]) + gamma_s_LO_0 = gamma_singlet_fact(gamma_s.copy(), 0, 3, 0) + np.testing.assert_allclose(gamma_s_LO_0, gamma_s) + gamma_s_LO_1 = gamma_singlet_fact(gamma_s.copy(), 0, 3, 1) + np.testing.assert_allclose(gamma_s_LO_1, gamma_s) + gamma_s_NLO_1 = gamma_singlet_fact(gamma_s.copy(), 1, 3, 1) + assert gamma_s_NLO_1[1] < gamma_s[1] + gamma_s_NNLO_1 = gamma_singlet_fact(gamma_s.copy(), 2, 3, 1) + assert gamma_s_NNLO_1[2] - gamma_s[2] == 8.0 From 5914f12dd9dc1ce7003186132191d33e85536867 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 8 Feb 2022 09:43:52 +0100 Subject: [PATCH 07/74] Fix names convention as suggested --- src/eko/evolution_operator/__init__.py | 2 +- src/eko/evolution_operator/grid.py | 2 +- .../scale_variations/{scheme_A.py => a.py} | 2 +- .../scale_variations/{scheme_B.py => b.py} | 0 tests/test_ev_operator.py | 28 +------------------ tests/{test_sv_scheme_A.py => test_sv_a.py} | 3 +- tests/{test_sv_scheme_B.py => test_sv_b.py} | 16 +++++------ 7 files changed, 13 insertions(+), 40 deletions(-) rename src/eko/scale_variations/{scheme_A.py => a.py} (97%) rename src/eko/scale_variations/{scheme_B.py => b.py} (100%) rename tests/{test_sv_scheme_A.py => test_sv_a.py} (90%) rename tests/{test_sv_scheme_B.py => test_sv_b.py} (91%) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 59218d0ae..709bc0a51 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -18,7 +18,7 @@ from ..kernels import non_singlet as ns from ..kernels import singlet as s from ..member import OpMember -from ..scale_variations.scheme_A import gamma_ns_fact, gamma_singlet_fact +from ..scale_variations.a import gamma_ns_fact, gamma_singlet_fact logger = logging.getLogger(__name__) diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py index 145626c3f..aa02e06e2 100644 --- a/src/eko/evolution_operator/grid.py +++ b/src/eko/evolution_operator/grid.py @@ -15,7 +15,7 @@ from eko.evolution_operator import flavors from ..matching_conditions.operator_matrix_element import OperatorMatrixElement -from ..scale_variations.scheme_B import ScaleVariationOperator +from ..scale_variations.b import ScaleVariationOperator from . import Operator, physical logger = logging.getLogger(__name__) diff --git a/src/eko/scale_variations/scheme_A.py b/src/eko/scale_variations/a.py similarity index 97% rename from src/eko/scale_variations/scheme_A.py rename to src/eko/scale_variations/a.py index 94bea7b97..6f268a03a 100644 --- a/src/eko/scale_variations/scheme_A.py +++ b/src/eko/scale_variations/a.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- r""" -This module contains the scale varion operator in scheme A +This module contains the scale varion for scheme A """ import numba as nb diff --git a/src/eko/scale_variations/scheme_B.py b/src/eko/scale_variations/b.py similarity index 100% rename from src/eko/scale_variations/scheme_B.py rename to src/eko/scale_variations/b.py diff --git a/tests/test_ev_operator.py b/tests/test_ev_operator.py index 49ec19b02..5af365a65 100644 --- a/tests/test_ev_operator.py +++ b/tests/test_ev_operator.py @@ -14,31 +14,6 @@ from eko.strong_coupling import StrongCoupling from eko.thresholds import ThresholdsAtlas -# def test_gamma_ns_fact(monkeypatch): -# gamma_ns = np.array([1.0, 0.5, 0.25]) -# monkeypatch.setattr(ad, "gamma_ns", lambda *args: gamma_ns.copy()) -# gamma_ns_LO_0 = gamma_ns_fact(0, "NS_p", 1, 3, 0) -# np.testing.assert_allclose(gamma_ns_LO_0, gamma_ns) -# gamma_ns_LO_1 = gamma_ns_fact(0, "NS_p", 1, 3, 1) -# np.testing.assert_allclose(gamma_ns_LO_1, gamma_ns) -# gamma_ns_NLO_1 = gamma_ns_fact(1, "NS_p", 1, 3, 1) -# assert gamma_ns_NLO_1[1] < gamma_ns[1] -# gamma_ns_NNLO_1 = gamma_ns_fact(2, "NS_p", 1, 3, 1) -# assert gamma_ns_NNLO_1[2] - gamma_ns[2] == 8.0 - - -# def test_gamma_singlet_fact(monkeypatch): -# gamma_s = np.array([1.0, 0.5, 0.25]) -# monkeypatch.setattr(ad, "gamma_singlet", lambda *args: gamma_s.copy()) -# gamma_s_LO_0 = gamma_singlet_fact(0, 1, 3, 0) -# np.testing.assert_allclose(gamma_s_LO_0, gamma_s) -# gamma_s_LO_1 = gamma_singlet_fact(0, 1, 3, 1) -# np.testing.assert_allclose(gamma_s_LO_1, gamma_s) -# gamma_s_NLO_1 = gamma_singlet_fact(1, 1, 3, 1) -# assert gamma_s_NLO_1[1] < gamma_s[1] -# gamma_s_NNLO_1 = gamma_singlet_fact(2, 1, 3, 1) -# assert gamma_s_NNLO_1[2] - gamma_s[2] == 8.0 - def test_quad_ker(monkeypatch): monkeypatch.setattr( @@ -222,7 +197,7 @@ def test_compute(self, monkeypatch): def test_pegasus_path(): def quad_ker_pegasus( - u, order, mode, method, logx, areas, a1, a0, nf, L, ev_op_iterations + u, order, mode, method, logx, areas, a1, a0, nf, ev_op_iterations ): # compute the mellin inversion as done in pegasus phi = 3 / 4 * np.pi @@ -294,7 +269,6 @@ def quad_ker_pegasus( a1, a0, nf, - L, ev_op_iterations, ), epsabs=1e-12, diff --git a/tests/test_sv_scheme_A.py b/tests/test_sv_a.py similarity index 90% rename from tests/test_sv_scheme_A.py rename to tests/test_sv_a.py index c287e246c..c11f00de9 100644 --- a/tests/test_sv_scheme_A.py +++ b/tests/test_sv_a.py @@ -2,8 +2,7 @@ import numpy as np -from eko import anomalous_dimensions as ad -from eko.scale_variations.scheme_A import gamma_ns_fact, gamma_singlet_fact +from eko.scale_variations.a import gamma_ns_fact, gamma_singlet_fact def test_gamma_ns_fact(): diff --git a/tests/test_sv_scheme_B.py b/tests/test_sv_b.py similarity index 91% rename from tests/test_sv_scheme_B.py rename to tests/test_sv_b.py index f01490218..61f22ce04 100644 --- a/tests/test_sv_scheme_B.py +++ b/tests/test_sv_b.py @@ -8,7 +8,7 @@ from eko.interpolation import InterpolatorDispatcher from eko.kernels import non_singlet as ns from eko.kernels import singlet as s -from eko.scale_variations import scheme_B +from eko.scale_variations import b from eko.strong_coupling import StrongCoupling from eko.thresholds import ThresholdsAtlas @@ -21,7 +21,7 @@ def test_ns_sv_dispacher(): nf = 5 a_s = 0.35 np.testing.assert_allclose( - scheme_B.non_singlet_dispatcher(gamma_ns, a_s, order, nf, L), 1 + b.non_singlet_dispatcher(gamma_ns, a_s, order, nf, L), 1 ) @@ -33,7 +33,7 @@ def test_singlet_sv_dispacher(): nf = 5 a_s = 0.35 np.testing.assert_allclose( - scheme_B.singlet_dispatcher(gamma_singlet, a_s, order, nf, L), np.eye(2) + b.singlet_dispatcher(gamma_singlet, a_s, order, nf, L), np.eye(2) ) @@ -49,7 +49,7 @@ def test_quad_ker(monkeypatch): monkeypatch.setattr(ns, "dispatcher", lambda *args: 1.0) monkeypatch.setattr(s, "dispatcher", lambda *args: np.identity(2)) for is_log in [True, False]: - res_ns = scheme_B.quad_ker( + res_ns = b.quad_ker( u=0, order=2, mode="NS_p", @@ -61,7 +61,7 @@ def test_quad_ker(monkeypatch): L=0, ) np.testing.assert_allclose(res_ns, 1.0) - res_s = scheme_B.quad_ker( + res_s = b.quad_ker( u=0, order=2, mode="S_qq", @@ -73,7 +73,7 @@ def test_quad_ker(monkeypatch): L=0, ) np.testing.assert_allclose(res_s, 1.0) - res_s = scheme_B.quad_ker( + res_s = b.quad_ker( u=0, order=2, mode="S_qg", @@ -85,7 +85,7 @@ def test_quad_ker(monkeypatch): L=0, ) np.testing.assert_allclose(res_s, 0.0) - res_logx = scheme_B.quad_ker( + res_logx = b.quad_ker( u=0, order=2, mode="S_qq", @@ -144,7 +144,7 @@ def test_compute(self, monkeypatch): StrongCoupling.from_dict(theory_card), InterpolatorDispatcher.from_dict(operators_card), ) - o = scheme_B.ScaleVariationOperator(g.config, g.managers, nf=3, q2=2) + o = b.ScaleVariationOperator(g.config, g.managers, nf=3, q2=2) # fake quad monkeypatch.setattr( scipy.integrate, "quad", lambda *args, **kwargs: np.random.rand(2) From 411102f9a3fafaf07b6e1029cb84e20190da7cfe Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 8 Feb 2022 10:45:22 +0100 Subject: [PATCH 08/74] Fix pegasus sv runner --- benchmarks/pegasus_bench.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmarks/pegasus_bench.py b/benchmarks/pegasus_bench.py index 5bf1d5892..88a07dde7 100644 --- a/benchmarks/pegasus_bench.py +++ b/benchmarks/pegasus_bench.py @@ -56,6 +56,7 @@ class BenchmarkVFNS(PegasusBenchmark): "Qref": np.sqrt(2.0), "alphas": 0.35, "Q0": np.sqrt(2.0), + "nfref": 3, } zm_theory = tolist(zm_theory) @@ -79,8 +80,7 @@ def benchmark_sv(self, pto, scheme): th.update( { "PTO": [pto], - # TODO: why do we need this epsilon to have a good match ?? - "fact_to_ren_scale_ratio": [np.sqrt(0.5),np.sqrt(2.0-1e-8)], + "fact_to_ren_scale_ratio": [np.sqrt(0.5),np.sqrt(2.0)], "SV_scheme": [scheme] } ) From 02dd139194b89e5277d9e0a53f3cd3dde743badb Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Wed, 9 Feb 2022 11:29:19 +0100 Subject: [PATCH 09/74] Add some docs for SV b --- doc/source/theory/pQCD.rst | 52 ++++++++++++++++++++++++++++------- src/eko/scale_variations/a.py | 2 +- src/eko/scale_variations/b.py | 2 +- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index 3a9aba25e..8054f4afb 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -46,23 +46,55 @@ Note the additional minus in the definition of :math:`\gamma`. Scale Variations ---------------- -The usual procedure in solving |DGLAP| that is also applied :doc:`here +The usual procedure in solving |DGLAP| applied :doc:`here ` is to rewrite the equations in term of the running coupling :math:`a_s` assuming the factorization scale :math:`\mu_F^2` (the inherit scale of the |PDF|) and the renormalization scale :math:`\mu_R^2` (the inherit scale -for the strong coupling) to be equal. This constraint can however be lifted by a -suitable redefinition of the splitting kernels :cite:`Vogt:2004ns`: +for the strong coupling) to be equal. +This constraint, however, can be lifted in order to provide an estimation of the +missing higher order uncertainties (MHOU) coming from |DGLAP| evolution :cite:`AbdulKhalek:2019ihb`. +Since scale-dependent contributions to a perturbative prediction are fixed by |RGE| invariance, +the scale variation can be used to generate higher order contributions, +which are then taken as a proxy for the whole missing higher orders. +This method provides many advantages: -.. math :: - \gamma^{(1)}(N) &\to \gamma^{(1)}(N) - \beta_0 \ln(\mu_F^2/\mu_R^2) \gamma^{(0)} \\ - \gamma^{(2)}(N) &\to \gamma^{(2)}(N) - 2 \beta_0 \ln(\mu_F^2/\mu_R^2) \gamma^{(1)} - ( \beta_1 \ln(\mu_F^2/\mu_R^2) - \beta_0^2 \ln^2(\mu_F^2/\mu_R^2) ) \gamma^{(0)} + * it naturally incorporates renormalization group invariance, + as the perturbative order increases, estimates of MHOU decrease; + * the same procedure can be used for any perturbative process, + since the scale dependence of the strong coupling :math:`a_s(\mu^2)` and of PDFs is universal; + +However there is no unique principle to determine the specific range of the scale variation; +the most used prescription specify to vary the factor :math:`\mu_F/\mu_R` in the range: +:math:`1/2 \le \mu_F/\mu_R \le 2`. + +This variation can be performed at least at two different levels during the |PDF| +evolution, always evaluating the strong coupling at :math:`\mu_R^2`. + + * For ``SV_scheme='A'`` the variation is applied directly to the splitting functions + and the anomalous dimension are then modified using :cite:`Vogt:2004ns`: + + .. math :: + & \gamma^{(1)}(N) \to \gamma^{(1)}(N) - \beta_0 L \gamma^{(0)} \\ + & \gamma^{(2)}(N) \to \gamma^{(2)}(N) - 2 \beta_0 L \gamma^{(1)} - ( \beta_1 L - \beta_0^2 L^2) \gamma^{(0)} \\ + & L= \ln(\mu_F^2/\mu_R^2) + + * In ``SV_scheme='B'`` the |EKO| is multiplied by an additional kernel, such that + the scale variation is applied to the whole |PDF| set: + + .. math :: + \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) = \left[ 1 - L \gamma +L^2(\gamma^{2} + \frac{\partial \gamma}{\partial a_s} \beta(a_s)) + ... \right] \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) + + where scale variation kernel is expanded consistently order by order in :math:`a_s`, + leading to: + .. math :: + 1 - L \gamma +L^2(\gamma^{2} + \frac{\partial \gamma}{\partial a_s} \beta(a_s)) = + 1 - a_s L \gamma^{(0)} + a_s^2 \left [ L \gamma^{(1)} + \frac{1}{2} L^2 \gamma^{(0)} (\gamma^{(0)}+\beta_0) \right ] -while keeping the evaluation of the strong coupling always at :math:`\mu_R^2`. -Estimating the theoretical uncertainties imposed on |PDF| determination due to -missing higher order corrections using scale variation in the evolution -corresponds to schemes A and B in :cite:`AbdulKhalek:2019ihb`. + In this way the dependence of the |EKO| on :math:`L` is factorized outside the unvaried evolution kernel. +Notice that the two methods should be equivalent, especially for fully linearized solutions +(`ModEv=truncaded,ev_op_max_order=1`) Heavy Quark Masses ------------------ diff --git a/src/eko/scale_variations/a.py b/src/eko/scale_variations/a.py index 6f268a03a..99e382292 100644 --- a/src/eko/scale_variations/a.py +++ b/src/eko/scale_variations/a.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- r""" -This module contains the scale varion for scheme A +This module contains the scale variation for scheme A """ import numba as nb diff --git a/src/eko/scale_variations/b.py b/src/eko/scale_variations/b.py index 890f31f6b..64fbd272e 100644 --- a/src/eko/scale_variations/b.py +++ b/src/eko/scale_variations/b.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- r""" -This module contains the scale varion operator in scheme B +This module contains the scale variation operator in scheme B """ import logging From 9ce322b3d2a5bc80147183ad56227158d6b337ff Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Fri, 11 Feb 2022 11:06:15 +0100 Subject: [PATCH 10/74] Update runners and adding eko_bench script --- benchmarks/apfel_bench.py | 9 +- benchmarks/eko_bench.py | 113 +++++++++++++++++++++++++ benchmarks/lha_paper_bench.py | 4 +- benchmarks/pegasus_bench.py | 8 +- benchmarks/sandbox.py | 2 +- doc/source/theory/pQCD.rst | 2 +- src/eko/evolution_operator/__init__.py | 2 +- 7 files changed, 129 insertions(+), 11 deletions(-) create mode 100644 benchmarks/eko_bench.py diff --git a/benchmarks/apfel_bench.py b/benchmarks/apfel_bench.py index d7ddb3c33..3c1a36841 100644 --- a/benchmarks/apfel_bench.py +++ b/benchmarks/apfel_bench.py @@ -11,6 +11,7 @@ register(__file__) + def tolist(input_dict): output_dict = input_dict.copy() for key, item in output_dict.items(): @@ -37,7 +38,7 @@ def skip_pdfs(_theory): class BenchmarkVFNS(ApfelBenchmark): - """Benckmark VFNS""" + """Benchmark VFNS""" vfns_theory = { "FNS": "ZM-VFNS", @@ -52,6 +53,8 @@ class BenchmarkVFNS(ApfelBenchmark): "Qref": np.sqrt(2.0), "alphas": 0.35, "Q0": np.sqrt(2.0), + "nfref": 3, + "nf0": 3, } vfns_theory = tolist(vfns_theory) @@ -187,7 +190,7 @@ def benchmark_sv(self, pto, scheme): obj = BenchmarkVFNS() # obj = BenchmarkFFNS() - # obj.benchmark_plain(1) - obj.benchmark_sv(1, "A") + # obj.benchmark_plain(2) + obj.benchmark_sv(2, "A") # obj.benchmark_kthr(2) # obj.benchmark_msbar(2) diff --git a/benchmarks/eko_bench.py b/benchmarks/eko_bench.py new file mode 100644 index 000000000..b4f75b63f --- /dev/null +++ b/benchmarks/eko_bench.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +""" +Run multiple eko benchmarks with the same VFNS settings (as LHA) +and and a fine grid +""" +import numpy as np +from banana import register + +from eko.interpolation import make_lambert_grid +from ekomark.benchmark.runner import Runner + +register(__file__) + +base_theory = { + "ModEv": "EXA", + "Q0": np.sqrt( + 2.0 + ), # Eq. (30) :cite:`Giele:2002hx`, Eq. (4.53) :cite:`Dittmar:2005ed` + "nfref": 3, + "nf0": 3, + "mc": np.sqrt( + 2.0 + ), # Eq. (34) :cite:`Giele:2002hx`, Eq. (4.56) :cite:`Dittmar:2005ed` + "mb": 4.5, + "mt": 175.0, + "Qref": np.sqrt( + 2.0 + ), # Eq. (32) :cite:`Giele:2002hx`,Eq. (4.53) :cite:`Dittmar:2005ed` + "alphas": 0.35, # Eq. (4.55) :cite:`Dittmar:2005ed` + "FNS": "ZM-VFNS", # ignored by eko, but needed by LHA_utils + "kcThr": 1.0, # here you need to start in nf=3 and do the match. + "kbThr": 1.0, + "ktThr": 1.0, +} +"""Global theory settings""" + + +class BenchmarkRunner(Runner): + """ + Generic benchmark runner using the LHA VFNS settings + """ + + def __init__(self, external): + super().__init__() + self.external = external + self.theory = base_theory + self.sandbox = True + self.rotate_to_evolution_basis = True + + def skip_pdfs(self, _theory): + return [22, -6, 6, "ph", "V35", "V24", "V15", "V8", "T35"] + + def run_lha(self, theory_updates): + """ + Enforce operators and PDF + + Parameters + ---------- + theory_updates : list(dict) + theory updates + """ + self.run( + theory_updates, + [ + { + "Q2grid": [1e4], + "ev_op_iterations": 10, + "interpolation_xgrid": make_lambert_grid(60).tolist(), + } + ], + ["ToyLH"], + ) + + def benchmark_sv(self, pto): + """ + Scale variations + + Parameters + ---------- + pto : int + perturbation order + + Returns + ------- + list(dict) + theory updates + """ + # low = base_theory.copy() + # low["PTO"] = pto + # low["fact_to_ren_scale_ratio"] = np.sqrt(1.0 / 2.0) + # low["SV_scheme"] = "A" + high = base_theory.copy() + high["PTO"] = pto + high["fact_to_ren_scale_ratio"] = np.sqrt(2.0) + high["SV_scheme"] = "A" + # needed for apfel + high["XIR"] = np.sqrt(0.5) + high["EScaleVar"] = 0 + self.run_lha([high]) + + def benchmark_plain(self, pto): + """Plain configuration""" + th = self.theory.copy() + th.update({"PTO": pto}) + self.run_lha([th]) + + +if __name__ == "__main__": + + programs = ["LHA", "pegasus", "apfel"] + for p in programs: + obj = BenchmarkRunner(p) + obj.benchmark_sv(2) diff --git a/benchmarks/lha_paper_bench.py b/benchmarks/lha_paper_bench.py index 03887f238..f96f442e9 100644 --- a/benchmarks/lha_paper_bench.py +++ b/benchmarks/lha_paper_bench.py @@ -3,8 +3,8 @@ Benchmark to :cite:`Giele:2002hx` (LO + NLO) and :cite:`Dittmar:2005ed` (NNLO) """ import numpy as np +from banana import register -from ekomark import register from ekomark.benchmark.runner import Runner register(__file__) @@ -14,7 +14,6 @@ "Q0": np.sqrt( 2.0 ), # Eq. (30) :cite:`Giele:2002hx`, Eq. (4.53) :cite:`Dittmar:2005ed` - "nfref": 3, "mc": np.sqrt( 2.0 ), # Eq. (34) :cite:`Giele:2002hx`, Eq. (4.56) :cite:`Dittmar:2005ed` @@ -143,6 +142,7 @@ class BenchmarkVFNS(LHABenchmark): "kbThr": 1.0, "ktThr": 1.0, "nf0": 3, + "nfref": 3, } ) diff --git a/benchmarks/pegasus_bench.py b/benchmarks/pegasus_bench.py index 88a07dde7..7a5feca5c 100644 --- a/benchmarks/pegasus_bench.py +++ b/benchmarks/pegasus_bench.py @@ -3,14 +3,15 @@ Benchmark to Pegasus :cite:`Vogt:2004ns` """ import numpy as np +from banana import register from banana.data import cartesian_product -from ekomark import register from ekomark.benchmark.runner import Runner from ekomark.data import operators register(__file__) + def tolist(input_dict): output_dict = input_dict.copy() for key, item in output_dict.items(): @@ -57,6 +58,7 @@ class BenchmarkVFNS(PegasusBenchmark): "alphas": 0.35, "Q0": np.sqrt(2.0), "nfref": 3, + "nf0": 3, } zm_theory = tolist(zm_theory) @@ -80,8 +82,8 @@ def benchmark_sv(self, pto, scheme): th.update( { "PTO": [pto], - "fact_to_ren_scale_ratio": [np.sqrt(0.5),np.sqrt(2.0)], - "SV_scheme": [scheme] + "fact_to_ren_scale_ratio": [np.sqrt(0.5), np.sqrt(2.0)], + "SV_scheme": [scheme], } ) self.run( diff --git a/benchmarks/sandbox.py b/benchmarks/sandbox.py index efa655934..f02ac47a5 100644 --- a/benchmarks/sandbox.py +++ b/benchmarks/sandbox.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- # pylint: skip-file import numpy as np +from banana import register -from ekomark import register from ekomark.benchmark.runner import Runner from ekomark.data import operators diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index 8054f4afb..3b8d2d530 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -94,7 +94,7 @@ evolution, always evaluating the strong coupling at :math:`\mu_R^2`. In this way the dependence of the |EKO| on :math:`L` is factorized outside the unvaried evolution kernel. Notice that the two methods should be equivalent, especially for fully linearized solutions -(`ModEv=truncaded,ev_op_max_order=1`) +(`ModEv=truncated,ev_op_max_iterations=1`) Heavy Quark Masses ------------------ diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 709bc0a51..1ddbba3cc 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -262,7 +262,7 @@ def compute(self): np.log(fact_to_ren), self.config["ev_op_iterations"], self.config["ev_op_max_order"], - self.config["SV_scheme"], + self.config["SV_scheme"] if self.config["SV_scheme"] is not None else "", ), epsabs=1e-12, epsrel=1e-5, From 056bac1fa9e391c317feb87264350e175ab668d7 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Fri, 11 Feb 2022 15:15:49 +0100 Subject: [PATCH 11/74] Allow for VFNS in scale variation B --- src/eko/evolution_operator/grid.py | 46 +++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py index aa02e06e2..74bf5bd90 100644 --- a/src/eko/evolution_operator/grid.py +++ b/src/eko/evolution_operator/grid.py @@ -81,6 +81,7 @@ def __init__( ) self._threshold_operators = {} self._matching_operators = {} + self._sv_operators = {} @classmethod def from_dict( @@ -186,6 +187,13 @@ def get_threshold_operators(self, path): kthr = thr_config.thresholds_ratios[seg.nf - shift] ome.compute(seg.q2_to, np.log(kthr), self.config["HQ"] == "MSBAR") self._matching_operators[seg.q2_to] = ome.ome_members + # compute the scale variation scheme B + if self.config["SV_scheme"] == "B" and seg.q2_to not in self._sv_operators: + scale_var = ScaleVariationOperator( + self.config, self.managers, seg.nf-shift+3, seg.q2_to + ) + scale_var.compute() + self._sv_operators[seg.q2_to] = scale_var return thr_ops def compute(self, q2grid=None): @@ -216,7 +224,7 @@ def compute(self, q2grid=None): def generate(self, q2): """ - Computes an single EKO. + Computes a single EKO. Parameters ---------- @@ -246,6 +254,19 @@ def generate(self, q2): operator.q2_to, intrinsic_range, ) + # Compute scale variation scheme B + if self.config["SV_scheme"] == "B": + scale_var = ScaleVariationOperator( + self.config, self.managers, operator.nf, operator.q2_to + ) + scale_var.compute() + scale_var_op = physical.PhysicalOperator.ad_to_evol_map( + scale_var.op_members, + scale_var.nf, + scale_var.q2_to, + intrinsic_range, + ) + final_op = scale_var_op @ final_op # and multiply the lower ones from the right for i, op in reversed(list(enumerate(thr_ops))): @@ -253,6 +274,16 @@ def generate(self, q2): phys_op = physical.PhysicalOperator.ad_to_evol_map( op.op_members, op.nf, op.q2_to, intrinsic_range ) + # add the scale variation scheme B operator + if op.q2_to in self._sv_operators: + scale_var = self._sv_operators[op.q2_to] + scale_var_op = physical.PhysicalOperator.ad_to_evol_map( + scale_var.op_members, + scale_var.nf, + scale_var.q2_to, + intrinsic_range, + ) + phys_op = scale_var_op @ phys_op # join with the basis rotation, since matching requires c+ (or likewise) if is_backward: @@ -278,19 +309,6 @@ def generate(self, q2): ) final_op = final_op @ rot @ matching @ phys_op - # Compute scale variation scheme B - if self.config["SV_scheme"] == "B": - scale_var = ScaleVariationOperator( - self.config, self.managers, path[-1].nf, final_op.q2_final - ) - scale_var.compute() - scale_var_op = physical.PhysicalOperator.ad_to_evol_map( - scale_var.op_members, - scale_var.nf, - scale_var.q2_to, - intrinsic_range, - ) - final_op = scale_var_op @ final_op values, errors = final_op.to_flavor_basis_tensor() fact_to_ren = self.config["fact_to_ren"] return { From a22205513adc2fc04a4b4abb64342e9de6df2088 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 15 Feb 2022 09:56:42 +0100 Subject: [PATCH 12/74] init rewrite quad_ker: mellin path class --- src/eko/evolution_operator/__init__.py | 52 +++++++++++++++----------- src/eko/interpolation.py | 28 ++++++++++++++ src/eko/mellin.py | 44 ++++++++++++++++++++++ src/eko/scale_variations/b.py | 30 ++++----------- 4 files changed, 111 insertions(+), 43 deletions(-) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 1ddbba3cc..8b5158909 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -23,6 +23,28 @@ logger = logging.getLogger(__name__) +@nb.njit("c16(c16[:,:],string)") +def select_singlet_element(ker, mode): + """ + Select element of the singlet matrix + + Parameters + ---------- + mode : str + sector element + ker : numpy.ndarray + singlet integration kernel + + Returns + ------- + ker : complex + singlet integration kernel element + """ + k = 0 if mode[2] == "q" else 1 + l = 0 if mode[3] == "q" else 1 + return ker[k, l] + + @nb.njit("f8(f8,u1,string,string,b1,f8,f8[:,:],f8,f8,f8,f8,u4,u1,string)", cache=True) def quad_ker( u, @@ -83,34 +105,21 @@ def quad_ker( # get transformation to N integral if logx == 0.0: return 0.0 - r = 0.4 * 16.0 / (-logx) - if is_singlet: - o = 1.0 - else: - o = 0.0 - n = mellin.Talbot_path(u, r, o) - jac = mellin.Talbot_jac(u, r, o) - # check PDF is active - if is_log: - pj = interpolation.log_evaluate_Nx(n, logx, areas) - else: - pj = interpolation.evaluate_Nx(n, logx, areas) + path = mellin.Path(u, logx, is_singlet) + pj = interpolation.evaluate_grid(path.n, is_log, logx, areas) if pj == 0.0: return 0.0 # compute the actual evolution kernel if is_singlet: - gamma_singlet = ad.gamma_singlet(order, n, nf) + gamma_singlet = ad.gamma_singlet(order, path.n, nf) if sv_scheme == "A": gamma_singlet = gamma_singlet_fact(gamma_singlet, order, nf, L) ker = s.dispatcher( order, method, gamma_singlet, a1, a0, nf, ev_op_iterations, ev_op_max_order ) - # select element of matrix - k = 0 if mode[2] == "q" else 1 - l = 0 if mode[3] == "q" else 1 - ker = ker[k, l] + ker = select_singlet_element(ker, mode) else: - gamma_ns = ad.gamma_ns(order, mode[-1], n, nf) + gamma_ns = ad.gamma_ns(order, mode[-1], path.n, nf) if sv_scheme == "A": gamma_ns = gamma_ns_fact(gamma_ns, order, nf, L) ker = ns.dispatcher( @@ -123,8 +132,7 @@ def quad_ker( ev_op_iterations, ) # recombine everthing - mellin_prefactor = complex(0.0, -1.0 / np.pi) - return np.real(mellin_prefactor * ker * pj * jac) + return np.real(path.prefactor * ker * pj * path.jac) class Operator: @@ -262,7 +270,9 @@ def compute(self): np.log(fact_to_ren), self.config["ev_op_iterations"], self.config["ev_op_max_order"], - self.config["SV_scheme"] if self.config["SV_scheme"] is not None else "", + self.config["SV_scheme"] + if self.config["SV_scheme"] is not None + else "", ), epsabs=1e-12, epsrel=1e-5, diff --git a/src/eko/interpolation.py b/src/eko/interpolation.py index 442bbd847..a30617072 100644 --- a/src/eko/interpolation.py +++ b/src/eko/interpolation.py @@ -176,6 +176,34 @@ def evaluate_Nx(N, logx, area_list): return res +@nb.njit("c16(c16,b1,f8,f8[:,:])", cache=True) +def evaluate_grid(N, is_log, logx, area_list): + """ + Evaluate interpolator in N-space + + Parameters + ---------- + N : complex + Mellin variable + is_log : boolean + is a logarithmic interpolation + logx : float + logarithm of inversion point + area_list : list + area configuration of basis function + + Returns + ------- + pj : float + basis function * inversion factor + """ "" + if is_log: + pj = log_evaluate_Nx(N, logx, area_list) + else: + pj = evaluate_Nx(N, logx, area_list) + return pj + + # TODO lift to runcard? _atol_eps = 10 * np.finfo(float).eps diff --git a/src/eko/mellin.py b/src/eko/mellin.py index 3abb6fc5d..e8cfdd4c4 100644 --- a/src/eko/mellin.py +++ b/src/eko/mellin.py @@ -198,3 +198,47 @@ def edge_jac(t, m, _c, phi): return -m * np.exp(complex(0, -phi)) else: return +m * np.exp(complex(0, phi)) + + +spec = [ + ("t", nb.float64), + ("r", nb.float64), + ("o", nb.int8), +] + + +@nb.experimental.jitclass(spec) +class Path: + """ + Mellin path dispatcher + + Parameters + ---------- + t : float + way parameter + logx : float + Mellin inversion point + axis_offset: bool + add offset on the real axis + """ + + def __init__(self, t, logx, axis_offset): + self.t = t + self.r = 0.4 * 16.0 / (-logx) + if axis_offset: + self.o = 1.0 + else: + self.o = 0.0 + + # TODO: make also the other 2 paths available ?? + @property + def n(self): + return Talbot_path(self.t, self.r, self.o) + + @property + def jac(self): + return Talbot_jac(self.t, self.r, self.o) + + @property + def prefactor(self): + return complex(0.0, -1.0 / np.pi) diff --git a/src/eko/scale_variations/b.py b/src/eko/scale_variations/b.py index 64fbd272e..c50e61500 100644 --- a/src/eko/scale_variations/b.py +++ b/src/eko/scale_variations/b.py @@ -10,10 +10,10 @@ import numpy as np from scipy import integrate -from ..evolution_operator import Operator from .. import anomalous_dimensions as ad from .. import beta, interpolation, mellin from ..basis_rotation import full_labels +from ..evolution_operator import Operator, select_singlet_element from ..member import OpMember logger = logging.getLogger(__name__) @@ -139,36 +139,22 @@ def quad_ker( # get transformation to N integral if logx == 0.0: return 0.0 - r = 0.4 * 16.0 / (-logx) - if is_singlet: - o = 1.0 - else: - o = 0.0 - n = mellin.Talbot_path(u, r, o) - jac = mellin.Talbot_jac(u, r, o) - # check PDF is active - if is_log: - pj = interpolation.log_evaluate_Nx(n, logx, areas) - else: - pj = interpolation.evaluate_Nx(n, logx, areas) + path = mellin.Path(u, logx, is_singlet) + pj = interpolation.evaluate_grid(path.n, is_log, logx, areas) if pj == 0.0: return 0.0 # compute the actual scale variation kernel if is_singlet: - gamma_singlet = ad.gamma_singlet(order, n, nf) + gamma_singlet = ad.gamma_singlet(order, path.n, nf) ker = singlet_dispatcher(gamma_singlet, a_s, order, nf, L) - # select element of matrix - k = 0 if mode[2] == "q" else 1 - l = 0 if mode[3] == "q" else 1 - ker = ker[k, l] + ker = select_singlet_element(ker, mode) else: - gamma_ns = ad.gamma_ns(order, mode[-1], n, nf) + gamma_ns = ad.gamma_ns(order, mode[-1], path.n, nf) ker = non_singlet_dispatcher(gamma_ns, a_s, order, nf, L) # recombine everthing - mellin_prefactor = complex(0.0, -1.0 / np.pi) - return np.real(mellin_prefactor * ker * pj * jac) + return np.real(path.prefactor * ker * pj * path.jac) class ScaleVariationOperator(Operator): @@ -224,7 +210,7 @@ def compute(self): # setup ingredients sc = self.managers["strong_coupling"] fact_to_ren = self.config["fact_to_ren"] - a_s = sc.a_s(self.q2_from / fact_to_ren, fact_scale=self.q2_from, nf_to=self.nf) + a_s = sc.a_s(self.q2_from / fact_to_ren, fact_scale=self.q2_from) logger.info( "Scale Variation: (µ_F/µ_R)^2 = %e, Q^2 = %e, nf=%d", fact_to_ren, From 4027729c92b5b77b91e53d41d303edd377dce85a Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 15 Feb 2022 13:16:32 +0100 Subject: [PATCH 13/74] More work on Quad ker base --- src/eko/evolution_operator/__init__.py | 88 ++++++++++++++++++++++---- src/eko/mellin.py | 3 + src/eko/scale_variations/b.py | 25 +++----- 3 files changed, 89 insertions(+), 27 deletions(-) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 8b5158909..63e4730b5 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -23,6 +23,7 @@ logger = logging.getLogger(__name__) +# TODO: add this to QuadKerBase class ?? @nb.njit("c16(c16[:,:],string)") def select_singlet_element(ker, mode): """ @@ -45,6 +46,72 @@ def select_singlet_element(ker, mode): return ker[k, l] +spec = [ + ("is_singlet", nb.boolean), + ("is_log", nb.boolean), + ("logx", nb.float64), + ("u", nb.float64), +] + + +@nb.experimental.jitclass(spec) +class QuadKerBase: + """ + Class to manage the common part of Mellin inversion integral + + Parameters + ---------- + u : float + quad argument + is_log : boolean + is a logarithmic interpolation + logx : float + Mellin inversion point + mode : str + sector element + """ + + def __init__(self, u, is_log, logx, mode): + self.is_singlet = mode[0] == "S" + self.is_log = is_log + self.u = u + self.logx = logx + + @property + def path(self): + """Returns the associated instance of :class:`eko.mellin.Path`""" + return mellin.Path(self.u, self.logx, self.is_singlet) + + @property + def n(self): + """Returns the Mellin moment N""" + return self.path.n + + def integrand( + self, + areas, + ): + """ + Get transformation to Mellin space integral + + Parameters + ---------- + areas : tuple + basis function configuration + + Returns + ------- + base_integrand: complex + common mellin inversion intgrand + """ + if self.logx == 0.0: + return 0.0 + pj = interpolation.evaluate_grid(self.path.n, self.is_log, self.logx, areas) + if pj == 0.0: + return 0.0 + return self.path.prefactor * pj * self.path.jac + + @nb.njit("f8(f8,u1,string,string,b1,f8,f8[:,:],f8,f8,f8,f8,u4,u1,string)", cache=True) def quad_ker( u, @@ -63,7 +130,7 @@ def quad_ker( sv_scheme, ): """ - Raw kernel inside quad. + Raw evolution kernel inside quad. Parameters ---------- @@ -101,17 +168,14 @@ def quad_ker( ker : float evaluated integration kernel """ - is_singlet = mode[0] == "S" - # get transformation to N integral - if logx == 0.0: - return 0.0 - path = mellin.Path(u, logx, is_singlet) - pj = interpolation.evaluate_grid(path.n, is_log, logx, areas) - if pj == 0.0: + ker_base = QuadKerBase(u, is_log, logx, mode) + integrand = ker_base.integrand(areas) + if integrand == 0.0: return 0.0 + # compute the actual evolution kernel - if is_singlet: - gamma_singlet = ad.gamma_singlet(order, path.n, nf) + if ker_base.is_singlet: + gamma_singlet = ad.gamma_singlet(order, ker_base.n, nf) if sv_scheme == "A": gamma_singlet = gamma_singlet_fact(gamma_singlet, order, nf, L) ker = s.dispatcher( @@ -119,7 +183,7 @@ def quad_ker( ) ker = select_singlet_element(ker, mode) else: - gamma_ns = ad.gamma_ns(order, mode[-1], path.n, nf) + gamma_ns = ad.gamma_ns(order, mode[-1], ker_base.n, nf) if sv_scheme == "A": gamma_ns = gamma_ns_fact(gamma_ns, order, nf, L) ker = ns.dispatcher( @@ -132,7 +196,7 @@ def quad_ker( ev_op_iterations, ) # recombine everthing - return np.real(path.prefactor * ker * pj * path.jac) + return np.real(ker * integrand) class Operator: diff --git a/src/eko/mellin.py b/src/eko/mellin.py index e8cfdd4c4..0990b3247 100644 --- a/src/eko/mellin.py +++ b/src/eko/mellin.py @@ -233,12 +233,15 @@ def __init__(self, t, logx, axis_offset): # TODO: make also the other 2 paths available ?? @property def n(self): + """Returns the Mellin moment N""" return Talbot_path(self.t, self.r, self.o) @property def jac(self): + """Returns the Jacobian of the Mellin path""" return Talbot_jac(self.t, self.r, self.o) @property def prefactor(self): + r"""Returns the mellin inversion prefactor :math:`-\frac{1}{\pi}`""" return complex(0.0, -1.0 / np.pi) diff --git a/src/eko/scale_variations/b.py b/src/eko/scale_variations/b.py index c50e61500..aa18afaf5 100644 --- a/src/eko/scale_variations/b.py +++ b/src/eko/scale_variations/b.py @@ -11,9 +11,9 @@ from scipy import integrate from .. import anomalous_dimensions as ad -from .. import beta, interpolation, mellin +from .. import beta from ..basis_rotation import full_labels -from ..evolution_operator import Operator, select_singlet_element +from ..evolution_operator import Operator, QuadKerBase, select_singlet_element from ..member import OpMember logger = logging.getLogger(__name__) @@ -106,7 +106,7 @@ def quad_ker( L, ): """ - Raw kernel inside quad. + Raw scale variation B kernel inside quad. Parameters ---------- @@ -134,27 +134,22 @@ def quad_ker( ker : float evaluated scale variation kernel """ - # TODO: this code is reperated twice or 3 times - is_singlet = mode[0] == "S" - # get transformation to N integral - if logx == 0.0: - return 0.0 - path = mellin.Path(u, logx, is_singlet) - pj = interpolation.evaluate_grid(path.n, is_log, logx, areas) - if pj == 0.0: + ker_base = QuadKerBase(u, is_log, logx, mode) + integrand = ker_base.integrand(areas) + if integrand == 0.0: return 0.0 # compute the actual scale variation kernel - if is_singlet: - gamma_singlet = ad.gamma_singlet(order, path.n, nf) + if ker_base.is_singlet: + gamma_singlet = ad.gamma_singlet(order, ker_base.n, nf) ker = singlet_dispatcher(gamma_singlet, a_s, order, nf, L) ker = select_singlet_element(ker, mode) else: - gamma_ns = ad.gamma_ns(order, mode[-1], path.n, nf) + gamma_ns = ad.gamma_ns(order, mode[-1], ker_base.n, nf) ker = non_singlet_dispatcher(gamma_ns, a_s, order, nf, L) # recombine everthing - return np.real(path.prefactor * ker * pj * path.jac) + return np.real(ker * integrand) class ScaleVariationOperator(Operator): From 2b019dc42d083c4143d25a9cc480cca5b067fafc Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 15 Feb 2022 15:18:08 +0100 Subject: [PATCH 14/74] recove 100% coverage --- benchmarks/eko_bench.py | 16 ++++++++++------ src/eko/mellin.py | 2 +- tests/test_ev_op_grid.py | 38 ++++++++++++++++++-------------------- tests/test_ev_operator.py | 19 +++++++++++++++++++ 4 files changed, 48 insertions(+), 27 deletions(-) diff --git a/benchmarks/eko_bench.py b/benchmarks/eko_bench.py index b4f75b63f..f81426f53 100644 --- a/benchmarks/eko_bench.py +++ b/benchmarks/eko_bench.py @@ -28,7 +28,7 @@ ), # Eq. (32) :cite:`Giele:2002hx`,Eq. (4.53) :cite:`Dittmar:2005ed` "alphas": 0.35, # Eq. (4.55) :cite:`Dittmar:2005ed` "FNS": "ZM-VFNS", # ignored by eko, but needed by LHA_utils - "kcThr": 1.0, # here you need to start in nf=3 and do the match. + "kcThr": 1.0, "kbThr": 1.0, "ktThr": 1.0, } @@ -85,10 +85,13 @@ def benchmark_sv(self, pto): list(dict) theory updates """ - # low = base_theory.copy() - # low["PTO"] = pto - # low["fact_to_ren_scale_ratio"] = np.sqrt(1.0 / 2.0) - # low["SV_scheme"] = "A" + low = base_theory.copy() + low["PTO"] = pto + low["fact_to_ren_scale_ratio"] = np.sqrt(1.0 / 2.0) + low["SV_scheme"] = "A" + # needed for apfel + low["XIR"] = np.sqrt(2.0) + low["EScaleVar"] = 0 high = base_theory.copy() high["PTO"] = pto high["fact_to_ren_scale_ratio"] = np.sqrt(2.0) @@ -96,7 +99,7 @@ def benchmark_sv(self, pto): # needed for apfel high["XIR"] = np.sqrt(0.5) high["EScaleVar"] = 0 - self.run_lha([high]) + self.run_lha([low, high]) def benchmark_plain(self, pto): """Plain configuration""" @@ -110,4 +113,5 @@ def benchmark_plain(self, pto): programs = ["LHA", "pegasus", "apfel"] for p in programs: obj = BenchmarkRunner(p) + # obj.benchmark_plain(2) obj.benchmark_sv(2) diff --git a/src/eko/mellin.py b/src/eko/mellin.py index 0990b3247..affa3543a 100644 --- a/src/eko/mellin.py +++ b/src/eko/mellin.py @@ -243,5 +243,5 @@ def jac(self): @property def prefactor(self): - r"""Returns the mellin inversion prefactor :math:`-\frac{1}{\pi}`""" + r"""Returns the mellin inversion prefactor :math:`-\frac{i}{\pi}`""" return complex(0.0, -1.0 / np.pi) diff --git a/tests/test_ev_op_grid.py b/tests/test_ev_op_grid.py index 622da59e1..0870ad1e2 100644 --- a/tests/test_ev_op_grid.py +++ b/tests/test_ev_op_grid.py @@ -39,7 +39,7 @@ def _get_setup(self, use_FFNS): "SV_scheme": None, } operators_card = { - "Q2grid": [1, 100**2], + "Q2grid": [1, 100 ** 2], "interpolation_xgrid": [0.1, 1.0], "interpolation_polynomial_degree": 1, "interpolation_is_log": True, @@ -122,7 +122,7 @@ def test_compute_q2grid(self): def test_grid_computation_VFNS(self): """Checks that the grid can be computed""" opgrid = self._get_operator_grid(False) - qgrid_check = [3, 5, 200**2] + qgrid_check = [3, 5, 200 ** 2] operators = opgrid.compute(qgrid_check) assert len(operators) == len(qgrid_check) @@ -137,21 +137,19 @@ def test_alphas(self): assert opg[3]["alphas"] < sv_opg[3]["alphas"] def test_scheme_B(self): - opgrid = self._get_operator_grid( - theory_update={ - "PTO": 1, - "SV_scheme": "B", - } - ) - opg = opgrid.compute(3) - sv_opgrid = self._get_operator_grid( - theory_update={ - "fact_to_ren_scale_ratio": 1.0 + 1e-3, - "PTO": 1, - "SV_scheme": "B", - } - ) - sv_opg = sv_opgrid.compute(3) - np.testing.assert_allclose( - opg[3]["operators"], sv_opg[3]["operators"], atol=1e-4 - ) + theory_update = { + "PTO": 1, + "SV_scheme": "B", + } + for ffns, epsilon, nf0 in zip([False, True], [1e-4, 1e-3], [5, 3]): + theory_update["nf0"] = nf0 + opgrid = self._get_operator_grid(use_FFNS=ffns, theory_update=theory_update) + opg = opgrid.compute(3) + theory_update["fact_to_ren_scale_ratio"] = 1.0 + epsilon + sv_opgrid = self._get_operator_grid( + use_FFNS=ffns, theory_update=theory_update + ) + sv_opg = sv_opgrid.compute(3) + np.testing.assert_allclose( + opg[3]["operators"], sv_opg[3]["operators"], atol=1e-4 + ) diff --git a/tests/test_ev_operator.py b/tests/test_ev_operator.py index 5af365a65..05c26d251 100644 --- a/tests/test_ev_operator.py +++ b/tests/test_ev_operator.py @@ -78,6 +78,25 @@ def test_quad_ker(monkeypatch): sv_scheme=None, ) np.testing.assert_allclose(res_s, 0.0) + for mode in ["NS_p", "S_qq"]: + res_sv = quad_ker( + u=0, + order=0, + mode=mode, + method="", + is_log=True, + logx=1.0, + areas=np.zeros(3), + a1=1, + a0=2, + nf=3, + L=0, + ev_op_iterations=0, + ev_op_max_order=0, + sv_scheme="A", + ) + np.testing.assert_allclose(res_sv, 1.0) + monkeypatch.setattr(interpolation, "log_evaluate_Nx", lambda *args: 0) res_ns = quad_ker( u=0, From efe2eef0bf63e34913ef61f3ce354f95de96f459 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 15 Feb 2022 15:47:34 +0100 Subject: [PATCH 15/74] uniform scale variation a for singlet and ns --- src/eko/evolution_operator/__init__.py | 7 ++--- src/eko/scale_variations/a.py | 42 +++----------------------- tests/test_sv_a.py | 18 +++++------ 3 files changed, 16 insertions(+), 51 deletions(-) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 63e4730b5..bd110146b 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -18,12 +18,11 @@ from ..kernels import non_singlet as ns from ..kernels import singlet as s from ..member import OpMember -from ..scale_variations.a import gamma_ns_fact, gamma_singlet_fact +from ..scale_variations.a import gamma_fact logger = logging.getLogger(__name__) -# TODO: add this to QuadKerBase class ?? @nb.njit("c16(c16[:,:],string)") def select_singlet_element(ker, mode): """ @@ -177,7 +176,7 @@ def quad_ker( if ker_base.is_singlet: gamma_singlet = ad.gamma_singlet(order, ker_base.n, nf) if sv_scheme == "A": - gamma_singlet = gamma_singlet_fact(gamma_singlet, order, nf, L) + gamma_singlet = gamma_fact(gamma_singlet, order, nf, L) ker = s.dispatcher( order, method, gamma_singlet, a1, a0, nf, ev_op_iterations, ev_op_max_order ) @@ -185,7 +184,7 @@ def quad_ker( else: gamma_ns = ad.gamma_ns(order, mode[-1], ker_base.n, nf) if sv_scheme == "A": - gamma_ns = gamma_ns_fact(gamma_ns, order, nf, L) + gamma_ns = gamma_fact(gamma_ns, order, nf, L) ker = ns.dispatcher( order, method, diff --git a/src/eko/scale_variations/a.py b/src/eko/scale_variations/a.py index 99e382292..15dab9cb8 100644 --- a/src/eko/scale_variations/a.py +++ b/src/eko/scale_variations/a.py @@ -6,11 +6,9 @@ from .. import beta -# TODO: if possible to unify this two functions, -# they differ only for the numba decorator -@nb.njit("c16[:](c16[:],u1,u1,f8)", cache=True) -def gamma_ns_fact(gamma,order, nf, L): +@nb.njit(["c16[:,:,:](c16[:,:,:],u1,u1,f8)", "c16[:](c16[:],u1,u1,f8)"], cache=True) +def gamma_fact(gamma, order, nf, L): """ Adjust the anomalous dimensions with the scale variations. @@ -27,43 +25,11 @@ def gamma_ns_fact(gamma,order, nf, L): Returns ------- - gamma_ns : numpy.ndarray - adjusted non-singlet anomalous dimensions - """ - # since we are modifying *in-place* be carefull, that the order matters! - # and indeed, we need to adjust the high elements first - if order >= 2: - gamma[2] -= ( - 2 * beta.beta(0, nf) * gamma[1] * L - + (beta.beta(1, nf) * L - beta.beta(0, nf) ** 2 * L ** 2) * gamma[0] - ) - if order >= 1: - gamma[1] -= beta.beta(0, nf) * gamma[0] * L - return gamma - - -@nb.njit("c16[:,:,:](c16[:,:,:],u1,u1,f8)", cache=True) -def gamma_singlet_fact(gamma, order, nf, L): - """ - Adjust the anomalous dimensions with the scale variations. - - Parameters - ---------- gamma : numpy.ndarray - anomalous dimensions - order : int - perturbation order - nf : int - number of active flavors - L : float - logarithmic ratio of factorization and renormalization scale - - Returns - ------- - gamma_singlet : numpy.ndarray adjusted singlet anomalous dimensions """ - # concerning order: see comment at gamma_ns_fact + # since we are modifying *in-place* be carefull, that the order matters! + # and indeed, we need to adjust the high elements first if order >= 2: gamma[2] -= ( 2 * beta.beta(0, nf) * gamma[1] * L diff --git a/tests/test_sv_a.py b/tests/test_sv_a.py index c11f00de9..bc6f308a9 100644 --- a/tests/test_sv_a.py +++ b/tests/test_sv_a.py @@ -2,28 +2,28 @@ import numpy as np -from eko.scale_variations.a import gamma_ns_fact, gamma_singlet_fact +from eko.scale_variations.a import gamma_fact def test_gamma_ns_fact(): gamma_ns = np.array([1.0, 0.5, 0.25]) - gamma_ns_LO_0 = gamma_ns_fact(gamma_ns.copy(), 0, 3, 0) + gamma_ns_LO_0 = gamma_fact(gamma_ns.copy(), 0, 3, 0) np.testing.assert_allclose(gamma_ns_LO_0, gamma_ns) - gamma_ns_LO_1 = gamma_ns_fact(gamma_ns.copy(), 0, 3, 1) + gamma_ns_LO_1 = gamma_fact(gamma_ns.copy(), 0, 3, 1) np.testing.assert_allclose(gamma_ns_LO_1, gamma_ns) - gamma_ns_NLO_1 = gamma_ns_fact(gamma_ns.copy(), 1, 3, 1) + gamma_ns_NLO_1 = gamma_fact(gamma_ns.copy(), 1, 3, 1) assert gamma_ns_NLO_1[1] < gamma_ns[1] - gamma_ns_NNLO_1 = gamma_ns_fact(gamma_ns.copy(), 2, 3, 1) + gamma_ns_NNLO_1 = gamma_fact(gamma_ns.copy(), 2, 3, 1) assert gamma_ns_NNLO_1[2] - gamma_ns[2] == 8.0 def test_gamma_singlet_fact(): gamma_s = np.array([1.0, 0.5, 0.25]) - gamma_s_LO_0 = gamma_singlet_fact(gamma_s.copy(), 0, 3, 0) + gamma_s_LO_0 = gamma_fact(gamma_s.copy(), 0, 3, 0) np.testing.assert_allclose(gamma_s_LO_0, gamma_s) - gamma_s_LO_1 = gamma_singlet_fact(gamma_s.copy(), 0, 3, 1) + gamma_s_LO_1 = gamma_fact(gamma_s.copy(), 0, 3, 1) np.testing.assert_allclose(gamma_s_LO_1, gamma_s) - gamma_s_NLO_1 = gamma_singlet_fact(gamma_s.copy(), 1, 3, 1) + gamma_s_NLO_1 = gamma_fact(gamma_s.copy(), 1, 3, 1) assert gamma_s_NLO_1[1] < gamma_s[1] - gamma_s_NNLO_1 = gamma_singlet_fact(gamma_s.copy(), 2, 3, 1) + gamma_s_NNLO_1 = gamma_fact(gamma_s.copy(), 2, 3, 1) assert gamma_s_NNLO_1[2] - gamma_s[2] == 8.0 From 5582d82b7bcbd82d79de50243bf72489b45bc398 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 15 Feb 2022 17:10:57 +0100 Subject: [PATCH 16/74] make Operator compute more atomic --- src/eko/evolution_operator/__init__.py | 91 ++++++++++++++++---------- src/eko/mellin.py | 1 + src/eko/scale_variations/b.py | 47 ++++--------- tests/test_ev_operator.py | 14 ++-- 4 files changed, 78 insertions(+), 75 deletions(-) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index bd110146b..d72908c9d 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -7,6 +7,7 @@ import logging import time +from functools import cached_property import numba as nb import numpy as np @@ -111,7 +112,7 @@ def integrand( return self.path.prefactor * pj * self.path.jac -@nb.njit("f8(f8,u1,string,string,b1,f8,f8[:,:],f8,f8,f8,f8,u4,u1,string)", cache=True) +@nb.njit("f8(f8,u1,string,string,b1,f8,f8[:,:],f8,f8,f8,f8,u4,u1,b1)", cache=True) def quad_ker( u, order, @@ -126,7 +127,7 @@ def quad_ker( L, ev_op_iterations, ev_op_max_order, - sv_scheme, + is_sv_scheme_a, ): """ Raw evolution kernel inside quad. @@ -159,8 +160,8 @@ def quad_ker( number of evolution steps ev_op_max_order : int perturbative expansion order of U - sv_scheme : string - scale variation scheme + is_sv_scheme_a : bool + use scale variation scheme A Returns ------- @@ -175,7 +176,7 @@ def quad_ker( # compute the actual evolution kernel if ker_base.is_singlet: gamma_singlet = ad.gamma_singlet(order, ker_base.n, nf) - if sv_scheme == "A": + if is_sv_scheme_a: gamma_singlet = gamma_fact(gamma_singlet, order, nf, L) ker = s.dispatcher( order, method, gamma_singlet, a1, a0, nf, ev_op_iterations, ev_op_max_order @@ -183,7 +184,7 @@ def quad_ker( ker = select_singlet_element(ker, mode) else: gamma_ns = ad.gamma_ns(order, mode[-1], ker_base.n, nf) - if sv_scheme == "A": + if is_sv_scheme_a: gamma_ns = gamma_fact(gamma_ns, order, nf, L) ker = ns.dispatcher( order, @@ -230,6 +231,27 @@ def __init__(self, config, managers, nf, q2_from, q2_to=None, mellin_cut=5e-2): self._mellin_cut = mellin_cut self.op_members = {} + @cached_property + def fact_to_ren(self): + """Returns the interpolation dispatcher""" + return self.config["fact_to_ren"] + + @cached_property + def int_disp(self): + """Returns the interpolation dispatcher""" + return self.managers["interpol_dispatcher"] + + @cached_property + def grid_size(self): + """Returns the grid size""" + return self.int_disp.xgrid.size + + @cached_property + def strong_coupling(self): + """Returns the instance of :class:`eko.strong_coupling.StrongCoupling`""" + return self.managers["strong_coupling"] + + @cached_property def labels(self): """ Compute necessary sector labels to compute. @@ -258,18 +280,14 @@ def labels(self): labels.extend(singlet_labels) return labels - def compute(self): - """compute the actual operators (i.e. run the integrations)""" - # Generic parameters - int_disp = self.managers["interpol_dispatcher"] - grid_size = len(int_disp.xgrid) - - # init all ops with identity or zeros if we skip them - labels = self.labels() - eye = OpMember(np.eye(grid_size), np.zeros((grid_size, grid_size))) - zero = OpMember(*[np.zeros((grid_size, grid_size))] * 2) + def initialize_op_members(self): + """Init all ops with identity or zeros if we skip them""" + eye = OpMember( + np.eye(self.grid_size), np.zeros((self.grid_size, self.grid_size)) + ) + zero = OpMember(*[np.zeros((self.grid_size, self.grid_size))] * 2) for n in full_labels: - if n in labels: + if n in self.labels: # off diag singlet are zero if n in ["S_qg", "S_gq"]: self.op_members[n] = zero.copy() @@ -277,6 +295,11 @@ def compute(self): self.op_members[n] = eye.copy() else: self.op_members[n] = zero.copy() + + def compute(self): + """compute the actual operators (i.e. run the integrations)""" + self.initialize_op_members() + # skip computation if np.isclose(self.q2_from, self.q2_to): logger.info("Evolution: skipping unity operator at %e", self.q2_from) @@ -284,10 +307,12 @@ def compute(self): return tot_start_time = time.perf_counter() # setup ingredients - sc = self.managers["strong_coupling"] - fact_to_ren = self.config["fact_to_ren"] - a0 = sc.a_s(self.q2_from / fact_to_ren, fact_scale=self.q2_from, nf_to=self.nf) - a1 = sc.a_s(self.q2_to / fact_to_ren, fact_scale=self.q2_to, nf_to=self.nf) + a0 = self.strong_coupling.a_s( + self.q2_from / self.fact_to_ren, fact_scale=self.q2_from, nf_to=self.nf + ) + a1 = self.strong_coupling.a_s( + self.q2_to / self.fact_to_ren, fact_scale=self.q2_to, nf_to=self.nf + ) logger.info( "Evolution: computing operators %e -> %e, nf=%d", self.q2_from, @@ -296,8 +321,8 @@ def compute(self): ) logger.info( "Evolution: µ_R^2 distance: %e -> %e", - self.q2_from / fact_to_ren, - self.q2_to / fact_to_ren, + self.q2_from / self.fact_to_ren, + self.q2_to / self.fact_to_ren, ) logger.info("Evolution: a_s distance: %e -> %e", a0, a1) logger.info( @@ -305,16 +330,16 @@ def compute(self): self.config["order"], self.config["method"], ) - logger.info("Evolution: computing operators - 0/%d", grid_size) + logger.info("Evolution: computing operators - 0/%d", self.grid_size) # iterate output grid - for k, logx in enumerate(np.log(int_disp.xgrid_raw)): + for k, logx in enumerate(np.log(self.int_disp.xgrid_raw)): start_time = time.perf_counter() # iterate basis functions - for l, bf in enumerate(int_disp): - if k == l and l == grid_size - 1: + for l, bf in enumerate(self.int_disp): + if k == l and l == self.grid_size - 1: continue # iterate sectors - for label in labels: + for label in self.labels: # compute and set res = integrate.quad( quad_ker, @@ -324,18 +349,16 @@ def compute(self): self.config["order"], label, self.config["method"], - int_disp.log, + self.int_disp.log, logx, bf.areas_representation, a1, a0, self.nf, - np.log(fact_to_ren), + np.log(self.fact_to_ren), self.config["ev_op_iterations"], self.config["ev_op_max_order"], - self.config["SV_scheme"] - if self.config["SV_scheme"] is not None - else "", + bool(self.config["SV_scheme"] == "A"), ), epsabs=1e-12, epsrel=1e-5, @@ -349,7 +372,7 @@ def compute(self): logger.info( "Evolution: computing operators - %d/%d took: %f s", k + 1, - grid_size, + self.grid_size, time.perf_counter() - start_time, ) diff --git a/src/eko/mellin.py b/src/eko/mellin.py index affa3543a..e718b7457 100644 --- a/src/eko/mellin.py +++ b/src/eko/mellin.py @@ -224,6 +224,7 @@ class Path: def __init__(self, t, logx, axis_offset): self.t = t + # TODO: shall we use: 0.4 * 16.0 / (1.0 - logx) ? self.r = 0.4 * 16.0 / (-logx) if axis_offset: self.o = 1.0 diff --git a/src/eko/scale_variations/b.py b/src/eko/scale_variations/b.py index aa18afaf5..518cdfd2a 100644 --- a/src/eko/scale_variations/b.py +++ b/src/eko/scale_variations/b.py @@ -12,9 +12,7 @@ from .. import anomalous_dimensions as ad from .. import beta -from ..basis_rotation import full_labels from ..evolution_operator import Operator, QuadKerBase, select_singlet_element -from ..member import OpMember logger = logging.getLogger(__name__) @@ -175,25 +173,7 @@ def __init__(self, config, managers, nf, q2): def compute(self): """compute the actual operators (i.e. run the integrations)""" - # TODO: here there are a lot of repetitions, you need to generalize - # the evolution operator - # Generic parameters - int_disp = self.managers["interpol_dispatcher"] - grid_size = len(int_disp.xgrid) - - # init all ops with identity or zeros if we skip them - labels = self.labels() - eye = OpMember(np.eye(grid_size), np.zeros((grid_size, grid_size))) - zero = OpMember(*[np.zeros((grid_size, grid_size))] * 2) - for n in full_labels: - if n in labels: - # off diag singlet are zero - if n in ["S_qg", "S_gq"]: - self.op_members[n] = zero.copy() - else: - self.op_members[n] = eye.copy() - else: - self.op_members[n] = zero.copy() + self.initialize_op_members() # At LO you don't need anything else if self.config["order"] == 0: @@ -202,26 +182,25 @@ def compute(self): return tot_start_time = time.perf_counter() - # setup ingredients - sc = self.managers["strong_coupling"] - fact_to_ren = self.config["fact_to_ren"] - a_s = sc.a_s(self.q2_from / fact_to_ren, fact_scale=self.q2_from) + a_s = self.strong_coupling.a_s( + self.q2_from / self.fact_to_ren, fact_scale=self.q2_from + ) logger.info( "Scale Variation: (µ_F/µ_R)^2 = %e, Q^2 = %e, nf=%d", - fact_to_ren, + self.fact_to_ren, self.q2_from, self.nf, ) - logger.info("Scale Variation: computing operators - 0/%d", grid_size) + logger.info("Scale Variation: computing operators - 0/%d", self.grid_size) # iterate output grid - for k, logx in enumerate(np.log(int_disp.xgrid_raw)): + for k, logx in enumerate(np.log(self.int_disp.xgrid_raw)): start_time = time.perf_counter() # iterate basis functions - for l, bf in enumerate(int_disp): - if k == l and l == grid_size - 1: + for l, bf in enumerate(self.int_disp): + if k == l and l == self.grid_size - 1: continue # iterate sectors - for label in labels: + for label in self.labels: # compute and set res = integrate.quad( quad_ker, @@ -230,12 +209,12 @@ def compute(self): args=( self.config["order"], label, - int_disp.log, + self.int_disp.log, logx, bf.areas_representation, a_s, self.nf, - np.log(fact_to_ren), + np.log(self.fact_to_ren), ), epsabs=1e-12, epsrel=1e-5, @@ -249,7 +228,7 @@ def compute(self): logger.info( "Scale Variation: computing operators - %d/%d took: %f s", k + 1, - grid_size, + self.grid_size, time.perf_counter() - start_time, ) diff --git a/tests/test_ev_operator.py b/tests/test_ev_operator.py index 05c26d251..49f644179 100644 --- a/tests/test_ev_operator.py +++ b/tests/test_ev_operator.py @@ -41,7 +41,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - sv_scheme=None, + is_sv_scheme_a=False, ) np.testing.assert_allclose(res_ns, 0.0) res_s = quad_ker( @@ -58,7 +58,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - sv_scheme=None, + is_sv_scheme_a=False, ) np.testing.assert_allclose(res_s, 1.0) res_s = quad_ker( @@ -75,7 +75,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - sv_scheme=None, + is_sv_scheme_a=False, ) np.testing.assert_allclose(res_s, 0.0) for mode in ["NS_p", "S_qq"]: @@ -93,7 +93,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - sv_scheme="A", + is_sv_scheme_a=False, ) np.testing.assert_allclose(res_sv, 1.0) @@ -112,7 +112,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - sv_scheme=None, + is_sv_scheme_a=False, ) np.testing.assert_allclose(res_ns, 0.0) @@ -126,7 +126,7 @@ def test_labels(self): 1, 2, ) - assert sorted(o.labels()) == sorted( + assert sorted(o.labels) == sorted( ["NS_p", "NS_m", "NS_v", "S_qq", "S_qg", "S_gq", "S_gg"] ) o = Operator( @@ -136,7 +136,7 @@ def test_labels(self): 1, 2, ) - assert sorted(o.labels()) == [] + assert sorted(o.labels) == [] def test_compute(self, monkeypatch): # setup objs From 312fb36d7d17398872beeba694ee2fe4a415c033 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 15 Feb 2022 17:24:53 +0100 Subject: [PATCH 17/74] recover full coverage --- src/eko/evolution_operator/__init__.py | 2 +- tests/test_ev_operator.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index d72908c9d..0f19f70b6 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -57,7 +57,7 @@ def select_singlet_element(ker, mode): @nb.experimental.jitclass(spec) class QuadKerBase: """ - Class to manage the common part of Mellin inversion integral + Manage the common part of Mellin inversion integral Parameters ---------- diff --git a/tests/test_ev_operator.py b/tests/test_ev_operator.py index 49f644179..b5284846f 100644 --- a/tests/test_ev_operator.py +++ b/tests/test_ev_operator.py @@ -93,7 +93,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - is_sv_scheme_a=False, + is_sv_scheme_a=True, ) np.testing.assert_allclose(res_sv, 1.0) From 6b10b6635670390736dde1b432c902e44de216dc Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Wed, 16 Feb 2022 12:02:47 +0100 Subject: [PATCH 18/74] apply scheme B directly on evolution kernels --- src/eko/evolution_operator/__init__.py | 52 ++-- src/eko/evolution_operator/grid.py | 33 --- src/eko/scale_variations/a.py | 4 +- src/eko/scale_variations/b.py | 322 ++++++++++++------------- tests/test_ev_op_grid.py | 4 +- tests/test_ev_operator.py | 45 ++-- tests/test_interpolation.py | 8 +- tests/test_sv_a.py | 18 +- tests/test_sv_b.py | 148 +----------- 9 files changed, 242 insertions(+), 392 deletions(-) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 0f19f70b6..2816df46e 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -7,7 +7,6 @@ import logging import time -from functools import cached_property import numba as nb import numpy as np @@ -19,7 +18,7 @@ from ..kernels import non_singlet as ns from ..kernels import singlet as s from ..member import OpMember -from ..scale_variations.a import gamma_fact +from ..scale_variations import a, b logger = logging.getLogger(__name__) @@ -112,7 +111,7 @@ def integrand( return self.path.prefactor * pj * self.path.jac -@nb.njit("f8(f8,u1,string,string,b1,f8,f8[:,:],f8,f8,f8,f8,u4,u1,b1)", cache=True) +@nb.njit("f8(f8,u1,string,string,b1,f8,f8[:,:],f8,f8,f8,f8,u4,u1,u1)", cache=True) def quad_ker( u, order, @@ -127,7 +126,7 @@ def quad_ker( L, ev_op_iterations, ev_op_max_order, - is_sv_scheme_a, + sv_scheme, ): """ Raw evolution kernel inside quad. @@ -160,8 +159,8 @@ def quad_ker( number of evolution steps ev_op_max_order : int perturbative expansion order of U - is_sv_scheme_a : bool - use scale variation scheme A + sv_scheme: int + use scale variation scheme 0: none, 1: A, 2: B Returns ------- @@ -176,16 +175,20 @@ def quad_ker( # compute the actual evolution kernel if ker_base.is_singlet: gamma_singlet = ad.gamma_singlet(order, ker_base.n, nf) - if is_sv_scheme_a: - gamma_singlet = gamma_fact(gamma_singlet, order, nf, L) + # scale var A is directly applied on gamma + if sv_scheme == 1: + gamma_singlet = a.gamma_variation(gamma_singlet, order, nf, L) ker = s.dispatcher( order, method, gamma_singlet, a1, a0, nf, ev_op_iterations, ev_op_max_order ) + # scale var B is applied on the kernel + if sv_scheme == 2: + ker = b.singlet_variation(ker, gamma_singlet, a1, order, nf, L) ker = select_singlet_element(ker, mode) else: gamma_ns = ad.gamma_ns(order, mode[-1], ker_base.n, nf) - if is_sv_scheme_a: - gamma_ns = gamma_fact(gamma_ns, order, nf, L) + if sv_scheme == 1: + gamma_ns = a.gamma_variation(gamma_ns, order, nf, L) ker = ns.dispatcher( order, method, @@ -195,6 +198,9 @@ def quad_ker( nf, ev_op_iterations, ) + if sv_scheme == 2: + ker = b.non_singlet_variation(ker, gamma_ns, a1, order, nf, L) + # recombine everthing return np.real(ker * integrand) @@ -231,27 +237,33 @@ def __init__(self, config, managers, nf, q2_from, q2_to=None, mellin_cut=5e-2): self._mellin_cut = mellin_cut self.op_members = {} - @cached_property + @property def fact_to_ren(self): - """Returns the interpolation dispatcher""" + """Returns the factor (µ_F/µ_R)^2""" return self.config["fact_to_ren"] - @cached_property + @property + def sv_scheme(self): + """Returns the scale variation scheme""" + sv_scheme_dict = {None: 0, "A": 1, "B": 2} + return sv_scheme_dict[self.config["SV_scheme"]] + + @property def int_disp(self): """Returns the interpolation dispatcher""" return self.managers["interpol_dispatcher"] - @cached_property + @property def grid_size(self): """Returns the grid size""" return self.int_disp.xgrid.size - @cached_property + @property def strong_coupling(self): """Returns the instance of :class:`eko.strong_coupling.StrongCoupling`""" return self.managers["strong_coupling"] - @cached_property + @property def labels(self): """ Compute necessary sector labels to compute. @@ -324,6 +336,12 @@ def compute(self): self.q2_from / self.fact_to_ren, self.q2_to / self.fact_to_ren, ) + if self.sv_scheme != 0: + logger.info( + "Scale Variation: (µ_F/µ_R)^2 = %e, scheme: %s", + self.fact_to_ren, + "A" if self.sv_scheme == 1 else "B", + ) logger.info("Evolution: a_s distance: %e -> %e", a0, a1) logger.info( "Evolution: order: %d, solution strategy: %s", @@ -358,7 +376,7 @@ def compute(self): np.log(self.fact_to_ren), self.config["ev_op_iterations"], self.config["ev_op_max_order"], - bool(self.config["SV_scheme"] == "A"), + self.sv_scheme, ), epsabs=1e-12, epsrel=1e-5, diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py index 74bf5bd90..ebce9079e 100644 --- a/src/eko/evolution_operator/grid.py +++ b/src/eko/evolution_operator/grid.py @@ -15,7 +15,6 @@ from eko.evolution_operator import flavors from ..matching_conditions.operator_matrix_element import OperatorMatrixElement -from ..scale_variations.b import ScaleVariationOperator from . import Operator, physical logger = logging.getLogger(__name__) @@ -81,7 +80,6 @@ def __init__( ) self._threshold_operators = {} self._matching_operators = {} - self._sv_operators = {} @classmethod def from_dict( @@ -187,13 +185,6 @@ def get_threshold_operators(self, path): kthr = thr_config.thresholds_ratios[seg.nf - shift] ome.compute(seg.q2_to, np.log(kthr), self.config["HQ"] == "MSBAR") self._matching_operators[seg.q2_to] = ome.ome_members - # compute the scale variation scheme B - if self.config["SV_scheme"] == "B" and seg.q2_to not in self._sv_operators: - scale_var = ScaleVariationOperator( - self.config, self.managers, seg.nf-shift+3, seg.q2_to - ) - scale_var.compute() - self._sv_operators[seg.q2_to] = scale_var return thr_ops def compute(self, q2grid=None): @@ -254,36 +245,12 @@ def generate(self, q2): operator.q2_to, intrinsic_range, ) - # Compute scale variation scheme B - if self.config["SV_scheme"] == "B": - scale_var = ScaleVariationOperator( - self.config, self.managers, operator.nf, operator.q2_to - ) - scale_var.compute() - scale_var_op = physical.PhysicalOperator.ad_to_evol_map( - scale_var.op_members, - scale_var.nf, - scale_var.q2_to, - intrinsic_range, - ) - final_op = scale_var_op @ final_op - # and multiply the lower ones from the right for i, op in reversed(list(enumerate(thr_ops))): is_backward = path[i].is_backward phys_op = physical.PhysicalOperator.ad_to_evol_map( op.op_members, op.nf, op.q2_to, intrinsic_range ) - # add the scale variation scheme B operator - if op.q2_to in self._sv_operators: - scale_var = self._sv_operators[op.q2_to] - scale_var_op = physical.PhysicalOperator.ad_to_evol_map( - scale_var.op_members, - scale_var.nf, - scale_var.q2_to, - intrinsic_range, - ) - phys_op = scale_var_op @ phys_op # join with the basis rotation, since matching requires c+ (or likewise) if is_backward: diff --git a/src/eko/scale_variations/a.py b/src/eko/scale_variations/a.py index 15dab9cb8..ab61da5c0 100644 --- a/src/eko/scale_variations/a.py +++ b/src/eko/scale_variations/a.py @@ -8,7 +8,7 @@ @nb.njit(["c16[:,:,:](c16[:,:,:],u1,u1,f8)", "c16[:](c16[:],u1,u1,f8)"], cache=True) -def gamma_fact(gamma, order, nf, L): +def gamma_variation(gamma, order, nf, L): """ Adjust the anomalous dimensions with the scale variations. @@ -33,7 +33,7 @@ def gamma_fact(gamma, order, nf, L): if order >= 2: gamma[2] -= ( 2 * beta.beta(0, nf) * gamma[1] * L - + (beta.beta(1, nf) * L - beta.beta(0, nf) ** 2 * L ** 2) * gamma[0] + + (beta.beta(1, nf) * L - beta.beta(0, nf) ** 2 * L**2) * gamma[0] ) if order >= 1: gamma[1] -= beta.beta(0, nf) * gamma[0] * L diff --git a/src/eko/scale_variations/b.py b/src/eko/scale_variations/b.py index 518cdfd2a..361ff0d3f 100644 --- a/src/eko/scale_variations/b.py +++ b/src/eko/scale_variations/b.py @@ -4,26 +4,24 @@ """ import logging -import time import numba as nb import numpy as np -from scipy import integrate -from .. import anomalous_dimensions as ad from .. import beta -from ..evolution_operator import Operator, QuadKerBase, select_singlet_element logger = logging.getLogger(__name__) -@nb.njit("c16(c16[:],f8,u1,u1,f8)", cache=True) -def non_singlet_dispatcher(gamma, a_s, order, nf, L): +@nb.njit("c16(c16,c16[:],f8,u1,u1,f8)", cache=True) +def non_singlet_variation(ker, gamma, a_s, order, nf, L): """ Scale Variation non singlet dispatcher Parameters ---------- + ker : complex + non singlet evolution kernel gamma : numpy.ndarray anomalous dimensions a_s : float @@ -40,24 +38,26 @@ def non_singlet_dispatcher(gamma, a_s, order, nf, L): sv_ker : numpy.ndarray scale varion kernel """ - sv_ker = 1.0 + sv_ker = ker if order >= 1: sv_ker -= a_s * L * gamma[0] if order >= 2: - sv_ker += a_s ** 2 * ( + sv_ker += a_s**2 * ( -gamma[1] * L - + 1 / 2 * (beta.beta_0(nf) * gamma[0] + gamma[0] * gamma[0]) * L ** 2 + + 1 / 2 * (beta.beta_0(nf) * gamma[0] + gamma[0] * gamma[0]) * L**2 ) return sv_ker -@nb.njit("c16[:,:](c16[:,:,:],f8,u1,u1,f8)", cache=True) -def singlet_dispatcher(gamma, a_s, order, nf, L): +@nb.njit("c16[:,:](c16[:,:],c16[:,:,:],f8,u1,u1,f8)", cache=True) +def singlet_variation(ker, gamma, a_s, order, nf, L): """ Scale Variation singlet dispatcher Parameters ---------- + ker : numpy.ndarray + singlet evolution kernel gamma : numpy.ndarray anomalous dimensions a_s : float @@ -74,11 +74,11 @@ def singlet_dispatcher(gamma, a_s, order, nf, L): sv_ker : numpy.ndarray scale varion kernel """ - sv_ker = np.eye(2, dtype=np.complex_) + sv_ker = ker if order >= 1: sv_ker -= a_s * L * gamma[0] if order >= 2: - sv_ker += a_s ** 2 * ( + sv_ker += a_s**2 * ( -gamma[1] * L + 1 / 2 @@ -86,155 +86,155 @@ def singlet_dispatcher(gamma, a_s, order, nf, L): beta.beta_0(nf) * gamma[0] + np.ascontiguousarray(gamma[0]) @ np.ascontiguousarray(gamma[0]) ) - * L ** 2 + * L**2 ) return sv_ker -@nb.njit("f8(f8,u1,string,b1,f8,f8[:,:],f8,u1,f8)", cache=True) -def quad_ker( - u, - order, - mode, - is_log, - logx, - areas, - a_s, - nf, - L, -): - """ - Raw scale variation B kernel inside quad. - - Parameters - ---------- - u : float - quad argument - order : int - perturbation order - mode : str - sector element - is_log : boolean - is a logarithmic interpolation - logx : float - Mellin inversion point - areas : tuple - basis function configuration - a_s : float - target coupling value - nf : int - number of active flavors - L : float - logarithm of the squared ratio of factorization and renormalization scale - - Returns - ------- - ker : float - evaluated scale variation kernel - """ - ker_base = QuadKerBase(u, is_log, logx, mode) - integrand = ker_base.integrand(areas) - if integrand == 0.0: - return 0.0 - - # compute the actual scale variation kernel - if ker_base.is_singlet: - gamma_singlet = ad.gamma_singlet(order, ker_base.n, nf) - ker = singlet_dispatcher(gamma_singlet, a_s, order, nf, L) - ker = select_singlet_element(ker, mode) - else: - gamma_ns = ad.gamma_ns(order, mode[-1], ker_base.n, nf) - ker = non_singlet_dispatcher(gamma_ns, a_s, order, nf, L) - - # recombine everthing - return np.real(ker * integrand) - - -class ScaleVariationOperator(Operator): - """ - Internal representation of a Scale Variation operator. - - The actual matrices are computed upon calling :meth:`compute`. - - Parameters - ---------- - config : dict - configuration - managers : dict - managers - nf : int - number of active flavors - q2 : float - evolution scale - """ - - def __init__(self, config, managers, nf, q2): - super().__init__(config, managers, nf, q2) - - def compute(self): - """compute the actual operators (i.e. run the integrations)""" - self.initialize_op_members() - - # At LO you don't need anything else - if self.config["order"] == 0: - logger.info("Scale Variation: no need to compute scale variations at LO") - self.copy_ns_ops() - return - - tot_start_time = time.perf_counter() - a_s = self.strong_coupling.a_s( - self.q2_from / self.fact_to_ren, fact_scale=self.q2_from - ) - logger.info( - "Scale Variation: (µ_F/µ_R)^2 = %e, Q^2 = %e, nf=%d", - self.fact_to_ren, - self.q2_from, - self.nf, - ) - logger.info("Scale Variation: computing operators - 0/%d", self.grid_size) - # iterate output grid - for k, logx in enumerate(np.log(self.int_disp.xgrid_raw)): - start_time = time.perf_counter() - # iterate basis functions - for l, bf in enumerate(self.int_disp): - if k == l and l == self.grid_size - 1: - continue - # iterate sectors - for label in self.labels: - # compute and set - res = integrate.quad( - quad_ker, - 0.5, - 1.0 - self._mellin_cut, - args=( - self.config["order"], - label, - self.int_disp.log, - logx, - bf.areas_representation, - a_s, - self.nf, - np.log(self.fact_to_ren), - ), - epsabs=1e-12, - epsrel=1e-5, - limit=100, - full_output=1, - ) - val, err = res[:2] - self.op_members[label].value[k][l] = val - self.op_members[label].error[k][l] = err - - logger.info( - "Scale Variation: computing operators - %d/%d took: %f s", - k + 1, - self.grid_size, - time.perf_counter() - start_time, - ) - - # closing comment - logger.info( - "Scale Variation: Total time %f s", time.perf_counter() - tot_start_time - ) - # copy non-singlet kernels, if necessary - self.copy_ns_ops() +# @nb.njit("f8(f8,u1,string,b1,f8,f8[:,:],f8,u1,f8)", cache=True) +# def quad_ker( +# u, +# order, +# mode, +# is_log, +# logx, +# areas, +# a_s, +# nf, +# L, +# ): +# """ +# Raw scale variation B kernel inside quad. + +# Parameters +# ---------- +# u : float +# quad argument +# order : int +# perturbation order +# mode : str +# sector element +# is_log : boolean +# is a logarithmic interpolation +# logx : float +# Mellin inversion point +# areas : tuple +# basis function configuration +# a_s : float +# target coupling value +# nf : int +# number of active flavors +# L : float +# logarithm of the squared ratio of factorization and renormalization scale + +# Returns +# ------- +# ker : float +# evaluated scale variation kernel +# """ +# ker_base = QuadKerBase(u, is_log, logx, mode) +# integrand = ker_base.integrand(areas) +# if integrand == 0.0: +# return 0.0 + +# # compute the actual scale variation kernel +# if ker_base.is_singlet: +# gamma_singlet = ad.gamma_singlet(order, ker_base.n, nf) +# ker = singlet_dispatcher(gamma_singlet, a_s, order, nf, L) +# ker = select_singlet_element(ker, mode) +# else: +# gamma_ns = ad.gamma_ns(order, mode[-1], ker_base.n, nf) +# ker = non_singlet_dispatcher(gamma_ns, a_s, order, nf, L) + +# # recombine everthing +# return np.real(ker * integrand) + + +# class ScaleVariationOperator(Operator): +# """ +# Internal representation of a Scale Variation operator. + +# The actual matrices are computed upon calling :meth:`compute`. + +# Parameters +# ---------- +# config : dict +# configuration +# managers : dict +# managers +# nf : int +# number of active flavors +# q2 : float +# evolution scale +# """ + +# def __init__(self, config, managers, nf, q2): +# super().__init__(config, managers, nf, q2) + +# def compute(self): +# """compute the actual operators (i.e. run the integrations)""" +# self.initialize_op_members() + +# # At LO you don't need anything else +# if self.config["order"] == 0: +# logger.info("Scale Variation: no need to compute scale variations at LO") +# self.copy_ns_ops() +# return + +# tot_start_time = time.perf_counter() +# a_s = self.strong_coupling.a_s( +# self.q2_from / self.fact_to_ren, fact_scale=self.q2_from +# ) +# logger.info( +# "Scale Variation: (µ_F/µ_R)^2 = %e, Q^2 = %e, nf=%d", +# self.fact_to_ren, +# self.q2_from, +# self.nf, +# ) +# logger.info("Scale Variation: computing operators - 0/%d", self.grid_size) +# # iterate output grid +# for k, logx in enumerate(np.log(self.int_disp.xgrid_raw)): +# start_time = time.perf_counter() +# # iterate basis functions +# for l, bf in enumerate(self.int_disp): +# if k == l and l == self.grid_size - 1: +# continue +# # iterate sectors +# for label in self.labels: +# # compute and set +# res = integrate.quad( +# quad_ker, +# 0.5, +# 1.0 - self._mellin_cut, +# args=( +# self.config["order"], +# label, +# self.int_disp.log, +# logx, +# bf.areas_representation, +# a_s, +# self.nf, +# np.log(self.fact_to_ren), +# ), +# epsabs=1e-12, +# epsrel=1e-5, +# limit=100, +# full_output=1, +# ) +# val, err = res[:2] +# self.op_members[label].value[k][l] = val +# self.op_members[label].error[k][l] = err + +# logger.info( +# "Scale Variation: computing operators - %d/%d took: %f s", +# k + 1, +# self.grid_size, +# time.perf_counter() - start_time, +# ) + +# # closing comment +# logger.info( +# "Scale Variation: Total time %f s", time.perf_counter() - tot_start_time +# ) +# # copy non-singlet kernels, if necessary +# self.copy_ns_ops() diff --git a/tests/test_ev_op_grid.py b/tests/test_ev_op_grid.py index 0870ad1e2..6720cae23 100644 --- a/tests/test_ev_op_grid.py +++ b/tests/test_ev_op_grid.py @@ -39,7 +39,7 @@ def _get_setup(self, use_FFNS): "SV_scheme": None, } operators_card = { - "Q2grid": [1, 100 ** 2], + "Q2grid": [1, 100**2], "interpolation_xgrid": [0.1, 1.0], "interpolation_polynomial_degree": 1, "interpolation_is_log": True, @@ -122,7 +122,7 @@ def test_compute_q2grid(self): def test_grid_computation_VFNS(self): """Checks that the grid can be computed""" opgrid = self._get_operator_grid(False) - qgrid_check = [3, 5, 200 ** 2] + qgrid_check = [3, 5, 200**2] operators = opgrid.compute(qgrid_check) assert len(operators) == len(qgrid_check) diff --git a/tests/test_ev_operator.py b/tests/test_ev_operator.py index b5284846f..76a01cd6f 100644 --- a/tests/test_ev_operator.py +++ b/tests/test_ev_operator.py @@ -41,7 +41,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - is_sv_scheme_a=False, + sv_scheme=0, ) np.testing.assert_allclose(res_ns, 0.0) res_s = quad_ker( @@ -58,7 +58,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - is_sv_scheme_a=False, + sv_scheme=0, ) np.testing.assert_allclose(res_s, 1.0) res_s = quad_ker( @@ -75,27 +75,28 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - is_sv_scheme_a=False, + sv_scheme=0, ) np.testing.assert_allclose(res_s, 0.0) for mode in ["NS_p", "S_qq"]: - res_sv = quad_ker( - u=0, - order=0, - mode=mode, - method="", - is_log=True, - logx=1.0, - areas=np.zeros(3), - a1=1, - a0=2, - nf=3, - L=0, - ev_op_iterations=0, - ev_op_max_order=0, - is_sv_scheme_a=True, - ) - np.testing.assert_allclose(res_sv, 1.0) + for sv in [1, 2]: + res_sv = quad_ker( + u=0, + order=0, + mode=mode, + method="", + is_log=True, + logx=1.0, + areas=np.zeros(3), + a1=1, + a0=2, + nf=3, + L=0, + ev_op_iterations=0, + ev_op_max_order=0, + sv_scheme=sv, + ) + np.testing.assert_allclose(res_sv, 1.0) monkeypatch.setattr(interpolation, "log_evaluate_Nx", lambda *args: 0) res_ns = quad_ker( @@ -112,7 +113,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - is_sv_scheme_a=False, + sv_scheme=0, ) np.testing.assert_allclose(res_ns, 0.0) @@ -267,7 +268,7 @@ def quad_ker_pegasus( L, ev_op_iterations, 10, - None, + 0, ), epsabs=1e-12, epsrel=1e-5, diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index a58c5e60d..c4e06b7b6 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -240,11 +240,11 @@ def test_log_eval_N(self): assert_almost_equal(act_c, res_c) # Full -> \tilde p_0(N) = exp(-N)(exp(N)-1-N)/N^2 # MMa: Integrate[x^(n-1) (-Log[x]),{x,1/E,1}] - p0Nref_full = lambda N, lnx: ((np.exp(N) - 1 - N) / N ** 2) * np.exp( + p0Nref_full = lambda N, lnx: ((np.exp(N) - 1 - N) / N**2) * np.exp( -N * (lnx + 1) ) # partial = lower bound is neglected; - p0Nref_partial = lambda N, lnx: (1 / N ** 2) * np.exp(-N * lnx) + p0Nref_partial = lambda N, lnx: (1 / N**2) * np.exp(-N * lnx) p1N = inter_N[1] assert len(p1N.areas) == 1 p1_cs_ref = [1, 1] @@ -252,8 +252,8 @@ def test_log_eval_N(self): assert_almost_equal(act_c, res_c) # p_1(x) = 1+\ln(x) -> \tilde p_1(N) = (exp(-N)-1+N)/N^2 # MMa: Integrate[x^(n-1) (1+Log[x]),{x,1/E,1}] - p1Nref_full = lambda N, lnx: ((np.exp(-N) - 1 + N) / N ** 2) * np.exp(-N * lnx) - p1Nref_partial = lambda N, lnx: (1 / N - 1 / N ** 2) * np.exp(-N * lnx) + p1Nref_full = lambda N, lnx: ((np.exp(-N) - 1 + N) / N**2) * np.exp(-N * lnx) + p1Nref_partial = lambda N, lnx: (1 / N - 1 / N**2) * np.exp(-N * lnx) # iterate configurations for N in [1.0, 2.0, complex(1.0, 1.0)]: # check skip diff --git a/tests/test_sv_a.py b/tests/test_sv_a.py index bc6f308a9..5c7e36ef1 100644 --- a/tests/test_sv_a.py +++ b/tests/test_sv_a.py @@ -2,28 +2,28 @@ import numpy as np -from eko.scale_variations.a import gamma_fact +from eko.scale_variations.a import gamma_variation def test_gamma_ns_fact(): gamma_ns = np.array([1.0, 0.5, 0.25]) - gamma_ns_LO_0 = gamma_fact(gamma_ns.copy(), 0, 3, 0) + gamma_ns_LO_0 = gamma_variation(gamma_ns.copy(), 0, 3, 0) np.testing.assert_allclose(gamma_ns_LO_0, gamma_ns) - gamma_ns_LO_1 = gamma_fact(gamma_ns.copy(), 0, 3, 1) + gamma_ns_LO_1 = gamma_variation(gamma_ns.copy(), 0, 3, 1) np.testing.assert_allclose(gamma_ns_LO_1, gamma_ns) - gamma_ns_NLO_1 = gamma_fact(gamma_ns.copy(), 1, 3, 1) + gamma_ns_NLO_1 = gamma_variation(gamma_ns.copy(), 1, 3, 1) assert gamma_ns_NLO_1[1] < gamma_ns[1] - gamma_ns_NNLO_1 = gamma_fact(gamma_ns.copy(), 2, 3, 1) + gamma_ns_NNLO_1 = gamma_variation(gamma_ns.copy(), 2, 3, 1) assert gamma_ns_NNLO_1[2] - gamma_ns[2] == 8.0 def test_gamma_singlet_fact(): gamma_s = np.array([1.0, 0.5, 0.25]) - gamma_s_LO_0 = gamma_fact(gamma_s.copy(), 0, 3, 0) + gamma_s_LO_0 = gamma_variation(gamma_s.copy(), 0, 3, 0) np.testing.assert_allclose(gamma_s_LO_0, gamma_s) - gamma_s_LO_1 = gamma_fact(gamma_s.copy(), 0, 3, 1) + gamma_s_LO_1 = gamma_variation(gamma_s.copy(), 0, 3, 1) np.testing.assert_allclose(gamma_s_LO_1, gamma_s) - gamma_s_NLO_1 = gamma_fact(gamma_s.copy(), 1, 3, 1) + gamma_s_NLO_1 = gamma_variation(gamma_s.copy(), 1, 3, 1) assert gamma_s_NLO_1[1] < gamma_s[1] - gamma_s_NNLO_1 = gamma_fact(gamma_s.copy(), 2, 3, 1) + gamma_s_NNLO_1 = gamma_variation(gamma_s.copy(), 2, 3, 1) assert gamma_s_NNLO_1[2] - gamma_s[2] == 8.0 diff --git a/tests/test_sv_b.py b/tests/test_sv_b.py index 61f22ce04..5ac6373b0 100644 --- a/tests/test_sv_b.py +++ b/tests/test_sv_b.py @@ -1,167 +1,31 @@ # -*- coding: utf-8 -*- import numpy as np -import scipy.integrate -from eko import interpolation, mellin -from eko.evolution_operator.grid import OperatorGrid -from eko.interpolation import InterpolatorDispatcher -from eko.kernels import non_singlet as ns -from eko.kernels import singlet as s from eko.scale_variations import b -from eko.strong_coupling import StrongCoupling -from eko.thresholds import ThresholdsAtlas def test_ns_sv_dispacher(): """Test to identity""" order = 2 - gamma_ns = np.random.random((order + 1, 2, 2)) + gamma_ns = np.random.rand(order + 1) L = 0 nf = 5 a_s = 0.35 + ker_test = np.random.random(1) np.testing.assert_allclose( - b.non_singlet_dispatcher(gamma_ns, a_s, order, nf, L), 1 + b.non_singlet_variation(ker_test, gamma_ns, a_s, order, nf, L), ker_test ) def test_singlet_sv_dispacher(): """Test to identity""" order = 2 - gamma_singlet = np.random.random((order + 1, 2, 2)) + gamma_singlet = np.random.rand(order + 1, 2, 2) L = 0 nf = 5 a_s = 0.35 + ker_test = np.random.rand(2, 2) np.testing.assert_allclose( - b.singlet_dispatcher(gamma_singlet, a_s, order, nf, L), np.eye(2) + b.singlet_variation(ker_test, gamma_singlet, a_s, order, nf, L), ker_test ) - - -def test_quad_ker(monkeypatch): - monkeypatch.setattr( - mellin, "Talbot_path", lambda *args: 2 - ) # N=2 is a safe evaluation point - monkeypatch.setattr( - mellin, "Talbot_jac", lambda *args: complex(0, np.pi) - ) # negate mellin prefactor - monkeypatch.setattr(interpolation, "log_evaluate_Nx", lambda *args: 1) - monkeypatch.setattr(interpolation, "evaluate_Nx", lambda *args: 1) - monkeypatch.setattr(ns, "dispatcher", lambda *args: 1.0) - monkeypatch.setattr(s, "dispatcher", lambda *args: np.identity(2)) - for is_log in [True, False]: - res_ns = b.quad_ker( - u=0, - order=2, - mode="NS_p", - is_log=is_log, - logx=1.0, - areas=np.zeros(3), - a_s=1, - nf=3, - L=0, - ) - np.testing.assert_allclose(res_ns, 1.0) - res_s = b.quad_ker( - u=0, - order=2, - mode="S_qq", - is_log=is_log, - logx=1.0, - areas=np.zeros(3), - a_s=1, - nf=3, - L=0, - ) - np.testing.assert_allclose(res_s, 1.0) - res_s = b.quad_ker( - u=0, - order=2, - mode="S_qg", - is_log=is_log, - logx=1.0, - areas=np.zeros(3), - a_s=1, - nf=3, - L=0, - ) - np.testing.assert_allclose(res_s, 0.0) - res_logx = b.quad_ker( - u=0, - order=2, - mode="S_qq", - is_log=is_log, - logx=0.0, - areas=np.zeros(3), - a_s=1, - nf=3, - L=10, - ) - np.testing.assert_allclose(res_logx, 0.0) - - -class TestOperator: - def test_compute(self, monkeypatch): - # setup objs - theory_card = { - "alphas": 0.35, - "PTO": 0, - "ModEv": "TRN", - "fact_to_ren_scale_ratio": np.sqrt(2), - "Qref": np.sqrt(2), - "nfref": None, - "Q0": np.sqrt(2), - "nf0": 3, - "FNS": "FFNS", - "NfFF": 3, - "IC": 0, - "IB": 0, - "mc": 1.0, - "mb": 4.75, - "mt": 173.0, - "kcThr": np.inf, - "kbThr": np.inf, - "ktThr": np.inf, - "MaxNfPdf": 6, - "MaxNfAs": 6, - "HQ": "POLE", - "SV_scheme": "B", - } - operators_card = { - "Q2grid": [1, 10], - "interpolation_xgrid": [0.1, 1.0], - "interpolation_polynomial_degree": 1, - "interpolation_is_log": True, - "debug_skip_singlet": False, - "debug_skip_non_singlet": False, - "ev_op_max_order": 1, - "ev_op_iterations": 1, - "backward_inversion": "exact", - } - g = OperatorGrid.from_dict( - theory_card, - operators_card, - ThresholdsAtlas.from_dict(theory_card), - StrongCoupling.from_dict(theory_card), - InterpolatorDispatcher.from_dict(operators_card), - ) - o = b.ScaleVariationOperator(g.config, g.managers, nf=3, q2=2) - # fake quad - monkeypatch.setattr( - scipy.integrate, "quad", lambda *args, **kwargs: np.random.rand(2) - ) - # LO - o.compute() - assert "NS_m" in o.op_members - np.testing.assert_allclose( - o.op_members["NS_m"].value, o.op_members["NS_p"].value - ) - np.testing.assert_allclose( - o.op_members["NS_v"].value, o.op_members["NS_p"].value - ) - # NLO - o.config["order"] = 1 - o.compute() - assert not np.allclose(o.op_members["NS_p"].value, o.op_members["NS_m"].value) - np.testing.assert_allclose( - o.op_members["NS_v"].value, o.op_members["NS_m"].value - ) From 1cafe12f2ac51ca1f858a260e495aef4974e0092 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Wed, 16 Feb 2022 14:38:55 +0100 Subject: [PATCH 19/74] Promote evolution labes to a dict --- src/eko/anomalous_dimensions/__init__.py | 16 +++++----- src/eko/evolution_operator/__init__.py | 22 +++++++------- tests/test_ad.py | 8 ++--- tests/test_ev_operator.py | 37 +++++++++++++++++++----- 4 files changed, 53 insertions(+), 30 deletions(-) diff --git a/src/eko/anomalous_dimensions/__init__.py b/src/eko/anomalous_dimensions/__init__.py index 173fe5ead..b4f2893ea 100644 --- a/src/eko/anomalous_dimensions/__init__.py +++ b/src/eko/anomalous_dimensions/__init__.py @@ -71,7 +71,7 @@ def exp_singlet(gamma_S): return exp, lambda_p, lambda_m, e_p, e_m -@nb.njit("c16[:](u1,string,c16,u1)", cache=True) +@nb.njit("c16[:](u1,u1,c16,u1)", cache=True) def gamma_ns(order, mode, n, nf): r""" Computes the tower of the non-singlet anomalous dimensions @@ -80,8 +80,8 @@ def gamma_ns(order, mode, n, nf): ---------- order : int perturbative order - mode : "m" | "p" | "v" - sector identifier + mode : int + sector identifier 4: m, 5: p, 6: v n : complex Mellin variable nf : int @@ -109,21 +109,21 @@ def gamma_ns(order, mode, n, nf): # NLO and beyond if order >= 1: # TODO: pass the necessary harmonics to nlo gammas - if mode == "p": + if mode == 5: gamma_ns_1 = nlo.gamma_nsp_1(n, nf) # To fill the full valence vector in NNLO we need to add gamma_ns^1 explicitly here - elif mode in ["m", "v"]: + elif mode in [4, 6]: gamma_ns_1 = nlo.gamma_nsm_1(n, nf) gamma_ns[1] = gamma_ns_1 # NNLO and beyond if order >= 2: sx = np.append(sx, harmonics.harmonic_S2(n)) sx = np.append(sx, harmonics.harmonic_S3(n)) - if mode == "p": + if mode == 5: gamma_ns_2 = -nnlo.gamma_nsp_2(n, nf, sx) - elif mode == "m": + elif mode == 4: gamma_ns_2 = -nnlo.gamma_nsm_2(n, nf, sx) - elif mode == "v": + elif mode == 6: gamma_ns_2 = -nnlo.gamma_nsv_2(n, nf, sx) gamma_ns[2] = gamma_ns_2 return gamma_ns diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 2816df46e..cab2d1d3e 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -22,15 +22,17 @@ logger = logging.getLogger(__name__) +full_labels_dict = dict(zip(full_labels, np.arange(len(full_labels)))) -@nb.njit("c16(c16[:,:],string)") + +@nb.njit("c16(c16[:,:],u1)", cache=True) def select_singlet_element(ker, mode): """ Select element of the singlet matrix Parameters ---------- - mode : str + mode : int sector element ker : numpy.ndarray singlet integration kernel @@ -40,8 +42,8 @@ def select_singlet_element(ker, mode): ker : complex singlet integration kernel element """ - k = 0 if mode[2] == "q" else 1 - l = 0 if mode[3] == "q" else 1 + k = 0 if mode < 2 else 1 + l = 0 if mode % 2 == 0 else 1 return ker[k, l] @@ -66,12 +68,12 @@ class QuadKerBase: is a logarithmic interpolation logx : float Mellin inversion point - mode : str + mode : int sector element """ def __init__(self, u, is_log, logx, mode): - self.is_singlet = mode[0] == "S" + self.is_singlet = mode < 4 self.is_log = is_log self.u = u self.logx = logx @@ -111,7 +113,7 @@ def integrand( return self.path.prefactor * pj * self.path.jac -@nb.njit("f8(f8,u1,string,string,b1,f8,f8[:,:],f8,f8,f8,f8,u4,u1,u1)", cache=True) +@nb.njit("f8(f8,u1,u1,string,b1,f8,f8[:,:],f8,f8,f8,f8,u4,u1,u1)", cache=True) def quad_ker( u, order, @@ -139,7 +141,7 @@ def quad_ker( perturbation order method : str method - mode : str + mode : int sector element is_log : boolean is a logarithmic interpolation @@ -186,7 +188,7 @@ def quad_ker( ker = b.singlet_variation(ker, gamma_singlet, a1, order, nf, L) ker = select_singlet_element(ker, mode) else: - gamma_ns = ad.gamma_ns(order, mode[-1], ker_base.n, nf) + gamma_ns = ad.gamma_ns(order, mode, ker_base.n, nf) if sv_scheme == 1: gamma_ns = a.gamma_variation(gamma_ns, order, nf, L) ker = ns.dispatcher( @@ -365,7 +367,7 @@ def compute(self): 1.0 - self._mellin_cut, args=( self.config["order"], - label, + full_labels_dict[label], self.config["method"], self.int_disp.log, logx, diff --git a/tests/test_ad.py b/tests/test_ad.py index 3363220c1..3356107ca 100644 --- a/tests/test_ad.py +++ b/tests/test_ad.py @@ -53,9 +53,9 @@ def test_eigensystem_gamma_singlet_projectors_EV(): def test_gamma_ns(): nf = 3 # LO - assert_almost_equal(ad.gamma_ns(2, "p", 1, nf)[0], 0.0) + assert_almost_equal(ad.gamma_ns(2, 5, 1, nf)[0], 0.0) # NLO - assert_allclose(ad.gamma_ns(1, "m", 1, nf), np.zeros(2), atol=2e-6) + assert_allclose(ad.gamma_ns(1, 4, 1, nf), np.zeros(2), atol=2e-6) # NNLO - assert_allclose(ad.gamma_ns(2, "m", 1, nf), np.zeros(3), atol=2e-4) - assert_allclose(ad.gamma_ns(2, "v", 1, nf), np.zeros(3), atol=8e-4) + assert_allclose(ad.gamma_ns(2, 4, 1, nf), np.zeros(3), atol=2e-4) + assert_allclose(ad.gamma_ns(2, 6, 1, nf), np.zeros(3), atol=8e-4) diff --git a/tests/test_ev_operator.py b/tests/test_ev_operator.py index 76a01cd6f..bddee5f84 100644 --- a/tests/test_ev_operator.py +++ b/tests/test_ev_operator.py @@ -6,7 +6,12 @@ from eko import anomalous_dimensions as ad from eko import basis_rotation as br from eko import interpolation, mellin -from eko.evolution_operator import Operator, quad_ker +from eko.evolution_operator import ( + Operator, + full_labels_dict, + quad_ker, + select_singlet_element, +) from eko.evolution_operator.grid import OperatorGrid from eko.interpolation import InterpolatorDispatcher from eko.kernels import non_singlet as ns @@ -15,6 +20,22 @@ from eko.thresholds import ThresholdsAtlas +def test_full_labels_dict(): + for mode in ["S_qq", "S_qg", "S_gq", "S_gg"]: + assert full_labels_dict[mode] < 4 + for mode in ["NS_p", "NS_m", "NS_v"]: + assert full_labels_dict[mode] >= 4 + + +def test_select_singlet_element(): + fake_singlet_ker = np.array([["S_qq", "S_qg"], ["S_gq", "S_gg"]]) + for mode in np.arange(4): + assert ( + select_singlet_element(fake_singlet_ker, mode) + == list(full_labels_dict)[mode] + ) + + def test_quad_ker(monkeypatch): monkeypatch.setattr( mellin, "Talbot_path", lambda *args: 2 @@ -30,7 +51,7 @@ def test_quad_ker(monkeypatch): res_ns = quad_ker( u=0, order=0, - mode="NS_p", + mode=full_labels_dict["NS_p"], method="", is_log=is_log, logx=0.0, @@ -47,7 +68,7 @@ def test_quad_ker(monkeypatch): res_s = quad_ker( u=0, order=0, - mode="S_qq", + mode=full_labels_dict["S_qq"], method="", is_log=is_log, logx=1.0, @@ -64,7 +85,7 @@ def test_quad_ker(monkeypatch): res_s = quad_ker( u=0, order=0, - mode="S_qg", + mode=full_labels_dict["S_qg"], method="", is_log=is_log, logx=0.0, @@ -83,7 +104,7 @@ def test_quad_ker(monkeypatch): res_sv = quad_ker( u=0, order=0, - mode=mode, + mode=full_labels_dict[mode], method="", is_log=True, logx=1.0, @@ -102,7 +123,7 @@ def test_quad_ker(monkeypatch): res_ns = quad_ker( u=0, order=0, - mode="NS_p", + mode=full_labels_dict["NS_p"], method="", is_log=True, logx=0.0, @@ -223,7 +244,7 @@ def quad_ker_pegasus( phi = 3 / 4 * np.pi c = 1.9 n = complex(c + u * np.exp(1j * phi)) - gamma_ns = ad.gamma_ns(order, mode[-1], n, nf) + gamma_ns = ad.gamma_ns(order, mode, n, nf) ker = ns.dispatcher( order, method, @@ -241,7 +262,7 @@ def quad_ker_pegasus( xgrid = np.geomspace(1e-7, 1, 10) int_disp = InterpolatorDispatcher(xgrid, 1, True) order = 1 - mode = "NS_p" + mode = full_labels_dict["NS_p"] method = "" logxs = np.log(int_disp.xgrid_raw) a1 = 1 From 43a75daa030f09be328cfff107151df8dd05df49 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Wed, 16 Feb 2022 16:20:56 +0100 Subject: [PATCH 20/74] Improve a_d and sv labels --- src/eko/anomalous_dimensions/__init__.py | 12 +++++---- src/eko/basis_rotation.py | 4 +++ src/eko/evolution_operator/__init__.py | 29 ++++++++++++++-------- src/eko/scale_variations/__init__.py | 5 ++++ tests/test_ev_operator.py | 31 +++++++++++++++--------- 5 files changed, 54 insertions(+), 27 deletions(-) diff --git a/src/eko/anomalous_dimensions/__init__.py b/src/eko/anomalous_dimensions/__init__.py index b4f2893ea..e5872bf2d 100644 --- a/src/eko/anomalous_dimensions/__init__.py +++ b/src/eko/anomalous_dimensions/__init__.py @@ -20,6 +20,7 @@ import numba as nb import numpy as np +from ..basis_rotation import anomalous_dimensions_basis from . import harmonics, lo, nlo, nnlo @@ -101,6 +102,7 @@ def gamma_ns(order, mode, n, nf): eko.anomalous_dimensions.nnlo.gamma_nsm_2 : :math:`\gamma_{ns,-}^{(2)}(N)` eko.anomalous_dimensions.nnlo.gamma_nsv_2 : :math:`\gamma_{ns,v}^{(2)}(N)` """ + label = anomalous_dimensions_basis[mode][-1] # cache the s-es sx = np.full(1, harmonics.harmonic_S1(n)) # now combine @@ -109,21 +111,21 @@ def gamma_ns(order, mode, n, nf): # NLO and beyond if order >= 1: # TODO: pass the necessary harmonics to nlo gammas - if mode == 5: + if label == "p": gamma_ns_1 = nlo.gamma_nsp_1(n, nf) # To fill the full valence vector in NNLO we need to add gamma_ns^1 explicitly here - elif mode in [4, 6]: + elif label in ["m", "v"]: gamma_ns_1 = nlo.gamma_nsm_1(n, nf) gamma_ns[1] = gamma_ns_1 # NNLO and beyond if order >= 2: sx = np.append(sx, harmonics.harmonic_S2(n)) sx = np.append(sx, harmonics.harmonic_S3(n)) - if mode == 5: + if label == "p": gamma_ns_2 = -nnlo.gamma_nsp_2(n, nf, sx) - elif mode == 4: + elif label == "m": gamma_ns_2 = -nnlo.gamma_nsm_2(n, nf, sx) - elif mode == 6: + elif label == "v": gamma_ns_2 = -nnlo.gamma_nsv_2(n, nf, sx) gamma_ns[2] = gamma_ns_2 return gamma_ns diff --git a/src/eko/basis_rotation.py b/src/eko/basis_rotation.py index 9647bd16c..3a49b8eac 100644 --- a/src/eko/basis_rotation.py +++ b/src/eko/basis_rotation.py @@ -73,6 +73,10 @@ r""" Sorted elements in Anomalous Dimensions Basis as :obj:`str`. """ +anomalous_dimensions_basis_idx = tuple(range(len(full_labels))) +r""" +Sorted elements in Anomalous Dimensions Basis as :obj:`int`. +""" # Tranformation from physical basis to QCD evolution basis rotate_flavor_to_evolution = np.array( diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index cab2d1d3e..9264611c1 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -14,7 +14,12 @@ from .. import anomalous_dimensions as ad from .. import interpolation, mellin -from ..basis_rotation import full_labels, singlet_labels +from .. import scale_variations as sv +from ..basis_rotation import ( + anomalous_dimensions_basis, + anomalous_dimensions_basis_idx, + singlet_labels, +) from ..kernels import non_singlet as ns from ..kernels import singlet as s from ..member import OpMember @@ -22,7 +27,8 @@ logger = logging.getLogger(__name__) -full_labels_dict = dict(zip(full_labels, np.arange(len(full_labels)))) +ad_basis_dict = dict(zip(anomalous_dimensions_basis, anomalous_dimensions_basis_idx)) +sv_scheme_dict = dict(zip([None, "A", "B"], [sv.unvaried, sv.scheme_A, sv.scheme_B])) @nb.njit("c16(c16[:,:],u1)", cache=True) @@ -33,7 +39,11 @@ def select_singlet_element(ker, mode): Parameters ---------- mode : int - sector element + sector element: + 0: "S_qq", ker[0,0] + 1: "S_qg", ker[0,1] + 2: "S_gq", ker[1,1] + 3: "S_gg", ker[1,1] ker : numpy.ndarray singlet integration kernel @@ -178,18 +188,18 @@ def quad_ker( if ker_base.is_singlet: gamma_singlet = ad.gamma_singlet(order, ker_base.n, nf) # scale var A is directly applied on gamma - if sv_scheme == 1: + if sv_scheme == sv.scheme_A: gamma_singlet = a.gamma_variation(gamma_singlet, order, nf, L) ker = s.dispatcher( order, method, gamma_singlet, a1, a0, nf, ev_op_iterations, ev_op_max_order ) # scale var B is applied on the kernel - if sv_scheme == 2: + if sv_scheme == sv.scheme_B: ker = b.singlet_variation(ker, gamma_singlet, a1, order, nf, L) ker = select_singlet_element(ker, mode) else: gamma_ns = ad.gamma_ns(order, mode, ker_base.n, nf) - if sv_scheme == 1: + if sv_scheme == sv.scheme_A: gamma_ns = a.gamma_variation(gamma_ns, order, nf, L) ker = ns.dispatcher( order, @@ -200,7 +210,7 @@ def quad_ker( nf, ev_op_iterations, ) - if sv_scheme == 2: + if sv_scheme == sv.scheme_B: ker = b.non_singlet_variation(ker, gamma_ns, a1, order, nf, L) # recombine everthing @@ -247,7 +257,6 @@ def fact_to_ren(self): @property def sv_scheme(self): """Returns the scale variation scheme""" - sv_scheme_dict = {None: 0, "A": 1, "B": 2} return sv_scheme_dict[self.config["SV_scheme"]] @property @@ -300,7 +309,7 @@ def initialize_op_members(self): np.eye(self.grid_size), np.zeros((self.grid_size, self.grid_size)) ) zero = OpMember(*[np.zeros((self.grid_size, self.grid_size))] * 2) - for n in full_labels: + for n in anomalous_dimensions_basis: if n in self.labels: # off diag singlet are zero if n in ["S_qg", "S_gq"]: @@ -367,7 +376,7 @@ def compute(self): 1.0 - self._mellin_cut, args=( self.config["order"], - full_labels_dict[label], + ad_basis_dict[label], self.config["method"], self.int_disp.log, logx, diff --git a/src/eko/scale_variations/__init__.py b/src/eko/scale_variations/__init__.py index 23a8fbaa6..c2a23ef2e 100644 --- a/src/eko/scale_variations/__init__.py +++ b/src/eko/scale_variations/__init__.py @@ -2,3 +2,8 @@ """ This module contain the possible scale variations integrals. """ + +unvaried = 0 +scheme_A = 1 +scheme_B = 2 +"""Scale Variation schemes""" diff --git a/tests/test_ev_operator.py b/tests/test_ev_operator.py index bddee5f84..3a20318f1 100644 --- a/tests/test_ev_operator.py +++ b/tests/test_ev_operator.py @@ -8,7 +8,7 @@ from eko import interpolation, mellin from eko.evolution_operator import ( Operator, - full_labels_dict, + ad_basis_dict, quad_ker, select_singlet_element, ) @@ -20,19 +20,26 @@ from eko.thresholds import ThresholdsAtlas -def test_full_labels_dict(): +def test_ad_basis_dict(): + assert ad_basis_dict["S_qq"] == 0 + assert ad_basis_dict["S_qg"] == 1 + assert ad_basis_dict["S_gq"] == 2 + assert ad_basis_dict["S_gg"] == 3 + assert ad_basis_dict["NS_m"] == 4 + assert ad_basis_dict["NS_p"] == 5 + assert ad_basis_dict["NS_v"] == 6 + for mode in ["S_qq", "S_qg", "S_gq", "S_gg"]: - assert full_labels_dict[mode] < 4 + assert ad_basis_dict[mode] < 4 for mode in ["NS_p", "NS_m", "NS_v"]: - assert full_labels_dict[mode] >= 4 + assert ad_basis_dict[mode] >= 4 def test_select_singlet_element(): fake_singlet_ker = np.array([["S_qq", "S_qg"], ["S_gq", "S_gg"]]) for mode in np.arange(4): assert ( - select_singlet_element(fake_singlet_ker, mode) - == list(full_labels_dict)[mode] + select_singlet_element(fake_singlet_ker, mode) == list(ad_basis_dict)[mode] ) @@ -51,7 +58,7 @@ def test_quad_ker(monkeypatch): res_ns = quad_ker( u=0, order=0, - mode=full_labels_dict["NS_p"], + mode=ad_basis_dict["NS_p"], method="", is_log=is_log, logx=0.0, @@ -68,7 +75,7 @@ def test_quad_ker(monkeypatch): res_s = quad_ker( u=0, order=0, - mode=full_labels_dict["S_qq"], + mode=ad_basis_dict["S_qq"], method="", is_log=is_log, logx=1.0, @@ -85,7 +92,7 @@ def test_quad_ker(monkeypatch): res_s = quad_ker( u=0, order=0, - mode=full_labels_dict["S_qg"], + mode=ad_basis_dict["S_qg"], method="", is_log=is_log, logx=0.0, @@ -104,7 +111,7 @@ def test_quad_ker(monkeypatch): res_sv = quad_ker( u=0, order=0, - mode=full_labels_dict[mode], + mode=ad_basis_dict[mode], method="", is_log=True, logx=1.0, @@ -123,7 +130,7 @@ def test_quad_ker(monkeypatch): res_ns = quad_ker( u=0, order=0, - mode=full_labels_dict["NS_p"], + mode=ad_basis_dict["NS_p"], method="", is_log=True, logx=0.0, @@ -262,7 +269,7 @@ def quad_ker_pegasus( xgrid = np.geomspace(1e-7, 1, 10) int_disp = InterpolatorDispatcher(xgrid, 1, True) order = 1 - mode = full_labels_dict["NS_p"] + mode = ad_basis_dict["NS_p"] method = "" logxs = np.log(int_disp.xgrid_raw) a1 = 1 From c75f578226615edb67dbf494623bf6935d399a18 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Wed, 16 Feb 2022 19:37:23 +0100 Subject: [PATCH 21/74] test sv A aginst sv B kernel --- src/eko/evolution_operator/__init__.py | 6 ++-- src/eko/scale_variations/b.py | 16 ++++----- tests/test_sv_b.py | 48 +++++++++++++++++++++++--- 3 files changed, 53 insertions(+), 17 deletions(-) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 9264611c1..adc24277f 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -195,7 +195,9 @@ def quad_ker( ) # scale var B is applied on the kernel if sv_scheme == sv.scheme_B: - ker = b.singlet_variation(ker, gamma_singlet, a1, order, nf, L) + ker = np.ascontiguousarray(ker) @ np.ascontiguousarray( + b.singlet_variation(gamma_singlet, a1, order, nf, L) + ) ker = select_singlet_element(ker, mode) else: gamma_ns = ad.gamma_ns(order, mode, ker_base.n, nf) @@ -211,7 +213,7 @@ def quad_ker( ev_op_iterations, ) if sv_scheme == sv.scheme_B: - ker = b.non_singlet_variation(ker, gamma_ns, a1, order, nf, L) + ker = ker * b.non_singlet_variation(gamma_ns, a1, order, nf, L) # recombine everthing return np.real(ker * integrand) diff --git a/src/eko/scale_variations/b.py b/src/eko/scale_variations/b.py index 361ff0d3f..5cb3e34e8 100644 --- a/src/eko/scale_variations/b.py +++ b/src/eko/scale_variations/b.py @@ -13,15 +13,13 @@ logger = logging.getLogger(__name__) -@nb.njit("c16(c16,c16[:],f8,u1,u1,f8)", cache=True) -def non_singlet_variation(ker, gamma, a_s, order, nf, L): +@nb.njit("c16(c16[:],f8,u1,u1,f8)", cache=True) +def non_singlet_variation(gamma, a_s, order, nf, L): """ Scale Variation non singlet dispatcher Parameters ---------- - ker : complex - non singlet evolution kernel gamma : numpy.ndarray anomalous dimensions a_s : float @@ -38,7 +36,7 @@ def non_singlet_variation(ker, gamma, a_s, order, nf, L): sv_ker : numpy.ndarray scale varion kernel """ - sv_ker = ker + sv_ker = 1.0 if order >= 1: sv_ker -= a_s * L * gamma[0] if order >= 2: @@ -49,15 +47,13 @@ def non_singlet_variation(ker, gamma, a_s, order, nf, L): return sv_ker -@nb.njit("c16[:,:](c16[:,:],c16[:,:,:],f8,u1,u1,f8)", cache=True) -def singlet_variation(ker, gamma, a_s, order, nf, L): +@nb.njit("c16[:,:](c16[:,:,:],f8,u1,u1,f8)", cache=True) +def singlet_variation(gamma, a_s, order, nf, L): """ Scale Variation singlet dispatcher Parameters ---------- - ker : numpy.ndarray - singlet evolution kernel gamma : numpy.ndarray anomalous dimensions a_s : float @@ -74,7 +70,7 @@ def singlet_variation(ker, gamma, a_s, order, nf, L): sv_ker : numpy.ndarray scale varion kernel """ - sv_ker = ker + sv_ker = np.eye(2, dtype=np.complex_) if order >= 1: sv_ker -= a_s * L * gamma[0] if order >= 2: diff --git a/tests/test_sv_b.py b/tests/test_sv_b.py index 5ac6373b0..1a1f2ffec 100644 --- a/tests/test_sv_b.py +++ b/tests/test_sv_b.py @@ -2,7 +2,9 @@ import numpy as np -from eko.scale_variations import b +from eko.anomalous_dimensions import gamma_ns, gamma_singlet +from eko.kernels import non_singlet, singlet +from eko.scale_variations import a, b def test_ns_sv_dispacher(): @@ -12,9 +14,8 @@ def test_ns_sv_dispacher(): L = 0 nf = 5 a_s = 0.35 - ker_test = np.random.random(1) np.testing.assert_allclose( - b.non_singlet_variation(ker_test, gamma_ns, a_s, order, nf, L), ker_test + b.non_singlet_variation(gamma_ns, a_s, order, nf, L), 1.0 ) @@ -25,7 +26,44 @@ def test_singlet_sv_dispacher(): L = 0 nf = 5 a_s = 0.35 - ker_test = np.random.rand(2, 2) np.testing.assert_allclose( - b.singlet_variation(ker_test, gamma_singlet, a_s, order, nf, L), ker_test + b.singlet_variation(gamma_singlet, a_s, order, nf, L), np.eye(2) ) + + +def test_scale_variation_a_vs_b(): + """Test sv_scheme A kernel vs sv_scheme B""" + nf = 5 + n = 10 + a1 = 0.118 / (4 * np.pi) + a0 = 0.30 / (4 * np.pi) + method = "truncated" + # one precision test and one with + # a more physical setting + for L in [np.log(2), np.log(1 + 1e-2)]: + ns_rtol = L / 2 + sing_rtol = L + for order in [0, 1, 2]: + # Non singlet kernels + gns = gamma_ns(order, 4, n, nf) + ker = non_singlet.dispatcher( + order, method, gns, a1, a0, nf, ev_op_iterations=1 + ) + gns_a = a.gamma_variation(gns, order, nf, L) + ker_a = non_singlet.dispatcher( + order, method, gns_a, a1, a0, nf, ev_op_iterations=1 + ) + ker_b = ker * b.non_singlet_variation(gns, a1, order, nf, L) + np.testing.assert_allclose(ker_a, ker_b, rtol=ns_rtol) + + # Singlet kernels + gs = gamma_singlet(order, n, nf) + ker = singlet.dispatcher( + order, method, gs, a1, a0, nf, ev_op_iterations=1, ev_op_max_order=1 + ) + gs_a = a.gamma_variation(gs, order, nf, L) + ker_a = singlet.dispatcher( + order, method, gs_a, a1, a0, nf, ev_op_iterations=1, ev_op_max_order=1 + ) + ker_b = ker @ b.singlet_variation(gs, a1, order, nf, L) + np.testing.assert_allclose(ker_a, ker_b, rtol=sing_rtol) From a06e57cde58d17dbaf07e6eec66957283402d144 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Wed, 16 Feb 2022 19:48:44 +0100 Subject: [PATCH 22/74] clean old implementation --- doc/source/theory/pQCD.rst | 3 +- src/eko/scale_variations/b.py | 149 ---------------------------------- 2 files changed, 2 insertions(+), 150 deletions(-) diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index 3b8d2d530..8e5f495a7 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -54,7 +54,7 @@ for the strong coupling) to be equal. This constraint, however, can be lifted in order to provide an estimation of the missing higher order uncertainties (MHOU) coming from |DGLAP| evolution :cite:`AbdulKhalek:2019ihb`. Since scale-dependent contributions to a perturbative prediction are fixed by |RGE| invariance, -the scale variation can be used to generate higher order contributions, +the scale variation can be used to generate higher order contributions, which are then taken as a proxy for the whole missing higher orders. This method provides many advantages: @@ -92,6 +92,7 @@ evolution, always evaluating the strong coupling at :math:`\mu_R^2`. 1 - a_s L \gamma^{(0)} + a_s^2 \left [ L \gamma^{(1)} + \frac{1}{2} L^2 \gamma^{(0)} (\gamma^{(0)}+\beta_0) \right ] In this way the dependence of the |EKO| on :math:`L` is factorized outside the unvaried evolution kernel. + This procedure is repeated for each different |FNS| present in the evolution path. Notice that the two methods should be equivalent, especially for fully linearized solutions (`ModEv=truncated,ev_op_max_iterations=1`) diff --git a/src/eko/scale_variations/b.py b/src/eko/scale_variations/b.py index 5cb3e34e8..4a1069cc6 100644 --- a/src/eko/scale_variations/b.py +++ b/src/eko/scale_variations/b.py @@ -85,152 +85,3 @@ def singlet_variation(gamma, a_s, order, nf, L): * L**2 ) return sv_ker - - -# @nb.njit("f8(f8,u1,string,b1,f8,f8[:,:],f8,u1,f8)", cache=True) -# def quad_ker( -# u, -# order, -# mode, -# is_log, -# logx, -# areas, -# a_s, -# nf, -# L, -# ): -# """ -# Raw scale variation B kernel inside quad. - -# Parameters -# ---------- -# u : float -# quad argument -# order : int -# perturbation order -# mode : str -# sector element -# is_log : boolean -# is a logarithmic interpolation -# logx : float -# Mellin inversion point -# areas : tuple -# basis function configuration -# a_s : float -# target coupling value -# nf : int -# number of active flavors -# L : float -# logarithm of the squared ratio of factorization and renormalization scale - -# Returns -# ------- -# ker : float -# evaluated scale variation kernel -# """ -# ker_base = QuadKerBase(u, is_log, logx, mode) -# integrand = ker_base.integrand(areas) -# if integrand == 0.0: -# return 0.0 - -# # compute the actual scale variation kernel -# if ker_base.is_singlet: -# gamma_singlet = ad.gamma_singlet(order, ker_base.n, nf) -# ker = singlet_dispatcher(gamma_singlet, a_s, order, nf, L) -# ker = select_singlet_element(ker, mode) -# else: -# gamma_ns = ad.gamma_ns(order, mode[-1], ker_base.n, nf) -# ker = non_singlet_dispatcher(gamma_ns, a_s, order, nf, L) - -# # recombine everthing -# return np.real(ker * integrand) - - -# class ScaleVariationOperator(Operator): -# """ -# Internal representation of a Scale Variation operator. - -# The actual matrices are computed upon calling :meth:`compute`. - -# Parameters -# ---------- -# config : dict -# configuration -# managers : dict -# managers -# nf : int -# number of active flavors -# q2 : float -# evolution scale -# """ - -# def __init__(self, config, managers, nf, q2): -# super().__init__(config, managers, nf, q2) - -# def compute(self): -# """compute the actual operators (i.e. run the integrations)""" -# self.initialize_op_members() - -# # At LO you don't need anything else -# if self.config["order"] == 0: -# logger.info("Scale Variation: no need to compute scale variations at LO") -# self.copy_ns_ops() -# return - -# tot_start_time = time.perf_counter() -# a_s = self.strong_coupling.a_s( -# self.q2_from / self.fact_to_ren, fact_scale=self.q2_from -# ) -# logger.info( -# "Scale Variation: (µ_F/µ_R)^2 = %e, Q^2 = %e, nf=%d", -# self.fact_to_ren, -# self.q2_from, -# self.nf, -# ) -# logger.info("Scale Variation: computing operators - 0/%d", self.grid_size) -# # iterate output grid -# for k, logx in enumerate(np.log(self.int_disp.xgrid_raw)): -# start_time = time.perf_counter() -# # iterate basis functions -# for l, bf in enumerate(self.int_disp): -# if k == l and l == self.grid_size - 1: -# continue -# # iterate sectors -# for label in self.labels: -# # compute and set -# res = integrate.quad( -# quad_ker, -# 0.5, -# 1.0 - self._mellin_cut, -# args=( -# self.config["order"], -# label, -# self.int_disp.log, -# logx, -# bf.areas_representation, -# a_s, -# self.nf, -# np.log(self.fact_to_ren), -# ), -# epsabs=1e-12, -# epsrel=1e-5, -# limit=100, -# full_output=1, -# ) -# val, err = res[:2] -# self.op_members[label].value[k][l] = val -# self.op_members[label].error[k][l] = err - -# logger.info( -# "Scale Variation: computing operators - %d/%d took: %f s", -# k + 1, -# self.grid_size, -# time.perf_counter() - start_time, -# ) - -# # closing comment -# logger.info( -# "Scale Variation: Total time %f s", time.perf_counter() - tot_start_time -# ) -# # copy non-singlet kernels, if necessary -# self.copy_ns_ops() From 086aa7c3e0a7a9d52006fb7597a9505862854aaf Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Thu, 17 Feb 2022 13:06:10 +0100 Subject: [PATCH 23/74] Fix minus sign convention --- doc/source/theory/pQCD.rst | 8 ++++---- src/eko/scale_variations/b.py | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index 8e5f495a7..e0061d5b6 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -82,17 +82,17 @@ evolution, always evaluating the strong coupling at :math:`\mu_R^2`. the scale variation is applied to the whole |PDF| set: .. math :: - \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) = \left[ 1 - L \gamma +L^2(\gamma^{2} + \frac{\partial \gamma}{\partial a_s} \beta(a_s)) + ... \right] \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) + \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) = \left[ 1 + L \gamma +L^2(\gamma^{2} - \frac{\partial \gamma}{\partial a_s} \beta(a_s)) + ... \right] \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) where scale variation kernel is expanded consistently order by order in :math:`a_s`, leading to: .. math :: - 1 - L \gamma +L^2(\gamma^{2} + \frac{\partial \gamma}{\partial a_s} \beta(a_s)) = - 1 - a_s L \gamma^{(0)} + a_s^2 \left [ L \gamma^{(1)} + \frac{1}{2} L^2 \gamma^{(0)} (\gamma^{(0)}+\beta_0) \right ] + 1 + L \gamma +L^2(\gamma^{2} - \frac{\partial \gamma}{\partial a_s} \beta(a_s)) = + 1 + a_s L \gamma^{(0)} + a_s^2 \left [ L \gamma^{(1)} + \frac{1}{2} L^2 \gamma^{(0)} (\gamma^{(0)}-\beta_0) \right ] In this way the dependence of the |EKO| on :math:`L` is factorized outside the unvaried evolution kernel. - This procedure is repeated for each different |FNS| present in the evolution path. + This procedure is repeated for each different flavor patch present in the evolution path. Notice that the two methods should be equivalent, especially for fully linearized solutions (`ModEv=truncated,ev_op_max_iterations=1`) diff --git a/src/eko/scale_variations/b.py b/src/eko/scale_variations/b.py index 4a1069cc6..efd0d3628 100644 --- a/src/eko/scale_variations/b.py +++ b/src/eko/scale_variations/b.py @@ -38,11 +38,11 @@ def non_singlet_variation(gamma, a_s, order, nf, L): """ sv_ker = 1.0 if order >= 1: - sv_ker -= a_s * L * gamma[0] + sv_ker += a_s * L * gamma[0] if order >= 2: sv_ker += a_s**2 * ( - -gamma[1] * L - + 1 / 2 * (beta.beta_0(nf) * gamma[0] + gamma[0] * gamma[0]) * L**2 + gamma[1] * L + + 1 / 2 * (-beta.beta_0(nf) * gamma[0] + gamma[0] * gamma[0]) * L**2 ) return sv_ker @@ -72,14 +72,14 @@ def singlet_variation(gamma, a_s, order, nf, L): """ sv_ker = np.eye(2, dtype=np.complex_) if order >= 1: - sv_ker -= a_s * L * gamma[0] + sv_ker += a_s * L * gamma[0] if order >= 2: sv_ker += a_s**2 * ( - -gamma[1] * L + gamma[1] * L + 1 / 2 * ( - beta.beta_0(nf) * gamma[0] + -beta.beta_0(nf) * gamma[0] + np.ascontiguousarray(gamma[0]) @ np.ascontiguousarray(gamma[0]) ) * L**2 From 107c9ff78d6992051d82c0c88d2f4bc0c0b0075b Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Thu, 17 Feb 2022 13:24:26 +0100 Subject: [PATCH 24/74] Improve test between sv_A and sv_B and minor fixes --- doc/source/theory/pQCD.rst | 8 +++-- src/eko/evolution_operator/__init__.py | 2 +- src/eko/scale_variations/b.py | 3 +- tests/test_sv_b.py | 46 +++++++++++++++++++------- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index e0061d5b6..ce0772b32 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -94,8 +94,12 @@ evolution, always evaluating the strong coupling at :math:`\mu_R^2`. In this way the dependence of the |EKO| on :math:`L` is factorized outside the unvaried evolution kernel. This procedure is repeated for each different flavor patch present in the evolution path. -Notice that the two methods should be equivalent, especially for fully linearized solutions -(`ModEv=truncated,ev_op_max_iterations=1`) +Notice that in principle the two methods should be equivalent, especially for fully linearized solutions +(`ModEv=truncated,ev_op_max_iterations=1`), where the difference depends only on the +perturbative expansion in :math:`a_s`. +However, in our implementation this is not exactly true; since the integral of :math:`\frac{\gamma}{\beta}` +is evaluated before the scale variation procedure is applied, the difference between the two +schemes depends also on the actual evolution distance and on the ratio :math:`\ln(\mu_F^2/\mu_R^2)`. Heavy Quark Masses ------------------ diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index adc24277f..d347ba1d0 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -253,7 +253,7 @@ def __init__(self, config, managers, nf, q2_from, q2_to=None, mellin_cut=5e-2): @property def fact_to_ren(self): - """Returns the factor (µ_F/µ_R)^2""" + r"""Returns the factor :math:`(\mu_F/\mu_R)^2`""" return self.config["fact_to_ren"] @property diff --git a/src/eko/scale_variations/b.py b/src/eko/scale_variations/b.py index efd0d3628..c82940cba 100644 --- a/src/eko/scale_variations/b.py +++ b/src/eko/scale_variations/b.py @@ -76,8 +76,7 @@ def singlet_variation(gamma, a_s, order, nf, L): if order >= 2: sv_ker += a_s**2 * ( gamma[1] * L - + 1 - / 2 + + (1 / 2) * ( -beta.beta_0(nf) * gamma[0] + np.ascontiguousarray(gamma[0]) @ np.ascontiguousarray(gamma[0]) diff --git a/tests/test_sv_b.py b/tests/test_sv_b.py index 1a1f2ffec..bf98f779c 100644 --- a/tests/test_sv_b.py +++ b/tests/test_sv_b.py @@ -3,6 +3,7 @@ import numpy as np from eko.anomalous_dimensions import gamma_ns, gamma_singlet +from eko.beta import beta_0 from eko.kernels import non_singlet, singlet from eko.scale_variations import a, b @@ -32,38 +33,59 @@ def test_singlet_sv_dispacher(): def test_scale_variation_a_vs_b(): - """Test sv_scheme A kernel vs sv_scheme B""" + r""" + Test sv_scheme A kernel vs sv_scheme B. + We test that the quantity :math:`(ker_A - ker_B)/ker_{unv}` depends + only on the accuracy in the :math:`\alpha_s` expansion + and not in the size of the `fact_to_ren` itself. + However in our implementation the sv_scheme A depends on + the actual value of a0 and a1, since the evolution integral in :math:`\alpha_s` + is evaluated, so this test ratio :math:`(ker_A - ker_B)/ker_{unv}` + still has contains a dependency on `fact_to_ren` + """ nf = 5 n = 10 a1 = 0.118 / (4 * np.pi) a0 = 0.30 / (4 * np.pi) - method = "truncated" - # one precision test and one with - # a more physical setting - for L in [np.log(2), np.log(1 + 1e-2)]: - ns_rtol = L / 2 - sing_rtol = L - for order in [0, 1, 2]: + method = "iterate-exact" + + def tolerance(g, k, pto, is_singlet): + if pto >= 1: + atol = g[0] * k * a0 + if pto >= 2: + b0 = beta_0(nf) + g02 = g[0] @ g[0] if is_singlet else g[0] ** 2 + atol += -(a0**2) * g[1] * k + k**2 * ( + 1 / 2 * a0**2 * b0 * g[0] - a1 * a0 * g02 + 1 / 2 * a0**2 * g02 + ) + return np.abs(atol) + + for L in [np.log(0.5), np.log(2)]: + for order in [1, 2]: # Non singlet kernels gns = gamma_ns(order, 4, n, nf) ker = non_singlet.dispatcher( order, method, gns, a1, a0, nf, ev_op_iterations=1 ) - gns_a = a.gamma_variation(gns, order, nf, L) + gns_a = a.gamma_variation(gns.copy(), order, nf, L) ker_a = non_singlet.dispatcher( order, method, gns_a, a1, a0, nf, ev_op_iterations=1 ) ker_b = ker * b.non_singlet_variation(gns, a1, order, nf, L) - np.testing.assert_allclose(ker_a, ker_b, rtol=ns_rtol) + ns_atol = tolerance(gns, L, order, False) + np.testing.assert_allclose((ker_a - ker_b) / ker, 0, atol=ns_atol) # Singlet kernels gs = gamma_singlet(order, n, nf) ker = singlet.dispatcher( order, method, gs, a1, a0, nf, ev_op_iterations=1, ev_op_max_order=1 ) - gs_a = a.gamma_variation(gs, order, nf, L) + gs_a = a.gamma_variation(gs.copy(), order, nf, L) ker_a = singlet.dispatcher( order, method, gs_a, a1, a0, nf, ev_op_iterations=1, ev_op_max_order=1 ) ker_b = ker @ b.singlet_variation(gs, a1, order, nf, L) - np.testing.assert_allclose(ker_a, ker_b, rtol=sing_rtol) + s_atol = tolerance(gs, L, order, True) + diff = (ker_a - ker_b) @ np.linalg.inv(ker) + for (i, j), el in np.ndenumerate(diff): + np.testing.assert_allclose(el, 0, atol=s_atol[i, j]) From f5f8bcb436f1985d533b6eb4843de9a1eecd9fe0 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Thu, 17 Feb 2022 13:30:50 +0100 Subject: [PATCH 25/74] fix ascontiguousarray in sv B --- src/eko/evolution_operator/__init__.py | 4 +--- src/eko/scale_variations/b.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index d347ba1d0..a562b8475 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -195,9 +195,7 @@ def quad_ker( ) # scale var B is applied on the kernel if sv_scheme == sv.scheme_B: - ker = np.ascontiguousarray(ker) @ np.ascontiguousarray( - b.singlet_variation(gamma_singlet, a1, order, nf, L) - ) + ker = ker @ b.singlet_variation(gamma_singlet, a1, order, nf, L) ker = select_singlet_element(ker, mode) else: gamma_ns = ad.gamma_ns(order, mode, ker_base.n, nf) diff --git a/src/eko/scale_variations/b.py b/src/eko/scale_variations/b.py index c82940cba..5523e3478 100644 --- a/src/eko/scale_variations/b.py +++ b/src/eko/scale_variations/b.py @@ -83,4 +83,4 @@ def singlet_variation(gamma, a_s, order, nf, L): ) * L**2 ) - return sv_ker + return np.ascontiguousarray(sv_ker) From 78a3d748de127d8bd83c95a84a695c3a7ec790e8 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Thu, 17 Feb 2022 13:39:28 +0100 Subject: [PATCH 26/74] recover grid test --- tests/test_ev_op_grid.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_ev_op_grid.py b/tests/test_ev_op_grid.py index 6720cae23..525cca75b 100644 --- a/tests/test_ev_op_grid.py +++ b/tests/test_ev_op_grid.py @@ -141,7 +141,8 @@ def test_scheme_B(self): "PTO": 1, "SV_scheme": "B", } - for ffns, epsilon, nf0 in zip([False, True], [1e-4, 1e-3], [5, 3]): + epsilon = 1e-1 + for ffns, nf0 in zip([False, True], [5, 3]): theory_update["nf0"] = nf0 opgrid = self._get_operator_grid(use_FFNS=ffns, theory_update=theory_update) opg = opgrid.compute(3) @@ -151,5 +152,5 @@ def test_scheme_B(self): ) sv_opg = sv_opgrid.compute(3) np.testing.assert_allclose( - opg[3]["operators"], sv_opg[3]["operators"], atol=1e-4 + opg[3]["operators"], sv_opg[3]["operators"], atol=0.7 * epsilon ) From 6dfb04d589345e8613ea35a10e03f8e917abf2ad Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Fri, 18 Feb 2022 17:02:03 +0100 Subject: [PATCH 27/74] making test sv A vs sv B more picky --- tests/test_sv_b.py | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/tests/test_sv_b.py b/tests/test_sv_b.py index bf98f779c..9c690f945 100644 --- a/tests/test_sv_b.py +++ b/tests/test_sv_b.py @@ -35,30 +35,31 @@ def test_singlet_sv_dispacher(): def test_scale_variation_a_vs_b(): r""" Test sv_scheme A kernel vs sv_scheme B. - We test that the quantity :math:`(ker_A - ker_B)/ker_{unv}` depends - only on the accuracy in the :math:`\alpha_s` expansion - and not in the size of the `fact_to_ren` itself. - However in our implementation the sv_scheme A depends on - the actual value of a0 and a1, since the evolution integral in :math:`\alpha_s` - is evaluated, so this test ratio :math:`(ker_A - ker_B)/ker_{unv}` - still has contains a dependency on `fact_to_ren` + We test that the quantity :math:`(ker_A - ker_B)/ker_{unv}` + which can be computed analytically + In particular we check the implementation for truncated solutions. + In scheme A since the evolution integral in :math:`\alpha_s` + is evaluated, this test ratio :math:`(ker_A - ker_B)/ker_{unv}` + still has contains a dependency also on the + distance between a0 and a1, moreover it depends on `fact_to_ren`. """ nf = 5 n = 10 a1 = 0.118 / (4 * np.pi) - a0 = 0.30 / (4 * np.pi) - method = "iterate-exact" + a0 = 0.20 / (4 * np.pi) + method = "truncated" - def tolerance(g, k, pto, is_singlet): + def scheme_diff(g, k, pto, is_singlet): if pto >= 1: - atol = g[0] * k * a0 + diff = g[0] * k * (-2 * a1 + a0) if pto >= 2: b0 = beta_0(nf) g02 = g[0] @ g[0] if is_singlet else g[0] ** 2 - atol += -(a0**2) * g[1] * k + k**2 * ( - 1 / 2 * a0**2 * b0 * g[0] - a1 * a0 * g02 + 1 / 2 * a0**2 * g02 + diff += g[1] * k * (-2 * a1**2 + a0**2) + k**2 * ( + b0 * g[0] * (a1**2 - 1 / 2 * a0**2) + + g02 * (-a1 * a0 + 1 / 2 * a0**2) ) - return np.abs(atol) + return diff for L in [np.log(0.5), np.log(2)]: for order in [1, 2]: @@ -72,8 +73,8 @@ def tolerance(g, k, pto, is_singlet): order, method, gns_a, a1, a0, nf, ev_op_iterations=1 ) ker_b = ker * b.non_singlet_variation(gns, a1, order, nf, L) - ns_atol = tolerance(gns, L, order, False) - np.testing.assert_allclose((ker_a - ker_b) / ker, 0, atol=ns_atol) + ns_diff = scheme_diff(gns, L, order, False) + np.testing.assert_allclose((ker_a - ker_b) / ker, ns_diff, atol=1e-3) # Singlet kernels gs = gamma_singlet(order, n, nf) @@ -85,7 +86,7 @@ def tolerance(g, k, pto, is_singlet): order, method, gs_a, a1, a0, nf, ev_op_iterations=1, ev_op_max_order=1 ) ker_b = ker @ b.singlet_variation(gs, a1, order, nf, L) - s_atol = tolerance(gs, L, order, True) - diff = (ker_a - ker_b) @ np.linalg.inv(ker) - for (i, j), el in np.ndenumerate(diff): - np.testing.assert_allclose(el, 0, atol=s_atol[i, j]) + s_diff = scheme_diff(gs, L, order, True) + np.testing.assert_allclose( + (ker_a - ker_b) @ np.linalg.inv(ker), s_diff, atol=5e-3 + ) From db73a155a667ead7897ce3c9a419e2fedf7128cd Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Sun, 20 Feb 2022 18:12:41 +0100 Subject: [PATCH 28/74] revert minus sign in sv b, with proper fixes --- doc/source/theory/pQCD.rst | 14 +++++++------- src/eko/scale_variations/b.py | 12 ++++++------ tests/test_sv_b.py | 28 ++++++++++++++++------------ 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index ce0772b32..5d08c5827 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -74,24 +74,24 @@ evolution, always evaluating the strong coupling at :math:`\mu_R^2`. and the anomalous dimension are then modified using :cite:`Vogt:2004ns`: .. math :: - & \gamma^{(1)}(N) \to \gamma^{(1)}(N) - \beta_0 L \gamma^{(0)} \\ - & \gamma^{(2)}(N) \to \gamma^{(2)}(N) - 2 \beta_0 L \gamma^{(1)} - ( \beta_1 L - \beta_0^2 L^2) \gamma^{(0)} \\ - & L= \ln(\mu_F^2/\mu_R^2) + & \gamma^{(1)}(N) \to \gamma^{(1)}(N) - \beta_0 k \gamma^{(0)} \\ + & \gamma^{(2)}(N) \to \gamma^{(2)}(N) - 2 \beta_0 k \gamma^{(1)} - ( \beta_1 k - \beta_0^2 k^2) \gamma^{(0)} \\ + & k = \ln(\mu_F^2/\mu_R^2) * In ``SV_scheme='B'`` the |EKO| is multiplied by an additional kernel, such that the scale variation is applied to the whole |PDF| set: .. math :: - \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) = \left[ 1 + L \gamma +L^2(\gamma^{2} - \frac{\partial \gamma}{\partial a_s} \beta(a_s)) + ... \right] \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) + \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) = \left[ 1 - k \gamma + k^2(\gamma^{2} - \frac{\partial \gamma}{\partial a_s} \beta(a_s)) + ... \right] \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) where scale variation kernel is expanded consistently order by order in :math:`a_s`, leading to: .. math :: - 1 + L \gamma +L^2(\gamma^{2} - \frac{\partial \gamma}{\partial a_s} \beta(a_s)) = - 1 + a_s L \gamma^{(0)} + a_s^2 \left [ L \gamma^{(1)} + \frac{1}{2} L^2 \gamma^{(0)} (\gamma^{(0)}-\beta_0) \right ] + 1 - k \gamma + k^2(\gamma^{2} - \frac{\partial \gamma}{\partial a_s} \beta(a_s)) = + 1 - a_s k \gamma^{(0)} + a_s^2 \left [ - k \gamma^{(1)} + \frac{1}{2} k^2 \gamma^{(0)} (\gamma^{(0)}+\beta_0) \right ] - In this way the dependence of the |EKO| on :math:`L` is factorized outside the unvaried evolution kernel. + In this way the dependence of the |EKO| on :math:`k` is factorized outside the unvaried evolution kernel. This procedure is repeated for each different flavor patch present in the evolution path. Notice that in principle the two methods should be equivalent, especially for fully linearized solutions diff --git a/src/eko/scale_variations/b.py b/src/eko/scale_variations/b.py index 5523e3478..37c9f8106 100644 --- a/src/eko/scale_variations/b.py +++ b/src/eko/scale_variations/b.py @@ -38,11 +38,11 @@ def non_singlet_variation(gamma, a_s, order, nf, L): """ sv_ker = 1.0 if order >= 1: - sv_ker += a_s * L * gamma[0] + sv_ker -= a_s * L * gamma[0] if order >= 2: sv_ker += a_s**2 * ( - gamma[1] * L - + 1 / 2 * (-beta.beta_0(nf) * gamma[0] + gamma[0] * gamma[0]) * L**2 + -gamma[1] * L + + 1 / 2 * (beta.beta_0(nf) * gamma[0] + gamma[0] * gamma[0]) * L**2 ) return sv_ker @@ -72,13 +72,13 @@ def singlet_variation(gamma, a_s, order, nf, L): """ sv_ker = np.eye(2, dtype=np.complex_) if order >= 1: - sv_ker += a_s * L * gamma[0] + sv_ker -= a_s * L * gamma[0] if order >= 2: sv_ker += a_s**2 * ( - gamma[1] * L + -gamma[1] * L + (1 / 2) * ( - -beta.beta_0(nf) * gamma[0] + beta.beta_0(nf) * gamma[0] + np.ascontiguousarray(gamma[0]) @ np.ascontiguousarray(gamma[0]) ) * L**2 diff --git a/tests/test_sv_b.py b/tests/test_sv_b.py index 9c690f945..572a2ecb2 100644 --- a/tests/test_sv_b.py +++ b/tests/test_sv_b.py @@ -35,29 +35,33 @@ def test_singlet_sv_dispacher(): def test_scale_variation_a_vs_b(): r""" Test sv_scheme A kernel vs sv_scheme B. - We test that the quantity :math:`(ker_A - ker_B)/ker_{unv}` - which can be computed analytically - In particular we check the implementation for truncated solutions. - In scheme A since the evolution integral in :math:`\alpha_s` - is evaluated, this test ratio :math:`(ker_A - ker_B)/ker_{unv}` - still has contains a dependency also on the - distance between a0 and a1, moreover it depends on `fact_to_ren`. + We test that the quantity :math:`(ker_A - ker_B)/ker_{unv}` depends + only on the accuracy in the :math:`\alpha_s` expansion + and not in the size of the `fact_to_ren` itself. + However in our implementation the sv_scheme A depends on + the actual value of a0 and a1, since the evolution integral in :math:`\alpha_s` + is evaluated. Thus this test ratio :math:`(ker_A - ker_B)/ker_{unv}` + still contains a dependency on `fact_to_ren`. """ nf = 5 n = 10 a1 = 0.118 / (4 * np.pi) - a0 = 0.20 / (4 * np.pi) + a0 = 0.2 / (4 * np.pi) method = "truncated" def scheme_diff(g, k, pto, is_singlet): + """ + :math:`(ker_A - ker_B)/ker_{unv}` for truncated expansion + Effects due to non commutativity are neglected thus, + he accuracy of singlet quantities is slightly worst. + """ if pto >= 1: - diff = g[0] * k * (-2 * a1 + a0) + diff = g[0] * k * a0 if pto >= 2: b0 = beta_0(nf) g02 = g[0] @ g[0] if is_singlet else g[0] ** 2 - diff += g[1] * k * (-2 * a1**2 + a0**2) + k**2 * ( - b0 * g[0] * (a1**2 - 1 / 2 * a0**2) - + g02 * (-a1 * a0 + 1 / 2 * a0**2) + diff += a0**2 * g[1] * k - k**2 * ( + 1 / 2 * a0**2 * b0 * g[0] + a1 * a0 * g02 - 1 / 2 * a0**2 * g02 ) return diff From ddd0ba1a973889152991af2fca49dfb171caee11 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 21 Feb 2022 15:13:50 +0100 Subject: [PATCH 29/74] Adding N3LO scalve variations --- src/eko/evolution_operator/__init__.py | 4 +- src/eko/scale_variations/a.py | 18 +++- src/eko/scale_variations/b.py | 119 +++++++++++++++++++++---- tests/test_sv_a.py | 8 +- tests/test_sv_b.py | 7 +- 5 files changed, 132 insertions(+), 24 deletions(-) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index a562b8475..d347ba1d0 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -195,7 +195,9 @@ def quad_ker( ) # scale var B is applied on the kernel if sv_scheme == sv.scheme_B: - ker = ker @ b.singlet_variation(gamma_singlet, a1, order, nf, L) + ker = np.ascontiguousarray(ker) @ np.ascontiguousarray( + b.singlet_variation(gamma_singlet, a1, order, nf, L) + ) ker = select_singlet_element(ker, mode) else: gamma_ns = ad.gamma_ns(order, mode, ker_base.n, nf) diff --git a/src/eko/scale_variations/a.py b/src/eko/scale_variations/a.py index ab61da5c0..4af0c7cd8 100644 --- a/src/eko/scale_variations/a.py +++ b/src/eko/scale_variations/a.py @@ -30,11 +30,23 @@ def gamma_variation(gamma, order, nf, L): """ # since we are modifying *in-place* be carefull, that the order matters! # and indeed, we need to adjust the high elements first + beta0 = beta.beta(0, nf) + beta1 = beta.beta(1, nf) + if order >= 3: + gamma[3] -= ( + 3 * beta0 * L * gamma[2] + + (2 * beta1 * L - 3 * beta0**2 * L**2) * gamma[1] + + ( + beta.beta(2, nf) * L + - 5 / 2 * beta1 * beta0 * L**2 + + beta0**3 * L**3 + ) + * gamma[0] + ) if order >= 2: gamma[2] -= ( - 2 * beta.beta(0, nf) * gamma[1] * L - + (beta.beta(1, nf) * L - beta.beta(0, nf) ** 2 * L**2) * gamma[0] + 2 * beta0 * gamma[1] * L + (beta1 * L - beta0**2 * L**2) * gamma[0] ) if order >= 1: - gamma[1] -= beta.beta(0, nf) * gamma[0] * L + gamma[1] -= beta0 * gamma[0] * L return gamma diff --git a/src/eko/scale_variations/b.py b/src/eko/scale_variations/b.py index 37c9f8106..13c0348cb 100644 --- a/src/eko/scale_variations/b.py +++ b/src/eko/scale_variations/b.py @@ -3,14 +3,95 @@ This module contains the scale variation operator in scheme B """ -import logging import numba as nb import numpy as np from .. import beta -logger = logging.getLogger(__name__) + +@nb.njit(["c16(c16[:],f8)", "c16[:,:](c16[:,:,:],f8)"], cache=True) +def gamma_1_variation(gamma, L): + r""" + Computes the |NLO| anomalous dimension variation. + + Parameters + ---------- + gamma : numpy.ndarray + anomalous dimensions + L : float + logarithmic ratio of factorization and renormalization scale + + Returns + ------- + gamma_1 : complex + variation to :math:`\gamma^{(1)}` + """ + return -L * gamma[0] + + +@nb.njit(["c16(c16[:],f8,f8,c16)", "c16[:,:](c16[:,:,:],f8,f8,c16[:,:])"], cache=True) +def gamma_2_variation(gamma, L, beta0, g0e2): + r""" + Computes the |NNLO| anomalous dimension variation. + + Parameters + ---------- + gamma : numpy.ndarray + anomalous dimensions + L : float + logarithmic ratio of factorization and renormalization scale + beta0: float + :math:`\beta_0` + g0e2: complex + :math:`\gamma^{(0),2}` + + Returns + ------- + gamma_2 : complex + variation to :math:`\gamma^{(2)}` + """ + return -gamma[1] * L + 1 / 2 * (beta0 * gamma[0] + g0e2) * L**2 + + +@nb.njit( + [ + "c16(c16[:],f8,f8,f8,c16,c16,c16)", + "c16[:,:](c16[:,:,:],f8,f8,f8,c16[:,:],c16[:,:],c16[:,:])", + ], + cache=True, +) +def gamma_3_variation(gamma, L, beta0, beta1, g0e2, g0e3, g1g0): + r""" + Computes the |N3LO| anomalous dimension variation. + + Parameters + ---------- + gamma : numpy.ndarray + anomalous dimensions + L : float + logarithmic ratio of factorization and renormalization scale + beta0: float + :math:`\beta_0` + beta0: float + :math:`\beta_1` + g0e2: complex + :math:`\gamma^{(0),2}` + g0e3: complex + :math:`\gamma^{(0),3}` + g1g0: complex + :math:`\gamma^{(1)} \gamma^{(0)}` + + Returns + ------- + gamma_3 : complex + variation to :math:`\gamma^{(3)}` + """ + return ( + -gamma[2] * L + + (1 / 2) * (beta1 * gamma[0] + 2 * beta0 * gamma[1] + 2 * g1g0) * L**2 + - (1 / 6) * (2 * beta0**2 * gamma[0] + 3 * beta0 * g0e2 + g0e3) * L**3 + ) @nb.njit("c16(c16[:],f8,u1,u1,f8)", cache=True) @@ -38,11 +119,14 @@ def non_singlet_variation(gamma, a_s, order, nf, L): """ sv_ker = 1.0 if order >= 1: - sv_ker -= a_s * L * gamma[0] + sv_ker += a_s * gamma_1_variation(gamma, L) if order >= 2: - sv_ker += a_s**2 * ( - -gamma[1] * L - + 1 / 2 * (beta.beta_0(nf) * gamma[0] + gamma[0] * gamma[0]) * L**2 + beta0 = beta.beta_0(nf) + sv_ker += a_s**2 * gamma_2_variation(gamma, L, beta0, gamma[0] ** 2) + if order >= 3: + beta1 = beta.beta(1, nf) + sv_ker += a_s**3 * gamma_3_variation( + gamma, L, beta0, beta1, gamma[0] ** 2, gamma[0] ** 3, gamma[0] * gamma[1] ) return sv_ker @@ -71,16 +155,19 @@ def singlet_variation(gamma, a_s, order, nf, L): scale varion kernel """ sv_ker = np.eye(2, dtype=np.complex_) + gamma = np.ascontiguousarray(gamma) if order >= 1: - sv_ker -= a_s * L * gamma[0] + sv_ker += a_s * gamma_1_variation(gamma, L) if order >= 2: - sv_ker += a_s**2 * ( - -gamma[1] * L - + (1 / 2) - * ( - beta.beta_0(nf) * gamma[0] - + np.ascontiguousarray(gamma[0]) @ np.ascontiguousarray(gamma[0]) - ) - * L**2 + beta0 = beta.beta_0(nf) + gamma0e2 = gamma[0] @ gamma[0] + sv_ker += a_s**2 * gamma_2_variation(gamma, L, beta0, gamma0e2) + if order >= 3: + beta1 = beta.beta(1, nf) + gamma0e3 = gamma0e2 @ gamma[0] + # here the product is not commutative + g1g0 = gamma[1] @ gamma[0] + sv_ker += a_s**3 * gamma_3_variation( + gamma, L, beta0, beta1, gamma0e2, gamma0e3, g1g0 ) - return np.ascontiguousarray(sv_ker) + return sv_ker diff --git a/tests/test_sv_a.py b/tests/test_sv_a.py index 5c7e36ef1..1c9842368 100644 --- a/tests/test_sv_a.py +++ b/tests/test_sv_a.py @@ -6,7 +6,7 @@ def test_gamma_ns_fact(): - gamma_ns = np.array([1.0, 0.5, 0.25]) + gamma_ns = np.array([1.0, 0.5, 0.25, 0.125]) gamma_ns_LO_0 = gamma_variation(gamma_ns.copy(), 0, 3, 0) np.testing.assert_allclose(gamma_ns_LO_0, gamma_ns) gamma_ns_LO_1 = gamma_variation(gamma_ns.copy(), 0, 3, 1) @@ -15,10 +15,12 @@ def test_gamma_ns_fact(): assert gamma_ns_NLO_1[1] < gamma_ns[1] gamma_ns_NNLO_1 = gamma_variation(gamma_ns.copy(), 2, 3, 1) assert gamma_ns_NNLO_1[2] - gamma_ns[2] == 8.0 + gamma_ns_N3LO_0 = gamma_variation(gamma_ns.copy(), 3, 3, 0) + assert gamma_ns_N3LO_0[3] == gamma_ns[3] def test_gamma_singlet_fact(): - gamma_s = np.array([1.0, 0.5, 0.25]) + gamma_s = np.array([1.0, 0.5, 0.25, 0.125]) gamma_s_LO_0 = gamma_variation(gamma_s.copy(), 0, 3, 0) np.testing.assert_allclose(gamma_s_LO_0, gamma_s) gamma_s_LO_1 = gamma_variation(gamma_s.copy(), 0, 3, 1) @@ -27,3 +29,5 @@ def test_gamma_singlet_fact(): assert gamma_s_NLO_1[1] < gamma_s[1] gamma_s_NNLO_1 = gamma_variation(gamma_s.copy(), 2, 3, 1) assert gamma_s_NNLO_1[2] - gamma_s[2] == 8.0 + gamma_s_N3LO_0 = gamma_variation(gamma_s.copy(), 3, 3, 0) + assert gamma_s_N3LO_0[3] == gamma_s[3] diff --git a/tests/test_sv_b.py b/tests/test_sv_b.py index 572a2ecb2..bd9ee501c 100644 --- a/tests/test_sv_b.py +++ b/tests/test_sv_b.py @@ -10,7 +10,7 @@ def test_ns_sv_dispacher(): """Test to identity""" - order = 2 + order = 3 gamma_ns = np.random.rand(order + 1) L = 0 nf = 5 @@ -22,7 +22,7 @@ def test_ns_sv_dispacher(): def test_singlet_sv_dispacher(): """Test to identity""" - order = 2 + order = 3 gamma_singlet = np.random.rand(order + 1, 2, 2) L = 0 nf = 5 @@ -65,6 +65,9 @@ def scheme_diff(g, k, pto, is_singlet): ) return diff + # TODO: perfor this test also at N3LO, once evolution kernels + # will be implemented + for L in [np.log(0.5), np.log(2)]: for order in [1, 2]: # Non singlet kernels From 14969c72f3ddce921dcc44b174a884713ca01bec Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 21 Feb 2022 15:14:50 +0100 Subject: [PATCH 30/74] Adding N3LO scale variations docs --- doc/source/shared/abbreviations.rst | 9 +++-- doc/source/theory/pQCD.rst | 55 ++++++++++++++++++----------- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/doc/source/shared/abbreviations.rst b/doc/source/shared/abbreviations.rst index 1aff4e212..288f8f49f 100644 --- a/doc/source/shared/abbreviations.rst +++ b/doc/source/shared/abbreviations.rst @@ -40,14 +40,19 @@ .. |pid| replace:: :abbr:`PID ((Monte Carlo) parton identifier)` +.. QCD + .. |OME| replace:: - :abbr:`OME (operator matrix element)` + :abbr:`OME (Operator Matrix Element)` .. |MSbar| replace:: :math:`\overline{MS}` .. |RGE| replace:: - :abbr:`RGE (renormalization group equation)` + :abbr:`RGE (Renormalization Group Equation)` + +.. |MHOU| replace:: + :abbr:`MHOU (Missing Higher Order Uncertainties)` .. external diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index ca0574f7e..944d25b0f 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -68,14 +68,14 @@ The usual procedure in solving |DGLAP| applied :doc:`here of the |PDF|) and the renormalization scale :math:`\mu_R^2` (the inherit scale for the strong coupling) to be equal. This constraint, however, can be lifted in order to provide an estimation of the -missing higher order uncertainties (MHOU) coming from |DGLAP| evolution :cite:`AbdulKhalek:2019ihb`. +missing higher order uncertainties (|MHOU|) coming from |DGLAP| evolution :cite:`AbdulKhalek:2019ihb`. Since scale-dependent contributions to a perturbative prediction are fixed by |RGE| invariance, the scale variation can be used to generate higher order contributions, which are then taken as a proxy for the whole missing higher orders. This method provides many advantages: * it naturally incorporates renormalization group invariance, - as the perturbative order increases, estimates of MHOU decrease; + as the perturbative order increases, estimates of |MHOU| decrease; * the same procedure can be used for any perturbative process, since the scale dependence of the strong coupling :math:`a_s(\mu^2)` and of PDFs is universal; @@ -89,33 +89,46 @@ evolution, always evaluating the strong coupling at :math:`\mu_R^2`. * For ``SV_scheme='A'`` the variation is applied directly to the splitting functions and the anomalous dimension are then modified using :cite:`Vogt:2004ns`: - .. math :: - & \gamma^{(1)}(N) \to \gamma^{(1)}(N) - \beta_0 k \gamma^{(0)} \\ - & \gamma^{(2)}(N) \to \gamma^{(2)}(N) - 2 \beta_0 k \gamma^{(1)} - ( \beta_1 k - \beta_0^2 k^2) \gamma^{(0)} \\ - & k = \ln(\mu_F^2/\mu_R^2) + .. math :: + & \gamma^{(1)}(N) \to \gamma^{(1)}(N) - \beta_0 k \gamma^{(0)} \\ + & \gamma^{(2)}(N) \to \gamma^{(2)}(N) - 2 \beta_0 k \gamma^{(1)} - ( \beta_1 k - \beta_0^2 k^2) \gamma^{(0)} \\ + & \gamma^{(3)}(N) \to \gamma^{(3)}(N) - 3 \beta_0 k \gamma^{(2)} - ( 2 \beta_1 k - 3 \beta_0^2 k^2) \gamma^{(1)} - (\beta_2 k - \frac{5}{2} \beta_1 \beta_0 k^2 + \beta_0^3 k^3) \gamma^{(0)} \\ + & k = \ln(\mu_F^2/\mu_R^2) * In ``SV_scheme='B'`` the |EKO| is multiplied by an additional kernel, such that the scale variation is applied to the whole |PDF| set: - .. math :: - \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) = \left[ 1 - k \gamma + k^2(\gamma^{2} - \frac{\partial \gamma}{\partial a_s} \beta(a_s)) + ... \right] \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) + .. math :: + & \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) = \tilde{\mathbf{K}}(a_s) \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) \\ + & \tilde{\mathbf{K}}(a_s) = 1 - k \gamma + \frac{1}{2} k^2 \left ( \gamma^{2} - \beta \frac{\partial \gamma}{\partial a_s} \right ) + \frac{1}{6} k^3 \left [ - \beta \frac{\partial}{\partial a_s} \left( \beta \frac{\partial \gamma}{\partial a_s} \right) + 3 \beta \frac{\partial \gamma}{\partial a_s} \gamma - \gamma^3 \right ] + \mathcal{O}(k^4) - where scale variation kernel is expanded consistently order by order in :math:`a_s`, - leading to: + where scale variation kernel is expanded consistently order by order in :math:`a_s`, + leading to: - .. math :: - 1 - k \gamma + k^2(\gamma^{2} - \frac{\partial \gamma}{\partial a_s} \beta(a_s)) = - 1 - a_s k \gamma^{(0)} + a_s^2 \left [ - k \gamma^{(1)} + \frac{1}{2} k^2 \gamma^{(0)} (\gamma^{(0)}+\beta_0) \right ] + .. math :: + \tilde{\mathbf{K}}(a_s) \approx & 1 - a_s k \gamma^{(0)} + a_s^2 \left [ - k \gamma^{(1)} + \frac{1}{2} k^2 \gamma^{(0)} (\beta_0 + \gamma^{(0)}) \right ] \\ + & + a_s^3 \left [ -k \gamma^{(2)} + \frac{1}{2} k^2 \left(\beta_1 \gamma^{(0)} + 2 \gamma^{(1)} (\beta_0 + \gamma^{(0)} ) \right) - \frac{1}{6} k^3 \gamma^{(0)} \left(2 \beta_0^2 + 3 \beta_0 \gamma^{(0)}+\gamma^{(0),2} \right) \right] + \mathcal{O}(a^4) - In this way the dependence of the |EKO| on :math:`k` is factorized outside the unvaried evolution kernel. - This procedure is repeated for each different flavor patch present in the evolution path. -Notice that in principle the two methods should be equivalent, especially for fully linearized solutions -(`ModEv=truncated,ev_op_max_iterations=1`), where the difference depends only on the -perturbative expansion in :math:`a_s`. -However, in our implementation this is not exactly true; since the integral of :math:`\frac{\gamma}{\beta}` -is evaluated before the scale variation procedure is applied, the difference between the two -schemes depends also on the actual evolution distance and on the ratio :math:`\ln(\mu_F^2/\mu_R^2)`. + In this way the dependence of the |EKO| on :math:`k` is factorized outside the unvaried evolution kernel. + This procedure is repeated for each different flavor patch present in the evolution path. + +By construction, the corrections of the order :math:`\mathcal{O}(k^n)` will appear +at the order :math:`n` in the expansion :math:`a_s`. +This happens because :math:`\beta \approx \mathcal{O}(a_s^2)`, :math:`\gamma \approx \mathcal{O}(a_s)` +and the contribution proportional to :math:`\mathcal{O}(k^n)` is originated +by the `n-th` derivative in :math:`\gamma` :cite:`AbdulKhalek:2019ihb`. + +Furthermore the distance between the varied |EKO| and the unvaried one will decrease increasing +the perturbative order in :math:`a_s` + +Notice that in principle the two methods should be equivalent, especially for fully +linearized solutions (``ModEv=truncated,ev_op_max_iterations=1``), +where the difference depends only on the perturbative expansion in :math:`a_s`. +However, in our implementation this is not exactly true; +since the integral of :math:`-\frac{\gamma(a_s)}{\beta(a_s)}` is evaluated before +the scale variation procedure is applied, the difference between the two schemes +depends also on the actual evolution distance and on the ratio :math:`k`. Heavy Quark Masses ------------------ From e5341094fae83cd78a53be11512cc0ff5716190d Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Wed, 23 Feb 2022 16:01:58 +0100 Subject: [PATCH 31/74] adopt new naming convention --- benchmarks/apfel_bench.py | 6 +-- benchmarks/eko_bench.py | 2 +- benchmarks/lha_paper_bench.py | 4 +- benchmarks/pegasus_bench.py | 2 +- src/eko/evolution_operator/__init__.py | 42 ++++++++++--------- src/eko/evolution_operator/grid.py | 2 +- src/eko/scale_variations/__init__.py | 6 +-- .../scale_variations/{b.py => expanded.py} | 2 +- .../{a.py => exponentiated.py} | 2 +- tests/benchmark_evol_to_unity.py | 2 +- tests/test_ev_op_grid.py | 6 +-- tests/test_ev_operator.py | 12 +++--- tests/test_ome.py | 4 +- tests/test_runner.py | 2 +- tests/test_strong_coupling.py | 2 +- tests/{test_sv_b.py => test_sv_expanded.py} | 20 ++++----- ...{test_sv_a.py => test_sv_exponentiated.py} | 2 +- 17 files changed, 60 insertions(+), 58 deletions(-) rename src/eko/scale_variations/{b.py => expanded.py} (98%) rename src/eko/scale_variations/{a.py => exponentiated.py} (95%) rename tests/{test_sv_b.py => test_sv_expanded.py} (79%) rename tests/{test_sv_a.py => test_sv_exponentiated.py} (95%) diff --git a/benchmarks/apfel_bench.py b/benchmarks/apfel_bench.py index 8d22bac9d..1acf4e052 100644 --- a/benchmarks/apfel_bench.py +++ b/benchmarks/apfel_bench.py @@ -74,7 +74,7 @@ def benchmark_sv(self, pto, scheme): th.update( { "PTO": [pto], - "XIR": [np.sqrt(0.5)], + "XIR": [1 / np.sqrt(2.0)], "fact_to_ren_scale_ratio": [np.sqrt(2.0)], "SV_scheme": [scheme], "EScaleVar": [0], @@ -165,7 +165,7 @@ def benchmark_sv(self, pto, scheme): th.update( { "PTO": [pto], - "XIR": [np.sqrt(0.5)], + "XIR": [1 / np.sqrt(2.0)], "fact_to_ren_scale_ratio": [np.sqrt(2.0)], "SV_scheme": [scheme], "EScaleVar": [0], @@ -192,6 +192,6 @@ def benchmark_sv(self, pto, scheme): # obj = BenchmarkFFNS() # obj.benchmark_plain(2) - obj.benchmark_sv(2, "A") + obj.benchmark_sv(2, "exponentiated") # obj.benchmark_kthr(2) # obj.benchmark_msbar(2) diff --git a/benchmarks/eko_bench.py b/benchmarks/eko_bench.py index f81426f53..8adb46a0b 100644 --- a/benchmarks/eko_bench.py +++ b/benchmarks/eko_bench.py @@ -88,7 +88,7 @@ def benchmark_sv(self, pto): low = base_theory.copy() low["PTO"] = pto low["fact_to_ren_scale_ratio"] = np.sqrt(1.0 / 2.0) - low["SV_scheme"] = "A" + low["SV_scheme"] = "exponentiated" # needed for apfel low["XIR"] = np.sqrt(2.0) low["EScaleVar"] = 0 diff --git a/benchmarks/lha_paper_bench.py b/benchmarks/lha_paper_bench.py index f96f442e9..cc8d5cd47 100644 --- a/benchmarks/lha_paper_bench.py +++ b/benchmarks/lha_paper_bench.py @@ -77,11 +77,11 @@ def sv_theories(self, pto): low = self.theory.copy() low["PTO"] = pto low["fact_to_ren_scale_ratio"] = np.sqrt(1.0 / 2.0) - low["SV_scheme"] = "A" + low["SV_scheme"] = "exponentiated" high = self.theory.copy() high["PTO"] = pto high["fact_to_ren_scale_ratio"] = np.sqrt(2.0) - high["SV_scheme"] = "A" + high["SV_scheme"] = "exponentiated" return [high, low] @staticmethod diff --git a/benchmarks/pegasus_bench.py b/benchmarks/pegasus_bench.py index 7a5feca5c..01b97d979 100644 --- a/benchmarks/pegasus_bench.py +++ b/benchmarks/pegasus_bench.py @@ -146,5 +146,5 @@ def benchmark_sv(self, pto, scheme): # obj = BenchmarkFFNS() # obj.benchmark_plain(1) - obj.benchmark_sv(2, "A") + obj.benchmark_sv(2, "exponentiated") # vfns.benchmark_sv() diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index d347ba1d0..554bc15a2 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -23,12 +23,14 @@ from ..kernels import non_singlet as ns from ..kernels import singlet as s from ..member import OpMember -from ..scale_variations import a, b +from ..scale_variations import expanded, exponentiated logger = logging.getLogger(__name__) ad_basis_dict = dict(zip(anomalous_dimensions_basis, anomalous_dimensions_basis_idx)) -sv_scheme_dict = dict(zip([None, "A", "B"], [sv.unvaried, sv.scheme_A, sv.scheme_B])) +sv_mode_dict = dict( + zip([None, "A", "B"], [sv.unvaried, sv.mode_exponentiated, sv.mode_expanded]) +) @nb.njit("c16(c16[:,:],u1)", cache=True) @@ -138,7 +140,7 @@ def quad_ker( L, ev_op_iterations, ev_op_max_order, - sv_scheme, + sv_mode, ): """ Raw evolution kernel inside quad. @@ -171,8 +173,8 @@ def quad_ker( number of evolution steps ev_op_max_order : int perturbative expansion order of U - sv_scheme: int - use scale variation scheme 0: none, 1: A, 2: B + sv_mode: int + use scale variation mode 0: none, 1: exponentiated, 2: expanded Returns ------- @@ -188,21 +190,21 @@ def quad_ker( if ker_base.is_singlet: gamma_singlet = ad.gamma_singlet(order, ker_base.n, nf) # scale var A is directly applied on gamma - if sv_scheme == sv.scheme_A: - gamma_singlet = a.gamma_variation(gamma_singlet, order, nf, L) + if sv_mode == sv.mode_exponentiated: + gamma_singlet = exponentiated.gamma_variation(gamma_singlet, order, nf, L) ker = s.dispatcher( order, method, gamma_singlet, a1, a0, nf, ev_op_iterations, ev_op_max_order ) # scale var B is applied on the kernel - if sv_scheme == sv.scheme_B: + if sv_mode == sv.mode_expanded: ker = np.ascontiguousarray(ker) @ np.ascontiguousarray( - b.singlet_variation(gamma_singlet, a1, order, nf, L) + expanded.singlet_variation(gamma_singlet, a1, order, nf, L) ) ker = select_singlet_element(ker, mode) else: gamma_ns = ad.gamma_ns(order, mode, ker_base.n, nf) - if sv_scheme == sv.scheme_A: - gamma_ns = a.gamma_variation(gamma_ns, order, nf, L) + if sv_mode == sv.mode_exponentiated: + gamma_ns = exponentiated.gamma_variation(gamma_ns, order, nf, L) ker = ns.dispatcher( order, method, @@ -212,8 +214,8 @@ def quad_ker( nf, ev_op_iterations, ) - if sv_scheme == sv.scheme_B: - ker = ker * b.non_singlet_variation(gamma_ns, a1, order, nf, L) + if sv_mode == sv.mode_expanded: + ker = ker * expanded.non_singlet_variation(gamma_ns, a1, order, nf, L) # recombine everthing return np.real(ker * integrand) @@ -257,9 +259,9 @@ def fact_to_ren(self): return self.config["fact_to_ren"] @property - def sv_scheme(self): - """Returns the scale variation scheme""" - return sv_scheme_dict[self.config["SV_scheme"]] + def sv_mode(self): + """Returns the scale variation mode""" + return sv_mode_dict[self.config["ModSV"]] @property def int_disp(self): @@ -349,11 +351,11 @@ def compute(self): self.q2_from / self.fact_to_ren, self.q2_to / self.fact_to_ren, ) - if self.sv_scheme != 0: + if self.sv_mode != 0: logger.info( - "Scale Variation: (µ_F/µ_R)^2 = %e, scheme: %s", + "Scale Variation: (µ_F/µ_R)^2 = %e, mode: %s", self.fact_to_ren, - "A" if self.sv_scheme == 1 else "B", + "A" if self.sv_mode == 1 else "B", ) logger.info("Evolution: a_s distance: %e -> %e", a0, a1) logger.info( @@ -389,7 +391,7 @@ def compute(self): np.log(self.fact_to_ren), self.config["ev_op_iterations"], self.config["ev_op_max_order"], - self.sv_scheme, + self.sv_mode, ), epsabs=1e-12, epsrel=1e-5, diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py index ebce9079e..efa1fe1a3 100644 --- a/src/eko/evolution_operator/grid.py +++ b/src/eko/evolution_operator/grid.py @@ -126,7 +126,7 @@ def from_dict( config["debug_skip_singlet"] = operators_card["debug_skip_singlet"] config["debug_skip_non_singlet"] = operators_card["debug_skip_non_singlet"] config["HQ"] = theory_card["HQ"] - config["SV_scheme"] = theory_card["SV_scheme"] + config["ModSV"] = theory_card["ModSV"] q2_grid = np.array(operators_card["Q2grid"], np.float_) intrinsic_range = [] if int(theory_card["IC"]) == 1: diff --git a/src/eko/scale_variations/__init__.py b/src/eko/scale_variations/__init__.py index c2a23ef2e..ac4230bce 100644 --- a/src/eko/scale_variations/__init__.py +++ b/src/eko/scale_variations/__init__.py @@ -4,6 +4,6 @@ """ unvaried = 0 -scheme_A = 1 -scheme_B = 2 -"""Scale Variation schemes""" +mode_exponentiated = 1 +mode_expanded = 2 +"""Scale Variation modes""" diff --git a/src/eko/scale_variations/b.py b/src/eko/scale_variations/expanded.py similarity index 98% rename from src/eko/scale_variations/b.py rename to src/eko/scale_variations/expanded.py index 13c0348cb..610f2f225 100644 --- a/src/eko/scale_variations/b.py +++ b/src/eko/scale_variations/expanded.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- r""" -This module contains the scale variation operator in scheme B +This module contains the scale variation operator in ``ModSV=expanded`` """ diff --git a/src/eko/scale_variations/a.py b/src/eko/scale_variations/exponentiated.py similarity index 95% rename from src/eko/scale_variations/a.py rename to src/eko/scale_variations/exponentiated.py index 4af0c7cd8..0375dcadc 100644 --- a/src/eko/scale_variations/a.py +++ b/src/eko/scale_variations/exponentiated.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- r""" -This module contains the scale variation for scheme A +This module contains the scale variation for ``ModSV=exponentiated``. """ import numba as nb diff --git a/tests/benchmark_evol_to_unity.py b/tests/benchmark_evol_to_unity.py index 3ce7c91a8..8ee69d425 100644 --- a/tests/benchmark_evol_to_unity.py +++ b/tests/benchmark_evol_to_unity.py @@ -33,7 +33,7 @@ class TestBackwardForward: "MaxNfPdf": 6, "MaxNfAs": 6, "HQ": "POLE", - "SV_scheme": None, + "ModSV": None, } operators_card = { "Q2grid": [10], diff --git a/tests/test_ev_op_grid.py b/tests/test_ev_op_grid.py index 525cca75b..e06af47ad 100644 --- a/tests/test_ev_op_grid.py +++ b/tests/test_ev_op_grid.py @@ -36,7 +36,7 @@ def _get_setup(self, use_FFNS): "MaxNfPdf": 6, "MaxNfAs": 6, "HQ": "POLE", - "SV_scheme": None, + "ModSV": None, } operators_card = { "Q2grid": [1, 100**2], @@ -136,10 +136,10 @@ def test_alphas(self): sv_opg = sv_opgrid.compute(3) assert opg[3]["alphas"] < sv_opg[3]["alphas"] - def test_scheme_B(self): + def test_mod_expanded(self): theory_update = { "PTO": 1, - "SV_scheme": "B", + "ModSV": "B", } epsilon = 1e-1 for ffns, nf0 in zip([False, True], [5, 3]): diff --git a/tests/test_ev_operator.py b/tests/test_ev_operator.py index 3a20318f1..5cabfea8e 100644 --- a/tests/test_ev_operator.py +++ b/tests/test_ev_operator.py @@ -69,7 +69,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - sv_scheme=0, + sv_mode=0, ) np.testing.assert_allclose(res_ns, 0.0) res_s = quad_ker( @@ -86,7 +86,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - sv_scheme=0, + sv_mode=0, ) np.testing.assert_allclose(res_s, 1.0) res_s = quad_ker( @@ -103,7 +103,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - sv_scheme=0, + sv_mode=0, ) np.testing.assert_allclose(res_s, 0.0) for mode in ["NS_p", "S_qq"]: @@ -122,7 +122,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - sv_scheme=sv, + sv_mode=sv, ) np.testing.assert_allclose(res_sv, 1.0) @@ -141,7 +141,7 @@ def test_quad_ker(monkeypatch): L=0, ev_op_iterations=0, ev_op_max_order=0, - sv_scheme=0, + sv_mode=0, ) np.testing.assert_allclose(res_ns, 0.0) @@ -191,7 +191,7 @@ def test_compute(self, monkeypatch): "MaxNfPdf": 6, "MaxNfAs": 6, "HQ": "POLE", - "SV_scheme": None, + "ModSV": None, } operators_card = { "Q2grid": [1, 10], diff --git a/tests/test_ome.py b/tests/test_ome.py index f286cebc6..a72f7e96c 100644 --- a/tests/test_ome.py +++ b/tests/test_ome.py @@ -150,7 +150,7 @@ def test_quad_ker(monkeypatch): else: np.testing.assert_allclose(res_ns, 0.0) - # test exact intrisic inverse kernel + # test exact intrinsic inverse kernel labels.extend( [ "S_Hq", @@ -220,7 +220,7 @@ class TestOperatorMatrixElement: "MaxNfPdf": 6, "MaxNfAs": 6, "HQ": "POLE", - "SV_scheme": None, + "ModSV": None, } def test_labels(self): diff --git a/tests/test_runner.py b/tests/test_runner.py index e02a45b1b..1523e4034 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -30,7 +30,7 @@ "Qmc": 1.0, "Qmb": 4.75, "Qmt": 173.0, - "SV_scheme": None, + "ModSV": None, } operators_card = { "Q2grid": [10, 100], diff --git a/tests/test_strong_coupling.py b/tests/test_strong_coupling.py index 4e09243ed..26751138d 100644 --- a/tests/test_strong_coupling.py +++ b/tests/test_strong_coupling.py @@ -28,7 +28,7 @@ def test_from_dict(self): "ktThr": 1.0, "MaxNfAs": 6, "HQ": "POLE", - "SV_scheme": None, + "ModSV": None, } sc = StrongCoupling.from_dict(d) assert sc.a_s(d["Qref"] ** 2) == d["alphas"] / (4.0 * np.pi) diff --git a/tests/test_sv_b.py b/tests/test_sv_expanded.py similarity index 79% rename from tests/test_sv_b.py rename to tests/test_sv_expanded.py index bd9ee501c..43fc703fb 100644 --- a/tests/test_sv_b.py +++ b/tests/test_sv_expanded.py @@ -5,7 +5,7 @@ from eko.anomalous_dimensions import gamma_ns, gamma_singlet from eko.beta import beta_0 from eko.kernels import non_singlet, singlet -from eko.scale_variations import a, b +from eko.scale_variations import expanded, exponentiated def test_ns_sv_dispacher(): @@ -16,7 +16,7 @@ def test_ns_sv_dispacher(): nf = 5 a_s = 0.35 np.testing.assert_allclose( - b.non_singlet_variation(gamma_ns, a_s, order, nf, L), 1.0 + expanded.non_singlet_variation(gamma_ns, a_s, order, nf, L), 1.0 ) @@ -28,17 +28,17 @@ def test_singlet_sv_dispacher(): nf = 5 a_s = 0.35 np.testing.assert_allclose( - b.singlet_variation(gamma_singlet, a_s, order, nf, L), np.eye(2) + expanded.singlet_variation(gamma_singlet, a_s, order, nf, L), np.eye(2) ) def test_scale_variation_a_vs_b(): r""" - Test sv_scheme A kernel vs sv_scheme B. + Test ``ModSV=exponentiated`` kernel vs ``ModSV=expanded``. We test that the quantity :math:`(ker_A - ker_B)/ker_{unv}` depends only on the accuracy in the :math:`\alpha_s` expansion and not in the size of the `fact_to_ren` itself. - However in our implementation the sv_scheme A depends on + However in our implementation the exponentiated mode depends on the actual value of a0 and a1, since the evolution integral in :math:`\alpha_s` is evaluated. Thus this test ratio :math:`(ker_A - ker_B)/ker_{unv}` still contains a dependency on `fact_to_ren`. @@ -65,7 +65,7 @@ def scheme_diff(g, k, pto, is_singlet): ) return diff - # TODO: perfor this test also at N3LO, once evolution kernels + # TODO: perform this test also at N3LO, once evolution kernels # will be implemented for L in [np.log(0.5), np.log(2)]: @@ -75,11 +75,11 @@ def scheme_diff(g, k, pto, is_singlet): ker = non_singlet.dispatcher( order, method, gns, a1, a0, nf, ev_op_iterations=1 ) - gns_a = a.gamma_variation(gns.copy(), order, nf, L) + gns_a = exponentiated.gamma_variation(gns.copy(), order, nf, L) ker_a = non_singlet.dispatcher( order, method, gns_a, a1, a0, nf, ev_op_iterations=1 ) - ker_b = ker * b.non_singlet_variation(gns, a1, order, nf, L) + ker_b = ker * expanded.non_singlet_variation(gns, a1, order, nf, L) ns_diff = scheme_diff(gns, L, order, False) np.testing.assert_allclose((ker_a - ker_b) / ker, ns_diff, atol=1e-3) @@ -88,11 +88,11 @@ def scheme_diff(g, k, pto, is_singlet): ker = singlet.dispatcher( order, method, gs, a1, a0, nf, ev_op_iterations=1, ev_op_max_order=1 ) - gs_a = a.gamma_variation(gs.copy(), order, nf, L) + gs_a = exponentiated.gamma_variation(gs.copy(), order, nf, L) ker_a = singlet.dispatcher( order, method, gs_a, a1, a0, nf, ev_op_iterations=1, ev_op_max_order=1 ) - ker_b = ker @ b.singlet_variation(gs, a1, order, nf, L) + ker_b = ker @ expanded.singlet_variation(gs, a1, order, nf, L) s_diff = scheme_diff(gs, L, order, True) np.testing.assert_allclose( (ker_a - ker_b) @ np.linalg.inv(ker), s_diff, atol=5e-3 diff --git a/tests/test_sv_a.py b/tests/test_sv_exponentiated.py similarity index 95% rename from tests/test_sv_a.py rename to tests/test_sv_exponentiated.py index 1c9842368..fe0367825 100644 --- a/tests/test_sv_a.py +++ b/tests/test_sv_exponentiated.py @@ -2,7 +2,7 @@ import numpy as np -from eko.scale_variations.a import gamma_variation +from eko.scale_variations.exponentiated import gamma_variation def test_gamma_ns_fact(): From 78a6816547a8c3f5ab7949701648578607c4bcee Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Wed, 23 Feb 2022 16:12:42 +0100 Subject: [PATCH 32/74] adopt new naming convention in docs --- doc/source/theory/pQCD.rst | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index 944d25b0f..6d1a2daa3 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -86,7 +86,7 @@ the most used prescription specify to vary the factor :math:`\mu_F/\mu_R` in the This variation can be performed at least at two different levels during the |PDF| evolution, always evaluating the strong coupling at :math:`\mu_R^2`. - * For ``SV_scheme='A'`` the variation is applied directly to the splitting functions + * For ``ModSV='exponentiated'`` the variation is applied directly to the splitting functions and the anomalous dimension are then modified using :cite:`Vogt:2004ns`: .. math :: @@ -95,23 +95,30 @@ evolution, always evaluating the strong coupling at :math:`\mu_R^2`. & \gamma^{(3)}(N) \to \gamma^{(3)}(N) - 3 \beta_0 k \gamma^{(2)} - ( 2 \beta_1 k - 3 \beta_0^2 k^2) \gamma^{(1)} - (\beta_2 k - \frac{5}{2} \beta_1 \beta_0 k^2 + \beta_0^3 k^3) \gamma^{(0)} \\ & k = \ln(\mu_F^2/\mu_R^2) - * In ``SV_scheme='B'`` the |EKO| is multiplied by an additional kernel, such that + This procedure corresponds to scheme A of :cite:`AbdulKhalek:2019ihb`, and we recommend to use it along with + ``ModEv='iterate-exact'`` in order to be in agreement with the treatment of the evolution integral expansion. + + + * In ``ModSV='expanded'`` the |EKO| is multiplied by an additional kernel, such that the scale variation is applied to the whole |PDF| set: .. math :: & \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) = \tilde{\mathbf{K}}(a_s) \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) \\ & \tilde{\mathbf{K}}(a_s) = 1 - k \gamma + \frac{1}{2} k^2 \left ( \gamma^{2} - \beta \frac{\partial \gamma}{\partial a_s} \right ) + \frac{1}{6} k^3 \left [ - \beta \frac{\partial}{\partial a_s} \left( \beta \frac{\partial \gamma}{\partial a_s} \right) + 3 \beta \frac{\partial \gamma}{\partial a_s} \gamma - \gamma^3 \right ] + \mathcal{O}(k^4) - where scale variation kernel is expanded consistently order by order in :math:`a_s`, - leading to: + where scale variation kernel is expanded consistently order by order in :math:`a_s`, + leading to: .. math :: \tilde{\mathbf{K}}(a_s) \approx & 1 - a_s k \gamma^{(0)} + a_s^2 \left [ - k \gamma^{(1)} + \frac{1}{2} k^2 \gamma^{(0)} (\beta_0 + \gamma^{(0)}) \right ] \\ & + a_s^3 \left [ -k \gamma^{(2)} + \frac{1}{2} k^2 \left(\beta_1 \gamma^{(0)} + 2 \gamma^{(1)} (\beta_0 + \gamma^{(0)} ) \right) - \frac{1}{6} k^3 \gamma^{(0)} \left(2 \beta_0^2 + 3 \beta_0 \gamma^{(0)}+\gamma^{(0),2} \right) \right] + \mathcal{O}(a^4) - In this way the dependence of the |EKO| on :math:`k` is factorized outside the unvaried evolution kernel. - This procedure is repeated for each different flavor patch present in the evolution path. + In this way the dependence of the |EKO| on :math:`k` is factorized outside the unvaried evolution kernel. + This procedure is repeated for each different flavor patch present in the evolution path. + It corresponds to scheme B of :cite:`AbdulKhalek:2019ihb`, and we recommend to use it along with + ``ModEv='truncated'`` in order to keep consistency with the evolution integral expansion. + By construction, the corrections of the order :math:`\mathcal{O}(k^n)` will appear at the order :math:`n` in the expansion :math:`a_s`. From 00db37927ace58b699995d3c2f5ea5f2c06bbffa Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Wed, 23 Feb 2022 16:37:59 +0100 Subject: [PATCH 33/74] More chamges in name convention --- benchmarks/apfel_bench.py | 6 +++--- benchmarks/eko_bench.py | 4 ++-- benchmarks/lha_paper_bench.py | 4 ++-- benchmarks/pegasus_bench.py | 4 ++-- src/eko/evolution_operator/__init__.py | 5 ++++- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/benchmarks/apfel_bench.py b/benchmarks/apfel_bench.py index 1acf4e052..0158f4ed7 100644 --- a/benchmarks/apfel_bench.py +++ b/benchmarks/apfel_bench.py @@ -76,7 +76,7 @@ def benchmark_sv(self, pto, scheme): "PTO": [pto], "XIR": [1 / np.sqrt(2.0)], "fact_to_ren_scale_ratio": [np.sqrt(2.0)], - "SV_scheme": [scheme], + "ModSv": [scheme], "EScaleVar": [0], } ) @@ -167,7 +167,7 @@ def benchmark_sv(self, pto, scheme): "PTO": [pto], "XIR": [1 / np.sqrt(2.0)], "fact_to_ren_scale_ratio": [np.sqrt(2.0)], - "SV_scheme": [scheme], + "ModSV": [scheme], "EScaleVar": [0], } ) @@ -178,7 +178,7 @@ def benchmark_sv(self, pto, scheme): # "PTO": [pto], # "XIR": [np.sqrt(2.0)], # "fact_to_ren_scale_ratio": [np.sqrt(0.5)], - # "SV_scheme": [scheme], + # "ModSV": [scheme], # "EScaleVar": [0], # } # ) diff --git a/benchmarks/eko_bench.py b/benchmarks/eko_bench.py index 8adb46a0b..968fc073f 100644 --- a/benchmarks/eko_bench.py +++ b/benchmarks/eko_bench.py @@ -88,14 +88,14 @@ def benchmark_sv(self, pto): low = base_theory.copy() low["PTO"] = pto low["fact_to_ren_scale_ratio"] = np.sqrt(1.0 / 2.0) - low["SV_scheme"] = "exponentiated" + low["ModSV"] = "exponentiated" # needed for apfel low["XIR"] = np.sqrt(2.0) low["EScaleVar"] = 0 high = base_theory.copy() high["PTO"] = pto high["fact_to_ren_scale_ratio"] = np.sqrt(2.0) - high["SV_scheme"] = "A" + high["ModSV"] = "A" # needed for apfel high["XIR"] = np.sqrt(0.5) high["EScaleVar"] = 0 diff --git a/benchmarks/lha_paper_bench.py b/benchmarks/lha_paper_bench.py index cc8d5cd47..f794692a4 100644 --- a/benchmarks/lha_paper_bench.py +++ b/benchmarks/lha_paper_bench.py @@ -77,11 +77,11 @@ def sv_theories(self, pto): low = self.theory.copy() low["PTO"] = pto low["fact_to_ren_scale_ratio"] = np.sqrt(1.0 / 2.0) - low["SV_scheme"] = "exponentiated" + low["ModSV"] = "exponentiated" high = self.theory.copy() high["PTO"] = pto high["fact_to_ren_scale_ratio"] = np.sqrt(2.0) - high["SV_scheme"] = "exponentiated" + high["ModSV"] = "exponentiated" return [high, low] @staticmethod diff --git a/benchmarks/pegasus_bench.py b/benchmarks/pegasus_bench.py index 01b97d979..3a40a0bc0 100644 --- a/benchmarks/pegasus_bench.py +++ b/benchmarks/pegasus_bench.py @@ -83,7 +83,7 @@ def benchmark_sv(self, pto, scheme): { "PTO": [pto], "fact_to_ren_scale_ratio": [np.sqrt(0.5), np.sqrt(2.0)], - "SV_scheme": [scheme], + "ModSV": [scheme], } ) self.run( @@ -132,7 +132,7 @@ def benchmark_sv(self, pto, scheme): { "PTO": [pto], "fact_to_ren_scale_ratio": [np.sqrt(0.5), np.sqrt(2.0)], - "SV_scheme": [scheme], + "ModSV": [scheme], } ) self.run( diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 554bc15a2..9fb2fba41 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -29,7 +29,10 @@ ad_basis_dict = dict(zip(anomalous_dimensions_basis, anomalous_dimensions_basis_idx)) sv_mode_dict = dict( - zip([None, "A", "B"], [sv.unvaried, sv.mode_exponentiated, sv.mode_expanded]) + zip( + [None, "exponentiated", "expanded"], + [sv.unvaried, sv.mode_exponentiated, sv.mode_expanded], + ) ) From 59c1df387f9d44b2b6246916e1aa72d495235343 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Wed, 23 Feb 2022 16:49:17 +0100 Subject: [PATCH 34/74] More chamges in name convention 3 --- src/eko/evolution_operator/__init__.py | 2 +- tests/test_ev_op_grid.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 9fb2fba41..adab80b35 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -358,7 +358,7 @@ def compute(self): logger.info( "Scale Variation: (µ_F/µ_R)^2 = %e, mode: %s", self.fact_to_ren, - "A" if self.sv_mode == 1 else "B", + "exponentiated" if self.sv_mode == 1 else "expanded", ) logger.info("Evolution: a_s distance: %e -> %e", a0, a1) logger.info( diff --git a/tests/test_ev_op_grid.py b/tests/test_ev_op_grid.py index e06af47ad..4354346a7 100644 --- a/tests/test_ev_op_grid.py +++ b/tests/test_ev_op_grid.py @@ -139,7 +139,7 @@ def test_alphas(self): def test_mod_expanded(self): theory_update = { "PTO": 1, - "ModSV": "B", + "ModSV": "expanded", } epsilon = 1e-1 for ffns, nf0 in zip([False, True], [5, 3]): From 1ce00982833f1603f7818c3be920136d35337289 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Thu, 24 Feb 2022 17:06:02 +0100 Subject: [PATCH 35/74] Parallelize eko computation --- benchmarks/apfel_bench.py | 2 +- src/eko/evolution_operator/__init__.py | 162 ++++++++++++++++--------- 2 files changed, 108 insertions(+), 56 deletions(-) diff --git a/benchmarks/apfel_bench.py b/benchmarks/apfel_bench.py index 0158f4ed7..8a687b4a5 100644 --- a/benchmarks/apfel_bench.py +++ b/benchmarks/apfel_bench.py @@ -76,7 +76,7 @@ def benchmark_sv(self, pto, scheme): "PTO": [pto], "XIR": [1 / np.sqrt(2.0)], "fact_to_ren_scale_ratio": [np.sqrt(2.0)], - "ModSv": [scheme], + "ModSV": [scheme], "EScaleVar": [0], } ) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index adab80b35..e36faf8c9 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -7,6 +7,7 @@ import logging import time +from multiprocessing import Pool import numba as nb import numpy as np @@ -277,9 +278,14 @@ def grid_size(self): return self.int_disp.xgrid.size @property - def strong_coupling(self): - """Returns the instance of :class:`eko.strong_coupling.StrongCoupling`""" - return self.managers["strong_coupling"] + def a_s(self): + """Returns the computed values for :math:`a_s`""" + sc = self.managers["strong_coupling"] + a0 = sc.a_s( + self.q2_from / self.fact_to_ren, fact_scale=self.q2_from, nf_to=self.nf + ) + a1 = sc.a_s(self.q2_to / self.fact_to_ren, fact_scale=self.q2_to, nf_to=self.nf) + return (a0, a1) @property def labels(self): @@ -310,6 +316,25 @@ def labels(self): labels.extend(singlet_labels) return labels + @property + def quad_ker(self): + """Integrand function""" + return quad_ker + # TODO: is there a way to pass here a partially initialized quad ker?? + # return functools.partial( + # quad_ker, + # order=self.config["order"], + # method=self.config["method"], + # is_log=self.int_disp.log, + # a1=self.a_s[1], + # a0=self.a_s[0], + # nf=self.nf, + # L=np.log(self.fact_to_ren), + # ev_op_iterations=self.config["ev_op_iterations"], + # ev_op_max_order=self.config["ev_op_max_order"], + # sv_mode=self.sv_mode, + # ) + def initialize_op_members(self): """Init all ops with identity or zeros if we skip them""" eye = OpMember( @@ -326,23 +351,77 @@ def initialize_op_members(self): else: self.op_members[n] = zero.copy() + def run_op_integration( + self, + log_grid, + ): + """ + Integration routine per operator + + Parameters + ---------- + log_grid : tuple(k, logx) + log grid point with relative index + + Returns + ------- + column : list + single operators column + + """ + column = [] + k, logx = log_grid + start_time = time.perf_counter() + # iterate basis functions + for l, bf in enumerate(self.int_disp): + if k == l and l == self.grid_size - 1: + continue + temp_dict = {} + # iterate sectors + for label in self.labels: + res = integrate.quad( + self.quad_ker, + 0.5, + 1.0 - self._mellin_cut, + args=( + self.config["order"], + ad_basis_dict[label], + self.config["method"], + self.int_disp.log, + logx, + bf.areas_representation, + self.a_s[1], + self.a_s[0], + self.nf, + np.log(self.fact_to_ren), + self.config["ev_op_iterations"], + self.config["ev_op_max_order"], + self.sv_mode, + ), + epsabs=1e-12, + epsrel=1e-5, + limit=100, + full_output=1, + ) + temp_dict[label] = res[:2] + column.append(temp_dict) + + print( + f"Evolution: computing operators: - {k+1}/{self.grid_size} took: {(time.perf_counter() - start_time)} s" # pylint: disable=line-too-long + ) + return column + def compute(self): """compute the actual operators (i.e. run the integrations)""" self.initialize_op_members() - # skip computation + # skip computation ? if np.isclose(self.q2_from, self.q2_to): logger.info("Evolution: skipping unity operator at %e", self.q2_from) self.copy_ns_ops() return + tot_start_time = time.perf_counter() - # setup ingredients - a0 = self.strong_coupling.a_s( - self.q2_from / self.fact_to_ren, fact_scale=self.q2_from, nf_to=self.nf - ) - a1 = self.strong_coupling.a_s( - self.q2_to / self.fact_to_ren, fact_scale=self.q2_to, nf_to=self.nf - ) logger.info( "Evolution: computing operators %e -> %e, nf=%d", self.q2_from, @@ -360,57 +439,30 @@ def compute(self): self.fact_to_ren, "exponentiated" if self.sv_mode == 1 else "expanded", ) - logger.info("Evolution: a_s distance: %e -> %e", a0, a1) + logger.info("Evolution: a_s distance: %e -> %e", self.a_s[0], self.a_s[1]) logger.info( "Evolution: order: %d, solution strategy: %s", self.config["order"], self.config["method"], ) - logger.info("Evolution: computing operators - 0/%d", self.grid_size) - # iterate output grid - for k, logx in enumerate(np.log(self.int_disp.xgrid_raw)): - start_time = time.perf_counter() - # iterate basis functions - for l, bf in enumerate(self.int_disp): - if k == l and l == self.grid_size - 1: - continue - # iterate sectors - for label in self.labels: - # compute and set - res = integrate.quad( - quad_ker, - 0.5, - 1.0 - self._mellin_cut, - args=( - self.config["order"], - ad_basis_dict[label], - self.config["method"], - self.int_disp.log, - logx, - bf.areas_representation, - a1, - a0, - self.nf, - np.log(self.fact_to_ren), - self.config["ev_op_iterations"], - self.config["ev_op_max_order"], - self.sv_mode, - ), - epsabs=1e-12, - epsrel=1e-5, - limit=100, - full_output=1, - ) - val, err = res[:2] - self.op_members[label].value[k][l] = val - self.op_members[label].error[k][l] = err - logger.info( - "Evolution: computing operators - %d/%d took: %f s", - k + 1, - self.grid_size, - time.perf_counter() - start_time, + # TODO: which is the optimal numbers of pool to open? + # make it an external parameter? + # run integration in parallel for each grid point + with Pool(8) as pool: + res = pool.map( + self.run_op_integration, + enumerate(np.log(self.int_disp.xgrid_raw)), ) + pool.close() + pool.join() + + # collect results + for k, row in enumerate(res): + for l, entry in enumerate(row): + for label, (val, err) in entry.items(): + self.op_members[label].value[k][l] = val + self.op_members[label].error[k][l] = err # closing comment logger.info("Evolution: Total time %f s", time.perf_counter() - tot_start_time) From d5f0212c2445e63cc204ae31439ce08eb879343b Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Thu, 24 Feb 2022 17:48:29 +0100 Subject: [PATCH 36/74] more on ev operators compute --- src/eko/evolution_operator/__init__.py | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index e36faf8c9..96030b889 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -320,20 +320,6 @@ def labels(self): def quad_ker(self): """Integrand function""" return quad_ker - # TODO: is there a way to pass here a partially initialized quad ker?? - # return functools.partial( - # quad_ker, - # order=self.config["order"], - # method=self.config["method"], - # is_log=self.int_disp.log, - # a1=self.a_s[1], - # a0=self.a_s[0], - # nf=self.nf, - # L=np.log(self.fact_to_ren), - # ev_op_iterations=self.config["ev_op_iterations"], - # ev_op_max_order=self.config["ev_op_max_order"], - # sv_mode=self.sv_mode, - # ) def initialize_op_members(self): """Init all ops with identity or zeros if we skip them""" @@ -356,7 +342,7 @@ def run_op_integration( log_grid, ): """ - Integration routine per operator + Run the integration for each grid point Parameters ---------- @@ -366,7 +352,7 @@ def run_op_integration( Returns ------- column : list - single operators column + computed operators at the give grid point """ column = [] @@ -446,8 +432,7 @@ def compute(self): self.config["method"], ) - # TODO: which is the optimal numbers of pool to open? - # make it an external parameter? + # TODO: make the number of pools an external parameter? # run integration in parallel for each grid point with Pool(8) as pool: res = pool.map( From 1073bccf5346cf7cbb196a7e03569f6397523497 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Thu, 24 Feb 2022 20:31:02 +0100 Subject: [PATCH 37/74] fix number of pools --- src/eko/evolution_operator/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 96030b889..4428817d5 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -6,6 +6,7 @@ """ import logging +import os import time from multiprocessing import Pool @@ -432,9 +433,8 @@ def compute(self): self.config["method"], ) - # TODO: make the number of pools an external parameter? # run integration in parallel for each grid point - with Pool(8) as pool: + with Pool(int(os.cpu_count() / 2)) as pool: res = pool.map( self.run_op_integration, enumerate(np.log(self.int_disp.xgrid_raw)), From 997f5e97bde6e23e47f1fc79e09cb7152f3b2ae7 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Fri, 25 Feb 2022 10:55:27 +0100 Subject: [PATCH 38/74] add multiprocess dep --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 99327c360..28546ed14 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,7 @@ scipy = "^1.7.3" PyYAML = "^6.0" lz4 = "^3.1.10" numba = "^0.55.0" +multiprocess ="^0.3.1" # docs dependencies (for readthedocs, https://github.com/readthedocs/readthedocs.org/issues/4912#issuecomment-664002569) Sphinx = { version = "^4.3.2", optional = true } sphinx-rtd-theme = { version = "^1.0.0", optional = true } From fc6e98b59e7e4ed839510d3717fe50a14732b4fb Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Fri, 25 Feb 2022 11:03:53 +0100 Subject: [PATCH 39/74] remove useless dep --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 28546ed14..99327c360 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,6 @@ scipy = "^1.7.3" PyYAML = "^6.0" lz4 = "^3.1.10" numba = "^0.55.0" -multiprocess ="^0.3.1" # docs dependencies (for readthedocs, https://github.com/readthedocs/readthedocs.org/issues/4912#issuecomment-664002569) Sphinx = { version = "^4.3.2", optional = true } sphinx-rtd-theme = { version = "^1.0.0", optional = true } From ce08b5e5fa06c0997bf3c8f1c8ab136376a0f56b Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Fri, 25 Feb 2022 15:07:06 +0100 Subject: [PATCH 40/74] small hack on eko bench --- benchmarks/eko_bench.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/benchmarks/eko_bench.py b/benchmarks/eko_bench.py index 968fc073f..36b70d13a 100644 --- a/benchmarks/eko_bench.py +++ b/benchmarks/eko_bench.py @@ -95,10 +95,21 @@ def benchmark_sv(self, pto): high = base_theory.copy() high["PTO"] = pto high["fact_to_ren_scale_ratio"] = np.sqrt(2.0) - high["ModSV"] = "A" + high["ModSV"] = "exponentiated" # needed for apfel high["XIR"] = np.sqrt(0.5) high["EScaleVar"] = 0 + + # here we need to adjust also the + # apfel initial nf, which we can't + # be accessed in other ways + # Be careful: this is and hack not a proper solution + if self.external == "apfel": + low["kcThr"] = 1.0 - 1e-15 + low["nf0"] = 4 + high["kcThr"] = 1.0 - 1e-15 + high["nf0"] = 4 + self.run_lha([low, high]) def benchmark_plain(self, pto): From da164445ab7dace64c240cef2a4a9db1d9b350e1 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Fri, 25 Feb 2022 19:54:00 +0100 Subject: [PATCH 41/74] Adding a lha setting a_s bench --- tests/benchmark_strong_coupling.py | 75 ++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/tests/benchmark_strong_coupling.py b/tests/benchmark_strong_coupling.py index a4caa9e7c..8dadc3a00 100644 --- a/tests/benchmark_strong_coupling.py +++ b/tests/benchmark_strong_coupling.py @@ -785,3 +785,78 @@ def benchmark_lhapdf_zmvfns_lo(self): # Max absolute difference: 2.58611282e-06 # Max relative difference: 0.00013379 np.testing.assert_allclose(lhapdf_vals, np.array(my_vals), rtol=1.5e-4) + + def benchmark_APFEL_fact_to_ren_lha_settings(self): + + theory_dict = { + "alphas": 0.1180, + "Qref": np.sqrt(2.0), + "nfref": 3, + "nf0": 3, + "MaxNfPdf": 6, + "MaxNfAs": 6, + "Q0": np.sqrt(2.0), + "fact_to_ren_scale_ratio": np.sqrt(2.0), + "mc": np.sqrt(2.0), + "mb": 4.1, + "mt": 175.0, + "kcThr": 1.0, + "kbThr": 1.0, + "ktThr": 1.0, + "HQ": "POLE", + "Qmc": np.sqrt(2.0), + "Qmb": 4.1, + "Qmt": 175.0, + "PTO": 2, + "ModEv": "EXA", + } + Q2s = [2.0] + sc = StrongCoupling.from_dict(theory_dict) + fact_to_ren = theory_dict["fact_to_ren_scale_ratio"] ** 2 + for Q2 in Q2s: + + my_vals = sc.a_s(Q2 / fact_to_ren, Q2) + path = sc.thresholds.path(Q2 / fact_to_ren) + my_vals_4 = sc.a_s(Q2 / fact_to_ren, Q2, nf_to=4) + path_4 = sc.thresholds.path(Q2 / fact_to_ren, 4) + my_vals_3 = sc.a_s(Q2 / fact_to_ren, Q2, nf_to=3) + path_3 = sc.thresholds.path(Q2 / fact_to_ren, 3) + + # TODO: path_3 is the same as path and it's, + # what we call in matching conditions, it's not matched + assert len(path_3) == 1 + assert len(path) == 1 + + # TODO: path_4 is forward in nf, but backward in q2 ?!?! + # this is called in evolution_operator and is considered + # forward ... + assert len(path_4) == 2 + assert path_4[1].nf > path_4[0].nf + assert path_4[1].q2_from < path_4[0].q2_from + + if use_APFEL: + # run apfel + apfel.CleanUp() + apfel.SetTheory("QCD") + apfel.SetPerturbativeOrder(theory_dict["PTO"]) + apfel.SetAlphaEvolution("exact") + apfel.SetAlphaQCDRef(theory_dict["alphas"], theory_dict["Qref"]) + apfel.SetVFNS() + apfel.SetPoleMasses( + theory_dict["mc"], + theory_dict["mb"], + theory_dict["mt"], + ) + apfel.SetMassMatchingScales( + theory_dict["kcThr"], + theory_dict["kbThr"], + theory_dict["ktThr"], + ) + apfel.SetRenFacRatio(1.0 / theory_dict["fact_to_ren_scale_ratio"]) + apfel.InitializeAPFEL() + # collect a_s + apfel_vals = apfel.AlphaQCD(np.sqrt(Q2)) / (4.0 * np.pi) + # check myself to APFEL + np.testing.assert_allclose(apfel_vals, my_vals, rtol=0.07) + np.testing.assert_allclose(apfel_vals, my_vals_4, rtol=0.0006) + np.testing.assert_allclose(my_vals, my_vals_3) From eca6f44509b761aaf2c2a27714ada27cf569d1a9 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 1 Mar 2022 15:22:41 +0100 Subject: [PATCH 42/74] Improve lha bench with sv and apfel --- benchmarks/eko_bench.py | 10 ++++----- tests/benchmark_strong_coupling.py | 33 +++++++++++++++--------------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/benchmarks/eko_bench.py b/benchmarks/eko_bench.py index 36b70d13a..9d28422b5 100644 --- a/benchmarks/eko_bench.py +++ b/benchmarks/eko_bench.py @@ -103,12 +103,9 @@ def benchmark_sv(self, pto): # here we need to adjust also the # apfel initial nf, which we can't # be accessed in other ways - # Be careful: this is and hack not a proper solution if self.external == "apfel": - low["kcThr"] = 1.0 - 1e-15 - low["nf0"] = 4 - high["kcThr"] = 1.0 - 1e-15 - high["nf0"] = 4 + high["kcThr"] = 1.0 + 1e-15 + low["kcThr"] = 1.0 + 1e-15 self.run_lha([low, high]) @@ -121,7 +118,8 @@ def benchmark_plain(self, pto): if __name__ == "__main__": - programs = ["LHA", "pegasus", "apfel"] + # programs = ["LHA", "pegasus", "apfel"] + programs = ["apfel"] for p in programs: obj = BenchmarkRunner(p) # obj.benchmark_plain(2) diff --git a/tests/benchmark_strong_coupling.py b/tests/benchmark_strong_coupling.py index 8dadc3a00..75ad58785 100644 --- a/tests/benchmark_strong_coupling.py +++ b/tests/benchmark_strong_coupling.py @@ -789,7 +789,7 @@ def benchmark_lhapdf_zmvfns_lo(self): def benchmark_APFEL_fact_to_ren_lha_settings(self): theory_dict = { - "alphas": 0.1180, + "alphas": 0.35, "Qref": np.sqrt(2.0), "nfref": 3, "nf0": 3, @@ -798,14 +798,14 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self): "Q0": np.sqrt(2.0), "fact_to_ren_scale_ratio": np.sqrt(2.0), "mc": np.sqrt(2.0), - "mb": 4.1, + "mb": 4.5, "mt": 175.0, "kcThr": 1.0, "kbThr": 1.0, "ktThr": 1.0, "HQ": "POLE", "Qmc": np.sqrt(2.0), - "Qmb": 4.1, + "Qmb": 4.5, "Qmt": 175.0, "PTO": 2, "ModEv": "EXA", @@ -815,21 +815,18 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self): fact_to_ren = theory_dict["fact_to_ren_scale_ratio"] ** 2 for Q2 in Q2s: - my_vals = sc.a_s(Q2 / fact_to_ren, Q2) + my_val = sc.a_s(Q2 / fact_to_ren, Q2) path = sc.thresholds.path(Q2 / fact_to_ren) - my_vals_4 = sc.a_s(Q2 / fact_to_ren, Q2, nf_to=4) + my_val_4 = sc.a_s(Q2 / fact_to_ren, Q2, nf_to=4) path_4 = sc.thresholds.path(Q2 / fact_to_ren, 4) - my_vals_3 = sc.a_s(Q2 / fact_to_ren, Q2, nf_to=3) + my_val_3 = sc.a_s(Q2 / fact_to_ren, Q2, nf_to=3) path_3 = sc.thresholds.path(Q2 / fact_to_ren, 3) - # TODO: path_3 is the same as path and it's, - # what we call in matching conditions, it's not matched + # path_3 is the same as path and it's not matched assert len(path_3) == 1 assert len(path) == 1 - # TODO: path_4 is forward in nf, but backward in q2 ?!?! - # this is called in evolution_operator and is considered - # forward ... + # path_4 is forward in nf, but backward in q2. assert len(path_4) == 2 assert path_4[1].nf > path_4[0].nf assert path_4[1].q2_from < path_4[0].q2_from @@ -855,8 +852,12 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self): apfel.SetRenFacRatio(1.0 / theory_dict["fact_to_ren_scale_ratio"]) apfel.InitializeAPFEL() # collect a_s - apfel_vals = apfel.AlphaQCD(np.sqrt(Q2)) / (4.0 * np.pi) - # check myself to APFEL - np.testing.assert_allclose(apfel_vals, my_vals, rtol=0.07) - np.testing.assert_allclose(apfel_vals, my_vals_4, rtol=0.0006) - np.testing.assert_allclose(my_vals, my_vals_3) + apfel_val = apfel.AlphaQCD( + np.sqrt(Q2) / theory_dict["fact_to_ren_scale_ratio"] + ) / (4.0 * np.pi) + else: + apfel_val = 0.03478112968976964 + # check myself to APFEL + np.testing.assert_allclose(apfel_val, my_val, rtol=0.04) + np.testing.assert_allclose(apfel_val, my_val_4, rtol=0.02) + np.testing.assert_allclose(my_val, my_val_3) From dcd66d82188ec23fe6f216bbd48c3e7202fea027 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 1 Mar 2022 15:23:53 +0100 Subject: [PATCH 43/74] passing nf to matching conditions --- src/eko/evolution_operator/grid.py | 7 ++++++- src/eko/matching_conditions/operator_matrix_element.py | 6 ++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py index 962dcc203..85385fbbf 100644 --- a/src/eko/evolution_operator/grid.py +++ b/src/eko/evolution_operator/grid.py @@ -182,7 +182,12 @@ def get_threshold_operators(self, path): # is_backward point to the smaller q2 shift = 3 if not seg.is_backward else 4 kthr = thr_config.thresholds_ratios[seg.nf - shift] - ome.compute(seg.q2_to, np.log(kthr), self.config["HQ"] == "MSBAR") + ome.compute( + seg.q2_to, + seg.nf - shift + 3, + np.log(kthr), + self.config["HQ"] == "MSBAR", + ) self._matching_operators[seg.q2_to] = ome.ome_members return thr_ops diff --git a/src/eko/matching_conditions/operator_matrix_element.py b/src/eko/matching_conditions/operator_matrix_element.py index 708ca218e..be4c99a92 100644 --- a/src/eko/matching_conditions/operator_matrix_element.py +++ b/src/eko/matching_conditions/operator_matrix_element.py @@ -286,7 +286,7 @@ def labels(self): # labels.extend(["S_qH"]) return labels - def compute(self, q2, L, is_msbar): + def compute(self, q2, nf, L, is_msbar): """ compute the actual operators (i.e. run the integrations) @@ -294,6 +294,8 @@ def compute(self, q2, L, is_msbar): ---------- q2: float threshold scale + nf: int + number of active flavor below threshold L: float log of K threshold squared is_msbar: bool @@ -319,7 +321,7 @@ def compute(self, q2, L, is_msbar): self.copy_ome() return - a_s = self.sc.a_s(q2 / self.config["fact_to_ren"], q2) + a_s = self.sc.a_s(q2 / self.config["fact_to_ren"], q2, nf) tot_start_time = time.perf_counter() logger.info("Matching: computing operators - 0/%d", grid_size) From 375a7bacd956d5be7c4e00a7480ccad8fdbece28 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 1 Mar 2022 15:43:38 +0100 Subject: [PATCH 44/74] fix ome tests and apfel bench --- benchmarks/apfel_bench.py | 32 ++++++++++++++++---------------- tests/test_ome.py | 12 ++++++------ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/benchmarks/apfel_bench.py b/benchmarks/apfel_bench.py index 8a687b4a5..017b68d3c 100644 --- a/benchmarks/apfel_bench.py +++ b/benchmarks/apfel_bench.py @@ -44,8 +44,8 @@ class BenchmarkVFNS(ApfelBenchmark): "FNS": "ZM-VFNS", "ModEv": [ "EXA", - # "EXP", - # "TRN", + "EXP", + "TRN", ], "kcThr": 1.0, "kbThr": 1.0, @@ -137,8 +137,8 @@ class BenchmarkFFNS(ApfelBenchmark): "FNS": "FFNS", "ModEv": [ "EXA", - # "EXP", - # "TRN", + "EXP", + "TRN", ], "NfFF": 4, "kcThr": 0.0, @@ -165,24 +165,24 @@ def benchmark_sv(self, pto, scheme): th.update( { "PTO": [pto], - "XIR": [1 / np.sqrt(2.0)], + "XIR": [np.sqrt(0.5)], "fact_to_ren_scale_ratio": [np.sqrt(2.0)], "ModSV": [scheme], "EScaleVar": [0], } ) ts.extend(cartesian_product(th)) - # th = self.ffns_theory.copy() - # th.update( - # { - # "PTO": [pto], - # "XIR": [np.sqrt(2.0)], - # "fact_to_ren_scale_ratio": [np.sqrt(0.5)], - # "ModSV": [scheme], - # "EScaleVar": [0], - # } - # ) - # ts.extend(cartesian_product(th)) + th = self.ffns_theory.copy() + th.update( + { + "PTO": [pto], + "XIR": [np.sqrt(2.0)], + "fact_to_ren_scale_ratio": [np.sqrt(0.5)], + "ModSV": [scheme], + "EScaleVar": [0], + } + ) + ts.extend(cartesian_product(th)) self.run(ts, operators.build(operators.apfel_config), ["ToyLH"]) diff --git a/tests/test_ome.py b/tests/test_ome.py index a72f7e96c..dc8b6355c 100644 --- a/tests/test_ome.py +++ b/tests/test_ome.py @@ -214,8 +214,8 @@ class TestOperatorMatrixElement: "mc": 1.0, "mb": 4.75, "mt": 173.0, - "kcThr": np.inf, - "kbThr": np.inf, + "kcThr": 1.0, + "kbThr": 1.0, "ktThr": np.inf, "MaxNfPdf": 6, "MaxNfAs": 6, @@ -279,7 +279,7 @@ def test_compute_lo(self): InterpolatorDispatcher.from_dict(operators_card), ) o = OperatorMatrixElement(g.config, g.managers, is_backward=False) - o.compute(self.theory_card["mb"] ** 2, L=0, is_msbar=False) + o.compute(self.theory_card["mb"] ** 2, nf=4, L=0, is_msbar=False) dim = o.ome_members["NS_qq"].value.shape for idx in ["S", "NS"]: @@ -318,12 +318,12 @@ def test_compute_nlo(self): g = OperatorGrid.from_dict( t, operators_card, - ThresholdsAtlas.from_dict(self.theory_card), - StrongCoupling.from_dict(self.theory_card), + ThresholdsAtlas.from_dict(t), + StrongCoupling.from_dict(t), InterpolatorDispatcher.from_dict(operators_card), ) o = OperatorMatrixElement(g.config, g.managers, is_backward=False) - o.compute(self.theory_card["mb"] ** 2, L=0, is_msbar=False) + o.compute(t["mb"] ** 2, nf=4, L=0, is_msbar=False) dim = len(operators_card["interpolation_xgrid"]) shape = (dim, dim) From 13a81690f923c7d617cbdd06ca0e20c34d56744f Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 1 Mar 2022 16:06:45 +0100 Subject: [PATCH 45/74] revert mode changes in evol op, will be done in #95 --- src/eko/anomalous_dimensions/__init__.py | 18 +++++----- src/eko/basis_rotation.py | 4 --- src/eko/evolution_operator/__init__.py | 35 +++++++------------ tests/test_ad.py | 8 ++--- tests/test_ev_operator.py | 44 +++++------------------- tests/test_sv_expanded.py | 2 +- 6 files changed, 34 insertions(+), 77 deletions(-) diff --git a/src/eko/anomalous_dimensions/__init__.py b/src/eko/anomalous_dimensions/__init__.py index e5872bf2d..173fe5ead 100644 --- a/src/eko/anomalous_dimensions/__init__.py +++ b/src/eko/anomalous_dimensions/__init__.py @@ -20,7 +20,6 @@ import numba as nb import numpy as np -from ..basis_rotation import anomalous_dimensions_basis from . import harmonics, lo, nlo, nnlo @@ -72,7 +71,7 @@ def exp_singlet(gamma_S): return exp, lambda_p, lambda_m, e_p, e_m -@nb.njit("c16[:](u1,u1,c16,u1)", cache=True) +@nb.njit("c16[:](u1,string,c16,u1)", cache=True) def gamma_ns(order, mode, n, nf): r""" Computes the tower of the non-singlet anomalous dimensions @@ -81,8 +80,8 @@ def gamma_ns(order, mode, n, nf): ---------- order : int perturbative order - mode : int - sector identifier 4: m, 5: p, 6: v + mode : "m" | "p" | "v" + sector identifier n : complex Mellin variable nf : int @@ -102,7 +101,6 @@ def gamma_ns(order, mode, n, nf): eko.anomalous_dimensions.nnlo.gamma_nsm_2 : :math:`\gamma_{ns,-}^{(2)}(N)` eko.anomalous_dimensions.nnlo.gamma_nsv_2 : :math:`\gamma_{ns,v}^{(2)}(N)` """ - label = anomalous_dimensions_basis[mode][-1] # cache the s-es sx = np.full(1, harmonics.harmonic_S1(n)) # now combine @@ -111,21 +109,21 @@ def gamma_ns(order, mode, n, nf): # NLO and beyond if order >= 1: # TODO: pass the necessary harmonics to nlo gammas - if label == "p": + if mode == "p": gamma_ns_1 = nlo.gamma_nsp_1(n, nf) # To fill the full valence vector in NNLO we need to add gamma_ns^1 explicitly here - elif label in ["m", "v"]: + elif mode in ["m", "v"]: gamma_ns_1 = nlo.gamma_nsm_1(n, nf) gamma_ns[1] = gamma_ns_1 # NNLO and beyond if order >= 2: sx = np.append(sx, harmonics.harmonic_S2(n)) sx = np.append(sx, harmonics.harmonic_S3(n)) - if label == "p": + if mode == "p": gamma_ns_2 = -nnlo.gamma_nsp_2(n, nf, sx) - elif label == "m": + elif mode == "m": gamma_ns_2 = -nnlo.gamma_nsm_2(n, nf, sx) - elif label == "v": + elif mode == "v": gamma_ns_2 = -nnlo.gamma_nsv_2(n, nf, sx) gamma_ns[2] = gamma_ns_2 return gamma_ns diff --git a/src/eko/basis_rotation.py b/src/eko/basis_rotation.py index a0b049dcf..0aa256380 100644 --- a/src/eko/basis_rotation.py +++ b/src/eko/basis_rotation.py @@ -76,10 +76,6 @@ r""" Sorted elements in Anomalous Dimensions Basis as :obj:`str`. """ -anomalous_dimensions_basis_idx = tuple(range(len(full_labels))) -r""" -Sorted elements in Anomalous Dimensions Basis as :obj:`int`. -""" # Tranformation from physical basis to QCD evolution basis rotate_flavor_to_evolution = np.array( diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 4428817d5..d9ba56c66 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -17,11 +17,7 @@ from .. import anomalous_dimensions as ad from .. import interpolation, mellin from .. import scale_variations as sv -from ..basis_rotation import ( - anomalous_dimensions_basis, - anomalous_dimensions_basis_idx, - singlet_labels, -) +from ..basis_rotation import full_labels, singlet_labels from ..kernels import non_singlet as ns from ..kernels import singlet as s from ..member import OpMember @@ -29,7 +25,6 @@ logger = logging.getLogger(__name__) -ad_basis_dict = dict(zip(anomalous_dimensions_basis, anomalous_dimensions_basis_idx)) sv_mode_dict = dict( zip( [None, "exponentiated", "expanded"], @@ -38,19 +33,15 @@ ) -@nb.njit("c16(c16[:,:],u1)", cache=True) +@nb.njit("c16(c16[:,:],string)") def select_singlet_element(ker, mode): """ Select element of the singlet matrix Parameters ---------- - mode : int - sector element: - 0: "S_qq", ker[0,0] - 1: "S_qg", ker[0,1] - 2: "S_gq", ker[1,1] - 3: "S_gg", ker[1,1] + mode : str + sector element ker : numpy.ndarray singlet integration kernel @@ -59,8 +50,8 @@ def select_singlet_element(ker, mode): ker : complex singlet integration kernel element """ - k = 0 if mode < 2 else 1 - l = 0 if mode % 2 == 0 else 1 + k = 0 if mode[2] == "q" else 1 + l = 0 if mode[3] == "q" else 1 return ker[k, l] @@ -85,12 +76,12 @@ class QuadKerBase: is a logarithmic interpolation logx : float Mellin inversion point - mode : int + mode : str sector element """ def __init__(self, u, is_log, logx, mode): - self.is_singlet = mode < 4 + self.is_singlet = mode[0] == "S" self.is_log = is_log self.u = u self.logx = logx @@ -130,7 +121,7 @@ def integrand( return self.path.prefactor * pj * self.path.jac -@nb.njit("f8(f8,u1,u1,string,b1,f8,f8[:,:],f8,f8,f8,f8,u4,u1,u1)", cache=True) +@nb.njit("f8(f8,u1,string,string,b1,f8,f8[:,:],f8,f8,f8,f8,u4,u1,u1)", cache=True) def quad_ker( u, order, @@ -158,7 +149,7 @@ def quad_ker( perturbation order method : str method - mode : int + mode : str sector element is_log : boolean is a logarithmic interpolation @@ -207,7 +198,7 @@ def quad_ker( ) ker = select_singlet_element(ker, mode) else: - gamma_ns = ad.gamma_ns(order, mode, ker_base.n, nf) + gamma_ns = ad.gamma_ns(order, mode[-1], ker_base.n, nf) if sv_mode == sv.mode_exponentiated: gamma_ns = exponentiated.gamma_variation(gamma_ns, order, nf, L) ker = ns.dispatcher( @@ -328,7 +319,7 @@ def initialize_op_members(self): np.eye(self.grid_size), np.zeros((self.grid_size, self.grid_size)) ) zero = OpMember(*[np.zeros((self.grid_size, self.grid_size))] * 2) - for n in anomalous_dimensions_basis: + for n in full_labels: if n in self.labels: # off diag singlet are zero if n in ["S_qg", "S_gq"]: @@ -372,7 +363,7 @@ def run_op_integration( 1.0 - self._mellin_cut, args=( self.config["order"], - ad_basis_dict[label], + label, self.config["method"], self.int_disp.log, logx, diff --git a/tests/test_ad.py b/tests/test_ad.py index 3356107ca..3363220c1 100644 --- a/tests/test_ad.py +++ b/tests/test_ad.py @@ -53,9 +53,9 @@ def test_eigensystem_gamma_singlet_projectors_EV(): def test_gamma_ns(): nf = 3 # LO - assert_almost_equal(ad.gamma_ns(2, 5, 1, nf)[0], 0.0) + assert_almost_equal(ad.gamma_ns(2, "p", 1, nf)[0], 0.0) # NLO - assert_allclose(ad.gamma_ns(1, 4, 1, nf), np.zeros(2), atol=2e-6) + assert_allclose(ad.gamma_ns(1, "m", 1, nf), np.zeros(2), atol=2e-6) # NNLO - assert_allclose(ad.gamma_ns(2, 4, 1, nf), np.zeros(3), atol=2e-4) - assert_allclose(ad.gamma_ns(2, 6, 1, nf), np.zeros(3), atol=8e-4) + assert_allclose(ad.gamma_ns(2, "m", 1, nf), np.zeros(3), atol=2e-4) + assert_allclose(ad.gamma_ns(2, "v", 1, nf), np.zeros(3), atol=8e-4) diff --git a/tests/test_ev_operator.py b/tests/test_ev_operator.py index 5cabfea8e..e242f5e17 100644 --- a/tests/test_ev_operator.py +++ b/tests/test_ev_operator.py @@ -6,12 +6,7 @@ from eko import anomalous_dimensions as ad from eko import basis_rotation as br from eko import interpolation, mellin -from eko.evolution_operator import ( - Operator, - ad_basis_dict, - quad_ker, - select_singlet_element, -) +from eko.evolution_operator import Operator, quad_ker from eko.evolution_operator.grid import OperatorGrid from eko.interpolation import InterpolatorDispatcher from eko.kernels import non_singlet as ns @@ -20,29 +15,6 @@ from eko.thresholds import ThresholdsAtlas -def test_ad_basis_dict(): - assert ad_basis_dict["S_qq"] == 0 - assert ad_basis_dict["S_qg"] == 1 - assert ad_basis_dict["S_gq"] == 2 - assert ad_basis_dict["S_gg"] == 3 - assert ad_basis_dict["NS_m"] == 4 - assert ad_basis_dict["NS_p"] == 5 - assert ad_basis_dict["NS_v"] == 6 - - for mode in ["S_qq", "S_qg", "S_gq", "S_gg"]: - assert ad_basis_dict[mode] < 4 - for mode in ["NS_p", "NS_m", "NS_v"]: - assert ad_basis_dict[mode] >= 4 - - -def test_select_singlet_element(): - fake_singlet_ker = np.array([["S_qq", "S_qg"], ["S_gq", "S_gg"]]) - for mode in np.arange(4): - assert ( - select_singlet_element(fake_singlet_ker, mode) == list(ad_basis_dict)[mode] - ) - - def test_quad_ker(monkeypatch): monkeypatch.setattr( mellin, "Talbot_path", lambda *args: 2 @@ -58,7 +30,7 @@ def test_quad_ker(monkeypatch): res_ns = quad_ker( u=0, order=0, - mode=ad_basis_dict["NS_p"], + mode="NS_p", method="", is_log=is_log, logx=0.0, @@ -75,7 +47,7 @@ def test_quad_ker(monkeypatch): res_s = quad_ker( u=0, order=0, - mode=ad_basis_dict["S_qq"], + mode="S_qq", method="", is_log=is_log, logx=1.0, @@ -92,7 +64,7 @@ def test_quad_ker(monkeypatch): res_s = quad_ker( u=0, order=0, - mode=ad_basis_dict["S_qg"], + mode="S_qg", method="", is_log=is_log, logx=0.0, @@ -111,7 +83,7 @@ def test_quad_ker(monkeypatch): res_sv = quad_ker( u=0, order=0, - mode=ad_basis_dict[mode], + mode=mode, method="", is_log=True, logx=1.0, @@ -130,7 +102,7 @@ def test_quad_ker(monkeypatch): res_ns = quad_ker( u=0, order=0, - mode=ad_basis_dict["NS_p"], + mode="NS_p", method="", is_log=True, logx=0.0, @@ -251,7 +223,7 @@ def quad_ker_pegasus( phi = 3 / 4 * np.pi c = 1.9 n = complex(c + u * np.exp(1j * phi)) - gamma_ns = ad.gamma_ns(order, mode, n, nf) + gamma_ns = ad.gamma_ns(order, mode[-1], n, nf) ker = ns.dispatcher( order, method, @@ -269,7 +241,7 @@ def quad_ker_pegasus( xgrid = np.geomspace(1e-7, 1, 10) int_disp = InterpolatorDispatcher(xgrid, 1, True) order = 1 - mode = ad_basis_dict["NS_p"] + mode = "NS_p" method = "" logxs = np.log(int_disp.xgrid_raw) a1 = 1 diff --git a/tests/test_sv_expanded.py b/tests/test_sv_expanded.py index 43fc703fb..076df98f0 100644 --- a/tests/test_sv_expanded.py +++ b/tests/test_sv_expanded.py @@ -71,7 +71,7 @@ def scheme_diff(g, k, pto, is_singlet): for L in [np.log(0.5), np.log(2)]: for order in [1, 2]: # Non singlet kernels - gns = gamma_ns(order, 4, n, nf) + gns = gamma_ns(order, "p", n, nf) ker = non_singlet.dispatcher( order, method, gns, a1, a0, nf, ev_op_iterations=1 ) From ff5bdac016c7c8ad6976013d762b6ee0ccaf8cd6 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 2 Mar 2022 13:05:25 +0100 Subject: [PATCH 46/74] Fix pool usage, scope all sv ingredients --- benchmarks/eko_bench.py | 2 +- src/eko/evolution_operator/__init__.py | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/benchmarks/eko_bench.py b/benchmarks/eko_bench.py index 9d28422b5..e7b16c229 100644 --- a/benchmarks/eko_bench.py +++ b/benchmarks/eko_bench.py @@ -101,7 +101,7 @@ def benchmark_sv(self, pto): high["EScaleVar"] = 0 # here we need to adjust also the - # apfel initial nf, which we can't + # apfel initial nf, which can't # be accessed in other ways if self.external == "apfel": high["kcThr"] = 1.0 + 1e-15 diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index d9ba56c66..a11b9c9c6 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -21,7 +21,6 @@ from ..kernels import non_singlet as ns from ..kernels import singlet as s from ..member import OpMember -from ..scale_variations import expanded, exponentiated logger = logging.getLogger(__name__) @@ -187,20 +186,22 @@ def quad_ker( gamma_singlet = ad.gamma_singlet(order, ker_base.n, nf) # scale var A is directly applied on gamma if sv_mode == sv.mode_exponentiated: - gamma_singlet = exponentiated.gamma_variation(gamma_singlet, order, nf, L) + gamma_singlet = sv.exponentiated.gamma_variation( + gamma_singlet, order, nf, L + ) ker = s.dispatcher( order, method, gamma_singlet, a1, a0, nf, ev_op_iterations, ev_op_max_order ) # scale var B is applied on the kernel if sv_mode == sv.mode_expanded: ker = np.ascontiguousarray(ker) @ np.ascontiguousarray( - expanded.singlet_variation(gamma_singlet, a1, order, nf, L) + sv.expanded.singlet_variation(gamma_singlet, a1, order, nf, L) ) ker = select_singlet_element(ker, mode) else: gamma_ns = ad.gamma_ns(order, mode[-1], ker_base.n, nf) if sv_mode == sv.mode_exponentiated: - gamma_ns = exponentiated.gamma_variation(gamma_ns, order, nf, L) + gamma_ns = sv.exponentiated.gamma_variation(gamma_ns, order, nf, L) ker = ns.dispatcher( order, method, @@ -211,7 +212,7 @@ def quad_ker( ev_op_iterations, ) if sv_mode == sv.mode_expanded: - ker = ker * expanded.non_singlet_variation(gamma_ns, a1, order, nf, L) + ker = ker * sv.expanded.non_singlet_variation(gamma_ns, a1, order, nf, L) # recombine everthing return np.real(ker * integrand) @@ -430,8 +431,6 @@ def compute(self): self.run_op_integration, enumerate(np.log(self.int_disp.xgrid_raw)), ) - pool.close() - pool.join() # collect results for k, row in enumerate(res): From 09ba94c6b361da8430d7cd8e7b923725935cd64a Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Wed, 2 Mar 2022 14:47:06 +0100 Subject: [PATCH 47/74] update lha bench and remove eko bench script --- benchmarks/eko_bench.py | 126 ---------------------------------- benchmarks/lha_paper_bench.py | 115 ++++++++++++++++++++++--------- 2 files changed, 84 insertions(+), 157 deletions(-) delete mode 100644 benchmarks/eko_bench.py diff --git a/benchmarks/eko_bench.py b/benchmarks/eko_bench.py deleted file mode 100644 index e7b16c229..000000000 --- a/benchmarks/eko_bench.py +++ /dev/null @@ -1,126 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Run multiple eko benchmarks with the same VFNS settings (as LHA) -and and a fine grid -""" -import numpy as np -from banana import register - -from eko.interpolation import make_lambert_grid -from ekomark.benchmark.runner import Runner - -register(__file__) - -base_theory = { - "ModEv": "EXA", - "Q0": np.sqrt( - 2.0 - ), # Eq. (30) :cite:`Giele:2002hx`, Eq. (4.53) :cite:`Dittmar:2005ed` - "nfref": 3, - "nf0": 3, - "mc": np.sqrt( - 2.0 - ), # Eq. (34) :cite:`Giele:2002hx`, Eq. (4.56) :cite:`Dittmar:2005ed` - "mb": 4.5, - "mt": 175.0, - "Qref": np.sqrt( - 2.0 - ), # Eq. (32) :cite:`Giele:2002hx`,Eq. (4.53) :cite:`Dittmar:2005ed` - "alphas": 0.35, # Eq. (4.55) :cite:`Dittmar:2005ed` - "FNS": "ZM-VFNS", # ignored by eko, but needed by LHA_utils - "kcThr": 1.0, - "kbThr": 1.0, - "ktThr": 1.0, -} -"""Global theory settings""" - - -class BenchmarkRunner(Runner): - """ - Generic benchmark runner using the LHA VFNS settings - """ - - def __init__(self, external): - super().__init__() - self.external = external - self.theory = base_theory - self.sandbox = True - self.rotate_to_evolution_basis = True - - def skip_pdfs(self, _theory): - return [22, -6, 6, "ph", "V35", "V24", "V15", "V8", "T35"] - - def run_lha(self, theory_updates): - """ - Enforce operators and PDF - - Parameters - ---------- - theory_updates : list(dict) - theory updates - """ - self.run( - theory_updates, - [ - { - "Q2grid": [1e4], - "ev_op_iterations": 10, - "interpolation_xgrid": make_lambert_grid(60).tolist(), - } - ], - ["ToyLH"], - ) - - def benchmark_sv(self, pto): - """ - Scale variations - - Parameters - ---------- - pto : int - perturbation order - - Returns - ------- - list(dict) - theory updates - """ - low = base_theory.copy() - low["PTO"] = pto - low["fact_to_ren_scale_ratio"] = np.sqrt(1.0 / 2.0) - low["ModSV"] = "exponentiated" - # needed for apfel - low["XIR"] = np.sqrt(2.0) - low["EScaleVar"] = 0 - high = base_theory.copy() - high["PTO"] = pto - high["fact_to_ren_scale_ratio"] = np.sqrt(2.0) - high["ModSV"] = "exponentiated" - # needed for apfel - high["XIR"] = np.sqrt(0.5) - high["EScaleVar"] = 0 - - # here we need to adjust also the - # apfel initial nf, which can't - # be accessed in other ways - if self.external == "apfel": - high["kcThr"] = 1.0 + 1e-15 - low["kcThr"] = 1.0 + 1e-15 - - self.run_lha([low, high]) - - def benchmark_plain(self, pto): - """Plain configuration""" - th = self.theory.copy() - th.update({"PTO": pto}) - self.run_lha([th]) - - -if __name__ == "__main__": - - # programs = ["LHA", "pegasus", "apfel"] - programs = ["apfel"] - for p in programs: - obj = BenchmarkRunner(p) - # obj.benchmark_plain(2) - obj.benchmark_sv(2) diff --git a/benchmarks/lha_paper_bench.py b/benchmarks/lha_paper_bench.py index f794692a4..a2cf15e6d 100644 --- a/benchmarks/lha_paper_bench.py +++ b/benchmarks/lha_paper_bench.py @@ -5,6 +5,7 @@ import numpy as np from banana import register +from eko.interpolation import make_lambert_grid from ekomark.benchmark.runner import Runner register(__file__) @@ -36,11 +37,11 @@ class LHABenchmark(Runner): Globally set the external program to LHA """ - external = "LHA" - - theory = {} - - rotate_to_evolution_basis = True + def __init__(self): + super().__init__() + self.external = "LHA" + self.theory = {} + self.rotate_to_evolution_basis = True def plain_theory(self, pto): """ @@ -116,7 +117,7 @@ def run_lha(self, theory_updates): { "Q2grid": [1e4], "ev_op_iterations": 10, - # "debug_skip_singlet": True + "interpolation_xgrid": make_lambert_grid(60).tolist(), } ], ["ToyLH"], @@ -134,33 +135,37 @@ def benchmark_sv(self, pto): class BenchmarkVFNS(LHABenchmark): """Variable Flavor Number Scheme""" - theory = base_theory.copy() - theory.update( - { - "FNS": "ZM-VFNS", # ignored by eko, but needed by LHA_utils - "kcThr": 1.0, - "kbThr": 1.0, - "ktThr": 1.0, - "nf0": 3, - "nfref": 3, - } - ) + def __init__(self): + super().__init__() + self.theory = base_theory.copy() + self.theory.update( + { + "FNS": "ZM-VFNS", # ignored by eko, but needed by LHA_utils + "kcThr": 1.0, + "kbThr": 1.0, + "ktThr": 1.0, + "nf0": 3, + "nfref": 3, + } + ) class BenchmarkFFNS(LHABenchmark): """Fixed Flavor Number Scheme""" - theory = base_theory.copy() - theory.update( - { - "FNS": "FFNS", # ignored by eko, but needed by LHA_utils - "NfFF": 4, - "nfref": 4, - "kcThr": 0.0, - "kbThr": np.inf, - "ktThr": np.inf, - } - ) + def __init__(self): + super().__init__() + self.theory = base_theory.copy() + self.theory.update( + { + "FNS": "FFNS", # ignored by eko, but needed by LHA_utils + "NfFF": 4, + "nfref": 4, + "kcThr": 0.0, + "kbThr": np.inf, + "ktThr": np.inf, + } + ) @staticmethod def skip_pdfs(theory): @@ -173,10 +178,58 @@ def skip_pdfs(theory): return ffns_skip_pdfs +class BenchmarkRunner(BenchmarkVFNS): + """ + Generic benchmark runner using the LHA VFNS settings + """ + + def __init__(self, external): + super().__init__() + self.external = external + self.sandbox = True + + def benchmark_sv(self, pto): + """ + Scale variations + + Parameters + ---------- + pto : int + perturbation order + + Returns + ------- + list(dict) + theory updates + """ + high, low = self.sv_theories(pto) + + # here we need to adjust also the + # apfel initial nf, which can't + # be accessed in other ways + if self.external == "apfel": + for sv_theory in [low, high]: + sv_theory["kcThr"] = 1.0 + 1e-15 + sv_theory["EScaleVar"] = 0 + low["XIR"] = np.sqrt(2.0) + high["XIR"] = np.sqrt(0.5) + + self.run_lha([low, high]) + + if __name__ == "__main__": - obj = BenchmarkVFNS() - # obj = BenchmarkFFNS() + # # Benchmark to LHA + # obj = BenchmarkVFNS() + # # obj = BenchmarkFFNS() # obj.benchmark_plain(2) - obj.benchmark_sv(1) + # # obj.benchmark_sv(2) + + # VFNS benchmarks with LHA settings + programs = ["LHA", "pegasus", "apfel"] + programs = ["apfel"] + for p in programs: + obj = BenchmarkRunner(p) + # obj.benchmark_plain(2) + obj.benchmark_sv(2) From 88f1d6fd6ba5875a6d6085356eee98953d4aa5e9 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Wed, 2 Mar 2022 16:27:45 +0100 Subject: [PATCH 48/74] Fix imports and banana.yaml --- benchmarks/banana.yaml | 3 ++- src/eko/scale_variations/__init__.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/benchmarks/banana.yaml b/benchmarks/banana.yaml index 98c209e7f..6236d3fc3 100644 --- a/benchmarks/banana.yaml +++ b/benchmarks/banana.yaml @@ -1,4 +1,5 @@ -database_path: data/benchmark.db +paths: + database: data/benchmark.db input_tables: - theories - operators diff --git a/src/eko/scale_variations/__init__.py b/src/eko/scale_variations/__init__.py index ac4230bce..942988e77 100644 --- a/src/eko/scale_variations/__init__.py +++ b/src/eko/scale_variations/__init__.py @@ -3,6 +3,8 @@ This module contain the possible scale variations integrals. """ +from . import expanded, exponentiated + unvaried = 0 mode_exponentiated = 1 mode_expanded = 2 From 425502effc6834a6f90d4826bd2c96a5eb691c41 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Wed, 2 Mar 2022 16:29:13 +0100 Subject: [PATCH 49/74] small clarificarions about nfref and Qref --- benchmarks/lha_paper_bench.py | 2 +- doc/source/theory/pQCD.rst | 3 +++ src/eko/evolution_operator/__init__.py | 2 +- tests/benchmark_strong_coupling.py | 22 ++++++++++++---------- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/benchmarks/lha_paper_bench.py b/benchmarks/lha_paper_bench.py index a2cf15e6d..60d6e54a1 100644 --- a/benchmarks/lha_paper_bench.py +++ b/benchmarks/lha_paper_bench.py @@ -83,6 +83,7 @@ def sv_theories(self, pto): high["PTO"] = pto high["fact_to_ren_scale_ratio"] = np.sqrt(2.0) high["ModSV"] = "exponentiated" + high["nfref"] = 4 return [high, low] @staticmethod @@ -228,7 +229,6 @@ def benchmark_sv(self, pto): # VFNS benchmarks with LHA settings programs = ["LHA", "pegasus", "apfel"] - programs = ["apfel"] for p in programs: obj = BenchmarkRunner(p) # obj.benchmark_plain(2) diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index cdc4dd843..c71cb2564 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -155,6 +155,9 @@ since the integral of :math:`-\frac{\gamma(a_s)}{\beta(a_s)}` is evaluated befor the scale variation procedure is applied, the difference between the two schemes depends also on the actual evolution distance and on the ratio :math:`k`. +When using the scale variations, boundary conditions for the strong coupling :math:`a_s` +(``Qref`` and ``nfref``) have to be given according to renormalization scales. + Heavy Quark Masses ------------------ diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index a11b9c9c6..8611e2b97 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -386,7 +386,7 @@ def run_op_integration( column.append(temp_dict) print( - f"Evolution: computing operators: - {k+1}/{self.grid_size} took: {(time.perf_counter() - start_time)} s" # pylint: disable=line-too-long + f"Evolution: computing operators: - {k+1}/{self.grid_size} took: {(time.perf_counter() - start_time):6f} s" # pylint: disable=line-too-long ) return column diff --git a/tests/benchmark_strong_coupling.py b/tests/benchmark_strong_coupling.py index 75ad58785..eefbb06cf 100644 --- a/tests/benchmark_strong_coupling.py +++ b/tests/benchmark_strong_coupling.py @@ -791,7 +791,7 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self): theory_dict = { "alphas": 0.35, "Qref": np.sqrt(2.0), - "nfref": 3, + "nfref": 4, "nf0": 3, "MaxNfPdf": 6, "MaxNfAs": 6, @@ -822,14 +822,14 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self): my_val_3 = sc.a_s(Q2 / fact_to_ren, Q2, nf_to=3) path_3 = sc.thresholds.path(Q2 / fact_to_ren, 3) - # path_3 is the same as path and it's not matched - assert len(path_3) == 1 - assert len(path) == 1 + # path_4 it's not matched + assert len(path_4) == 1 - # path_4 is forward in nf, but backward in q2. - assert len(path_4) == 2 - assert path_4[1].nf > path_4[0].nf - assert path_4[1].q2_from < path_4[0].q2_from + # path_3 is the same as path backward in nf and in q2. + assert len(path_3) == 2 + assert len(path) == 2 + assert path_3[1].nf < path_3[0].nf + assert path_3[1].q2_from < path_3[0].q2_from if use_APFEL: # run apfel @@ -858,6 +858,8 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self): else: apfel_val = 0.03478112968976964 # check myself to APFEL - np.testing.assert_allclose(apfel_val, my_val, rtol=0.04) - np.testing.assert_allclose(apfel_val, my_val_4, rtol=0.02) + # notice that Apfel computes alpha in nf=4 by default, + # but what has to be used during the matching is alpha in nf=3 + np.testing.assert_allclose(apfel_val, my_val, rtol=0.03) + np.testing.assert_allclose(apfel_val, my_val_4) np.testing.assert_allclose(my_val, my_val_3) From 2efccf36fa657a2ee95f6ee9104b5e718f8315d5 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Thu, 3 Mar 2022 15:48:13 +0100 Subject: [PATCH 50/74] Minimal fix for banana to work --- benchmarks/banana.yaml | 9 +++++---- benchmarks/lha_paper_bench.py | 11 ++++++----- src/ekomark/benchmark/runner.py | 2 +- src/ekomark/navigator/__init__.py | 13 +++++++++++-- src/ekomark/navigator/navigator.py | 2 +- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/benchmarks/banana.yaml b/benchmarks/banana.yaml index 6236d3fc3..7c28b7cb9 100644 --- a/benchmarks/banana.yaml +++ b/benchmarks/banana.yaml @@ -1,6 +1,7 @@ paths: database: data/benchmark.db -input_tables: - - theories - - operators - - cache +input: + tables: + - theories + - operators + - cache diff --git a/benchmarks/lha_paper_bench.py b/benchmarks/lha_paper_bench.py index 60d6e54a1..5c093dd81 100644 --- a/benchmarks/lha_paper_bench.py +++ b/benchmarks/lha_paper_bench.py @@ -220,15 +220,16 @@ def benchmark_sv(self, pto): if __name__ == "__main__": - # # Benchmark to LHA + # Benchmark to LHA # obj = BenchmarkVFNS() - # # obj = BenchmarkFFNS() + # obj = BenchmarkFFNS() # obj.benchmark_plain(2) - # # obj.benchmark_sv(2) + # obj.benchmark_sv(2) - # VFNS benchmarks with LHA settings - programs = ["LHA", "pegasus", "apfel"] + # # VFNS benchmarks with LHA settings + # programs = ["LHA", "pegasus", "apfel"] + programs = ["apfel"] for p in programs: obj = BenchmarkRunner(p) # obj.benchmark_plain(2) diff --git a/src/ekomark/benchmark/runner.py b/src/ekomark/benchmark/runner.py index 8ddf809cf..9f4e5e9c3 100644 --- a/src/ekomark/benchmark/runner.py +++ b/src/ekomark/benchmark/runner.py @@ -72,7 +72,7 @@ def run_me(self, theory, ocard, _pdf): if self.sandbox: rerun = True ops_id = f"o{ocard['hash'][:6]}_t{theory['hash'][:6]}" - path = f"{banana_cfg.cfg['database_path'].parents[0]}/{ops_id}.yaml" + path = f"{banana_cfg.cfg['paths']['database'].parents[0]}/{ops_id}.yaml" if os.path.exists(path): rerun = False diff --git a/src/ekomark/navigator/__init__.py b/src/ekomark/navigator/__init__.py index d9befee26..5daa46b57 100755 --- a/src/ekomark/navigator/__init__.py +++ b/src/ekomark/navigator/__init__.py @@ -2,11 +2,17 @@ """ ekomark specialization of the navigator """ +import pathlib + from banana import cfg as banana_cfg from banana import navigator as bnav +from banana import register from . import navigator +benchmarks_path = pathlib.Path(__file__).parents[3] / "benchmarks" +register(benchmarks_path) + def yelp(*args): """ @@ -37,7 +43,7 @@ def yelp(*args): h = yelp -app = navigator.NavigatorApp(banana_cfg.cfg, "sandbox") +app = navigator.NavigatorApp(benchmarks_path / banana_cfg.name, "sandbox") # register banana functions bnav.register_globals(globals(), app) @@ -52,4 +58,7 @@ def yelp(*args): def launch_navigator(): """CLI Entry point""" - return bnav.launch_navigator("eko", "ekomark") + # ekomark.navigator makes the globals here (e.g. app, ls, t) available inside IPython + return bnav.launch_navigator( + ["eko", "ekomark", "ekomark.navigator"], benchmarks_path + ) diff --git a/src/ekomark/navigator/navigator.py b/src/ekomark/navigator/navigator.py index a817bb632..a86cdd319 100644 --- a/src/ekomark/navigator/navigator.py +++ b/src/ekomark/navigator/navigator.py @@ -15,7 +15,7 @@ from ..data import db from ..plots import input_figure, plot_dist -table_objects = bnav.table_objects +table_objects = bnav.navigator.table_objects table_objects["o"] = db.Operator From 59795b2e78268b1a64c0225c10bfce12f23038a0 Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Thu, 3 Mar 2022 17:02:30 +0100 Subject: [PATCH 51/74] Upgrade eko navigator --- poetry.lock | 333 ++++++++++++++++++------------ pyproject.toml | 6 +- src/ekomark/navigator/__init__.py | 42 ++-- src/ekomark/navigator/glob.py | 2 + 4 files changed, 231 insertions(+), 152 deletions(-) mode change 100755 => 100644 src/ekomark/navigator/__init__.py create mode 100644 src/ekomark/navigator/glob.py diff --git a/poetry.lock b/poetry.lock index 5410f9075..cbe3eb49a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -6,6 +6,14 @@ category = "main" optional = false python-versions = "*" +[[package]] +name = "appdirs" +version = "1.4.4" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "main" +optional = true +python-versions = "*" + [[package]] name = "appnope" version = "0.1.2" @@ -27,6 +35,20 @@ lazy-object-proxy = ">=1.4.0" typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} wrapt = ">=1.11,<1.14" +[[package]] +name = "asttokens" +version = "2.0.5" +description = "Annotate AST trees with source code positions" +category = "main" +optional = true +python-versions = "*" + +[package.dependencies] +six = "*" + +[package.extras] +test = ["astroid", "pytest"] + [[package]] name = "atomicwrites" version = "1.4.0" @@ -70,16 +92,17 @@ python-versions = "*" [[package]] name = "banana-hep" -version = "0.6.0" +version = "0.6.3" description = "Benchmark QCD physics" category = "main" optional = true -python-versions = ">=3.7.1,<3.11" +python-versions = ">=3.8.0,<3.11" [package.dependencies] +appdirs = ">=1.4.4,<2.0.0" click = ">=8.0.3,<9.0.0" eko = ">=0.8.2,<0.9.0" -ipython = ">=7.30.1,<8.0.0" +ipython = ">=8.1.0,<9.0.0" matplotlib = ">=3.5.1,<4.0.0" numpy = ">=1.21.0,<2.0.0" pandas = ">=1.3.5,<2.0.0" @@ -142,7 +165,7 @@ unicode_backport = ["unicodedata2"] [[package]] name = "click" -version = "8.0.3" +version = "8.0.4" description = "Composable command line interface toolkit" category = "main" optional = false @@ -172,7 +195,7 @@ test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] [[package]] name = "coverage" -version = "6.3.1" +version = "6.3.2" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -216,6 +239,14 @@ category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +[[package]] +name = "executing" +version = "0.8.3" +description = "Get the currently executing AST node of a frame, and other information" +category = "main" +optional = true +python-versions = "*" + [[package]] name = "fancycompleter" version = "0.9.1" @@ -230,7 +261,7 @@ pyrepl = ">=0.8.2" [[package]] name = "filelock" -version = "3.4.2" +version = "3.6.0" description = "A platform independent file lock." category = "dev" optional = false @@ -274,7 +305,7 @@ docs = ["sphinx"] [[package]] name = "identify" -version = "2.4.10" +version = "2.4.11" description = "File identification library for Python" category = "dev" optional = false @@ -301,7 +332,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "importlib-metadata" -version = "4.11.0" +version = "4.11.2" description = "Read metadata from Python packages" category = "main" optional = false @@ -311,9 +342,9 @@ python-versions = ">=3.7" zipp = ">=0.5" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] perf = ["ipython"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] [[package]] name = "iniconfig" @@ -325,11 +356,11 @@ python-versions = "*" [[package]] name = "ipython" -version = "7.31.1" +version = "8.1.1" description = "IPython: Productive Interactive Computing" category = "main" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" [package.dependencies] appnope = {version = "*", markers = "sys_platform == \"darwin\""} @@ -341,19 +372,22 @@ matplotlib-inline = "*" pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} pickleshare = "*" prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" -pygments = "*" -traitlets = ">=4.2" +pygments = ">=2.4.0" +stack-data = "*" +traitlets = ">=5" [package.extras] -all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.17)", "pygments", "qtconsole", "requests", "testpath"] +all = ["black", "Sphinx (>=1.3)", "ipykernel", "nbconvert", "nbformat", "ipywidgets", "notebook", "ipyparallel", "qtconsole", "curio", "matplotlib (!=3.2.0)", "numpy (>=1.19)", "pandas", "pytest", "testpath", "trio", "pytest-asyncio"] +black = ["black"] doc = ["Sphinx (>=1.3)"] kernel = ["ipykernel"] nbconvert = ["nbconvert"] nbformat = ["nbformat"] -notebook = ["notebook", "ipywidgets"] +notebook = ["ipywidgets", "notebook"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] -test = ["nose (>=0.10.1)", "requests", "testpath", "pygments", "nbformat", "ipykernel", "numpy (>=1.17)"] +test = ["pytest", "pytest-asyncio", "testpath"] +test_extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pandas", "pytest", "testpath", "trio"] [[package]] name = "isort" @@ -448,11 +482,11 @@ tests = ["pytest (!=3.3.0)", "psutil", "pytest-cov"] [[package]] name = "markupsafe" -version = "2.0.1" +version = "2.1.0" description = "Safely add untrusted strings to HTML/XML markup." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "matplotlib" @@ -638,7 +672,7 @@ python-versions = ">=3.7" [[package]] name = "platformdirs" -version = "2.5.0" +version = "2.5.1" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false @@ -695,6 +729,17 @@ category = "main" optional = true python-versions = "*" +[[package]] +name = "pure-eval" +version = "0.2.2" +description = "Safely evaluate AST nodes without side effects" +category = "main" +optional = true +python-versions = "*" + +[package.extras] +tests = ["pytest"] + [[package]] name = "py" version = "1.11.0" @@ -1106,6 +1151,22 @@ postgresql_psycopg2cffi = ["psycopg2cffi"] pymysql = ["pymysql (<1)", "pymysql"] sqlcipher = ["sqlcipher3-binary"] +[[package]] +name = "stack-data" +version = "0.2.0" +description = "Extract data from python stack frames and tracebacks for informative displays" +category = "main" +optional = true +python-versions = "*" + +[package.dependencies] +asttokens = "*" +executing = "*" +pure-eval = "*" + +[package.extras] +tests = ["pytest", "typeguard", "pygments", "littleutils", "cython"] + [[package]] name = "toml" version = "0.10.2" @@ -1156,7 +1217,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.13.1" +version = "20.13.2" description = "Virtual Python Environment builder" category = "dev" optional = false @@ -1215,13 +1276,17 @@ mark = ["banana-hep", "sqlalchemy", "pandas", "matplotlib"] [metadata] lock-version = "1.1" python-versions = "^3.8,<3.11" -content-hash = "ffe8b44e472a8495bfc6b6bf908ab4f7a1bc1fe68fb55ea1d7378cadc49d958e" +content-hash = "60dca8c0733ff8dadaf2f53401c28ba2e8470b6cea98f22474e65224cb9a807d" [metadata.files] alabaster = [ {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, ] +appdirs = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] appnope = [ {file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"}, {file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"}, @@ -1230,6 +1295,10 @@ astroid = [ {file = "astroid-2.9.3-py3-none-any.whl", hash = "sha256:506daabe5edffb7e696ad82483ad0228245a9742ed7d2d8c9cdb31537decf9f6"}, {file = "astroid-2.9.3.tar.gz", hash = "sha256:1efdf4e867d4d8ba4a9f6cf9ce07cd182c4c41de77f23814feb27ca93ca9d877"}, ] +asttokens = [ + {file = "asttokens-2.0.5-py2.py3-none-any.whl", hash = "sha256:0844691e88552595a6f4a4281a9f7f79b8dd45ca4ccea82e5e05b4bbdb76705c"}, + {file = "asttokens-2.0.5.tar.gz", hash = "sha256:9a54c114f02c7a9480d56550932546a3f1fe71d8a02f1bc7ccd0ee3ee35cf4d5"}, +] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, @@ -1247,8 +1316,8 @@ backcall = [ {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] banana-hep = [ - {file = "banana-hep-0.6.0.tar.gz", hash = "sha256:83cbf7341a01fdfb6fe410abac776dc3103da1e4f5154deb9d5e8e79ff82284b"}, - {file = "banana_hep-0.6.0-py3-none-any.whl", hash = "sha256:98f5fac7f874e7f03781c65a1bde9c47b5d4368ab2b66c568f39943fe073a87b"}, + {file = "banana-hep-0.6.3.tar.gz", hash = "sha256:296e5e7fa79c2271348258b6f2165cc34067b2a9c60e2c97aec035eb645fe014"}, + {file = "banana_hep-0.6.3-py3-none-any.whl", hash = "sha256:aa52344c4fac9e9e5475dbe175da44fd52ab37bb25b68c0a71eff6f704cd5b82"}, ] black = [ {file = "black-22.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6"}, @@ -1288,8 +1357,8 @@ charset-normalizer = [ {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, ] click = [ - {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, - {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, + {file = "click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1"}, + {file = "click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"}, ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, @@ -1300,47 +1369,47 @@ commonmark = [ {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, ] coverage = [ - {file = "coverage-6.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeffd96882d8c06d31b65dddcf51db7c612547babc1c4c5db6a011abe9798525"}, - {file = "coverage-6.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:621f6ea7260ea2ffdaec64fe5cb521669984f567b66f62f81445221d4754df4c"}, - {file = "coverage-6.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84f2436d6742c01136dd940ee158bfc7cf5ced3da7e4c949662b8703b5cd8145"}, - {file = "coverage-6.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de73fca6fb403dd72d4da517cfc49fcf791f74eee697d3219f6be29adf5af6ce"}, - {file = "coverage-6.3.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78fbb2be068a13a5d99dce9e1e7d168db880870f7bc73f876152130575bd6167"}, - {file = "coverage-6.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f5a4551dfd09c3bd12fca8144d47fe7745275adf3229b7223c2f9e29a975ebda"}, - {file = "coverage-6.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7bff3a98f63b47464480de1b5bdd80c8fade0ba2832c9381253c9b74c4153c27"}, - {file = "coverage-6.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a06c358f4aed05fa1099c39decc8022261bb07dfadc127c08cfbd1391b09689e"}, - {file = "coverage-6.3.1-cp310-cp310-win32.whl", hash = "sha256:9fff3ff052922cb99f9e52f63f985d4f7a54f6b94287463bc66b7cdf3eb41217"}, - {file = "coverage-6.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:276b13cc085474e482566c477c25ed66a097b44c6e77132f3304ac0b039f83eb"}, - {file = "coverage-6.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:56c4a409381ddd7bbff134e9756077860d4e8a583d310a6f38a2315b9ce301d0"}, - {file = "coverage-6.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9eb494070aa060ceba6e4bbf44c1bc5fa97bfb883a0d9b0c9049415f9e944793"}, - {file = "coverage-6.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e15d424b8153756b7c903bde6d4610be0c3daca3986173c18dd5c1a1625e4cd"}, - {file = "coverage-6.3.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61d47a897c1e91f33f177c21de897267b38fbb45f2cd8e22a710bcef1df09ac1"}, - {file = "coverage-6.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:25e73d4c81efa8ea3785274a2f7f3bfbbeccb6fcba2a0bdd3be9223371c37554"}, - {file = "coverage-6.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:fac0bcc5b7e8169bffa87f0dcc24435446d329cbc2b5486d155c2e0f3b493ae1"}, - {file = "coverage-6.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:72128176fea72012063200b7b395ed8a57849282b207321124d7ff14e26988e8"}, - {file = "coverage-6.3.1-cp37-cp37m-win32.whl", hash = "sha256:1bc6d709939ff262fd1432f03f080c5042dc6508b6e0d3d20e61dd045456a1a0"}, - {file = "coverage-6.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:618eeba986cea7f621d8607ee378ecc8c2504b98b3fdc4952b30fe3578304687"}, - {file = "coverage-6.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d5ed164af5c9078596cfc40b078c3b337911190d3faeac830c3f1274f26b8320"}, - {file = "coverage-6.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:352c68e233409c31048a3725c446a9e48bbff36e39db92774d4f2380d630d8f8"}, - {file = "coverage-6.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:448d7bde7ceb6c69e08474c2ddbc5b4cd13c9e4aa4a717467f716b5fc938a734"}, - {file = "coverage-6.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9fde6b90889522c220dd56a670102ceef24955d994ff7af2cb786b4ba8fe11e4"}, - {file = "coverage-6.3.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e647a0be741edbb529a72644e999acb09f2ad60465f80757da183528941ff975"}, - {file = "coverage-6.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a5cdc3adb4f8bb8d8f5e64c2e9e282bc12980ef055ec6da59db562ee9bdfefa"}, - {file = "coverage-6.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2dd70a167843b4b4b2630c0c56f1b586fe965b4f8ac5da05b6690344fd065c6b"}, - {file = "coverage-6.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9ad0a117b8dc2061ce9461ea4c1b4799e55edceb236522c5b8f958ce9ed8fa9a"}, - {file = "coverage-6.3.1-cp38-cp38-win32.whl", hash = "sha256:e92c7a5f7d62edff50f60a045dc9542bf939758c95b2fcd686175dd10ce0ed10"}, - {file = "coverage-6.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:482fb42eea6164894ff82abbcf33d526362de5d1a7ed25af7ecbdddd28fc124f"}, - {file = "coverage-6.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c5b81fb37db76ebea79aa963b76d96ff854e7662921ce742293463635a87a78d"}, - {file = "coverage-6.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a4f923b9ab265136e57cc14794a15b9dcea07a9c578609cd5dbbfff28a0d15e6"}, - {file = "coverage-6.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56d296cbc8254a7dffdd7bcc2eb70be5a233aae7c01856d2d936f5ac4e8ac1f1"}, - {file = "coverage-6.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1245ab82e8554fa88c4b2ab1e098ae051faac5af829efdcf2ce6b34dccd5567c"}, - {file = "coverage-6.3.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f2b05757c92ad96b33dbf8e8ec8d4ccb9af6ae3c9e9bd141c7cc44d20c6bcba"}, - {file = "coverage-6.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9e3dd806f34de38d4c01416344e98eab2437ac450b3ae39c62a0ede2f8b5e4ed"}, - {file = "coverage-6.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d651fde74a4d3122e5562705824507e2f5b2d3d57557f1916c4b27635f8fbe3f"}, - {file = "coverage-6.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:704f89b87c4f4737da2860695a18c852b78ec7279b24eedacab10b29067d3a38"}, - {file = "coverage-6.3.1-cp39-cp39-win32.whl", hash = "sha256:2aed4761809640f02e44e16b8b32c1a5dee5e80ea30a0ff0912158bde9c501f2"}, - {file = "coverage-6.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:9976fb0a5709988778ac9bc44f3d50fccd989987876dfd7716dee28beed0a9fa"}, - {file = "coverage-6.3.1-pp36.pp37.pp38-none-any.whl", hash = "sha256:463e52616ea687fd323888e86bf25e864a3cc6335a043fad6bbb037dbf49bbe2"}, - {file = "coverage-6.3.1.tar.gz", hash = "sha256:6c3f6158b02ac403868eea390930ae64e9a9a2a5bbfafefbb920d29258d9f2f8"}, + {file = "coverage-6.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b27d894748475fa858f9597c0ee1d4829f44683f3813633aaf94b19cb5453cf"}, + {file = "coverage-6.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37d1141ad6b2466a7b53a22e08fe76994c2d35a5b6b469590424a9953155afac"}, + {file = "coverage-6.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9987b0354b06d4df0f4d3e0ec1ae76d7ce7cbca9a2f98c25041eb79eec766f1"}, + {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26e2deacd414fc2f97dd9f7676ee3eaecd299ca751412d89f40bc01557a6b1b4"}, + {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd8bafa458b5c7d061540f1ee9f18025a68e2d8471b3e858a9dad47c8d41903"}, + {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:46191097ebc381fbf89bdce207a6c107ac4ec0890d8d20f3360345ff5976155c"}, + {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6f89d05e028d274ce4fa1a86887b071ae1755082ef94a6740238cd7a8178804f"}, + {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:58303469e9a272b4abdb9e302a780072c0633cdcc0165db7eec0f9e32f901e05"}, + {file = "coverage-6.3.2-cp310-cp310-win32.whl", hash = "sha256:2fea046bfb455510e05be95e879f0e768d45c10c11509e20e06d8fcaa31d9e39"}, + {file = "coverage-6.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:a2a8b8bcc399edb4347a5ca8b9b87e7524c0967b335fbb08a83c8421489ddee1"}, + {file = "coverage-6.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f1555ea6d6da108e1999b2463ea1003fe03f29213e459145e70edbaf3e004aaa"}, + {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5f4e1edcf57ce94e5475fe09e5afa3e3145081318e5fd1a43a6b4539a97e518"}, + {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a15dc0a14008f1da3d1ebd44bdda3e357dbabdf5a0b5034d38fcde0b5c234b7"}, + {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21b7745788866028adeb1e0eca3bf1101109e2dc58456cb49d2d9b99a8c516e6"}, + {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8ce257cac556cb03be4a248d92ed36904a59a4a5ff55a994e92214cde15c5bad"}, + {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b0be84e5a6209858a1d3e8d1806c46214e867ce1b0fd32e4ea03f4bd8b2e3359"}, + {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:acf53bc2cf7282ab9b8ba346746afe703474004d9e566ad164c91a7a59f188a4"}, + {file = "coverage-6.3.2-cp37-cp37m-win32.whl", hash = "sha256:8bdde1177f2311ee552f47ae6e5aa7750c0e3291ca6b75f71f7ffe1f1dab3dca"}, + {file = "coverage-6.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b31651d018b23ec463e95cf10070d0b2c548aa950a03d0b559eaa11c7e5a6fa3"}, + {file = "coverage-6.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07e6db90cd9686c767dcc593dff16c8c09f9814f5e9c51034066cad3373b914d"}, + {file = "coverage-6.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c6dbb42f3ad25760010c45191e9757e7dce981cbfb90e42feef301d71540059"}, + {file = "coverage-6.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76aeef1b95aff3905fb2ae2d96e319caca5b76fa41d3470b19d4e4a3a313512"}, + {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cf5cfcb1521dc3255d845d9dca3ff204b3229401994ef8d1984b32746bb45ca"}, + {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fbbdc8d55990eac1b0919ca69eb5a988a802b854488c34b8f37f3e2025fa90d"}, + {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ec6bc7fe73a938933d4178c9b23c4e0568e43e220aef9472c4f6044bfc6dd0f0"}, + {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9baff2a45ae1f17c8078452e9e5962e518eab705e50a0aa8083733ea7d45f3a6"}, + {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd9e830e9d8d89b20ab1e5af09b32d33e1a08ef4c4e14411e559556fd788e6b2"}, + {file = "coverage-6.3.2-cp38-cp38-win32.whl", hash = "sha256:f7331dbf301b7289013175087636bbaf5b2405e57259dd2c42fdcc9fcc47325e"}, + {file = "coverage-6.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:68353fe7cdf91f109fc7d474461b46e7f1f14e533e911a2a2cbb8b0fc8613cf1"}, + {file = "coverage-6.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b78e5afb39941572209f71866aa0b206c12f0109835aa0d601e41552f9b3e620"}, + {file = "coverage-6.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e21876082ed887baed0146fe222f861b5815455ada3b33b890f4105d806128d"}, + {file = "coverage-6.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34626a7eee2a3da12af0507780bb51eb52dca0e1751fd1471d0810539cefb536"}, + {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ebf730d2381158ecf3dfd4453fbca0613e16eaa547b4170e2450c9707665ce7"}, + {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd6fe30bd519694b356cbfcaca9bd5c1737cddd20778c6a581ae20dc8c04def2"}, + {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96f8a1cb43ca1422f36492bebe63312d396491a9165ed3b9231e778d43a7fca4"}, + {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dd035edafefee4d573140a76fdc785dc38829fe5a455c4bb12bac8c20cfc3d69"}, + {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ca5aeb4344b30d0bec47481536b8ba1181d50dbe783b0e4ad03c95dc1296684"}, + {file = "coverage-6.3.2-cp39-cp39-win32.whl", hash = "sha256:f5fa5803f47e095d7ad8443d28b01d48c0359484fec1b9d8606d0e3282084bc4"}, + {file = "coverage-6.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:9548f10d8be799551eb3a9c74bbf2b4934ddb330e08a73320123c07f95cc2d92"}, + {file = "coverage-6.3.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:18d520c6860515a771708937d2f78f63cc47ab3b80cb78e86573b0a760161faf"}, + {file = "coverage-6.3.2.tar.gz", hash = "sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9"}, ] cycler = [ {file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"}, @@ -1358,13 +1427,17 @@ docutils = [ {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"}, {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, ] +executing = [ + {file = "executing-0.8.3-py2.py3-none-any.whl", hash = "sha256:d1eef132db1b83649a3905ca6dd8897f71ac6f8cac79a7e58a1a09cf137546c9"}, + {file = "executing-0.8.3.tar.gz", hash = "sha256:c6554e21c6b060590a6d3be4b82fb78f8f0194d809de5ea7df1c093763311501"}, +] fancycompleter = [ {file = "fancycompleter-0.9.1-py3-none-any.whl", hash = "sha256:dd076bca7d9d524cc7f25ec8f35ef95388ffef9ef46def4d3d25e9b044ad7080"}, {file = "fancycompleter-0.9.1.tar.gz", hash = "sha256:09e0feb8ae242abdfd7ef2ba55069a46f011814a80fe5476be48f51b00247272"}, ] filelock = [ - {file = "filelock-3.4.2-py3-none-any.whl", hash = "sha256:cf0fc6a2f8d26bd900f19bf33915ca70ba4dd8c56903eeb14e1e7a2fd7590146"}, - {file = "filelock-3.4.2.tar.gz", hash = "sha256:38b4f4c989f9d06d44524df1b24bd19e167d851f19b50bf3e3559952dddc5b80"}, + {file = "filelock-3.6.0-py3-none-any.whl", hash = "sha256:f8314284bfffbdcfa0ff3d7992b023d4c628ced6feb957351d4c48d059f56bc0"}, + {file = "filelock-3.6.0.tar.gz", hash = "sha256:9cd540a9352e432c7246a48fe4e8712b10acb1df2ad1f30e8c070b82ae1fed85"}, ] fonttools = [ {file = "fonttools-4.29.1-py3-none-any.whl", hash = "sha256:1933415e0fbdf068815cb1baaa1f159e17830215f7e8624e5731122761627557"}, @@ -1423,8 +1496,8 @@ greenlet = [ {file = "greenlet-1.1.2.tar.gz", hash = "sha256:e30f5ea4ae2346e62cedde8794a56858a67b878dd79f7df76a0767e356b1744a"}, ] identify = [ - {file = "identify-2.4.10-py2.py3-none-any.whl", hash = "sha256:7d10baf6ba6f1912a0a49f4c1c2c49fa1718765c3a37d72d13b07779567c5b85"}, - {file = "identify-2.4.10.tar.gz", hash = "sha256:e12b2aea3cf108de73ae055c2260783bde6601de09718f6768cf8e9f6f6322a6"}, + {file = "identify-2.4.11-py2.py3-none-any.whl", hash = "sha256:fd906823ed1db23c7a48f9b176a1d71cb8abede1e21ebe614bac7bdd688d9213"}, + {file = "identify-2.4.11.tar.gz", hash = "sha256:2986942d3974c8f2e5019a190523b0b0e2a07cb8e89bf236727fb4b26f27f8fd"}, ] idna = [ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, @@ -1435,16 +1508,16 @@ imagesize = [ {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"}, ] importlib-metadata = [ - {file = "importlib_metadata-4.11.0-py3-none-any.whl", hash = "sha256:6affcdb3aec542dd98df8211e730bba6c5f2bec8288d47bacacde898f548c9ad"}, - {file = "importlib_metadata-4.11.0.tar.gz", hash = "sha256:9e5e553bbba1843cb4a00823014b907616be46ee503d2b9ba001d214a8da218f"}, + {file = "importlib_metadata-4.11.2-py3-none-any.whl", hash = "sha256:d16e8c1deb60de41b8e8ed21c1a7b947b0bc62fab7e1d470bcdf331cea2e6735"}, + {file = "importlib_metadata-4.11.2.tar.gz", hash = "sha256:b36ffa925fe3139b2f6ff11d6925ffd4fa7bc47870165e3ac260ac7b4f91e6ac"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] ipython = [ - {file = "ipython-7.31.1-py3-none-any.whl", hash = "sha256:55df3e0bd0f94e715abd968bedd89d4e8a7bce4bf498fb123fed4f5398fea874"}, - {file = "ipython-7.31.1.tar.gz", hash = "sha256:b5548ec5329a4bcf054a5deed5099b0f9622eb9ea51aaa7104d215fece201d8c"}, + {file = "ipython-8.1.1-py3-none-any.whl", hash = "sha256:6f56bfaeaa3247aa3b9cd3b8cbab3a9c0abf7428392f97b21902d12b2f42a381"}, + {file = "ipython-8.1.1.tar.gz", hash = "sha256:8138762243c9b3a3ffcf70b37151a2a35c23d3a29f9743878c33624f4207be3d"}, ] isort = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, @@ -1598,60 +1671,46 @@ lz4 = [ {file = "lz4-3.1.10.tar.gz", hash = "sha256:439e575ecfa9ecffcbd63cfed99baefbe422ab9645b1e82278024d8a21d9720b"}, ] markupsafe = [ - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, - {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3028252424c72b2602a323f70fbf50aa80a5d3aa616ea6add4ba21ae9cc9da4c"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:290b02bab3c9e216da57c1d11d2ba73a9f73a614bbdcc027d299a60cdfabb11a"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e104c0c2b4cd765b4e83909cde7ec61a1e313f8a75775897db321450e928cce"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24c3be29abb6b34052fd26fc7a8e0a49b1ee9d282e3665e8ad09a0a68faee5b3"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204730fd5fe2fe3b1e9ccadb2bd18ba8712b111dcabce185af0b3b5285a7c989"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d3b64c65328cb4cd252c94f83e66e3d7acf8891e60ebf588d7b493a55a1dbf26"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:96de1932237abe0a13ba68b63e94113678c379dca45afa040a17b6e1ad7ed076"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75bb36f134883fdbe13d8e63b8675f5f12b80bb6627f7714c7d6c5becf22719f"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-win32.whl", hash = "sha256:4056f752015dfa9828dce3140dbadd543b555afb3252507348c493def166d454"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:d4e702eea4a2903441f2735799d217f4ac1b55f7d8ad96ab7d4e25417cb0827c"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f0eddfcabd6936558ec020130f932d479930581171368fd728efcfb6ef0dd357"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddea4c352a488b5e1069069f2f501006b1a4362cb906bee9a193ef1245a7a61"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09c86c9643cceb1d87ca08cdc30160d1b7ab49a8a21564868921959bd16441b8"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0a0abef2ca47b33fb615b491ce31b055ef2430de52c5b3fb19a4042dbc5cadb"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:736895a020e31b428b3382a7887bfea96102c529530299f426bf2e636aacec9e"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:679cbb78914ab212c49c67ba2c7396dc599a8479de51b9a87b174700abd9ea49"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:84ad5e29bf8bab3ad70fd707d3c05524862bddc54dc040982b0dbcff36481de7"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-win32.whl", hash = "sha256:8da5924cb1f9064589767b0f3fc39d03e3d0fb5aa29e0cb21d43106519bd624a"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:454ffc1cbb75227d15667c09f164a0099159da0c1f3d2636aa648f12675491ad"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:142119fb14a1ef6d758912b25c4e803c3ff66920635c44078666fe7cc3f8f759"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b2a5a856019d2833c56a3dcac1b80fe795c95f401818ea963594b345929dffa7"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d1fb9b2eec3c9714dd936860850300b51dbaa37404209c8d4cb66547884b7ed"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62c0285e91414f5c8f621a17b69fc0088394ccdaa961ef469e833dbff64bd5ea"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc3150f85e2dbcf99e65238c842d1cfe69d3e7649b19864c1cc043213d9cd730"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f02cf7221d5cd915d7fa58ab64f7ee6dd0f6cddbb48683debf5d04ae9b1c2cc1"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5653619b3eb5cbd35bfba3c12d575db2a74d15e0e1c08bf1db788069d410ce8"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7d2f5d97fcbd004c03df8d8fe2b973fe2b14e7bfeb2cfa012eaa8759ce9a762f"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-win32.whl", hash = "sha256:3cace1837bc84e63b3fd2dfce37f08f8c18aeb81ef5cf6bb9b51f625cb4e6cd8"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:fabbe18087c3d33c5824cb145ffca52eccd053061df1d79d4b66dafa5ad2a5ea"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:023af8c54fe63530545f70dd2a2a7eed18d07a9a77b94e8bf1e2ff7f252db9a3"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d66624f04de4af8bbf1c7f21cc06649c1c69a7f84109179add573ce35e46d448"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c532d5ab79be0199fa2658e24a02fce8542df196e60665dd322409a03db6a52c"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ec74fada3841b8c5f4c4f197bea916025cb9aa3fe5abf7d52b655d042f956"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c653fde75a6e5eb814d2a0a89378f83d1d3f502ab710904ee585c38888816c"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:961eb86e5be7d0973789f30ebcf6caab60b844203f4396ece27310295a6082c7"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:598b65d74615c021423bd45c2bc5e9b59539c875a9bdb7e5f2a6b92dfcfc268d"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:599941da468f2cf22bf90a84f6e2a65524e87be2fce844f96f2dd9a6c9d1e635"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-win32.whl", hash = "sha256:e6f7f3f41faffaea6596da86ecc2389672fa949bd035251eab26dc6697451d05"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:b8811d48078d1cf2a6863dafb896e68406c5f513048451cd2ded0473133473c7"}, + {file = "MarkupSafe-2.1.0.tar.gz", hash = "sha256:80beaf63ddfbc64a0452b841d8036ca0611e049650e20afcb882f5d3c266d65f"}, ] matplotlib = [ {file = "matplotlib-3.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:456cc8334f6d1124e8ff856b42d2cc1c84335375a16448189999496549f7182b"}, @@ -1873,8 +1932,8 @@ pillow = [ {file = "Pillow-9.0.1.tar.gz", hash = "sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa"}, ] platformdirs = [ - {file = "platformdirs-2.5.0-py3-none-any.whl", hash = "sha256:30671902352e97b1eafd74ade8e4a694782bd3471685e78c32d0fdfd3aa7e7bb"}, - {file = "platformdirs-2.5.0.tar.gz", hash = "sha256:8ec11dfba28ecc0715eb5fb0147a87b1bf325f349f3da9aab2cd6b50b96b692b"}, + {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, + {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, @@ -1892,6 +1951,10 @@ ptyprocess = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, ] +pure-eval = [ + {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, + {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, +] py = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, @@ -2101,6 +2164,10 @@ sqlalchemy = [ {file = "SQLAlchemy-1.4.31-cp39-cp39-win_amd64.whl", hash = "sha256:9e4fb2895b83993831ba2401b6404de953fdbfa9d7d4fa6a4756294a83bbc94f"}, {file = "SQLAlchemy-1.4.31.tar.gz", hash = "sha256:582b59d1e5780a447aada22b461e50b404a9dc05768da1d87368ad8190468418"}, ] +stack-data = [ + {file = "stack_data-0.2.0-py3-none-any.whl", hash = "sha256:999762f9c3132308789affa03e9271bbbe947bf78311851f4d485d8402ed858e"}, + {file = "stack_data-0.2.0.tar.gz", hash = "sha256:45692d41bd633a9503a5195552df22b583caf16f0b27c4e58c98d88c8b648e12"}, +] toml = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, @@ -2122,8 +2189,8 @@ urllib3 = [ {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"}, ] virtualenv = [ - {file = "virtualenv-20.13.1-py2.py3-none-any.whl", hash = "sha256:45e1d053cad4cd453181ae877c4ffc053546ae99e7dd049b9ff1d9be7491abf7"}, - {file = "virtualenv-20.13.1.tar.gz", hash = "sha256:e0621bcbf4160e4e1030f05065c8834b4e93f4fcc223255db2a823440aca9c14"}, + {file = "virtualenv-20.13.2-py2.py3-none-any.whl", hash = "sha256:e7b34c9474e6476ee208c43a4d9ac1510b041c68347eabfe9a9ea0c86aa0a46b"}, + {file = "virtualenv-20.13.2.tar.gz", hash = "sha256:01f5f80744d24a3743ce61858123488e91cb2dd1d3bdf92adaf1bba39ffdedf0"}, ] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, diff --git a/pyproject.toml b/pyproject.toml index 1766e6d44..bae161d77 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,7 @@ Sphinx = { version = "^4.3.2", optional = true } sphinx-rtd-theme = { version = "^1.0.0", optional = true } sphinxcontrib-bibtex = { version = "^2.4.1", optional = true } # ekomark -banana-hep = { version = "^0.6.0", optional = true } +banana-hep = { version = "^0.6.3", optional = true } sqlalchemy = { version = "^1.4.21", optional = true } pandas = { version = "^1.3.0", optional = true } matplotlib = { version = "^3.5.1", optional = true } @@ -79,8 +79,8 @@ test = { "shell" = "pytest tests" } lint = "pylint src/**/*.py -E" lint-warnings = "pylint src/**/*.py --exit-zero" sandbox = "python benchmarks/sandbox.py" -nav = "ekonav" -navigator = "ekonav" +nav = "ekonav --config benchmarks/banana.yaml" +navigator = "ekonav --config benchmarks/banana.yaml" black = "black ." isort = "isort ." format = ["black", "isort"] diff --git a/src/ekomark/navigator/__init__.py b/src/ekomark/navigator/__init__.py old mode 100755 new mode 100644 index 5daa46b57..8197fb35b --- a/src/ekomark/navigator/__init__.py +++ b/src/ekomark/navigator/__init__.py @@ -2,16 +2,13 @@ """ ekomark specialization of the navigator """ +import argparse import pathlib from banana import cfg as banana_cfg from banana import navigator as bnav -from banana import register -from . import navigator - -benchmarks_path = pathlib.Path(__file__).parents[3] / "benchmarks" -register(benchmarks_path) +from . import navigator, glob def yelp(*args): @@ -41,24 +38,37 @@ def yelp(*args): return None -h = yelp +def register_globals(configpath): + app = navigator.NavigatorApp(configpath, "sandbox") + glob.app = app -app = navigator.NavigatorApp(benchmarks_path / banana_cfg.name, "sandbox") + glob.glob["yelp"] = yelp + glob.glob["h"] = yelp -# register banana functions -bnav.register_globals(globals(), app) + # register banana functions + bnav.register_globals(glob.glob, glob.app) -# add my functions -dfl = app.log_as_dfd -check_log = app.check_log -plot_pdfs = app.plot_pdfs -display_pdfs = app.display_pdfs -compare = app.compare_external + # add my functions + glob.glob["dfl"] = app.log_as_dfd + glob.glob["check_log"] = app.check_log + glob.glob["plot_pdfs"] = app.plot_pdfs + glob.glob["display_pdfs"] = app.display_pdfs + glob.glob["compare"] = app.compare_external def launch_navigator(): """CLI Entry point""" + parser = argparse.ArgumentParser() + + parser.add_argument( + "-c", "--config", type=pathlib.Path, default=None, help="Path to config file" + ) + + args = parser.parse_args() + + register_globals(banana_cfg.detect(args.config)) + # ekomark.navigator makes the globals here (e.g. app, ls, t) available inside IPython return bnav.launch_navigator( - ["eko", "ekomark", "ekomark.navigator"], benchmarks_path + ["eko", "ekomark", "ekomark.navigator.glob"], skip_cfg=True ) diff --git a/src/ekomark/navigator/glob.py b/src/ekomark/navigator/glob.py new file mode 100644 index 000000000..893dbb324 --- /dev/null +++ b/src/ekomark/navigator/glob.py @@ -0,0 +1,2 @@ +app = None +glob = globals() From ffda8ad539d77904099b3ef1895261d08d959135 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Fri, 4 Mar 2022 13:00:06 +0100 Subject: [PATCH 52/74] remove scheme A and B, fix typos, update apfel bench --- benchmarks/apfel_bench.py | 2 ++ benchmarks/lha_paper_bench.py | 3 +-- doc/source/theory/pQCD.rst | 4 ++-- src/eko/evolution_operator/__init__.py | 2 +- src/eko/scale_variations/exponentiated.py | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/benchmarks/apfel_bench.py b/benchmarks/apfel_bench.py index 017b68d3c..a111ccac9 100644 --- a/benchmarks/apfel_bench.py +++ b/benchmarks/apfel_bench.py @@ -55,6 +55,7 @@ class BenchmarkVFNS(ApfelBenchmark): "Q0": np.sqrt(2.0), "nfref": 3, "nf0": 3, + "mc": 1.51, } vfns_theory = tolist(vfns_theory) @@ -78,6 +79,7 @@ def benchmark_sv(self, pto, scheme): "fact_to_ren_scale_ratio": [np.sqrt(2.0)], "ModSV": [scheme], "EScaleVar": [0], + "nfref": [4], } ) self.run( diff --git a/benchmarks/lha_paper_bench.py b/benchmarks/lha_paper_bench.py index 5c093dd81..cd07f126d 100644 --- a/benchmarks/lha_paper_bench.py +++ b/benchmarks/lha_paper_bench.py @@ -228,8 +228,7 @@ def benchmark_sv(self, pto): # obj.benchmark_sv(2) # # VFNS benchmarks with LHA settings - # programs = ["LHA", "pegasus", "apfel"] - programs = ["apfel"] + programs = ["LHA", "pegasus", "apfel"] for p in programs: obj = BenchmarkRunner(p) # obj.benchmark_plain(2) diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index c71cb2564..42f2ba19b 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -113,7 +113,7 @@ evolution, always evaluating the strong coupling at :math:`\mu_R^2`. & \gamma^{(3)}(N) \to \gamma^{(3)}(N) - 3 \beta_0 k \gamma^{(2)} - ( 2 \beta_1 k - 3 \beta_0^2 k^2) \gamma^{(1)} - (\beta_2 k - \frac{5}{2} \beta_1 \beta_0 k^2 + \beta_0^3 k^3) \gamma^{(0)} \\ & k = \ln(\mu_F^2/\mu_R^2) - This procedure corresponds to scheme A of :cite:`AbdulKhalek:2019ihb`, and we recommend to use it along with + This procedure corresponds to Eq. (3.32) of :cite:`AbdulKhalek:2019ihb`, and we recommend to use it along with ``ModEv='iterate-exact'`` in order to be in agreement with the treatment of the evolution integral expansion. @@ -134,7 +134,7 @@ evolution, always evaluating the strong coupling at :math:`\mu_R^2`. In this way the dependence of the |EKO| on :math:`k` is factorized outside the unvaried evolution kernel. This procedure is repeated for each different flavor patch present in the evolution path. - It corresponds to scheme B of :cite:`AbdulKhalek:2019ihb`, and we recommend to use it along with + It corresponds to Eq. (3.35) of :cite:`AbdulKhalek:2019ihb`, and we recommend to use it along with ``ModEv='truncated'`` in order to keep consistency with the evolution integral expansion. diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py index 8611e2b97..ac18eb7b4 100644 --- a/src/eko/evolution_operator/__init__.py +++ b/src/eko/evolution_operator/__init__.py @@ -240,7 +240,7 @@ class Operator: cut to the upper limit in the mellin inversion """ - def __init__(self, config, managers, nf, q2_from, q2_to=None, mellin_cut=5e-2): + def __init__(self, config, managers, nf, q2_from, q2_to, mellin_cut=5e-2): self.config = config self.managers = managers self.nf = nf diff --git a/src/eko/scale_variations/exponentiated.py b/src/eko/scale_variations/exponentiated.py index 0375dcadc..d0657de12 100644 --- a/src/eko/scale_variations/exponentiated.py +++ b/src/eko/scale_variations/exponentiated.py @@ -26,7 +26,7 @@ def gamma_variation(gamma, order, nf, L): Returns ------- gamma : numpy.ndarray - adjusted singlet anomalous dimensions + adjusted anomalous dimensions """ # since we are modifying *in-place* be carefull, that the order matters! # and indeed, we need to adjust the high elements first From 6efb366466a8d3601b478268fe389a5365afe833 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Fri, 4 Mar 2022 16:03:27 +0100 Subject: [PATCH 53/74] Passing nf+1 to a_s inside matching --- doc/source/theory/Matching.rst | 5 +++-- src/eko/matching_conditions/operator_matrix_element.py | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/source/theory/Matching.rst b/doc/source/theory/Matching.rst index b2e2046a1..cc2902022 100644 --- a/doc/source/theory/Matching.rst +++ b/doc/source/theory/Matching.rst @@ -66,8 +66,7 @@ Furthermore in the right side basis :math:`\tilde h^{+}, \tilde h^{-}` are intri The :math:`\mathbf{A}^{(n_f)}(\mu_{h+1}^2)` can be computed order by order in :math:`a_s`: .. math :: - \mathbf{A}^{(n_f)}(\mu_{h}^2) = \mathbf{I} + a_s^{(n_f)}(\mu_{h}^2) \mathbf{A}^{(n_f),(1)} + \left(a_s^{(n_f)}(\mu_{h}^2)\right)^2 \mathbf{A}^{(n_f),(2)} - + \mathbf{A}^{(n_f)}(\mu_{h}^2) = \mathbf{I} + a_s^{(n_f+1)}(\mu_{h}^2) \mathbf{A}^{(n_f),(1)} + \left(a_s^{(n_f+1)}(\mu_{h}^2)\right)^2 \mathbf{A}^{(n_f),(2)} where the :math:`\mathbf{A}^{(n_f),(k)}` are given up to |NNLO| by the following expressions: @@ -83,6 +82,8 @@ The coefficients :math:`A^{(n_f),(k)}_{ij}(z,\mu_{h}^2)` have been firstly compu been :doc:`Mellin transformed ` to be used inside EKO. They depend on the scale :math:`\mu_{h}^2` only through the logarithm :math:`\ln(\mu_{h}^2/m_{h}^2)`, in particular the coefficient :math:`A_{gg,H}^{S,(1)}` is fully proportional to :math:`\ln(\mu_{h}^2/m_{h}^2)`. +During the matching we use :math:`a_s^{(n_f+1)}`: in fact the :math:`a_s` decoupling gives raise to some additional logarithms +:math:`\ln(\mu_{h}^2/m_{h}^2)`, which are cancelled by the OME's :math:`A_{kl,H}`. We remark that contributions of the higher quark at |NNLO| have not been computed yet, thus the elements :math:`A_{qH}^{(2)},A_{gH}^{(2)}A_{HH}^{(2)}` are not encoded in EKO despite of being present. On the other hand the elements :math:`A_{qq}^{ps},A_{qg}` are known to start at |N3LO|. diff --git a/src/eko/matching_conditions/operator_matrix_element.py b/src/eko/matching_conditions/operator_matrix_element.py index be4c99a92..b610f10a0 100644 --- a/src/eko/matching_conditions/operator_matrix_element.py +++ b/src/eko/matching_conditions/operator_matrix_element.py @@ -321,7 +321,8 @@ def compute(self, q2, nf, L, is_msbar): self.copy_ome() return - a_s = self.sc.a_s(q2 / self.config["fact_to_ren"], q2, nf) + # Note that here you need to use a_s^{nf+1}(q2) + a_s = self.sc.a_s(q2 / self.config["fact_to_ren"], q2, nf + 1) tot_start_time = time.perf_counter() logger.info("Matching: computing operators - 0/%d", grid_size) From 0933fd80d36b5a9a17d347607b36fbefa4e2d3a6 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Fri, 4 Mar 2022 16:48:26 +0100 Subject: [PATCH 54/74] remove wrong comment --- tests/benchmark_strong_coupling.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/benchmark_strong_coupling.py b/tests/benchmark_strong_coupling.py index eefbb06cf..6589e4fe8 100644 --- a/tests/benchmark_strong_coupling.py +++ b/tests/benchmark_strong_coupling.py @@ -858,8 +858,6 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self): else: apfel_val = 0.03478112968976964 # check myself to APFEL - # notice that Apfel computes alpha in nf=4 by default, - # but what has to be used during the matching is alpha in nf=3 np.testing.assert_allclose(apfel_val, my_val, rtol=0.03) np.testing.assert_allclose(apfel_val, my_val_4) np.testing.assert_allclose(my_val, my_val_3) From a0dd26835bca3902871bb8718381e05b3d9b32ec Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 7 Mar 2022 12:22:00 +0100 Subject: [PATCH 55/74] relate is_downward to nf flow --- benchmarks/lha_paper_bench.py | 2 +- src/eko/evolution_operator/grid.py | 18 +++++++++------- src/eko/matching_conditions/__init__.py | 2 -- src/eko/strong_coupling.py | 8 ++----- src/eko/thresholds.py | 28 ++++++++++++++++++++++++- tests/test_thresholds.py | 22 ++++++++++++++++++- 6 files changed, 61 insertions(+), 19 deletions(-) diff --git a/benchmarks/lha_paper_bench.py b/benchmarks/lha_paper_bench.py index cd07f126d..415ed665d 100644 --- a/benchmarks/lha_paper_bench.py +++ b/benchmarks/lha_paper_bench.py @@ -83,7 +83,6 @@ def sv_theories(self, pto): high["PTO"] = pto high["fact_to_ren_scale_ratio"] = np.sqrt(2.0) high["ModSV"] = "exponentiated" - high["nfref"] = 4 return [high, low] @staticmethod @@ -211,6 +210,7 @@ def benchmark_sv(self, pto): if self.external == "apfel": for sv_theory in [low, high]: sv_theory["kcThr"] = 1.0 + 1e-15 + sv_theory["nfref"] = 4 sv_theory["EScaleVar"] = 0 low["XIR"] = np.sqrt(2.0) high["XIR"] = np.sqrt(0.5) diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py index 85385fbbf..8fb6c37e9 100644 --- a/src/eko/evolution_operator/grid.py +++ b/src/eko/evolution_operator/grid.py @@ -11,6 +11,8 @@ import numpy as np +from eko.thresholds import is_downward_path + from .. import basis_rotation as br from .. import matching_conditions, member from ..matching_conditions.operator_matrix_element import OperatorMatrixElement @@ -154,7 +156,7 @@ def get_threshold_operators(self, path): It computes and stores the necessary macthing operators Parameters ---------- - path: list(PathSegment) + path: list(`eko.thresholds.PathSegment`) thresholds path Returns @@ -163,9 +165,11 @@ def get_threshold_operators(self, path): """ # The base area is always that of the reference q thr_ops = [] + # is_downward point to smaller nf + is_downward, shift = is_downward_path(path) for seg in path[:-1]: new_op_key = seg.tuple - ome = OperatorMatrixElement(self.config, self.managers, seg.is_backward) + ome = OperatorMatrixElement(self.config, self.managers, is_downward) if new_op_key not in self._threshold_operators: # Compute the operator and store it logger.info("Prepare threshold operator") @@ -179,8 +183,6 @@ def get_threshold_operators(self, path): # Compute the matching conditions and store it if seg.q2_to not in self._matching_operators: thr_config = self.managers["thresholds_config"] - # is_backward point to the smaller q2 - shift = 3 if not seg.is_backward else 4 kthr = thr_config.thresholds_ratios[seg.nf - shift] ome.compute( seg.q2_to, @@ -241,7 +243,8 @@ def generate(self, q2): ) operator.compute() intrinsic_range = self.config["intrinsic_range"] - if path[-1].is_backward: + is_downward = is_downward_path(path)[0] + if is_downward: intrinsic_range = [4, 5, 6] final_op = physical.PhysicalOperator.ad_to_evol_map( operator.op_members, @@ -250,14 +253,13 @@ def generate(self, q2): intrinsic_range, ) # and multiply the lower ones from the right - for i, op in reversed(list(enumerate(thr_ops))): - is_backward = path[i].is_backward + for op in reversed(list(thr_ops)): phys_op = physical.PhysicalOperator.ad_to_evol_map( op.op_members, op.nf, op.q2_to, intrinsic_range ) # join with the basis rotation, since matching requires c+ (or likewise) - if is_backward: + if is_downward: matching = matching_conditions.MatchingCondition.split_ad_to_evol_map( self._matching_operators[op.q2_to], op.nf - 1, diff --git a/src/eko/matching_conditions/__init__.py b/src/eko/matching_conditions/__init__.py index 3b7ae3c72..96cf0356e 100644 --- a/src/eko/matching_conditions/__init__.py +++ b/src/eko/matching_conditions/__init__.py @@ -39,8 +39,6 @@ def split_ad_to_evol_map( threshold value intrinsic_range : list list of intrinsic quark pids - is_backward: bool - True for backward evolution """ m = { diff --git a/src/eko/strong_coupling.py b/src/eko/strong_coupling.py index 3e977da7a..a7b228f4d 100644 --- a/src/eko/strong_coupling.py +++ b/src/eko/strong_coupling.py @@ -371,10 +371,7 @@ def a_s( # Set up the path to follow in order to go from q2_0 to q2_ref final_as = self.as_ref path = self.thresholds.path(scale_to, nf_to) - is_downward_path = False - if len(path) > 1: - is_downward_path = path[1].nf < path[0].nf - shift = 3 if not is_downward_path else 4 + is_downward, shift = thresholds.is_downward_path(path) # as a default assume mu_F^2 = mu_R^2 if fact_scale is None: @@ -394,7 +391,7 @@ def a_s( ) m_coeffs = ( compute_matching_coeffs_down(self.hqm_scheme, seg.nf - 1) - if is_downward_path + if is_downward else compute_matching_coeffs_up(self.hqm_scheme, seg.nf) ) fact = 1.0 @@ -402,7 +399,6 @@ def a_s( for n in range(1, self.order + 1): for l in range(n + 1): fact += new_as**n * L**l * m_coeffs[n, l] - # shift new_as *= fact final_as = new_as return final_as diff --git a/src/eko/thresholds.py b/src/eko/thresholds.py index 36936c7a6..b2e03c96a 100644 --- a/src/eko/thresholds.py +++ b/src/eko/thresholds.py @@ -29,7 +29,7 @@ def __init__(self, q2_from, q2_to, nf): self.nf = nf @property - def is_backward(self): + def is_downward_q2(self): """True if q2_from bigger than q2_to""" return self.q2_from > self.q2_to @@ -260,3 +260,29 @@ def nf(self, q2): """ ref_idx = np.digitize(q2, self.area_walls) return 2 + ref_idx + + +def is_downward_path(path): + """ + Determine if a path is downward: + - in the number of active flavors when the path list contains more than one `PathSegment`, + note this can be different from each `PathSegment.is_downward` + - in :math:`Q^2` when just one single `PathSegment` is given + + Parameters + ---------- + path: list(`eko.thresholds.PathSegment`) + + Returns + ------- + is_downward: bool + True is number of flavor is decreasing + shift: 3, 4 + shift to number of light flavors + """ + if len(path) == 1: + is_downward = path[0].is_downward_q2 + else: + is_downward = path[1].nf < path[0].nf + shift = 4 if is_downward else 3 + return is_downward, shift diff --git a/tests/test_thresholds.py b/tests/test_thresholds.py index b5b55ff7a..803591bfc 100644 --- a/tests/test_thresholds.py +++ b/tests/test_thresholds.py @@ -5,7 +5,7 @@ import numpy as np import pytest -from eko.thresholds import PathSegment, ThresholdsAtlas +from eko.thresholds import PathSegment, ThresholdsAtlas, is_downward_path class TestPathSegment: @@ -197,3 +197,23 @@ def test_errors(self): HQ="FAIL", ), ) + + +def test_is_downward_path(): + thr_atlas = ThresholdsAtlas( + masses=np.power([2, 3, 4], 2), + q2_ref=91**2, + nf_ref=3, + thresholds_ratios=[1, 1, 1], + ) + q2_to = 5**2 + path_3 = thr_atlas.path(q2_to, nf_to=3) + # path_3 is downward in q2 + is_downward, shift = is_downward_path(path_3) + assert is_downward is True + assert shift == 4 + # path_6 is downward in q2, but forward in nf + path_6 = thr_atlas.path(q2_to, nf_to=6) + is_downward, shift = is_downward_path(path_6) + assert is_downward is False + assert shift == 3 From 85879ca7779e14f56a211b9f0c12ea5405357b11 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 7 Mar 2022 12:31:20 +0100 Subject: [PATCH 56/74] Update msbar evolution using ThrAtlas, make nf management more clear --- src/eko/msbar_masses.py | 97 +++++++++++++++--------------- src/eko/strong_coupling.py | 6 +- tests/benchmark_msbar_evolution.py | 53 ++++++++++------ tests/test_msbar_masses.py | 8 +-- 4 files changed, 91 insertions(+), 73 deletions(-) diff --git a/src/eko/msbar_masses.py b/src/eko/msbar_masses.py index 6c3813d63..cf2260752 100644 --- a/src/eko/msbar_masses.py +++ b/src/eko/msbar_masses.py @@ -10,6 +10,7 @@ from .beta import b, beta from .gamma import gamma from .strong_coupling import StrongCoupling, invert_matching_coeffs +from .thresholds import ThresholdsAtlas, is_downward_path def ker_exact(a0, a1, order, nf): @@ -163,12 +164,12 @@ def ker_dispatcher(q2_to, q2m_ref, strong_coupling, fact_to_ren, nf): ker: Expanded or exact |MSbar| kernel """ - a0 = strong_coupling.a_s(q2m_ref / fact_to_ren, q2m_ref) - a1 = strong_coupling.a_s(q2_to / fact_to_ren, q2_to) + a0 = strong_coupling.a_s(q2m_ref / fact_to_ren, q2m_ref, nf) + a1 = strong_coupling.a_s(q2_to / fact_to_ren, q2_to, nf) method = strong_coupling.method order = strong_coupling.order if method == "expanded": - return ker_expanded(a0, a1, order, nf) + return ker_expanded(a0, float(a1), order, nf) return ker_exact(a0, a1, order, nf) @@ -267,11 +268,7 @@ def rge(m2, q2m_ref, strong_coupling, fact_to_ren, nf_ref): def evolve( - m2_ref, - q2m_ref, - strong_coupling, - fact_to_ren, - q2_to, + m2_ref, q2m_ref, strong_coupling, fact_to_ren, q2_to, nf_ref=None, nf_to=None ): r""" Perform the |MSbar| mass evolution up to given scale. @@ -288,55 +285,56 @@ def evolve( any q fact_to_ren: float :math:`\mu_F^2/\mu_R^2` - q2_to: float, optional + q2_to: float scale at which the mass is computed + nf_ref: int + number of flavor active at the reference scale + nf_to: int + number of flavor active at the target scale Returns ------- m2 : float :math:`m_{\overline{MS}}(\mu_2)^2` """ - # evolution might involve different number of active flavors. - # Find out the evolution path (always sorted) - q2_low, q2_high = sorted([q2m_ref, q2_to]) - - area_walls = np.array(strong_coupling.thresholds.area_walls) - path = np.concatenate( - ( - [q2_low], - area_walls[(q2_low < area_walls) & (area_walls < q2_high)], - [q2_high], - ) + thr_atlas = ThresholdsAtlas( + np.array(strong_coupling.thresholds.area_walls)[1:-1], + q2m_ref, + nf_ref, + strong_coupling.thresholds.thresholds_ratios, ) - nf_init = len(area_walls[q2_low >= area_walls]) + 2 - nf_final = len(area_walls[q2_high > area_walls]) + 2 + path = thr_atlas.path(q2_to, nf_to) + is_downward, shift = is_downward_path(path) ev_mass = 1.0 - is_downward_path = bool(q2m_ref > q2_to) - for i, nf in enumerate(np.arange(nf_init, nf_final + 1)): - q2_init = path[i] - q2_final = path[i + 1] - # if you are going backward - # need to reverse the evolution in each path segment - if is_downward_path: - m_coeffs = compute_matching_coeffs_down(nf - 1) - q2_init, q2_final = q2_final, q2_init - shift = 4 - else: - m_coeffs = compute_matching_coeffs_up(nf) - shift = 3 - fact = 1.0 - # shift - for pto in range(1, strong_coupling.order + 1): - for l in range(pto + 1): - as_thr = strong_coupling.a_s(q2_final / fact_to_ren, q2_final) - # TODO: do we need to add np.log(fac_to_ren) here ??? - L = np.log(strong_coupling.thresholds.thresholds_ratios[pto - shift]) - fact += as_thr**pto * L**l * m_coeffs[pto, l] - ev_mass *= ( - fact - * ker_dispatcher(q2_final, q2_init, strong_coupling, fact_to_ren, nf) ** 2 - ) + for k, seg in enumerate(path): + # skip a very short segment, but keep the matching + ker_evol = 1.0 + if not np.isclose(seg.q2_from, seg.q2_to): + ker_evol = ( + ker_dispatcher( + seg.q2_to, seg.q2_from, strong_coupling, fact_to_ren, seg.nf + ) + ** 2 + ) + # apply matching condition + if k < len(path) - 1: + # TODO: do we need to add np.log(fac_to_ren) here ??? + L = np.log(thr_atlas.thresholds_ratios[seg.nf - shift]) + m_coeffs = ( + compute_matching_coeffs_down(seg.nf - 1) + if is_downward + else compute_matching_coeffs_up(seg.nf) + ) + matching = 1.0 + for pto in range(1, strong_coupling.order + 1): + for l in range(pto + 1): + as_thr = strong_coupling.a_s( + seg.q2_to / fact_to_ren, seg.q2_to, seg.nf - shift + 4 + ) + matching += as_thr**pto * L**l * m_coeffs[pto, l] + ker_evol *= matching + ev_mass *= ker_evol return m2_ref * ev_mass @@ -421,7 +419,8 @@ def sc(thr_masses): # you need to evolve it until nf_target patch wall is reached: # for backward you reach the higher, for forward the lower. # len(masses[q2m_ref > masses]) + 3 is the nf at the given reference scale - if nf_target != len(masses[q2m_ref > masses]) + 3: + nf_ref = len(masses[q2m_ref > masses]) + 3 + if nf_target != nf_ref: q2_to = masses[q_idx + shift] m2_ref = evolve( m2_ref, @@ -429,6 +428,8 @@ def sc(thr_masses): sc(masses), fact_to_ren, q2_to, + nf_ref=nf_ref, + nf_to=nf_target, ) q2m_ref = q2_to diff --git a/src/eko/strong_coupling.py b/src/eko/strong_coupling.py index a7b228f4d..711579685 100644 --- a/src/eko/strong_coupling.py +++ b/src/eko/strong_coupling.py @@ -151,9 +151,9 @@ class StrongCoupling: scale_ref : float reference scale :math:`\mu_0^2` masses : list(float) - list with quark masses + list with quark masses squared thresholds_ratios : list(float) - list with ratios between the mass and the thresholds + list with ratios between the mass and the thresholds squared order: int Evaluated order of the beta function: ``0`` = LO, ... method : ["expanded", "exact"] @@ -342,7 +342,7 @@ def compute(self, as_ref, nf, scale_from, scale_to): as_new = self.compute_exact(float(as_ref), nf, scale_from, scale_to) else: as_new = as_expanded( - self.order, float(as_ref), nf, scale_from, scale_to + self.order, float(as_ref), nf, scale_from, float(scale_to) ) self.cache[key] = as_new return as_new diff --git a/tests/benchmark_msbar_evolution.py b/tests/benchmark_msbar_evolution.py index 63f16eb63..86dc0979f 100644 --- a/tests/benchmark_msbar_evolution.py +++ b/tests/benchmark_msbar_evolution.py @@ -1,8 +1,11 @@ # -*- coding: utf-8 -*- """This module benchmarks MSbar mass evolution against APFEL.""" +import copy + import numpy as np from eko import msbar_masses +from eko.basis_rotation import quark_names from eko.strong_coupling import StrongCoupling # try to load APFEL - if not available, we'll use the cached values @@ -38,12 +41,19 @@ class BenchmarkMSbar: def benchmark_APFEL_msbar_evolution(self): + theory = copy.deepcopy(theory_dict) Q2s = np.power([1, 96, 150], 2) - alphas_ref = 0.118 - scale_ref = 91.0**2 - thresholds_ratios = np.power((1.0, 1.0, 1.0), 2) - Q2m = np.power([2.0, 4.5, 175], 2) - m2 = np.power((1.4, 4.5, 175), 2) + nfs = [3, 5, 5] + theory.update( + { + "mc": 1.4, + "mb": 4.5, + "mt": 175.0, + "Qmc": 2.0, + "Qmb": 4.5, + "Qmt": 175.0, + } + ) apfel_vals_dict = { "exact": { 0: np.array( @@ -94,27 +104,32 @@ def benchmark_APFEL_msbar_evolution(self): } # collect my values for method in ["exact", "expanded"]: + theory["ModEv"] = "EXP" if method == "expanded" else "EXA" for order in [0, 1, 2]: + theory["PTO"] = order as_VFNS = StrongCoupling( - alphas_ref, - scale_ref, - m2, - thresholds_ratios, + theory["alphas"], + theory["Qref"] ** 2, + msbar_masses.compute(theory), + np.power([theory["kcThr"], theory["kbThr"], theory["ktThr"]], 2), order=order, method=method, - hqm_scheme="MSBAR", + nf_ref=theory["nfref"], + hqm_scheme=theory["HQ"], ) my_vals = [] - for Q2 in Q2s: + for nf_to, Q2 in zip(nfs, Q2s): my_masses = [] for n in [3, 4, 5]: my_masses.append( msbar_masses.evolve( - m2[n - 3], - Q2m[n - 3], + theory[f"m{quark_names[n]}"] ** 2, + theory[f"Qm{quark_names[n]}"] ** 2, strong_coupling=as_VFNS, fact_to_ren=1.0, q2_to=Q2, + nf_ref=n, + nf_to=nf_to, ) ) my_vals.append(my_masses) @@ -126,10 +141,12 @@ def benchmark_APFEL_msbar_evolution(self): apfel.SetTheory("QCD") apfel.SetPerturbativeOrder(order) apfel.SetAlphaEvolution(method) - apfel.SetAlphaQCDRef(alphas_ref, np.sqrt(scale_ref)) + apfel.SetAlphaQCDRef(theory["alphas"], theory["Qref"]) apfel.SetVFNS() - apfel.SetMSbarMasses(*np.sqrt(m2)) - apfel.SetMassScaleReference(*np.sqrt(Q2m)) + apfel.SetMSbarMasses(theory["mc"], theory["mb"], theory["mt"]) + apfel.SetMassScaleReference( + theory["Qmc"], theory["Qmb"], theory["Qmt"] + ) apfel.SetRenFacRatio(1.0) apfel.InitializeAPFEL() # collect apfel masses @@ -145,7 +162,7 @@ def benchmark_APFEL_msbar_evolution(self): ) # check myself to APFEL np.testing.assert_allclose( - apfel_vals, np.sqrt(np.array(my_vals)), rtol=2e-3 + apfel_vals, np.sqrt(np.array(my_vals)), rtol=2.3e-3 ) def benchmark_APFEL_msbar_solution(self): @@ -185,7 +202,7 @@ def benchmark_APFEL_msbar_solution(self): apfel.EnableWelcomeMessage(1) # check myself to APFEL np.testing.assert_allclose( - apfel_vals, np.sqrt(np.array(my_masses)), rtol=5e-5 + apfel_vals, np.sqrt(np.array(my_masses)), rtol=4e-4 ) def benchmark_msbar_solution_kthr(self): diff --git a/tests/test_msbar_masses.py b/tests/test_msbar_masses.py index ec77fe302..beed1d40e 100644 --- a/tests/test_msbar_masses.py +++ b/tests/test_msbar_masses.py @@ -38,10 +38,10 @@ def test_compute_msbar_mass(self): for method in ["EXA", "EXP"]: for order in [1, 2, 3]: theory_dict.update({"ModEv": method, "PTO": order}) - strong_coupling = StrongCoupling.from_dict(theory_dict) # compute the scale such msbar(m) = m m2_computed = msbar_masses.compute(theory_dict) + strong_coupling = StrongCoupling.from_dict(theory_dict, m2_computed) m2_test = [] for nf in [3, 4, 5]: # compute msbar( m ) @@ -56,7 +56,7 @@ def test_compute_msbar_mass(self): q2_to=m2_computed[nf - 3], ) ) - np.testing.assert_allclose(m2_computed, m2_test, rtol=4e-3) + np.testing.assert_allclose(m2_computed, m2_test, rtol=6e-4) def test_compute_msbar_mass_VFNS(self): # test the solution now with some initial contition @@ -71,9 +71,9 @@ def test_compute_msbar_mass_VFNS(self): "Qmb": 85.0, } ) - strong_coupling = StrongCoupling.from_dict(theory_dict) # compute the scale such msbar(m) = m m2_computed = msbar_masses.compute(theory_dict) + strong_coupling = StrongCoupling.from_dict(theory_dict, m2_computed) m2_test = [] for nf in [3, 4, 5]: # compute msbar( m ) @@ -88,7 +88,7 @@ def test_compute_msbar_mass_VFNS(self): q2_to=m2_computed[nf - 3], ) ) - np.testing.assert_allclose(m2_computed, m2_test, rtol=3e-3) + np.testing.assert_allclose(m2_computed, m2_test, rtol=6e-4) def test_errors(self): From 9ba36826712da6d812ed9979281adb13431f6f85 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 7 Mar 2022 13:38:18 +0100 Subject: [PATCH 57/74] Add an explit exmple of how path determination works --- doc/source/code/Utilities.rst | 34 ++++++++++++++++++++++++++++++++++ doc/source/theory/pQCD.rst | 5 +++++ 2 files changed, 39 insertions(+) diff --git a/doc/source/code/Utilities.rst b/doc/source/code/Utilities.rst index d19a9262f..20be69c4a 100644 --- a/doc/source/code/Utilities.rst +++ b/doc/source/code/Utilities.rst @@ -8,6 +8,40 @@ Apart from the :doc:`operator ` classes, `eko` also provides some uti - Implementation of the flavor number scheme and the quark thresholds both for the :class:`eko.strong_coupling.StrongCoupling` and the :doc:`operators <../theory/Matching>` + When running in |VFNS| it is important to specify the number of flavors active at each given scale, since evolution path + can be different depending of the chosen setting. This path is determined by :meth:`eko.thresholds.ThresholdsAtlas.path`. + + Let us consider an example to better illustrate how it works. + Imagine to have a boundary condition ``q2_ref=64, nf_ref=3`` and would like to evolve your object (|PDF| or :math:`a_s`) to a lower + scale (say ``Q=7``) but giving different number of active flavors to the final state and having set the heavy quarks mass thresholds + at: ``mc=2, mb=3, mt=4``. In this case some possible paths are: + + - a path to ``Q=7`` with ``nf=6`` (default) which is given by the following list of :class:`eko.thresholds.PathSegment` : + + .. code-block:: + + [PathSegment(64 -> 4, nf=3), PathSegment(4 -> 9, nf=4), PathSegment(9 -> 16, nf=5), PathSegment(16 -> 49, nf=6)] + + and it's determined according to the list of heavy quark thresholds. + + - A path to ``Q=7`` enforcing ``nf=3`` which will simply contain a single :class:`eko.thresholds.PathSegment`: + + .. code-block:: + + [PathSegment(64 -> 49, nf=3)] + + - A path to ``Q=7`` enforcing ``nf=4``: + + .. code-block:: + + [PathSegment(64 -> 4, nf=3), PathSegment(4 -> 49, nf=4)] + + As first step, you always go back to the closest matching scale (closest in ``nf``), + running in ``nf=3``, since that is what has been specified in the boundary conditions. + Then you are back in the normal flow, and you cross all the other thresholds going according to the prescription given + by the :class:``eko.thresholds.ThresholdAtlas``. + You can noticed that :meth:`eko.thresholds.ThresholdsAtlas.path` are always ordered according to `nf` and not `Q2` scales. + This property is used in |VFNS| to determine if a path is backward or not modifying the way the different patches are matched. .. include:: IO-tabs/ThresholdConfig.rst diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index 42f2ba19b..ae6349e64 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -46,6 +46,11 @@ have to be applied :cite:`Schroder:2005hy,Chetyrkin:2005ia`. In particular, the matching involved in the change from :math:`n_f` to :math:`n_f-1` schemes is presented in equation 3.1 of :cite:`Schroder:2005hy` for |MSbar| masses, while the same expression for POLE masses is reported in Appendix A. +For this reason the boundary conditions of :class:`eko.strong_coupling.StrongCoupling` +can be specified at `scale_ref` along with ``nf_ref`` and, the computed result can +depend on the number of flavors at the target scale, see :meth:`StrongCoupling.a_s` +An example how the evolution path is determined is given :doc:`here`. + QCD Splitting Functions ----------------------- From 10c480a3f81cf90b03612506ae4aff218fff1db5 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Mon, 7 Mar 2022 16:00:49 +0100 Subject: [PATCH 58/74] Some fixes in utilities docs --- .../code/IO-tabs/InterpolatorDispatcher.rst | 9 ++++--- doc/source/code/IO-tabs/ThresholdConfig.rst | 12 ++++++--- doc/source/code/Utilities.rst | 25 +++++++++++++------ doc/source/theory/pQCD.rst | 2 +- src/eko/evolution_operator/grid.py | 4 +-- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/doc/source/code/IO-tabs/InterpolatorDispatcher.rst b/doc/source/code/IO-tabs/InterpolatorDispatcher.rst index f8c128cc7..2d98736d1 100644 --- a/doc/source/code/IO-tabs/InterpolatorDispatcher.rst +++ b/doc/source/code/IO-tabs/InterpolatorDispatcher.rst @@ -1,5 +1,6 @@ -InterpolatorDispatcher parameter: +InterpolatorDispatcher parameters: -- :py:obj:`list(float)` ``interpolation_xgrid`` the interpolation grid; **Required** -- :py:obj:`int` ``interpolation_polynomial_degree`` polynomial degree of the interpolating function; **Required** -- :py:obj:`bool` ``interpolation_is_log`` use logarithmic interpolation? **Required** +- :obj:`list(float)` ``interpolation_xgrid`` the interpolation grid; **Required** +- :obj:`int` ``interpolation_polynomial_degree`` polynomial degree of the interpolating function; **Required** +- :obj:`bool` ``log`` use logarithmic interpolation? +- :obj:`bool` ``mode_N`` if true compiles the function on N, otherwise compiles x diff --git a/doc/source/code/IO-tabs/ThresholdConfig.rst b/doc/source/code/IO-tabs/ThresholdConfig.rst index cc1f4393c..3d14c2688 100644 --- a/doc/source/code/IO-tabs/ThresholdConfig.rst +++ b/doc/source/code/IO-tabs/ThresholdConfig.rst @@ -1,6 +1,10 @@ ThresholdConfig parameters: -- :py:obj:`float` ``Q0`` reference scale from which to start; **Required** -- :py:obj:`float` ``mc`` charm mass in GeV; **Required** -- :py:obj:`float` ``mb`` bottom mass in GeV; **Required** -- :py:obj:`float` ``mt`` top mass in GeV; **Required** +- :obj:`list(float)`: **Required** + - :obj:`float` ``mc`` charm mass squared in GeV; + - :obj:`float` ``mb`` bottom mass squared in GeV; + - :obj:`float` ``mt`` top mass squared in GeV; +- :obj:`float` ``q2_ref`` reference scale squared in GeV; +- :obj:`int` ``nf_ref`` number of active flavors at the reference scale +- :obj`list(float)`: list of ratios between masses and matching thresholds squared +- :obj:`int` ``max_nf`` maximum number of active flavors diff --git a/doc/source/code/Utilities.rst b/doc/source/code/Utilities.rst index 20be69c4a..367db3083 100644 --- a/doc/source/code/Utilities.rst +++ b/doc/source/code/Utilities.rst @@ -8,21 +8,30 @@ Apart from the :doc:`operator ` classes, `eko` also provides some uti - Implementation of the flavor number scheme and the quark thresholds both for the :class:`eko.strong_coupling.StrongCoupling` and the :doc:`operators <../theory/Matching>` - When running in |VFNS| it is important to specify the number of flavors active at each given scale, since evolution path + .. include:: IO-tabs/ThresholdConfig.rst + + When running in |VFNS| it is important to specify the number of flavors active at each given scale, since the evolution path can be different depending of the chosen setting. This path is determined by :meth:`eko.thresholds.ThresholdsAtlas.path`. Let us consider an example to better illustrate how it works. Imagine to have a boundary condition ``q2_ref=64, nf_ref=3`` and would like to evolve your object (|PDF| or :math:`a_s`) to a lower scale (say ``Q=7``) but giving different number of active flavors to the final state and having set the heavy quarks mass thresholds - at: ``mc=2, mb=3, mt=4``. In this case some possible paths are: + at: ``mc=2, mb=3, mt=4``. + + .. code-block:: + + ThresholdsAtlas [0.00e+00 - 4.00e+00 - 9.00e+00 - 16.00e+00 - inf], ref=49.000000000000001 @ 3 - - a path to ``Q=7`` with ``nf=6`` (default) which is given by the following list of :class:`eko.thresholds.PathSegment` : + In this case some possible paths are: + + - a path to ``Q=7`` with ``nf=6`` which is given by the following list of :class:`eko.thresholds.PathSegment` : .. code-block:: [PathSegment(64 -> 4, nf=3), PathSegment(4 -> 9, nf=4), PathSegment(9 -> 16, nf=5), PathSegment(16 -> 49, nf=6)] - and it's determined according to the list of heavy quark thresholds. + and it's determined according to the list of heavy quark thresholds. This path is default option when the argument + ``nf_to`` is not given. - A path to ``Q=7`` enforcing ``nf=3`` which will simply contain a single :class:`eko.thresholds.PathSegment`: @@ -43,9 +52,11 @@ Apart from the :doc:`operator ` classes, `eko` also provides some uti You can noticed that :meth:`eko.thresholds.ThresholdsAtlas.path` are always ordered according to `nf` and not `Q2` scales. This property is used in |VFNS| to determine if a path is backward or not modifying the way the different patches are matched. -.. include:: IO-tabs/ThresholdConfig.rst +- :class:`eko.strong_coupling.StrongCoupling`: Implementation of the :ref:`theory/pQCD:strong coupling` + + .. include:: IO-tabs/StrongCoupling.rst -- :class:`eko.strong_coupling.StrongCoupling` Implementation of the :ref:`theory/pQCD:strong coupling` +- :class:`eko.interpolation.InterpolatorDispatcher`: Implementation of the :doc:`../theory/Interpolation` -- :class:`eko.interpolation.InterpolatorDispatcher` Implementation of the :doc:`../theory/Interpolation` + .. include:: IO-tabs/InterpolatorDispatcher.rst diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index ae6349e64..417839c22 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -48,7 +48,7 @@ is presented in equation 3.1 of :cite:`Schroder:2005hy` for |MSbar| masses, whil same expression for POLE masses is reported in Appendix A. For this reason the boundary conditions of :class:`eko.strong_coupling.StrongCoupling` can be specified at `scale_ref` along with ``nf_ref`` and, the computed result can -depend on the number of flavors at the target scale, see :meth:`StrongCoupling.a_s` +depend on the number of flavors at the target scale, see :meth:`eko.strong_coupling.StrongCoupling.a_s` An example how the evolution path is determined is given :doc:`here`. diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py index 8fb6c37e9..750edb8de 100644 --- a/src/eko/evolution_operator/grid.py +++ b/src/eko/evolution_operator/grid.py @@ -243,7 +243,7 @@ def generate(self, q2): ) operator.compute() intrinsic_range = self.config["intrinsic_range"] - is_downward = is_downward_path(path)[0] + is_downward, _ = is_downward_path(path) if is_downward: intrinsic_range = [4, 5, 6] final_op = physical.PhysicalOperator.ad_to_evol_map( @@ -288,7 +288,7 @@ def generate(self, q2): "operators": values, "operator_errors": errors, "alphas": self.managers["strong_coupling"].a_s( - q2 / fact_to_ren, fact_scale=q2 + q2 / fact_to_ren, fact_scale=q2, nf_to=path[-1].nf ) * 4.0 * np.pi, From 50d212a865679703c88b8513b53b5f87bd015f49 Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Tue, 8 Mar 2022 10:28:39 +0100 Subject: [PATCH 59/74] Poetry update --- poetry.lock | 2204 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2204 insertions(+) create mode 100644 poetry.lock diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 000000000..4594bf08a --- /dev/null +++ b/poetry.lock @@ -0,0 +1,2204 @@ +[[package]] +name = "a3b2bbc3ced97675ac3a71df45f55ba" +version = "6.4.0" +description = "The LHAPDF parton density evaluation library" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "alabaster" +version = "0.7.12" +description = "A configurable sidebar-enabled Sphinx theme" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "appdirs" +version = "1.4.4" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "appnope" +version = "0.1.2" +description = "Disable App Nap on macOS >= 10.9" +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "astroid" +version = "2.9.3" +description = "An abstract syntax tree for Python with inference support." +category = "dev" +optional = false +python-versions = ">=3.6.2" + +[package.dependencies] +lazy-object-proxy = ">=1.4.0" +typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} +wrapt = ">=1.11,<1.14" + +[[package]] +name = "asttokens" +version = "2.0.5" +description = "Annotate AST trees with source code positions" +category = "main" +optional = true +python-versions = "*" + +[package.dependencies] +six = "*" + +[package.extras] +test = ["astroid", "pytest"] + +[[package]] +name = "atomicwrites" +version = "1.4.0" +description = "Atomic file writes." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "attrs" +version = "21.4.0" +description = "Classes Without Boilerplate" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.extras] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] +docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] + +[[package]] +name = "babel" +version = "2.9.1" +description = "Internationalization utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +pytz = ">=2015.7" + +[[package]] +name = "backcall" +version = "0.2.0" +description = "Specifications for callback functions passed in to an API" +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "banana-hep" +version = "0.6.3" +description = "Benchmark QCD physics" +category = "main" +optional = true +python-versions = ">=3.8.0,<3.11" + +[package.dependencies] +appdirs = ">=1.4.4,<2.0.0" +click = ">=8.0.3,<9.0.0" +eko = ">=0.8.2,<0.9.0" +ipython = ">=8.1.0,<9.0.0" +matplotlib = ">=3.5.1,<4.0.0" +numpy = ">=1.21.0,<2.0.0" +pandas = ">=1.3.5,<2.0.0" +pendulum = ">=2.1.2,<3.0.0" +PyYAML = ">=6.0,<7.0" +rich = ">=10.16.1,<11.0.0" +SQLAlchemy = ">=1.4.29,<2.0.0" + +[package.extras] +docs = ["Sphinx (>=4.3.2,<5.0.0)", "sphinx-rtd-theme (>=1.0.0,<2.0.0)", "sphinxcontrib-bibtex (>=2.4.1,<3.0.0)"] + +[[package]] +name = "certifi" +version = "2021.10.8" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "cfgv" +version = "3.3.1" +description = "Validate configuration and produce human readable error messages." +category = "dev" +optional = false +python-versions = ">=3.6.1" + +[[package]] +name = "charset-normalizer" +version = "2.0.12" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.5.0" + +[package.extras] +unicode_backport = ["unicodedata2"] + +[[package]] +name = "click" +version = "8.0.4" +description = "Composable command line interface toolkit" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.4" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "commonmark" +version = "0.9.1" +description = "Python parser for the CommonMark Markdown spec" +category = "main" +optional = true +python-versions = "*" + +[package.extras] +test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] + +[[package]] +name = "coverage" +version = "6.3.2" +description = "Code coverage measurement for Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "cycler" +version = "0.11.0" +description = "Composable style cycles" +category = "main" +optional = true +python-versions = ">=3.6" + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +category = "main" +optional = true +python-versions = ">=3.5" + +[[package]] +name = "distlib" +version = "0.3.4" +description = "Distribution utilities" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "docutils" +version = "0.17.1" +description = "Docutils -- Python Documentation Utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "executing" +version = "0.8.3" +description = "Get the currently executing AST node of a frame, and other information" +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "fancycompleter" +version = "0.9.1" +description = "colorful TAB completion for Python prompt" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +pyreadline = {version = "*", markers = "platform_system == \"Windows\""} +pyrepl = ">=0.8.2" + +[[package]] +name = "filelock" +version = "3.6.0" +description = "A platform independent file lock." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] +testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"] + +[[package]] +name = "fonttools" +version = "4.29.1" +description = "Tools to manipulate font files" +category = "main" +optional = true +python-versions = ">=3.7" + +[package.extras] +all = ["fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "zopfli (>=0.1.4)", "lz4 (>=1.7.4.2)", "matplotlib", "sympy", "skia-pathops (>=0.5.0)", "brotlicffi (>=0.8.0)", "scipy", "brotli (>=1.0.1)", "munkres", "unicodedata2 (>=14.0.0)", "xattr"] +graphite = ["lz4 (>=1.7.4.2)"] +interpolatable = ["scipy", "munkres"] +lxml = ["lxml (>=4.0,<5)"] +pathops = ["skia-pathops (>=0.5.0)"] +plot = ["matplotlib"] +symfont = ["sympy"] +type1 = ["xattr"] +ufo = ["fs (>=2.2.0,<3)"] +unicode = ["unicodedata2 (>=14.0.0)"] +woff = ["zopfli (>=0.1.4)", "brotlicffi (>=0.8.0)", "brotli (>=1.0.1)"] + +[[package]] +name = "greenlet" +version = "1.1.2" +description = "Lightweight in-process concurrent programming" +category = "main" +optional = true +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" + +[package.extras] +docs = ["sphinx"] + +[[package]] +name = "identify" +version = "2.4.11" +description = "File identification library for Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "idna" +version = "3.3" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "imagesize" +version = "1.3.0" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "importlib-metadata" +version = "4.11.2" +description = "Read metadata from Python packages" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] +perf = ["ipython"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] + +[[package]] +name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "ipython" +version = "8.1.1" +description = "IPython: Productive Interactive Computing" +category = "main" +optional = true +python-versions = ">=3.8" + +[package.dependencies] +appnope = {version = "*", markers = "sys_platform == \"darwin\""} +backcall = "*" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +decorator = "*" +jedi = ">=0.16" +matplotlib-inline = "*" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} +pickleshare = "*" +prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" +pygments = ">=2.4.0" +stack-data = "*" +traitlets = ">=5" + +[package.extras] +all = ["black", "Sphinx (>=1.3)", "ipykernel", "nbconvert", "nbformat", "ipywidgets", "notebook", "ipyparallel", "qtconsole", "curio", "matplotlib (!=3.2.0)", "numpy (>=1.19)", "pandas", "pytest", "testpath", "trio", "pytest-asyncio"] +black = ["black"] +doc = ["Sphinx (>=1.3)"] +kernel = ["ipykernel"] +nbconvert = ["nbconvert"] +nbformat = ["nbformat"] +notebook = ["ipywidgets", "notebook"] +parallel = ["ipyparallel"] +qtconsole = ["qtconsole"] +test = ["pytest", "pytest-asyncio", "testpath"] +test_extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pandas", "pytest", "testpath", "trio"] + +[[package]] +name = "isort" +version = "5.10.1" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.6.1,<4.0" + +[package.extras] +pipfile_deprecated_finder = ["pipreqs", "requirementslib"] +requirements_deprecated_finder = ["pipreqs", "pip-api"] +colors = ["colorama (>=0.4.3,<0.5.0)"] +plugins = ["setuptools"] + +[[package]] +name = "jedi" +version = "0.18.1" +description = "An autocompletion tool for Python that can be used for text editors." +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +parso = ">=0.8.0,<0.9.0" + +[package.extras] +qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] +testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"] + +[[package]] +name = "jinja2" +version = "3.0.3" +description = "A very fast and expressive template engine." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "kiwisolver" +version = "1.3.2" +description = "A fast implementation of the Cassowary constraint solver" +category = "main" +optional = true +python-versions = ">=3.7" + +[[package]] +name = "latexcodec" +version = "2.0.1" +description = "A lexer and codec to work with LaTeX code in Python." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +six = ">=1.4.1" + +[[package]] +name = "lazy-object-proxy" +version = "1.7.1" +description = "A fast and thorough lazy object proxy." +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "llvmlite" +version = "0.38.0" +description = "lightweight wrapper around basic LLVM functionality" +category = "main" +optional = false +python-versions = ">=3.7,<3.11" + +[[package]] +name = "lz4" +version = "3.1.10" +description = "LZ4 Bindings for Python" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.extras] +docs = ["sphinx (>=1.6.0)", "sphinx-bootstrap-theme"] +flake8 = ["flake8"] +tests = ["pytest (!=3.3.0)", "psutil", "pytest-cov"] + +[[package]] +name = "markupsafe" +version = "2.1.0" +description = "Safely add untrusted strings to HTML/XML markup." +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "matplotlib" +version = "3.5.1" +description = "Python plotting package" +category = "main" +optional = true +python-versions = ">=3.7" + +[package.dependencies] +cycler = ">=0.10" +fonttools = ">=4.22.0" +kiwisolver = ">=1.0.1" +numpy = ">=1.17" +packaging = ">=20.0" +pillow = ">=6.2.0" +pyparsing = ">=2.2.1" +python-dateutil = ">=2.7" +setuptools_scm = ">=4" + +[[package]] +name = "matplotlib-inline" +version = "0.1.3" +description = "Inline Matplotlib backend for Jupyter" +category = "main" +optional = true +python-versions = ">=3.5" + +[package.dependencies] +traitlets = "*" + +[[package]] +name = "mccabe" +version = "0.6.1" +description = "McCabe checker, plugin for flake8" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "nodeenv" +version = "1.6.0" +description = "Node.js virtual environment builder" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "numba" +version = "0.55.1" +description = "compiling Python code using LLVM" +category = "main" +optional = false +python-versions = ">=3.7,<3.11" + +[package.dependencies] +llvmlite = ">=0.38.0rc1,<0.39" +numpy = ">=1.18,<1.22" + +[[package]] +name = "numpy" +version = "1.21.5" +description = "NumPy is the fundamental package for array computing with Python." +category = "main" +optional = false +python-versions = ">=3.7,<3.11" + +[[package]] +name = "packaging" +version = "21.3" +description = "Core utilities for Python packages" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" + +[[package]] +name = "pandas" +version = "1.4.1" +description = "Powerful data structures for data analysis, time series, and statistics" +category = "main" +optional = true +python-versions = ">=3.8" + +[package.dependencies] +numpy = [ + {version = ">=1.18.5", markers = "platform_machine != \"aarch64\" and platform_machine != \"arm64\" and python_version < \"3.10\""}, + {version = ">=1.19.2", markers = "platform_machine == \"aarch64\" and python_version < \"3.10\""}, + {version = ">=1.20.0", markers = "platform_machine == \"arm64\" and python_version < \"3.10\""}, + {version = ">=1.21.0", markers = "python_version >= \"3.10\""}, +] +python-dateutil = ">=2.8.1" +pytz = ">=2020.1" + +[package.extras] +test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] + +[[package]] +name = "parso" +version = "0.8.3" +description = "A Python Parser" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.extras] +qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] +testing = ["docopt", "pytest (<6.0.0)"] + +[[package]] +name = "pdbpp" +version = "0.10.3" +description = "pdb++, a drop-in replacement for pdb" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +fancycompleter = ">=0.8" +pygments = "*" +wmctrl = "*" + +[package.extras] +funcsigs = ["funcsigs"] +testing = ["funcsigs", "pytest"] + +[[package]] +name = "pendulum" +version = "2.1.2" +description = "Python datetimes made easy" +category = "main" +optional = true +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.dependencies] +python-dateutil = ">=2.6,<3.0" +pytzdata = ">=2020.1" + +[[package]] +name = "pexpect" +version = "4.8.0" +description = "Pexpect allows easy control of interactive console applications." +category = "main" +optional = true +python-versions = "*" + +[package.dependencies] +ptyprocess = ">=0.5" + +[[package]] +name = "pickleshare" +version = "0.7.5" +description = "Tiny 'shelve'-like database with concurrency support" +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "pillow" +version = "9.0.1" +description = "Python Imaging Library (Fork)" +category = "main" +optional = true +python-versions = ">=3.7" + +[[package]] +name = "platformdirs" +version = "2.5.1" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] +test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] + +[[package]] +name = "pluggy" +version = "1.0.0" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pre-commit" +version = "2.17.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +category = "dev" +optional = false +python-versions = ">=3.6.1" + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +toml = "*" +virtualenv = ">=20.0.8" + +[[package]] +name = "prompt-toolkit" +version = "3.0.28" +description = "Library for building powerful interactive command lines in Python" +category = "main" +optional = true +python-versions = ">=3.6.2" + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "ptyprocess" +version = "0.7.0" +description = "Run a subprocess in a pseudo terminal" +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "pure-eval" +version = "0.2.2" +description = "Safely evaluate AST nodes without side effects" +category = "main" +optional = true +python-versions = "*" + +[package.extras] +tests = ["pytest"] + +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "pybtex" +version = "0.24.0" +description = "A BibTeX-compatible bibliography processor in Python" +category = "main" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*" + +[package.dependencies] +latexcodec = ">=1.0.4" +PyYAML = ">=3.01" +six = "*" + +[package.extras] +test = ["pytest"] + +[[package]] +name = "pybtex-docutils" +version = "1.0.1" +description = "A docutils backend for pybtex." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +docutils = ">=0.8" +pybtex = ">=0.16" + +[[package]] +name = "pygments" +version = "2.11.2" +description = "Pygments is a syntax highlighting package written in Python." +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "pylint" +version = "2.12.2" +description = "python code static checker" +category = "dev" +optional = false +python-versions = ">=3.6.2" + +[package.dependencies] +astroid = ">=2.9.0,<2.10" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +isort = ">=4.2.5,<6" +mccabe = ">=0.6,<0.7" +platformdirs = ">=2.2.0" +toml = ">=0.9.2" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[[package]] +name = "pyparsing" +version = "3.0.7" +description = "Python parsing module" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "pyreadline" +version = "2.1" +description = "A python implmementation of GNU readline." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "pyrepl" +version = "0.9.0" +description = "A library for building flexible command line interfaces" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "pytest" +version = "6.2.5" +description = "pytest: simple powerful testing with Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +py = ">=1.8.2" +toml = "*" + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "3.0.0" +description = "Pytest plugin for measuring coverage." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] + +[[package]] +name = "pytest-env" +version = "0.6.2" +description = "py.test plugin that allows you to add environment variables." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +pytest = ">=2.6.0" + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +category = "main" +optional = true +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytz" +version = "2021.3" +description = "World timezone definitions, modern and historical" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "pytzdata" +version = "2020.1" +description = "The Olson timezone database for Python." +category = "main" +optional = true +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "requests" +version = "2.27.1" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} +idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] + +[[package]] +name = "rich" +version = "10.16.2" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "main" +optional = true +python-versions = ">=3.6.2,<4.0.0" + +[package.dependencies] +colorama = ">=0.4.0,<0.5.0" +commonmark = ">=0.9.0,<0.10.0" +pygments = ">=2.6.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] + +[[package]] +name = "scipy" +version = "1.8.0" +description = "SciPy: Scientific Library for Python" +category = "main" +optional = false +python-versions = ">=3.8,<3.11" + +[package.dependencies] +numpy = ">=1.17.3,<1.25.0" + +[[package]] +name = "setuptools-scm" +version = "6.4.2" +description = "the blessed package to manage your versions by scm tags" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +packaging = ">=20.0" +tomli = ">=1.0.0" + +[package.extras] +test = ["pytest (>=6.2)", "virtualenv (>20)"] +toml = ["setuptools (>=42)"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "sphinx" +version = "4.4.0" +description = "Python documentation generator" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=1.3" +colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.14,<0.18" +imagesize = "*" +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} +Jinja2 = ">=2.3" +packaging = "*" +Pygments = ">=2.0" +requests = ">=2.5.0" +snowballstemmer = ">=1.1" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.5" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.931)", "docutils-stubs", "types-typed-ast", "types-requests"] +test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"] + +[[package]] +name = "sphinx-rtd-theme" +version = "1.0.0" +description = "Read the Docs theme for Sphinx" +category = "main" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" + +[package.dependencies] +docutils = "<0.18" +sphinx = ">=1.6" + +[package.extras] +dev = ["transifex-client", "sphinxcontrib-httpdomain", "bump2version"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.2" +description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-bibtex" +version = "2.4.1" +description = "Sphinx extension for BibTeX style citations." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +docutils = ">=0.8" +pybtex = ">=0.20" +pybtex-docutils = ">=1.0.0" +Sphinx = ">=2.1" + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.2" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +category = "main" +optional = false +python-versions = ">=3.5" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.0" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest", "html5lib"] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.extras] +test = ["pytest", "flake8", "mypy"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.3" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +category = "main" +optional = false +python-versions = ">=3.5" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.5" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +category = "main" +optional = false +python-versions = ">=3.5" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +name = "sqlalchemy" +version = "1.4.32" +description = "Database Abstraction Library" +category = "main" +optional = true +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" + +[package.dependencies] +greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} + +[package.extras] +aiomysql = ["greenlet (!=0.4.17)", "aiomysql"] +aiosqlite = ["typing_extensions (!=3.10.0.1)", "greenlet (!=0.4.17)", "aiosqlite"] +asyncio = ["greenlet (!=0.4.17)"] +asyncmy = ["greenlet (!=0.4.17)", "asyncmy (>=0.2.3)"] +mariadb_connector = ["mariadb (>=1.0.1)"] +mssql = ["pyodbc"] +mssql_pymssql = ["pymssql"] +mssql_pyodbc = ["pyodbc"] +mypy = ["sqlalchemy2-stubs", "mypy (>=0.910)"] +mysql = ["mysqlclient (>=1.4.0,<2)", "mysqlclient (>=1.4.0)"] +mysql_connector = ["mysql-connector-python"] +oracle = ["cx_oracle (>=7,<8)", "cx_oracle (>=7)"] +postgresql = ["psycopg2 (>=2.7)"] +postgresql_asyncpg = ["greenlet (!=0.4.17)", "asyncpg"] +postgresql_pg8000 = ["pg8000 (>=1.16.6)"] +postgresql_psycopg2binary = ["psycopg2-binary"] +postgresql_psycopg2cffi = ["psycopg2cffi"] +pymysql = ["pymysql (<1)", "pymysql"] +sqlcipher = ["sqlcipher3-binary"] + +[[package]] +name = "stack-data" +version = "0.2.0" +description = "Extract data from python stack frames and tracebacks for informative displays" +category = "main" +optional = true +python-versions = "*" + +[package.dependencies] +asttokens = "*" +executing = "*" +pure-eval = "*" + +[package.extras] +tests = ["pytest", "typeguard", "pygments", "littleutils", "cython"] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "dev" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "traitlets" +version = "5.1.1" +description = "Traitlets Python configuration system" +category = "main" +optional = true +python-versions = ">=3.7" + +[package.extras] +test = ["pytest"] + +[[package]] +name = "typing-extensions" +version = "4.1.1" +description = "Backported and Experimental Type Hints for Python 3.6+" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "urllib3" +version = "1.26.8" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" + +[package.extras] +brotli = ["brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "virtualenv" +version = "20.13.3" +description = "Virtual Python Environment builder" +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[package.dependencies] +distlib = ">=0.3.1,<1" +filelock = ">=3.2,<4" +platformdirs = ">=2,<3" +six = ">=1.9.0,<2" + +[package.extras] +docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] +testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] + +[[package]] +name = "wcwidth" +version = "0.2.5" +description = "Measures the displayed width of unicode strings in a terminal" +category = "main" +optional = true +python-versions = "*" + +[[package]] +name = "wmctrl" +version = "0.4" +description = "A tool to programmatically control windows inside X" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "wrapt" +version = "1.13.3" +description = "Module for decorators, wrappers and monkey patching." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[[package]] +name = "zipp" +version = "3.7.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] + +[extras] +box = ["banana-hep", "sqlalchemy", "pandas", "matplotlib"] +docs = ["Sphinx", "sphinx-rtd-theme", "sphinxcontrib-bibtex"] +mark = ["banana-hep", "sqlalchemy", "pandas", "matplotlib"] + +[metadata] +lock-version = "1.1" +python-versions = "^3.8,<3.11" +content-hash = "1b6fb7851a767927d7a6b3aceafd6fcc9a7ee27752e5c402629b173fac56fea9" + +[metadata.files] +a3b2bbc3ced97675ac3a71df45f55ba = [ + {file = "a3b2bbc3ced97675ac3a71df45f55ba-6.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d47714ce84c5cd94cc5512d5683b39c5cd681e13ad086961770b4eb093e11154"}, + {file = "a3b2bbc3ced97675ac3a71df45f55ba-6.4.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ee7ba0247c67a8357685e5ad415df8b2322baf7eadd53120819a6c8d35484fe"}, + {file = "a3b2bbc3ced97675ac3a71df45f55ba-6.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a01f7629db6684f9b231e60f98426b70fc66d45efa6a80ba26c6cacec5a95a7b"}, + {file = "a3b2bbc3ced97675ac3a71df45f55ba-6.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0eaca66dafb9ab775e6aa2bd3e94e11f70b1bd28fa636fb047b917653b77ad4"}, + {file = "a3b2bbc3ced97675ac3a71df45f55ba-6.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b3aab2121fa218ab30fa7ce72452646f74c183c00639d8d865a4abec57e92f2"}, + {file = "a3b2bbc3ced97675ac3a71df45f55ba-6.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0147a1d9dab10f8b23ef5fc97f570ce044e9f8409bfee2fbce551180fafcbb2e"}, + {file = "a3b2bbc3ced97675ac3a71df45f55ba-6.4.0.tar.gz", hash = "sha256:1bd60035f9862db1130be035f631c2cfcf90d2ee0cfc6f33ce29fbf8a70b5a04"}, +] +alabaster = [ + {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, + {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, +] +appdirs = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] +appnope = [ + {file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"}, + {file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"}, +] +astroid = [ + {file = "astroid-2.9.3-py3-none-any.whl", hash = "sha256:506daabe5edffb7e696ad82483ad0228245a9742ed7d2d8c9cdb31537decf9f6"}, + {file = "astroid-2.9.3.tar.gz", hash = "sha256:1efdf4e867d4d8ba4a9f6cf9ce07cd182c4c41de77f23814feb27ca93ca9d877"}, +] +asttokens = [ + {file = "asttokens-2.0.5-py2.py3-none-any.whl", hash = "sha256:0844691e88552595a6f4a4281a9f7f79b8dd45ca4ccea82e5e05b4bbdb76705c"}, + {file = "asttokens-2.0.5.tar.gz", hash = "sha256:9a54c114f02c7a9480d56550932546a3f1fe71d8a02f1bc7ccd0ee3ee35cf4d5"}, +] +atomicwrites = [ + {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, + {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, +] +attrs = [ + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, +] +babel = [ + {file = "Babel-2.9.1-py2.py3-none-any.whl", hash = "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9"}, + {file = "Babel-2.9.1.tar.gz", hash = "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"}, +] +backcall = [ + {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, + {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, +] +banana-hep = [ + {file = "banana-hep-0.6.3.tar.gz", hash = "sha256:296e5e7fa79c2271348258b6f2165cc34067b2a9c60e2c97aec035eb645fe014"}, + {file = "banana_hep-0.6.3-py3-none-any.whl", hash = "sha256:aa52344c4fac9e9e5475dbe175da44fd52ab37bb25b68c0a71eff6f704cd5b82"}, +] +certifi = [ + {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, + {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, +] +cfgv = [ + {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, + {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, +] +charset-normalizer = [ + {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, + {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, +] +click = [ + {file = "click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1"}, + {file = "click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"}, +] +colorama = [ + {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, + {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, +] +commonmark = [ + {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, + {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, +] +coverage = [ + {file = "coverage-6.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b27d894748475fa858f9597c0ee1d4829f44683f3813633aaf94b19cb5453cf"}, + {file = "coverage-6.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37d1141ad6b2466a7b53a22e08fe76994c2d35a5b6b469590424a9953155afac"}, + {file = "coverage-6.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9987b0354b06d4df0f4d3e0ec1ae76d7ce7cbca9a2f98c25041eb79eec766f1"}, + {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26e2deacd414fc2f97dd9f7676ee3eaecd299ca751412d89f40bc01557a6b1b4"}, + {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd8bafa458b5c7d061540f1ee9f18025a68e2d8471b3e858a9dad47c8d41903"}, + {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:46191097ebc381fbf89bdce207a6c107ac4ec0890d8d20f3360345ff5976155c"}, + {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6f89d05e028d274ce4fa1a86887b071ae1755082ef94a6740238cd7a8178804f"}, + {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:58303469e9a272b4abdb9e302a780072c0633cdcc0165db7eec0f9e32f901e05"}, + {file = "coverage-6.3.2-cp310-cp310-win32.whl", hash = "sha256:2fea046bfb455510e05be95e879f0e768d45c10c11509e20e06d8fcaa31d9e39"}, + {file = "coverage-6.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:a2a8b8bcc399edb4347a5ca8b9b87e7524c0967b335fbb08a83c8421489ddee1"}, + {file = "coverage-6.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f1555ea6d6da108e1999b2463ea1003fe03f29213e459145e70edbaf3e004aaa"}, + {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5f4e1edcf57ce94e5475fe09e5afa3e3145081318e5fd1a43a6b4539a97e518"}, + {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a15dc0a14008f1da3d1ebd44bdda3e357dbabdf5a0b5034d38fcde0b5c234b7"}, + {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21b7745788866028adeb1e0eca3bf1101109e2dc58456cb49d2d9b99a8c516e6"}, + {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8ce257cac556cb03be4a248d92ed36904a59a4a5ff55a994e92214cde15c5bad"}, + {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b0be84e5a6209858a1d3e8d1806c46214e867ce1b0fd32e4ea03f4bd8b2e3359"}, + {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:acf53bc2cf7282ab9b8ba346746afe703474004d9e566ad164c91a7a59f188a4"}, + {file = "coverage-6.3.2-cp37-cp37m-win32.whl", hash = "sha256:8bdde1177f2311ee552f47ae6e5aa7750c0e3291ca6b75f71f7ffe1f1dab3dca"}, + {file = "coverage-6.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b31651d018b23ec463e95cf10070d0b2c548aa950a03d0b559eaa11c7e5a6fa3"}, + {file = "coverage-6.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07e6db90cd9686c767dcc593dff16c8c09f9814f5e9c51034066cad3373b914d"}, + {file = "coverage-6.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c6dbb42f3ad25760010c45191e9757e7dce981cbfb90e42feef301d71540059"}, + {file = "coverage-6.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76aeef1b95aff3905fb2ae2d96e319caca5b76fa41d3470b19d4e4a3a313512"}, + {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cf5cfcb1521dc3255d845d9dca3ff204b3229401994ef8d1984b32746bb45ca"}, + {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fbbdc8d55990eac1b0919ca69eb5a988a802b854488c34b8f37f3e2025fa90d"}, + {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ec6bc7fe73a938933d4178c9b23c4e0568e43e220aef9472c4f6044bfc6dd0f0"}, + {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9baff2a45ae1f17c8078452e9e5962e518eab705e50a0aa8083733ea7d45f3a6"}, + {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd9e830e9d8d89b20ab1e5af09b32d33e1a08ef4c4e14411e559556fd788e6b2"}, + {file = "coverage-6.3.2-cp38-cp38-win32.whl", hash = "sha256:f7331dbf301b7289013175087636bbaf5b2405e57259dd2c42fdcc9fcc47325e"}, + {file = "coverage-6.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:68353fe7cdf91f109fc7d474461b46e7f1f14e533e911a2a2cbb8b0fc8613cf1"}, + {file = "coverage-6.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b78e5afb39941572209f71866aa0b206c12f0109835aa0d601e41552f9b3e620"}, + {file = "coverage-6.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e21876082ed887baed0146fe222f861b5815455ada3b33b890f4105d806128d"}, + {file = "coverage-6.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34626a7eee2a3da12af0507780bb51eb52dca0e1751fd1471d0810539cefb536"}, + {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ebf730d2381158ecf3dfd4453fbca0613e16eaa547b4170e2450c9707665ce7"}, + {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd6fe30bd519694b356cbfcaca9bd5c1737cddd20778c6a581ae20dc8c04def2"}, + {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96f8a1cb43ca1422f36492bebe63312d396491a9165ed3b9231e778d43a7fca4"}, + {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dd035edafefee4d573140a76fdc785dc38829fe5a455c4bb12bac8c20cfc3d69"}, + {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ca5aeb4344b30d0bec47481536b8ba1181d50dbe783b0e4ad03c95dc1296684"}, + {file = "coverage-6.3.2-cp39-cp39-win32.whl", hash = "sha256:f5fa5803f47e095d7ad8443d28b01d48c0359484fec1b9d8606d0e3282084bc4"}, + {file = "coverage-6.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:9548f10d8be799551eb3a9c74bbf2b4934ddb330e08a73320123c07f95cc2d92"}, + {file = "coverage-6.3.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:18d520c6860515a771708937d2f78f63cc47ab3b80cb78e86573b0a760161faf"}, + {file = "coverage-6.3.2.tar.gz", hash = "sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9"}, +] +cycler = [ + {file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"}, + {file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"}, +] +decorator = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] +distlib = [ + {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, + {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, +] +docutils = [ + {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"}, + {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, +] +executing = [ + {file = "executing-0.8.3-py2.py3-none-any.whl", hash = "sha256:d1eef132db1b83649a3905ca6dd8897f71ac6f8cac79a7e58a1a09cf137546c9"}, + {file = "executing-0.8.3.tar.gz", hash = "sha256:c6554e21c6b060590a6d3be4b82fb78f8f0194d809de5ea7df1c093763311501"}, +] +fancycompleter = [ + {file = "fancycompleter-0.9.1-py3-none-any.whl", hash = "sha256:dd076bca7d9d524cc7f25ec8f35ef95388ffef9ef46def4d3d25e9b044ad7080"}, + {file = "fancycompleter-0.9.1.tar.gz", hash = "sha256:09e0feb8ae242abdfd7ef2ba55069a46f011814a80fe5476be48f51b00247272"}, +] +filelock = [ + {file = "filelock-3.6.0-py3-none-any.whl", hash = "sha256:f8314284bfffbdcfa0ff3d7992b023d4c628ced6feb957351d4c48d059f56bc0"}, + {file = "filelock-3.6.0.tar.gz", hash = "sha256:9cd540a9352e432c7246a48fe4e8712b10acb1df2ad1f30e8c070b82ae1fed85"}, +] +fonttools = [ + {file = "fonttools-4.29.1-py3-none-any.whl", hash = "sha256:1933415e0fbdf068815cb1baaa1f159e17830215f7e8624e5731122761627557"}, + {file = "fonttools-4.29.1.zip", hash = "sha256:2b18a172120e32128a80efee04cff487d5d140fe7d817deb648b2eee023a40e4"}, +] +greenlet = [ + {file = "greenlet-1.1.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:58df5c2a0e293bf665a51f8a100d3e9956febfbf1d9aaf8c0677cf70218910c6"}, + {file = "greenlet-1.1.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:aec52725173bd3a7b56fe91bc56eccb26fbdff1386ef123abb63c84c5b43b63a"}, + {file = "greenlet-1.1.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:833e1551925ed51e6b44c800e71e77dacd7e49181fdc9ac9a0bf3714d515785d"}, + {file = "greenlet-1.1.2-cp27-cp27m-win32.whl", hash = "sha256:aa5b467f15e78b82257319aebc78dd2915e4c1436c3c0d1ad6f53e47ba6e2713"}, + {file = "greenlet-1.1.2-cp27-cp27m-win_amd64.whl", hash = "sha256:40b951f601af999a8bf2ce8c71e8aaa4e8c6f78ff8afae7b808aae2dc50d4c40"}, + {file = "greenlet-1.1.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:95e69877983ea39b7303570fa6760f81a3eec23d0e3ab2021b7144b94d06202d"}, + {file = "greenlet-1.1.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:356b3576ad078c89a6107caa9c50cc14e98e3a6c4874a37c3e0273e4baf33de8"}, + {file = "greenlet-1.1.2-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8639cadfda96737427330a094476d4c7a56ac03de7265622fcf4cfe57c8ae18d"}, + {file = "greenlet-1.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e5306482182170ade15c4b0d8386ded995a07d7cc2ca8f27958d34d6736497"}, + {file = "greenlet-1.1.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6a36bb9474218c7a5b27ae476035497a6990e21d04c279884eb10d9b290f1b1"}, + {file = "greenlet-1.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abb7a75ed8b968f3061327c433a0fbd17b729947b400747c334a9c29a9af6c58"}, + {file = "greenlet-1.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:14d4f3cd4e8b524ae9b8aa567858beed70c392fdec26dbdb0a8a418392e71708"}, + {file = "greenlet-1.1.2-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:17ff94e7a83aa8671a25bf5b59326ec26da379ace2ebc4411d690d80a7fbcf23"}, + {file = "greenlet-1.1.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9f3cba480d3deb69f6ee2c1825060177a22c7826431458c697df88e6aeb3caee"}, + {file = "greenlet-1.1.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:fa877ca7f6b48054f847b61d6fa7bed5cebb663ebc55e018fda12db09dcc664c"}, + {file = "greenlet-1.1.2-cp35-cp35m-win32.whl", hash = "sha256:7cbd7574ce8e138bda9df4efc6bf2ab8572c9aff640d8ecfece1b006b68da963"}, + {file = "greenlet-1.1.2-cp35-cp35m-win_amd64.whl", hash = "sha256:903bbd302a2378f984aef528f76d4c9b1748f318fe1294961c072bdc7f2ffa3e"}, + {file = "greenlet-1.1.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:049fe7579230e44daef03a259faa24511d10ebfa44f69411d99e6a184fe68073"}, + {file = "greenlet-1.1.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:dd0b1e9e891f69e7675ba5c92e28b90eaa045f6ab134ffe70b52e948aa175b3c"}, + {file = "greenlet-1.1.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7418b6bfc7fe3331541b84bb2141c9baf1ec7132a7ecd9f375912eca810e714e"}, + {file = "greenlet-1.1.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9d29ca8a77117315101425ec7ec2a47a22ccf59f5593378fc4077ac5b754fce"}, + {file = "greenlet-1.1.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:21915eb821a6b3d9d8eefdaf57d6c345b970ad722f856cd71739493ce003ad08"}, + {file = "greenlet-1.1.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eff9d20417ff9dcb0d25e2defc2574d10b491bf2e693b4e491914738b7908168"}, + {file = "greenlet-1.1.2-cp36-cp36m-win32.whl", hash = "sha256:32ca72bbc673adbcfecb935bb3fb1b74e663d10a4b241aaa2f5a75fe1d1f90aa"}, + {file = "greenlet-1.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f0214eb2a23b85528310dad848ad2ac58e735612929c8072f6093f3585fd342d"}, + {file = "greenlet-1.1.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:b92e29e58bef6d9cfd340c72b04d74c4b4e9f70c9fa7c78b674d1fec18896dc4"}, + {file = "greenlet-1.1.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fdcec0b8399108577ec290f55551d926d9a1fa6cad45882093a7a07ac5ec147b"}, + {file = "greenlet-1.1.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:93f81b134a165cc17123626ab8da2e30c0455441d4ab5576eed73a64c025b25c"}, + {file = "greenlet-1.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e12bdc622676ce47ae9abbf455c189e442afdde8818d9da983085df6312e7a1"}, + {file = "greenlet-1.1.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c790abda465726cfb8bb08bd4ca9a5d0a7bd77c7ac1ca1b839ad823b948ea28"}, + {file = "greenlet-1.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f276df9830dba7a333544bd41070e8175762a7ac20350786b322b714b0e654f5"}, + {file = "greenlet-1.1.2-cp37-cp37m-win32.whl", hash = "sha256:64e6175c2e53195278d7388c454e0b30997573f3f4bd63697f88d855f7a6a1fc"}, + {file = "greenlet-1.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b11548073a2213d950c3f671aa88e6f83cda6e2fb97a8b6317b1b5b33d850e06"}, + {file = "greenlet-1.1.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:9633b3034d3d901f0a46b7939f8c4d64427dfba6bbc5a36b1a67364cf148a1b0"}, + {file = "greenlet-1.1.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:eb6ea6da4c787111adf40f697b4e58732ee0942b5d3bd8f435277643329ba627"}, + {file = "greenlet-1.1.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:f3acda1924472472ddd60c29e5b9db0cec629fbe3c5c5accb74d6d6d14773478"}, + {file = "greenlet-1.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e859fcb4cbe93504ea18008d1df98dee4f7766db66c435e4882ab35cf70cac43"}, + {file = "greenlet-1.1.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00e44c8afdbe5467e4f7b5851be223be68adb4272f44696ee71fe46b7036a711"}, + {file = "greenlet-1.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec8c433b3ab0419100bd45b47c9c8551248a5aee30ca5e9d399a0b57ac04651b"}, + {file = "greenlet-1.1.2-cp38-cp38-win32.whl", hash = "sha256:288c6a76705dc54fba69fbcb59904ae4ad768b4c768839b8ca5fdadec6dd8cfd"}, + {file = "greenlet-1.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:8d2f1fb53a421b410751887eb4ff21386d119ef9cde3797bf5e7ed49fb51a3b3"}, + {file = "greenlet-1.1.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:166eac03e48784a6a6e0e5f041cfebb1ab400b394db188c48b3a84737f505b67"}, + {file = "greenlet-1.1.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:572e1787d1460da79590bf44304abbc0a2da944ea64ec549188fa84d89bba7ab"}, + {file = "greenlet-1.1.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:be5f425ff1f5f4b3c1e33ad64ab994eed12fc284a6ea71c5243fd564502ecbe5"}, + {file = "greenlet-1.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1692f7d6bc45e3200844be0dba153612103db241691088626a33ff1f24a0d88"}, + {file = "greenlet-1.1.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7227b47e73dedaa513cdebb98469705ef0d66eb5a1250144468e9c3097d6b59b"}, + {file = "greenlet-1.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ff61ff178250f9bb3cd89752df0f1dd0e27316a8bd1465351652b1b4a4cdfd3"}, + {file = "greenlet-1.1.2-cp39-cp39-win32.whl", hash = "sha256:f70a9e237bb792c7cc7e44c531fd48f5897961701cdaa06cf22fc14965c496cf"}, + {file = "greenlet-1.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:013d61294b6cd8fe3242932c1c5e36e5d1db2c8afb58606c5a67efce62c1f5fd"}, + {file = "greenlet-1.1.2.tar.gz", hash = "sha256:e30f5ea4ae2346e62cedde8794a56858a67b878dd79f7df76a0767e356b1744a"}, +] +identify = [ + {file = "identify-2.4.11-py2.py3-none-any.whl", hash = "sha256:fd906823ed1db23c7a48f9b176a1d71cb8abede1e21ebe614bac7bdd688d9213"}, + {file = "identify-2.4.11.tar.gz", hash = "sha256:2986942d3974c8f2e5019a190523b0b0e2a07cb8e89bf236727fb4b26f27f8fd"}, +] +idna = [ + {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, + {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, +] +imagesize = [ + {file = "imagesize-1.3.0-py2.py3-none-any.whl", hash = "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c"}, + {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"}, +] +importlib-metadata = [ + {file = "importlib_metadata-4.11.2-py3-none-any.whl", hash = "sha256:d16e8c1deb60de41b8e8ed21c1a7b947b0bc62fab7e1d470bcdf331cea2e6735"}, + {file = "importlib_metadata-4.11.2.tar.gz", hash = "sha256:b36ffa925fe3139b2f6ff11d6925ffd4fa7bc47870165e3ac260ac7b4f91e6ac"}, +] +iniconfig = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] +ipython = [ + {file = "ipython-8.1.1-py3-none-any.whl", hash = "sha256:6f56bfaeaa3247aa3b9cd3b8cbab3a9c0abf7428392f97b21902d12b2f42a381"}, + {file = "ipython-8.1.1.tar.gz", hash = "sha256:8138762243c9b3a3ffcf70b37151a2a35c23d3a29f9743878c33624f4207be3d"}, +] +isort = [ + {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, + {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, +] +jedi = [ + {file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"}, + {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"}, +] +jinja2 = [ + {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, + {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"}, +] +kiwisolver = [ + {file = "kiwisolver-1.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1d819553730d3c2724582124aee8a03c846ec4362ded1034c16fb3ef309264e6"}, + {file = "kiwisolver-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d93a1095f83e908fc253f2fb569c2711414c0bfd451cab580466465b235b470"}, + {file = "kiwisolver-1.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4550a359c5157aaf8507e6820d98682872b9100ce7607f8aa070b4b8af6c298"}, + {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2210f28778c7d2ee13f3c2a20a3a22db889e75f4ec13a21072eabb5693801e84"}, + {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:82f49c5a79d3839bc8f38cb5f4bfc87e15f04cbafa5fbd12fb32c941cb529cfb"}, + {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9661a04ca3c950a8ac8c47f53cbc0b530bce1b52f516a1e87b7736fec24bfff0"}, + {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ddb500a2808c100e72c075cbb00bf32e62763c82b6a882d403f01a119e3f402"}, + {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72be6ebb4e92520b9726d7146bc9c9b277513a57a38efcf66db0620aec0097e0"}, + {file = "kiwisolver-1.3.2-cp310-cp310-win32.whl", hash = "sha256:83d2c9db5dfc537d0171e32de160461230eb14663299b7e6d18ca6dca21e4977"}, + {file = "kiwisolver-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:cba430db673c29376135e695c6e2501c44c256a81495da849e85d1793ee975ad"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4116ba9a58109ed5e4cb315bdcbff9838f3159d099ba5259c7c7fb77f8537492"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19554bd8d54cf41139f376753af1a644b63c9ca93f8f72009d50a2080f870f77"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a4cf5bbdc861987a7745aed7a536c6405256853c94abc9f3287c3fa401b174"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0007840186bacfaa0aba4466d5890334ea5938e0bb7e28078a0eb0e63b5b59d5"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec2eba188c1906b05b9b49ae55aae4efd8150c61ba450e6721f64620c50b59eb"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3dbb3cea20b4af4f49f84cffaf45dd5f88e8594d18568e0225e6ad9dec0e7967"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-win32.whl", hash = "sha256:5326ddfacbe51abf9469fe668944bc2e399181a2158cb5d45e1d40856b2a0589"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:c6572c2dab23c86a14e82c245473d45b4c515314f1f859e92608dcafbd2f19b8"}, + {file = "kiwisolver-1.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b5074fb09429f2b7bc82b6fb4be8645dcbac14e592128beeff5461dcde0af09f"}, + {file = "kiwisolver-1.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:22521219ca739654a296eea6d4367703558fba16f98688bd8ce65abff36eaa84"}, + {file = "kiwisolver-1.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c358721aebd40c243894298f685a19eb0491a5c3e0b923b9f887ef1193ddf829"}, + {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ba5a1041480c6e0a8b11a9544d53562abc2d19220bfa14133e0cdd9967e97af"}, + {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44e6adf67577dbdfa2d9f06db9fbc5639afefdb5bf2b4dfec25c3a7fbc619536"}, + {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d45d1c74f88b9f41062716c727f78f2a59a5476ecbe74956fafb423c5c87a76"}, + {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70adc3658138bc77a36ce769f5f183169bc0a2906a4f61f09673f7181255ac9b"}, + {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6a5431940f28b6de123de42f0eb47b84a073ee3c3345dc109ad550a3307dd28"}, + {file = "kiwisolver-1.3.2-cp38-cp38-win32.whl", hash = "sha256:ee040a7de8d295dbd261ef2d6d3192f13e2b08ec4a954de34a6fb8ff6422e24c"}, + {file = "kiwisolver-1.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:8dc3d842fa41a33fe83d9f5c66c0cc1f28756530cd89944b63b072281e852031"}, + {file = "kiwisolver-1.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a498bcd005e8a3fedd0022bb30ee0ad92728154a8798b703f394484452550507"}, + {file = "kiwisolver-1.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:80efd202108c3a4150e042b269f7c78643420cc232a0a771743bb96b742f838f"}, + {file = "kiwisolver-1.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f8eb7b6716f5b50e9c06207a14172cf2de201e41912ebe732846c02c830455b9"}, + {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f441422bb313ab25de7b3dbfd388e790eceb76ce01a18199ec4944b369017009"}, + {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:30fa008c172355c7768159983a7270cb23838c4d7db73d6c0f6b60dde0d432c6"}, + {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f8f6c8f4f1cff93ca5058d6ec5f0efda922ecb3f4c5fb76181f327decff98b8"}, + {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba677bcaff9429fd1bf01648ad0901cea56c0d068df383d5f5856d88221fe75b"}, + {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7843b1624d6ccca403a610d1277f7c28ad184c5aa88a1750c1a999754e65b439"}, + {file = "kiwisolver-1.3.2-cp39-cp39-win32.whl", hash = "sha256:e6f5eb2f53fac7d408a45fbcdeda7224b1cfff64919d0f95473420a931347ae9"}, + {file = "kiwisolver-1.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:eedd3b59190885d1ebdf6c5e0ca56828beb1949b4dfe6e5d0256a461429ac386"}, + {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:dedc71c8eb9c5096037766390172c34fb86ef048b8e8958b4e484b9e505d66bc"}, + {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:bf7eb45d14fc036514c09554bf983f2a72323254912ed0c3c8e697b62c4c158f"}, + {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2b65bd35f3e06a47b5c30ea99e0c2b88f72c6476eedaf8cfbc8e66adb5479dcf"}, + {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25405f88a37c5f5bcba01c6e350086d65e7465fd1caaf986333d2a045045a223"}, + {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:bcadb05c3d4794eb9eee1dddf1c24215c92fb7b55a80beae7a60530a91060560"}, + {file = "kiwisolver-1.3.2.tar.gz", hash = "sha256:fc4453705b81d03568d5b808ad8f09c77c47534f6ac2e72e733f9ca4714aa75c"}, +] +latexcodec = [ + {file = "latexcodec-2.0.1-py2.py3-none-any.whl", hash = "sha256:c277a193638dc7683c4c30f6684e3db728a06efb0dc9cf346db8bd0aa6c5d271"}, + {file = "latexcodec-2.0.1.tar.gz", hash = "sha256:2aa2551c373261cefe2ad3a8953a6d6533e68238d180eb4bb91d7964adb3fe9a"}, +] +lazy-object-proxy = [ + {file = "lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-win32.whl", hash = "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9"}, + {file = "lazy_object_proxy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win32.whl", hash = "sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb"}, + {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win32.whl", hash = "sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69"}, + {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-win32.whl", hash = "sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55"}, + {file = "lazy_object_proxy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-win32.whl", hash = "sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f"}, + {file = "lazy_object_proxy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61"}, + {file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"}, +] +llvmlite = [ + {file = "llvmlite-0.38.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0497a19428083a0544663732a925994d74e3b15c3c94946c6e7b6bf21a391264"}, + {file = "llvmlite-0.38.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b040d392e998582883cd680e81afb4cd2d331d69cb93d605c735bfd2caa09805"}, + {file = "llvmlite-0.38.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8b88cc3c6c0010df8a720c777ef1c0879d304404e0727c4ac9e3dc98d5815e10"}, + {file = "llvmlite-0.38.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87805405ccdd1add51f51d85997fbff01c920adf4da600dbe197e1f3eebd1e57"}, + {file = "llvmlite-0.38.0-cp310-cp310-win32.whl", hash = "sha256:17140e1462aa7f9250428fff7dd24187ea30498034a832bdb7385cbdc28fd4bf"}, + {file = "llvmlite-0.38.0-cp310-cp310-win_amd64.whl", hash = "sha256:c0f11feda33f2b49abf5acc11828eebb3098050bbf6cd1cd75e2b05eb7676cb1"}, + {file = "llvmlite-0.38.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f7a438917c30e87ac79bb89c773c100560dc346e0f0b03aabd88a6f6de3556c6"}, + {file = "llvmlite-0.38.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e8bbb8e97d7cc0b6d124ba9f8577955fdc7639715f925c410abe02d2bc92862"}, + {file = "llvmlite-0.38.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5845432b4660c530d27c46434b9669290f205d9b1c1e02e52f43f6d11782b4be"}, + {file = "llvmlite-0.38.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a91e25488609cc91db91de206e023b7fe0889ac007adb31c713e685384497ba"}, + {file = "llvmlite-0.38.0-cp37-cp37m-win32.whl", hash = "sha256:2426bfff67fdab577c7d5321c252d880434911caa6f9152f5be98da71b30e084"}, + {file = "llvmlite-0.38.0-cp37-cp37m-win_amd64.whl", hash = "sha256:6b48c8fffc3512a2e97c6f70deb09eb49c419af66ced79e317cc2323117dcec6"}, + {file = "llvmlite-0.38.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e1095557a27b041f1217036e568a5449d4b385c2415cb4316b2f5476f96e9a58"}, + {file = "llvmlite-0.38.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:081d9c36d8e012b86bac02af49e225d883975ab5978ba33c3cc291474620c84d"}, + {file = "llvmlite-0.38.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:63e178c6f7872a39572e210cb266fb6db6386f5e622e2d8c79491b6d8c7aa942"}, + {file = "llvmlite-0.38.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48558fddce5ff351f9de98beff35888aa351598e5635b3b91d67ec9e10d458cc"}, + {file = "llvmlite-0.38.0-cp38-cp38-win32.whl", hash = "sha256:7e07bacc2bb2ef1bf33dbf64d4bd13330baeae2287902100b144e43bcd1b066b"}, + {file = "llvmlite-0.38.0-cp38-cp38-win_amd64.whl", hash = "sha256:37b66bf3624dd0b3739b4cf1b3cc3735dbe7799bc90d2a7a79a54b0ce37e1a38"}, + {file = "llvmlite-0.38.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f43861f382b954fbf2ff88db5f13b00ac11ec4353445d3ba80e1eadcdd06c149"}, + {file = "llvmlite-0.38.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fb7cb2907814dd03a152549d1c4dfee4854881d9cc7da85414b77903a681aa6"}, + {file = "llvmlite-0.38.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c967b96d708556597e003217fd99f0c20e73d09c91d6d5054c538becc396ba79"}, + {file = "llvmlite-0.38.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b2838898c80557e959f83fb28d260e5e2301396f34830f3ec6811ae53f6be"}, + {file = "llvmlite-0.38.0-cp39-cp39-win32.whl", hash = "sha256:de321a680690d1ce040f34294d215ed0ac5fdcf7c98f044d11ac9b9d9ebc969f"}, + {file = "llvmlite-0.38.0-cp39-cp39-win_amd64.whl", hash = "sha256:70734d46c2611f3fe765985fe356aaec393dc79bbd735f7f4d23f910b5148dc3"}, + {file = "llvmlite-0.38.0.tar.gz", hash = "sha256:a99d166ccf3b116f3b9ed23b9b70ba2415640a9c978f3aaa13fad49c58f4965c"}, +] +lz4 = [ + {file = "lz4-3.1.10-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3fcd913191a34c59ff07a5b8594d3b61213ae0044bba618f74202722a2efbe2f"}, + {file = "lz4-3.1.10-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:6e72e3bc14230db9baf56b05ac15ddc38a9246c414a95ca725af8d5d2226944a"}, + {file = "lz4-3.1.10-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:a8991ac13743b09cf3d3d69c3ee6991c4e636886dbcdac584a672e38ba14d36f"}, + {file = "lz4-3.1.10-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:6d16fd11e6998d4b48771e345eefb5a800a41fdf7df29ffc6b4cd36fea213172"}, + {file = "lz4-3.1.10-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:dcda8a5fb286251422b271e785b340d551e42f2ffd10953d6aa77a12263d0868"}, + {file = "lz4-3.1.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f38880f66f8fbb8fa94cf08a2120f7bee7bf9ad35cf85259b1c3598ba17e5f9e"}, + {file = "lz4-3.1.10-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:be542ae2466597f31fe37ff5a8a29b124c9b4dc5fef7effa80b194aa887c01ef"}, + {file = "lz4-3.1.10-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1587538466ecb8c18a58425a9513321e218c9518198d3e3b1897876686edd5c7"}, + {file = "lz4-3.1.10-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:c716eb1cd08c966952c7d8af481b4407db29fd63f151bc23b3783e8b87ddce20"}, + {file = "lz4-3.1.10-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:d36d0cc0942ef2b30ed69a64ded5e10e64061b2f8e8011c99ffea8a3f8d429c5"}, + {file = "lz4-3.1.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:48c67beaa312d7f3db66c78cd3d8b4332512489af8ebd9783d4ec735e3337923"}, + {file = "lz4-3.1.10-cp38-cp38-manylinux1_i686.whl", hash = "sha256:dcdaf01dc092c192576626a84c9d2fdc79c0a9b03735af9a7c153fda49ac4cfc"}, + {file = "lz4-3.1.10-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b089376694da9dfeb7ce3c881b3271f8983c70eea4be5a1f692d97c5880ddd04"}, + {file = "lz4-3.1.10-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:e6dc7f003c010f8198d2ebca7d11b141c1b96f7e350c0fdb5f9b52a1966f79ff"}, + {file = "lz4-3.1.10-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:060a69c1b8111c1428a4aabc031e79b861442bf92eeb9a48a97cab9ba4a54194"}, + {file = "lz4-3.1.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a987774fa38fa05a0440344ce839c512d1c51908da5d8cabbb0a2c435922477f"}, + {file = "lz4-3.1.10-cp39-cp39-manylinux1_i686.whl", hash = "sha256:72945fab7f3ab486ba92a83c43c65736be9775f1b6d5f25b5f89022c476e2705"}, + {file = "lz4-3.1.10-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:e87619075e2302f4f2ee4dafebd5e3ff47e09420df34bcfe8fc0839af4f5bac5"}, + {file = "lz4-3.1.10-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:bf1d6dee89ef0fe0835529b9248ba503eaa918cfd1aafa02f2ab61587c387068"}, + {file = "lz4-3.1.10-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:59afeb136957ed7a2058e4ef61cb2d0f5894ca866a8bfca5ff43d49a5cbe4aa2"}, + {file = "lz4-3.1.10.tar.gz", hash = "sha256:439e575ecfa9ecffcbd63cfed99baefbe422ab9645b1e82278024d8a21d9720b"}, +] +markupsafe = [ + {file = "MarkupSafe-2.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3028252424c72b2602a323f70fbf50aa80a5d3aa616ea6add4ba21ae9cc9da4c"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:290b02bab3c9e216da57c1d11d2ba73a9f73a614bbdcc027d299a60cdfabb11a"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e104c0c2b4cd765b4e83909cde7ec61a1e313f8a75775897db321450e928cce"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24c3be29abb6b34052fd26fc7a8e0a49b1ee9d282e3665e8ad09a0a68faee5b3"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204730fd5fe2fe3b1e9ccadb2bd18ba8712b111dcabce185af0b3b5285a7c989"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d3b64c65328cb4cd252c94f83e66e3d7acf8891e60ebf588d7b493a55a1dbf26"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:96de1932237abe0a13ba68b63e94113678c379dca45afa040a17b6e1ad7ed076"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75bb36f134883fdbe13d8e63b8675f5f12b80bb6627f7714c7d6c5becf22719f"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-win32.whl", hash = "sha256:4056f752015dfa9828dce3140dbadd543b555afb3252507348c493def166d454"}, + {file = "MarkupSafe-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:d4e702eea4a2903441f2735799d217f4ac1b55f7d8ad96ab7d4e25417cb0827c"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f0eddfcabd6936558ec020130f932d479930581171368fd728efcfb6ef0dd357"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddea4c352a488b5e1069069f2f501006b1a4362cb906bee9a193ef1245a7a61"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09c86c9643cceb1d87ca08cdc30160d1b7ab49a8a21564868921959bd16441b8"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0a0abef2ca47b33fb615b491ce31b055ef2430de52c5b3fb19a4042dbc5cadb"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:736895a020e31b428b3382a7887bfea96102c529530299f426bf2e636aacec9e"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:679cbb78914ab212c49c67ba2c7396dc599a8479de51b9a87b174700abd9ea49"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:84ad5e29bf8bab3ad70fd707d3c05524862bddc54dc040982b0dbcff36481de7"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-win32.whl", hash = "sha256:8da5924cb1f9064589767b0f3fc39d03e3d0fb5aa29e0cb21d43106519bd624a"}, + {file = "MarkupSafe-2.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:454ffc1cbb75227d15667c09f164a0099159da0c1f3d2636aa648f12675491ad"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:142119fb14a1ef6d758912b25c4e803c3ff66920635c44078666fe7cc3f8f759"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b2a5a856019d2833c56a3dcac1b80fe795c95f401818ea963594b345929dffa7"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d1fb9b2eec3c9714dd936860850300b51dbaa37404209c8d4cb66547884b7ed"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62c0285e91414f5c8f621a17b69fc0088394ccdaa961ef469e833dbff64bd5ea"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc3150f85e2dbcf99e65238c842d1cfe69d3e7649b19864c1cc043213d9cd730"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f02cf7221d5cd915d7fa58ab64f7ee6dd0f6cddbb48683debf5d04ae9b1c2cc1"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5653619b3eb5cbd35bfba3c12d575db2a74d15e0e1c08bf1db788069d410ce8"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7d2f5d97fcbd004c03df8d8fe2b973fe2b14e7bfeb2cfa012eaa8759ce9a762f"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-win32.whl", hash = "sha256:3cace1837bc84e63b3fd2dfce37f08f8c18aeb81ef5cf6bb9b51f625cb4e6cd8"}, + {file = "MarkupSafe-2.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:fabbe18087c3d33c5824cb145ffca52eccd053061df1d79d4b66dafa5ad2a5ea"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:023af8c54fe63530545f70dd2a2a7eed18d07a9a77b94e8bf1e2ff7f252db9a3"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d66624f04de4af8bbf1c7f21cc06649c1c69a7f84109179add573ce35e46d448"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c532d5ab79be0199fa2658e24a02fce8542df196e60665dd322409a03db6a52c"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ec74fada3841b8c5f4c4f197bea916025cb9aa3fe5abf7d52b655d042f956"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c653fde75a6e5eb814d2a0a89378f83d1d3f502ab710904ee585c38888816c"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:961eb86e5be7d0973789f30ebcf6caab60b844203f4396ece27310295a6082c7"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:598b65d74615c021423bd45c2bc5e9b59539c875a9bdb7e5f2a6b92dfcfc268d"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:599941da468f2cf22bf90a84f6e2a65524e87be2fce844f96f2dd9a6c9d1e635"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-win32.whl", hash = "sha256:e6f7f3f41faffaea6596da86ecc2389672fa949bd035251eab26dc6697451d05"}, + {file = "MarkupSafe-2.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:b8811d48078d1cf2a6863dafb896e68406c5f513048451cd2ded0473133473c7"}, + {file = "MarkupSafe-2.1.0.tar.gz", hash = "sha256:80beaf63ddfbc64a0452b841d8036ca0611e049650e20afcb882f5d3c266d65f"}, +] +matplotlib = [ + {file = "matplotlib-3.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:456cc8334f6d1124e8ff856b42d2cc1c84335375a16448189999496549f7182b"}, + {file = "matplotlib-3.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8a77906dc2ef9b67407cec0bdbf08e3971141e535db888974a915be5e1e3efc6"}, + {file = "matplotlib-3.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e70ae6475cfd0fad3816dcbf6cac536dc6f100f7474be58d59fa306e6e768a4"}, + {file = "matplotlib-3.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53273c5487d1c19c3bc03b9eb82adaf8456f243b97ed79d09dded747abaf1235"}, + {file = "matplotlib-3.5.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e3b6f3fd0d8ca37861c31e9a7cab71a0ef14c639b4c95654ea1dd153158bf0df"}, + {file = "matplotlib-3.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8c87cdaf06fd7b2477f68909838ff4176f105064a72ca9d24d3f2a29f73d393"}, + {file = "matplotlib-3.5.1-cp310-cp310-win32.whl", hash = "sha256:e2f28a07b4f82abb40267864ad7b3a4ed76f1b1663e81c7efc84a9b9248f672f"}, + {file = "matplotlib-3.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:d70a32ee1f8b55eed3fd4e892f0286df8cccc7e0475c11d33b5d0a148f5c7599"}, + {file = "matplotlib-3.5.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:68fa30cec89b6139dc559ed6ef226c53fd80396da1919a1b5ef672c911aaa767"}, + {file = "matplotlib-3.5.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e3484d8455af3fdb0424eae1789af61f6a79da0c80079125112fd5c1b604218"}, + {file = "matplotlib-3.5.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e293b16cf303fe82995e41700d172a58a15efc5331125d08246b520843ef21ee"}, + {file = "matplotlib-3.5.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e3520a274a0e054e919f5b3279ee5dbccf5311833819ccf3399dab7c83e90a25"}, + {file = "matplotlib-3.5.1-cp37-cp37m-win32.whl", hash = "sha256:2252bfac85cec7af4a67e494bfccf9080bcba8a0299701eab075f48847cca907"}, + {file = "matplotlib-3.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:abf67e05a1b7f86583f6ebd01f69b693b9c535276f4e943292e444855870a1b8"}, + {file = "matplotlib-3.5.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6c094e4bfecd2fa7f9adffd03d8abceed7157c928c2976899de282f3600f0a3d"}, + {file = "matplotlib-3.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:506b210cc6e66a0d1c2bb765d055f4f6bc2745070fb1129203b67e85bbfa5c18"}, + {file = "matplotlib-3.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b04fc29bcef04d4e2d626af28d9d892be6aba94856cb46ed52bcb219ceac8943"}, + {file = "matplotlib-3.5.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:577ed20ec9a18d6bdedb4616f5e9e957b4c08563a9f985563a31fd5b10564d2a"}, + {file = "matplotlib-3.5.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e486f60db0cd1c8d68464d9484fd2a94011c1ac8593d765d0211f9daba2bd535"}, + {file = "matplotlib-3.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b71f3a7ca935fc759f2aed7cec06cfe10bc3100fadb5dbd9c435b04e557971e1"}, + {file = "matplotlib-3.5.1-cp38-cp38-win32.whl", hash = "sha256:d24e5bb8028541ce25e59390122f5e48c8506b7e35587e5135efcb6471b4ac6c"}, + {file = "matplotlib-3.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:778d398c4866d8e36ee3bf833779c940b5f57192fa0a549b3ad67bc4c822771b"}, + {file = "matplotlib-3.5.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bb1c613908f11bac270bc7494d68b1ef6e7c224b7a4204d5dacf3522a41e2bc3"}, + {file = "matplotlib-3.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:edf5e4e1d5fb22c18820e8586fb867455de3b109c309cb4fce3aaed85d9468d1"}, + {file = "matplotlib-3.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:40e0d7df05e8efe60397c69b467fc8f87a2affeb4d562fe92b72ff8937a2b511"}, + {file = "matplotlib-3.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a350ca685d9f594123f652ba796ee37219bf72c8e0fc4b471473d87121d6d34"}, + {file = "matplotlib-3.5.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3e66497cd990b1a130e21919b004da2f1dc112132c01ac78011a90a0f9229778"}, + {file = "matplotlib-3.5.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:87900c67c0f1728e6db17c6809ec05c025c6624dcf96a8020326ea15378fe8e7"}, + {file = "matplotlib-3.5.1-cp39-cp39-win32.whl", hash = "sha256:b8a4fb2a0c5afbe9604f8a91d7d0f27b1832c3e0b5e365f95a13015822b4cd65"}, + {file = "matplotlib-3.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:fe8d40c434a8e2c68d64c6d6a04e77f21791a93ff6afe0dce169597c110d3079"}, + {file = "matplotlib-3.5.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:34a1fc29f8f96e78ec57a5eff5e8d8b53d3298c3be6df61e7aa9efba26929522"}, + {file = "matplotlib-3.5.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b19a761b948e939a9e20173aaae76070025f0024fc8f7ba08bef22a5c8573afc"}, + {file = "matplotlib-3.5.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6803299cbf4665eca14428d9e886de62e24f4223ac31ab9c5d6d5339a39782c7"}, + {file = "matplotlib-3.5.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:14334b9902ec776461c4b8c6516e26b450f7ebe0b3ef8703bf5cdfbbaecf774a"}, + {file = "matplotlib-3.5.1.tar.gz", hash = "sha256:b2e9810e09c3a47b73ce9cab5a72243a1258f61e7900969097a817232246ce1c"}, +] +matplotlib-inline = [ + {file = "matplotlib-inline-0.1.3.tar.gz", hash = "sha256:a04bfba22e0d1395479f866853ec1ee28eea1485c1d69a6faf00dc3e24ff34ee"}, + {file = "matplotlib_inline-0.1.3-py3-none-any.whl", hash = "sha256:aed605ba3b72462d64d475a21a9296f400a19c4f74a31b59103d2a99ffd5aa5c"}, +] +mccabe = [ + {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, + {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, +] +nodeenv = [ + {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, + {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, +] +numba = [ + {file = "numba-0.55.1-1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:be56fb78303973e6c19c7c2759996a5863bac69ca87570543d9f18f2f287a441"}, + {file = "numba-0.55.1-1-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ee71407be9cba09b4f68afa668317e97d66d5f83c37ab4caa20d8abcf5fad32b"}, + {file = "numba-0.55.1-1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:39a109efc317e8eb786feff0a29476036971ce08e3280be8153c3b6c1ccba415"}, + {file = "numba-0.55.1-1-cp37-cp37m-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0dc8294b2b6b2dbe3a709787bbb1e6f9dcef62197429de8daaa714d77052eefe"}, + {file = "numba-0.55.1-1-cp37-cp37m-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:bcd5e09dba5e19ff7a1b9716a1ce58f0931cec09515683011e57415c6a33ac3d"}, + {file = "numba-0.55.1-1-cp37-cp37m-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:64209d71b1e33415d5b1b177ed218d679062f844667dd279ee9094c4e3e2babc"}, + {file = "numba-0.55.1-1-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff5ed5c7665f8a5405af53332d224caca68358909abde9ca8dfef3495cdea789"}, + {file = "numba-0.55.1-1-cp38-cp38-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:d80afc5618e66af2d101eff0e6214acb865136ae886d8b01414ca3dedd9166d6"}, + {file = "numba-0.55.1-1-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6d0042371880fa56ed58be27502b11a08bff0b6335f0ebde82af1a7aef5e1287"}, + {file = "numba-0.55.1-1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4a5cb8930e729aeed96809524ca4df41b6f2432b379f220014ef4fdff21dbfe6"}, + {file = "numba-0.55.1-1-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:fee529ddc9c0584b932f7885735162e52344eded8c01c78c17e2768aa6787780"}, + {file = "numba-0.55.1-1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:230e542649c7087454bc851d2e22b5e15694b6cf0549a27234d1baea6c2e0a87"}, + {file = "numba-0.55.1-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:adc88fe64f5235c8b1e7230ae29476a08ffb61a65e9f79f745bd357f215e2d52"}, + {file = "numba-0.55.1-cp310-cp310-win32.whl", hash = "sha256:a5af7f1d30f56029d1b9ea288372f924f9dcb322f0e6358f6d5203b20eb6f7a0"}, + {file = "numba-0.55.1-cp310-cp310-win_amd64.whl", hash = "sha256:71815c501b2f6309c432e98ff93a582a9bfb61da943e0cb9a52595fadbb1131d"}, + {file = "numba-0.55.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:53909143917ea4962cfbfae7038ac882987ff54cb2c408538ce71f83b356f106"}, + {file = "numba-0.55.1-cp37-cp37m-win32.whl", hash = "sha256:cddc13939e2b27782258826686800ae9c2e90b35c36ef1ab5ccfae7cedca0516"}, + {file = "numba-0.55.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ac6ae19ff5093a42bf8b365550322a2e39650d608daa379dff71571272d88d93"}, + {file = "numba-0.55.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:77187ed09e6b25ae24b840e1acc4b5f9886b551cdc5f919ddad8e5933a6027d5"}, + {file = "numba-0.55.1-cp38-cp38-win32.whl", hash = "sha256:53ee562b873e00eaa26390690ac5d36b706782d429e5a18b255161f607f13c17"}, + {file = "numba-0.55.1-cp38-cp38-win_amd64.whl", hash = "sha256:02fb0ecd218ab1e1171cbaee11235a3a1f7dcf79dee3fa786243a2a6411f2fea"}, + {file = "numba-0.55.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:6aa8f18a003a0e4876826fe080e6038fc6da083899873b77172ec29c32e49b56"}, + {file = "numba-0.55.1-cp39-cp39-win32.whl", hash = "sha256:d5ee721ce884f8313802295633fdd3e7c83541e0917bafea2bdfed6aabab93bf"}, + {file = "numba-0.55.1-cp39-cp39-win_amd64.whl", hash = "sha256:b72350160eb9a73a36aa17d808f954353a263a0295d495497c87439d79bdaec7"}, + {file = "numba-0.55.1.tar.gz", hash = "sha256:03e9069a2666d1c84f93b00dbd716fb8fedde8bb2c6efafa2f04842a46442ea3"}, +] +numpy = [ + {file = "numpy-1.21.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:301e408a052fdcda5cdcf03021ebafc3c6ea093021bf9d1aa47c54d48bdad166"}, + {file = "numpy-1.21.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a7e8f6216f180f3fd4efb73de5d1eaefb5f5a1ee5b645c67333033e39440e63a"}, + {file = "numpy-1.21.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fc7a7d7b0ed72589fd8b8486b9b42a564f10b8762be8bd4d9df94b807af4a089"}, + {file = "numpy-1.21.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58ca1d7c8aef6e996112d0ce873ac9dfa1eaf4a1196b4ff7ff73880a09923ba7"}, + {file = "numpy-1.21.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc4b2fb01f1b4ddbe2453468ea0719f4dbb1f5caa712c8b21bb3dd1480cd30d9"}, + {file = "numpy-1.21.5-cp310-cp310-win_amd64.whl", hash = "sha256:cc1b30205d138d1005adb52087ff45708febbef0e420386f58664f984ef56954"}, + {file = "numpy-1.21.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:08de8472d9f7571f9d51b27b75e827f5296295fa78817032e84464be8bb905bc"}, + {file = "numpy-1.21.5-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4fe6a006557b87b352c04596a6e3f12a57d6e5f401d804947bd3188e6b0e0e76"}, + {file = "numpy-1.21.5-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3d893b0871322eaa2f8c7072cdb552d8e2b27645b7875a70833c31e9274d4611"}, + {file = "numpy-1.21.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:341dddcfe3b7b6427a28a27baa59af5ad51baa59bfec3264f1ab287aa3b30b13"}, + {file = "numpy-1.21.5-cp37-cp37m-win32.whl", hash = "sha256:ca9c23848292c6fe0a19d212790e62f398fd9609aaa838859be8459bfbe558aa"}, + {file = "numpy-1.21.5-cp37-cp37m-win_amd64.whl", hash = "sha256:025b497014bc33fc23897859350f284323f32a2fff7654697f5a5fc2a19e9939"}, + {file = "numpy-1.21.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3a5098df115340fb17fc93867317a947e1dcd978c3888c5ddb118366095851f8"}, + {file = "numpy-1.21.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:311283acf880cfcc20369201bd75da907909afc4666966c7895cbed6f9d2c640"}, + {file = "numpy-1.21.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b545ebadaa2b878c8630e5bcdb97fc4096e779f335fc0f943547c1c91540c815"}, + {file = "numpy-1.21.5-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c5562bcc1a9b61960fc8950ade44d00e3de28f891af0acc96307c73613d18f6e"}, + {file = "numpy-1.21.5-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:eed2afaa97ec33b4411995be12f8bdb95c87984eaa28d76cf628970c8a2d689a"}, + {file = "numpy-1.21.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61bada43d494515d5b122f4532af226fdb5ee08fe5b5918b111279843dc6836a"}, + {file = "numpy-1.21.5-cp38-cp38-win32.whl", hash = "sha256:7b9d6b14fc9a4864b08d1ba57d732b248f0e482c7b2ff55c313137e3ed4d8449"}, + {file = "numpy-1.21.5-cp38-cp38-win_amd64.whl", hash = "sha256:dbce7adeb66b895c6aaa1fad796aaefc299ced597f6fbd9ceddb0dd735245354"}, + {file = "numpy-1.21.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:507c05c7a37b3683eb08a3ff993bd1ee1e6c752f77c2f275260533b265ecdb6c"}, + {file = "numpy-1.21.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:00c9fa73a6989895b8815d98300a20ac993c49ac36c8277e8ffeaa3631c0dbbb"}, + {file = "numpy-1.21.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:69a5a8d71c308d7ef33ef72371c2388a90e3495dbb7993430e674006f94797d5"}, + {file = "numpy-1.21.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2d8adfca843bc46ac199a4645233f13abf2011a0b2f4affc5c37cd552626f27b"}, + {file = "numpy-1.21.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c293d3c0321996cd8ffe84215ffe5d269fd9d1d12c6f4ffe2b597a7c30d3e593"}, + {file = "numpy-1.21.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c978544be9e04ed12016dd295a74283773149b48f507d69b36f91aa90a643e5"}, + {file = "numpy-1.21.5-cp39-cp39-win32.whl", hash = "sha256:2a9add27d7fc0fdb572abc3b2486eb3b1395da71e0254c5552b2aad2a18b5441"}, + {file = "numpy-1.21.5-cp39-cp39-win_amd64.whl", hash = "sha256:1964db2d4a00348b7a60ee9d013c8cb0c566644a589eaa80995126eac3b99ced"}, + {file = "numpy-1.21.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a7c4b701ca418cd39e28ec3b496e6388fe06de83f5f0cb74794fa31cfa384c02"}, + {file = "numpy-1.21.5.zip", hash = "sha256:6a5928bc6241264dce5ed509e66f33676fc97f464e7a919edc672fb5532221ee"}, +] +packaging = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] +pandas = [ + {file = "pandas-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3dfb32ed50122fe8c5e7f2b8d97387edd742cc78f9ec36f007ee126cd3720907"}, + {file = "pandas-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0259cd11e7e6125aaea3af823b80444f3adad6149ff4c97fef760093598b3e34"}, + {file = "pandas-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96e9ece5759f9b47ae43794b6359bbc54805d76e573b161ae770c1ea59393106"}, + {file = "pandas-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:508c99debccd15790d526ce6b1624b97a5e1e4ca5b871319fb0ebfd46b8f4dad"}, + {file = "pandas-1.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6a7bbbb7950063bfc942f8794bc3e31697c020a14f1cd8905fc1d28ec674a01"}, + {file = "pandas-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:c614001129b2a5add5e3677c3a213a9e6fd376204cb8d17c04e84ff7dfc02a73"}, + {file = "pandas-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:4e1176f45981c8ccc8161bc036916c004ca51037a7ed73f2d2a9857e6dbe654f"}, + {file = "pandas-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bbb15ad79050e8b8d39ec40dd96a30cd09b886a2ae8848d0df1abba4d5502a67"}, + {file = "pandas-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6d6ad1da00c7cc7d8dd1559a6ba59ba3973be6b15722d49738b2be0977eb8a0c"}, + {file = "pandas-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:358b0bc98a5ff067132d23bf7a2242ee95db9ea5b7bbc401cf79205f11502fd3"}, + {file = "pandas-1.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6105af6533f8b63a43ea9f08a2ede04e8f43e49daef0209ab0d30352bcf08bee"}, + {file = "pandas-1.4.1-cp38-cp38-win32.whl", hash = "sha256:04dd15d9db538470900c851498e532ef28d4e56bfe72c9523acb32042de43dfb"}, + {file = "pandas-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:1b384516dbb4e6aae30e3464c2e77c563da5980440fbdfbd0968e3942f8f9d70"}, + {file = "pandas-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f02e85e6d832be37d7f16cf6ac8bb26b519ace3e5f3235564a91c7f658ab2a43"}, + {file = "pandas-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0b1a13f647e4209ed7dbb5da3497891d0045da9785327530ab696417ef478f84"}, + {file = "pandas-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:19f7c632436b1b4f84615c3b127bbd7bc603db95e3d4332ed259dc815c9aaa26"}, + {file = "pandas-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ea47ba1d6f359680130bd29af497333be6110de8f4c35b9211eec5a5a9630fa"}, + {file = "pandas-1.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e5a7a1e0ecaac652326af627a3eca84886da9e667d68286866d4e33f6547caf"}, + {file = "pandas-1.4.1-cp39-cp39-win32.whl", hash = "sha256:1d85d5f6be66dfd6d1d8d13b9535e342a2214260f1852654b19fa4d7b8d1218b"}, + {file = "pandas-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:3129a35d9dad1d80c234dd78f8f03141b914395d23f97cf92a366dcd19f8f8bf"}, + {file = "pandas-1.4.1.tar.gz", hash = "sha256:8db93ec98ac7cb5f8ac1420c10f5e3c43533153f253fe7fb6d891cf5aa2b80d2"}, +] +parso = [ + {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, + {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, +] +pdbpp = [ + {file = "pdbpp-0.10.3-py2.py3-none-any.whl", hash = "sha256:79580568e33eb3d6f6b462b1187f53e10cd8e4538f7d31495c9181e2cf9665d1"}, + {file = "pdbpp-0.10.3.tar.gz", hash = "sha256:d9e43f4fda388eeb365f2887f4e7b66ac09dce9b6236b76f63616530e2f669f5"}, +] +pendulum = [ + {file = "pendulum-2.1.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:b6c352f4bd32dff1ea7066bd31ad0f71f8d8100b9ff709fb343f3b86cee43efe"}, + {file = "pendulum-2.1.2-cp27-cp27m-win_amd64.whl", hash = "sha256:318f72f62e8e23cd6660dbafe1e346950281a9aed144b5c596b2ddabc1d19739"}, + {file = "pendulum-2.1.2-cp35-cp35m-macosx_10_15_x86_64.whl", hash = "sha256:0731f0c661a3cb779d398803655494893c9f581f6488048b3fb629c2342b5394"}, + {file = "pendulum-2.1.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:3481fad1dc3f6f6738bd575a951d3c15d4b4ce7c82dce37cf8ac1483fde6e8b0"}, + {file = "pendulum-2.1.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9702069c694306297ed362ce7e3c1ef8404ac8ede39f9b28b7c1a7ad8c3959e3"}, + {file = "pendulum-2.1.2-cp35-cp35m-win_amd64.whl", hash = "sha256:fb53ffa0085002ddd43b6ca61a7b34f2d4d7c3ed66f931fe599e1a531b42af9b"}, + {file = "pendulum-2.1.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:c501749fdd3d6f9e726086bf0cd4437281ed47e7bca132ddb522f86a1645d360"}, + {file = "pendulum-2.1.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c807a578a532eeb226150d5006f156632df2cc8c5693d778324b43ff8c515dd0"}, + {file = "pendulum-2.1.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2d1619a721df661e506eff8db8614016f0720ac171fe80dda1333ee44e684087"}, + {file = "pendulum-2.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f888f2d2909a414680a29ae74d0592758f2b9fcdee3549887779cd4055e975db"}, + {file = "pendulum-2.1.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:e95d329384717c7bf627bf27e204bc3b15c8238fa8d9d9781d93712776c14002"}, + {file = "pendulum-2.1.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4c9c689747f39d0d02a9f94fcee737b34a5773803a64a5fdb046ee9cac7442c5"}, + {file = "pendulum-2.1.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1245cd0075a3c6d889f581f6325dd8404aca5884dea7223a5566c38aab94642b"}, + {file = "pendulum-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:db0a40d8bcd27b4fb46676e8eb3c732c67a5a5e6bfab8927028224fbced0b40b"}, + {file = "pendulum-2.1.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f5e236e7730cab1644e1b87aca3d2ff3e375a608542e90fe25685dae46310116"}, + {file = "pendulum-2.1.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:de42ea3e2943171a9e95141f2eecf972480636e8e484ccffaf1e833929e9e052"}, + {file = "pendulum-2.1.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7c5ec650cb4bec4c63a89a0242cc8c3cebcec92fcfe937c417ba18277d8560be"}, + {file = "pendulum-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:33fb61601083f3eb1d15edeb45274f73c63b3c44a8524703dc143f4212bf3269"}, + {file = "pendulum-2.1.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:29c40a6f2942376185728c9a0347d7c0f07905638c83007e1d262781f1e6953a"}, + {file = "pendulum-2.1.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:94b1fc947bfe38579b28e1cccb36f7e28a15e841f30384b5ad6c5e31055c85d7"}, + {file = "pendulum-2.1.2.tar.gz", hash = "sha256:b06a0ca1bfe41c990bbf0c029f0b6501a7f2ec4e38bfec730712015e8860f207"}, +] +pexpect = [ + {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, + {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, +] +pickleshare = [ + {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, + {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, +] +pillow = [ + {file = "Pillow-9.0.1-1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a5d24e1d674dd9d72c66ad3ea9131322819ff86250b30dc5821cbafcfa0b96b4"}, + {file = "Pillow-9.0.1-1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2632d0f846b7c7600edf53c48f8f9f1e13e62f66a6dbc15191029d950bfed976"}, + {file = "Pillow-9.0.1-1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9618823bd237c0d2575283f2939655f54d51b4527ec3972907a927acbcc5bfc"}, + {file = "Pillow-9.0.1-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:9bfdb82cdfeccec50aad441afc332faf8606dfa5e8efd18a6692b5d6e79f00fd"}, + {file = "Pillow-9.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5100b45a4638e3c00e4d2320d3193bdabb2d75e79793af7c3eb139e4f569f16f"}, + {file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:528a2a692c65dd5cafc130de286030af251d2ee0483a5bf50c9348aefe834e8a"}, + {file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f29d831e2151e0b7b39981756d201f7108d3d215896212ffe2e992d06bfe049"}, + {file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:855c583f268edde09474b081e3ddcd5cf3b20c12f26e0d434e1386cc5d318e7a"}, + {file = "Pillow-9.0.1-cp310-cp310-win32.whl", hash = "sha256:d9d7942b624b04b895cb95af03a23407f17646815495ce4547f0e60e0b06f58e"}, + {file = "Pillow-9.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:81c4b81611e3a3cb30e59b0cf05b888c675f97e3adb2c8672c3154047980726b"}, + {file = "Pillow-9.0.1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:413ce0bbf9fc6278b2d63309dfeefe452835e1c78398efb431bab0672fe9274e"}, + {file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80fe64a6deb6fcfdf7b8386f2cf216d329be6f2781f7d90304351811fb591360"}, + {file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cef9c85ccbe9bee00909758936ea841ef12035296c748aaceee535969e27d31b"}, + {file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d19397351f73a88904ad1aee421e800fe4bbcd1aeee6435fb62d0a05ccd1030"}, + {file = "Pillow-9.0.1-cp37-cp37m-win32.whl", hash = "sha256:d21237d0cd37acded35154e29aec853e945950321dd2ffd1a7d86fe686814669"}, + {file = "Pillow-9.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ede5af4a2702444a832a800b8eb7f0a7a1c0eed55b644642e049c98d589e5092"}, + {file = "Pillow-9.0.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:b5b3f092fe345c03bca1e0b687dfbb39364b21ebb8ba90e3fa707374b7915204"}, + {file = "Pillow-9.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:335ace1a22325395c4ea88e00ba3dc89ca029bd66bd5a3c382d53e44f0ccd77e"}, + {file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db6d9fac65bd08cea7f3540b899977c6dee9edad959fa4eaf305940d9cbd861c"}, + {file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f154d173286a5d1863637a7dcd8c3437bb557520b01bddb0be0258dcb72696b5"}, + {file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d4b1341ac07ae07eb2cc682f459bec932a380c3b122f5540432d8977e64eae"}, + {file = "Pillow-9.0.1-cp38-cp38-win32.whl", hash = "sha256:effb7749713d5317478bb3acb3f81d9d7c7f86726d41c1facca068a04cf5bb4c"}, + {file = "Pillow-9.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:7f7609a718b177bf171ac93cea9fd2ddc0e03e84d8fa4e887bdfc39671d46b00"}, + {file = "Pillow-9.0.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:80ca33961ced9c63358056bd08403ff866512038883e74f3a4bf88ad3eb66838"}, + {file = "Pillow-9.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c3c33ac69cf059bbb9d1a71eeaba76781b450bc307e2291f8a4764d779a6b28"}, + {file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12875d118f21cf35604176872447cdb57b07126750a33748bac15e77f90f1f9c"}, + {file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:514ceac913076feefbeaf89771fd6febde78b0c4c1b23aaeab082c41c694e81b"}, + {file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3c5c79ab7dfce6d88f1ba639b77e77a17ea33a01b07b99840d6ed08031cb2a7"}, + {file = "Pillow-9.0.1-cp39-cp39-win32.whl", hash = "sha256:718856856ba31f14f13ba885ff13874be7fefc53984d2832458f12c38205f7f7"}, + {file = "Pillow-9.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:f25ed6e28ddf50de7e7ea99d7a976d6a9c415f03adcaac9c41ff6ff41b6d86ac"}, + {file = "Pillow-9.0.1-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:011233e0c42a4a7836498e98c1acf5e744c96a67dd5032a6f666cc1fb97eab97"}, + {file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:253e8a302a96df6927310a9d44e6103055e8fb96a6822f8b7f514bb7ef77de56"}, + {file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6295f6763749b89c994fcb6d8a7f7ce03c3992e695f89f00b741b4580b199b7e"}, + {file = "Pillow-9.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a9f44cd7e162ac6191491d7249cceb02b8116b0f7e847ee33f739d7cb1ea1f70"}, + {file = "Pillow-9.0.1.tar.gz", hash = "sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa"}, +] +platformdirs = [ + {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, + {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, +] +pluggy = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] +pre-commit = [ + {file = "pre_commit-2.17.0-py2.py3-none-any.whl", hash = "sha256:725fa7459782d7bec5ead072810e47351de01709be838c2ce1726b9591dad616"}, + {file = "pre_commit-2.17.0.tar.gz", hash = "sha256:c1a8040ff15ad3d648c70cc3e55b93e4d2d5b687320955505587fd79bbaed06a"}, +] +prompt-toolkit = [ + {file = "prompt_toolkit-3.0.28-py3-none-any.whl", hash = "sha256:30129d870dcb0b3b6a53efdc9d0a83ea96162ffd28ffe077e94215b233dc670c"}, + {file = "prompt_toolkit-3.0.28.tar.gz", hash = "sha256:9f1cd16b1e86c2968f2519d7fb31dd9d669916f515612c269d14e9ed52b51650"}, +] +ptyprocess = [ + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, +] +pure-eval = [ + {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, + {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, +] +py = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] +pybtex = [ + {file = "pybtex-0.24.0-py2.py3-none-any.whl", hash = "sha256:e1e0c8c69998452fea90e9179aa2a98ab103f3eed894405b7264e517cc2fcc0f"}, + {file = "pybtex-0.24.0.tar.gz", hash = "sha256:818eae35b61733e5c007c3fcd2cfb75ed1bc8b4173c1f70b56cc4c0802d34755"}, +] +pybtex-docutils = [ + {file = "pybtex-docutils-1.0.1.tar.gz", hash = "sha256:d53aa0c31dc94d61fd30ea3f06c749e6f510f9ff0e78cb2765a9300f173d8626"}, + {file = "pybtex_docutils-1.0.1-py3-none-any.whl", hash = "sha256:42e379bd1d5473b9fd7be4b3a64ca291d4fdc9ae6c6854e52d1d0157c955bbfa"}, +] +pygments = [ + {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"}, + {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"}, +] +pylint = [ + {file = "pylint-2.12.2-py3-none-any.whl", hash = "sha256:daabda3f7ed9d1c60f52d563b1b854632fd90035bcf01443e234d3dc794e3b74"}, + {file = "pylint-2.12.2.tar.gz", hash = "sha256:9d945a73640e1fec07ee34b42f5669b770c759acd536ec7b16d7e4b87a9c9ff9"}, +] +pyparsing = [ + {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"}, + {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"}, +] +pyreadline = [ + {file = "pyreadline-2.1.win-amd64.exe", hash = "sha256:9ce5fa65b8992dfa373bddc5b6e0864ead8f291c94fbfec05fbd5c836162e67b"}, + {file = "pyreadline-2.1.win32.exe", hash = "sha256:65540c21bfe14405a3a77e4c085ecfce88724743a4ead47c66b84defcf82c32e"}, + {file = "pyreadline-2.1.zip", hash = "sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1"}, +] +pyrepl = [ + {file = "pyrepl-0.9.0.tar.gz", hash = "sha256:292570f34b5502e871bbb966d639474f2b57fbfcd3373c2d6a2f3d56e681a775"}, +] +pytest = [ + {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, + {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, +] +pytest-cov = [ + {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, + {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, +] +pytest-env = [ + {file = "pytest-env-0.6.2.tar.gz", hash = "sha256:7e94956aef7f2764f3c147d216ce066bf6c42948bb9e293169b1b1c880a580c2"}, +] +python-dateutil = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] +pytz = [ + {file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"}, + {file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"}, +] +pytzdata = [ + {file = "pytzdata-2020.1-py2.py3-none-any.whl", hash = "sha256:e1e14750bcf95016381e4d472bad004eef710f2d6417240904070b3d6654485f"}, + {file = "pytzdata-2020.1.tar.gz", hash = "sha256:3efa13b335a00a8de1d345ae41ec78dd11c9f8807f522d39850f2dd828681540"}, +] +pyyaml = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] +requests = [ + {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, + {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, +] +rich = [ + {file = "rich-10.16.2-py3-none-any.whl", hash = "sha256:c59d73bd804c90f747c8d7b1d023b88f2a9ac2454224a4aeaf959b21eeb42d03"}, + {file = "rich-10.16.2.tar.gz", hash = "sha256:720974689960e06c2efdb54327f8bf0cdbdf4eae4ad73b6c94213cad405c371b"}, +] +scipy = [ + {file = "scipy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:87b01c7d5761e8a266a0fbdb9d88dcba0910d63c1c671bdb4d99d29f469e9e03"}, + {file = "scipy-1.8.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ae3e327da323d82e918e593460e23babdce40d7ab21490ddf9fc06dec6b91a18"}, + {file = "scipy-1.8.0-cp310-cp310-macosx_12_0_universal2.macosx_10_9_x86_64.whl", hash = "sha256:16e09ef68b352d73befa8bcaf3ebe25d3941fe1a58c82909d5589856e6bc8174"}, + {file = "scipy-1.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c17a1878d00a5dd2797ccd73623ceca9d02375328f6218ee6d921e1325e61aff"}, + {file = "scipy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937d28722f13302febde29847bbe554b89073fbb924a30475e5ed7b028898b5f"}, + {file = "scipy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:8f4d059a97b29c91afad46b1737274cb282357a305a80bdd9e8adf3b0ca6a3f0"}, + {file = "scipy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:38aa39b6724cb65271e469013aeb6f2ce66fd44f093e241c28a9c6bc64fd79ed"}, + {file = "scipy-1.8.0-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:559a8a4c03a5ba9fe3232f39ed24f86457e4f3f6c0abbeae1fb945029f092720"}, + {file = "scipy-1.8.0-cp38-cp38-macosx_12_0_universal2.macosx_10_9_x86_64.whl", hash = "sha256:f4a6d3b9f9797eb2d43938ac2c5d96d02aed17ef170c8b38f11798717523ddba"}, + {file = "scipy-1.8.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92b2c2af4183ed09afb595709a8ef5783b2baf7f41e26ece24e1329c109691a7"}, + {file = "scipy-1.8.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a279e27c7f4566ef18bab1b1e2c37d168e365080974758d107e7d237d3f0f484"}, + {file = "scipy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad5be4039147c808e64f99c0e8a9641eb5d2fa079ff5894dcd8240e94e347af4"}, + {file = "scipy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:3d9dd6c8b93a22bf9a3a52d1327aca7e092b1299fb3afc4f89e8eba381be7b59"}, + {file = "scipy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:5e73343c5e0d413c1f937302b2e04fb07872f5843041bcfd50699aef6e95e399"}, + {file = "scipy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:de2e80ee1d925984c2504812a310841c241791c5279352be4707cdcd7c255039"}, + {file = "scipy-1.8.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:c2bae431d127bf0b1da81fc24e4bba0a84d058e3a96b9dd6475dfcb3c5e8761e"}, + {file = "scipy-1.8.0-cp39-cp39-macosx_12_0_universal2.macosx_10_9_x86_64.whl", hash = "sha256:723b9f878095ed994756fa4ee3060c450e2db0139c5ba248ee3f9628bd64e735"}, + {file = "scipy-1.8.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:011d4386b53b933142f58a652aa0f149c9b9242abd4f900b9f4ea5fbafc86b89"}, + {file = "scipy-1.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6f0cd9c0bd374ef834ee1e0f0999678d49dcc400ea6209113d81528958f97c7"}, + {file = "scipy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3720d0124aced49f6f2198a6900304411dbbeed12f56951d7c66ebef05e3df6"}, + {file = "scipy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:3d573228c10a3a8c32b9037be982e6440e411b443a6267b067cac72f690b8d56"}, + {file = "scipy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:bb7088e89cd751acf66195d2f00cf009a1ea113f3019664032d9075b1e727b6c"}, + {file = "scipy-1.8.0.tar.gz", hash = "sha256:31d4f2d6b724bc9a98e527b5849b8a7e589bf1ea630c33aa563eda912c9ff0bd"}, +] +setuptools-scm = [ + {file = "setuptools_scm-6.4.2-py3-none-any.whl", hash = "sha256:acea13255093849de7ccb11af9e1fb8bde7067783450cee9ef7a93139bddf6d4"}, + {file = "setuptools_scm-6.4.2.tar.gz", hash = "sha256:6833ac65c6ed9711a4d5d2266f8024cfa07c533a0e55f4c12f6eff280a5a9e30"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +snowballstemmer = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] +sphinx = [ + {file = "Sphinx-4.4.0-py3-none-any.whl", hash = "sha256:5da895959511473857b6d0200f56865ed62c31e8f82dd338063b84ec022701fe"}, + {file = "Sphinx-4.4.0.tar.gz", hash = "sha256:6caad9786055cb1fa22b4a365c1775816b876f91966481765d7d50e9f0dd35cc"}, +] +sphinx-rtd-theme = [ + {file = "sphinx_rtd_theme-1.0.0-py2.py3-none-any.whl", hash = "sha256:4d35a56f4508cfee4c4fb604373ede6feae2a306731d533f409ef5c3496fdbd8"}, + {file = "sphinx_rtd_theme-1.0.0.tar.gz", hash = "sha256:eec6d497e4c2195fa0e8b2016b337532b8a699a68bcb22a512870e16925c6a5c"}, +] +sphinxcontrib-applehelp = [ + {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, + {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, +] +sphinxcontrib-bibtex = [ + {file = "sphinxcontrib-bibtex-2.4.1.tar.gz", hash = "sha256:282223309bbaf34cd20a8fe1ba346fe8642f403a8930607e77a8cb08ae81fc5f"}, + {file = "sphinxcontrib_bibtex-2.4.1-py3-none-any.whl", hash = "sha256:b7da94e960a855c07c6816c7b0f4e8619b5b3ada00a5cb99b1eaa847a788f779"}, +] +sphinxcontrib-devhelp = [ + {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, + {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, +] +sphinxcontrib-htmlhelp = [ + {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"}, + {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"}, +] +sphinxcontrib-jsmath = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] +sphinxcontrib-qthelp = [ + {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, + {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, +] +sphinxcontrib-serializinghtml = [ + {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, + {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, +] +sqlalchemy = [ + {file = "SQLAlchemy-1.4.32-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:4b2bcab3a914715d332ca783e9bda13bc570d8b9ef087563210ba63082c18c16"}, + {file = "SQLAlchemy-1.4.32-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:159c2f69dd6efd28e894f261ffca1100690f28210f34cfcd70b895e0ea7a64f3"}, + {file = "SQLAlchemy-1.4.32-cp27-cp27m-win_amd64.whl", hash = "sha256:d7e483f4791fbda60e23926b098702340504f7684ce7e1fd2c1bf02029288423"}, + {file = "SQLAlchemy-1.4.32-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4aa96e957141006181ca58e792e900ee511085b8dae06c2d08c00f108280fb8a"}, + {file = "SQLAlchemy-1.4.32-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:576684771456d02e24078047c2567025f2011977aa342063468577d94e194b00"}, + {file = "SQLAlchemy-1.4.32-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fff677fa4522dafb5a5e2c0cf909790d5d367326321aeabc0dffc9047cb235bd"}, + {file = "SQLAlchemy-1.4.32-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8679f9aba5ac22e7bce54ccd8a77641d3aea3e2d96e73e4356c887ebf8ff1082"}, + {file = "SQLAlchemy-1.4.32-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7046f7aa2db445daccc8424f50b47a66c4039c9f058246b43796aa818f8b751"}, + {file = "SQLAlchemy-1.4.32-cp310-cp310-win32.whl", hash = "sha256:bedd89c34ab62565d44745212814e4b57ef1c24ad4af9b29c504ce40f0dc6558"}, + {file = "SQLAlchemy-1.4.32-cp310-cp310-win_amd64.whl", hash = "sha256:199dc6d0068753b6a8c0bd3aceb86a3e782df118260ebc1fa981ea31ee054674"}, + {file = "SQLAlchemy-1.4.32-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:8e1e5d96b744a4f91163290b01045430f3f32579e46d87282449e5b14d27d4ac"}, + {file = "SQLAlchemy-1.4.32-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edfcf93fd92e2f9eef640b3a7a40db20fe3c1d7c2c74faa41424c63dead61b76"}, + {file = "SQLAlchemy-1.4.32-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04164e0063feb7aedd9d073db0fd496edb244be40d46ea1f0d8990815e4b8c34"}, + {file = "SQLAlchemy-1.4.32-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba59761c19b800bc2e1c9324da04d35ef51e4ee9621ff37534bc2290d258f71"}, + {file = "SQLAlchemy-1.4.32-cp36-cp36m-win32.whl", hash = "sha256:708973b5d9e1e441188124aaf13c121e5b03b6054c2df59b32219175a25aa13e"}, + {file = "SQLAlchemy-1.4.32-cp36-cp36m-win_amd64.whl", hash = "sha256:316270e5867566376e69a0ac738b863d41396e2b63274616817e1d34156dff0e"}, + {file = "SQLAlchemy-1.4.32-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:9a0195af6b9050c9322a97cf07514f66fe511968e623ca87b2df5e3cf6349615"}, + {file = "SQLAlchemy-1.4.32-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7e4a3c0c3c596296b37f8427c467c8e4336dc8d50f8ed38042e8ba79507b2c9"}, + {file = "SQLAlchemy-1.4.32-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bca714d831e5b8860c3ab134c93aec63d1a4f493bed20084f54e3ce9f0a3bf99"}, + {file = "SQLAlchemy-1.4.32-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9a680d9665f88346ed339888781f5236347933906c5a56348abb8261282ec48"}, + {file = "SQLAlchemy-1.4.32-cp37-cp37m-win32.whl", hash = "sha256:9cb5698c896fa72f88e7ef04ef62572faf56809093180771d9be8d9f2e264a13"}, + {file = "SQLAlchemy-1.4.32-cp37-cp37m-win_amd64.whl", hash = "sha256:8b9a395122770a6f08ebfd0321546d7379f43505882c7419d7886856a07caa13"}, + {file = "SQLAlchemy-1.4.32-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:3f88a4ee192142eeed3fe173f673ea6ab1f5a863810a9d85dbf6c67a9bd08f97"}, + {file = "SQLAlchemy-1.4.32-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd93162615870c976dba43963a24bb418b28448fef584f30755990c134a06a55"}, + {file = "SQLAlchemy-1.4.32-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a2e73508f939175363d8a4be9dcdc84cf16a92578d7fa86e6e4ca0e6b3667b2"}, + {file = "SQLAlchemy-1.4.32-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfec934aac7f9fa95fc82147a4ba5db0a8bdc4ebf1e33b585ab8860beb10232f"}, + {file = "SQLAlchemy-1.4.32-cp38-cp38-win32.whl", hash = "sha256:bb42f9b259c33662c6a9b866012f6908a91731a419e69304e1261ba3ab87b8d1"}, + {file = "SQLAlchemy-1.4.32-cp38-cp38-win_amd64.whl", hash = "sha256:7ff72b3cc9242d1a1c9b84bd945907bf174d74fc2519efe6184d6390a8df478b"}, + {file = "SQLAlchemy-1.4.32-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:5dc9801ae9884e822ba942ca493642fb50f049c06b6dbe3178691fce48ceb089"}, + {file = "SQLAlchemy-1.4.32-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4607d2d16330757818c9d6fba322c2e80b4b112ff24295d1343a80b876eb0ed"}, + {file = "SQLAlchemy-1.4.32-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:20e9eba7fd86ef52e0df25bea83b8b518dfdf0bce09b336cfe51671f52aaaa3f"}, + {file = "SQLAlchemy-1.4.32-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:290cbdf19129ae520d4bdce392648c6fcdbee763bc8f750b53a5ab51880cb9c9"}, + {file = "SQLAlchemy-1.4.32-cp39-cp39-win32.whl", hash = "sha256:1bbac3e8293b34c4403d297e21e8f10d2a57756b75cff101dc62186adec725f5"}, + {file = "SQLAlchemy-1.4.32-cp39-cp39-win_amd64.whl", hash = "sha256:b3f1d9b3aa09ab9adc7f8c4b40fc3e081eb903054c9a6f9ae1633fe15ae503b4"}, + {file = "SQLAlchemy-1.4.32.tar.gz", hash = "sha256:6fdd2dc5931daab778c2b65b03df6ae68376e028a3098eb624d0909d999885bc"}, +] +stack-data = [ + {file = "stack_data-0.2.0-py3-none-any.whl", hash = "sha256:999762f9c3132308789affa03e9271bbbe947bf78311851f4d485d8402ed858e"}, + {file = "stack_data-0.2.0.tar.gz", hash = "sha256:45692d41bd633a9503a5195552df22b583caf16f0b27c4e58c98d88c8b648e12"}, +] +toml = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] +tomli = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] +traitlets = [ + {file = "traitlets-5.1.1-py3-none-any.whl", hash = "sha256:2d313cc50a42cd6c277e7d7dc8d4d7fedd06a2c215f78766ae7b1a66277e0033"}, + {file = "traitlets-5.1.1.tar.gz", hash = "sha256:059f456c5a7c1c82b98c2e8c799f39c9b8128f6d0d46941ee118daace9eb70c7"}, +] +typing-extensions = [ + {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, + {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, +] +urllib3 = [ + {file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"}, + {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"}, +] +virtualenv = [ + {file = "virtualenv-20.13.3-py2.py3-none-any.whl", hash = "sha256:dd448d1ded9f14d1a4bfa6bfc0c5b96ae3be3f2d6c6c159b23ddcfd701baa021"}, + {file = "virtualenv-20.13.3.tar.gz", hash = "sha256:e9dd1a1359d70137559034c0f5433b34caf504af2dc756367be86a5a32967134"}, +] +wcwidth = [ + {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, + {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, +] +wmctrl = [ + {file = "wmctrl-0.4.tar.gz", hash = "sha256:66cbff72b0ca06a22ec3883ac3a4d7c41078bdae4fb7310f52951769b10e14e0"}, +] +wrapt = [ + {file = "wrapt-1.13.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:e05e60ff3b2b0342153be4d1b597bbcfd8330890056b9619f4ad6b8d5c96a81a"}, + {file = "wrapt-1.13.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:85148f4225287b6a0665eef08a178c15097366d46b210574a658c1ff5b377489"}, + {file = "wrapt-1.13.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2dded5496e8f1592ec27079b28b6ad2a1ef0b9296d270f77b8e4a3a796cf6909"}, + {file = "wrapt-1.13.3-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:e94b7d9deaa4cc7bac9198a58a7240aaf87fe56c6277ee25fa5b3aa1edebd229"}, + {file = "wrapt-1.13.3-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:498e6217523111d07cd67e87a791f5e9ee769f9241fcf8a379696e25806965af"}, + {file = "wrapt-1.13.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ec7e20258ecc5174029a0f391e1b948bf2906cd64c198a9b8b281b811cbc04de"}, + {file = "wrapt-1.13.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:87883690cae293541e08ba2da22cacaae0a092e0ed56bbba8d018cc486fbafbb"}, + {file = "wrapt-1.13.3-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:f99c0489258086308aad4ae57da9e8ecf9e1f3f30fa35d5e170b4d4896554d80"}, + {file = "wrapt-1.13.3-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6a03d9917aee887690aa3f1747ce634e610f6db6f6b332b35c2dd89412912bca"}, + {file = "wrapt-1.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:936503cb0a6ed28dbfa87e8fcd0a56458822144e9d11a49ccee6d9a8adb2ac44"}, + {file = "wrapt-1.13.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f9c51d9af9abb899bd34ace878fbec8bf357b3194a10c4e8e0a25512826ef056"}, + {file = "wrapt-1.13.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:220a869982ea9023e163ba915077816ca439489de6d2c09089b219f4e11b6785"}, + {file = "wrapt-1.13.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0877fe981fd76b183711d767500e6b3111378ed2043c145e21816ee589d91096"}, + {file = "wrapt-1.13.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:43e69ffe47e3609a6aec0fe723001c60c65305784d964f5007d5b4fb1bc6bf33"}, + {file = "wrapt-1.13.3-cp310-cp310-win32.whl", hash = "sha256:78dea98c81915bbf510eb6a3c9c24915e4660302937b9ae05a0947164248020f"}, + {file = "wrapt-1.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:ea3e746e29d4000cd98d572f3ee2a6050a4f784bb536f4ac1f035987fc1ed83e"}, + {file = "wrapt-1.13.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:8c73c1a2ec7c98d7eaded149f6d225a692caa1bd7b2401a14125446e9e90410d"}, + {file = "wrapt-1.13.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:086218a72ec7d986a3eddb7707c8c4526d677c7b35e355875a0fe2918b059179"}, + {file = "wrapt-1.13.3-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:e92d0d4fa68ea0c02d39f1e2f9cb5bc4b4a71e8c442207433d8db47ee79d7aa3"}, + {file = "wrapt-1.13.3-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:d4a5f6146cfa5c7ba0134249665acd322a70d1ea61732723c7d3e8cc0fa80755"}, + {file = "wrapt-1.13.3-cp35-cp35m-win32.whl", hash = "sha256:8aab36778fa9bba1a8f06a4919556f9f8c7b33102bd71b3ab307bb3fecb21851"}, + {file = "wrapt-1.13.3-cp35-cp35m-win_amd64.whl", hash = "sha256:944b180f61f5e36c0634d3202ba8509b986b5fbaf57db3e94df11abee244ba13"}, + {file = "wrapt-1.13.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2ebdde19cd3c8cdf8df3fc165bc7827334bc4e353465048b36f7deeae8ee0918"}, + {file = "wrapt-1.13.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:610f5f83dd1e0ad40254c306f4764fcdc846641f120c3cf424ff57a19d5f7ade"}, + {file = "wrapt-1.13.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5601f44a0f38fed36cc07db004f0eedeaadbdcec90e4e90509480e7e6060a5bc"}, + {file = "wrapt-1.13.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:e6906d6f48437dfd80464f7d7af1740eadc572b9f7a4301e7dd3d65db285cacf"}, + {file = "wrapt-1.13.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:766b32c762e07e26f50d8a3468e3b4228b3736c805018e4b0ec8cc01ecd88125"}, + {file = "wrapt-1.13.3-cp36-cp36m-win32.whl", hash = "sha256:5f223101f21cfd41deec8ce3889dc59f88a59b409db028c469c9b20cfeefbe36"}, + {file = "wrapt-1.13.3-cp36-cp36m-win_amd64.whl", hash = "sha256:f122ccd12fdc69628786d0c947bdd9cb2733be8f800d88b5a37c57f1f1d73c10"}, + {file = "wrapt-1.13.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:46f7f3af321a573fc0c3586612db4decb7eb37172af1bc6173d81f5b66c2e068"}, + {file = "wrapt-1.13.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:778fd096ee96890c10ce96187c76b3e99b2da44e08c9e24d5652f356873f6709"}, + {file = "wrapt-1.13.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0cb23d36ed03bf46b894cfec777eec754146d68429c30431c99ef28482b5c1df"}, + {file = "wrapt-1.13.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:96b81ae75591a795d8c90edc0bfaab44d3d41ffc1aae4d994c5aa21d9b8e19a2"}, + {file = "wrapt-1.13.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7dd215e4e8514004c8d810a73e342c536547038fb130205ec4bba9f5de35d45b"}, + {file = "wrapt-1.13.3-cp37-cp37m-win32.whl", hash = "sha256:47f0a183743e7f71f29e4e21574ad3fa95676136f45b91afcf83f6a050914829"}, + {file = "wrapt-1.13.3-cp37-cp37m-win_amd64.whl", hash = "sha256:fd76c47f20984b43d93de9a82011bb6e5f8325df6c9ed4d8310029a55fa361ea"}, + {file = "wrapt-1.13.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b73d4b78807bd299b38e4598b8e7bd34ed55d480160d2e7fdaabd9931afa65f9"}, + {file = "wrapt-1.13.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ec9465dd69d5657b5d2fa6133b3e1e989ae27d29471a672416fd729b429eb554"}, + {file = "wrapt-1.13.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dd91006848eb55af2159375134d724032a2d1d13bcc6f81cd8d3ed9f2b8e846c"}, + {file = "wrapt-1.13.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ae9de71eb60940e58207f8e71fe113c639da42adb02fb2bcbcaccc1ccecd092b"}, + {file = "wrapt-1.13.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:51799ca950cfee9396a87f4a1240622ac38973b6df5ef7a41e7f0b98797099ce"}, + {file = "wrapt-1.13.3-cp38-cp38-win32.whl", hash = "sha256:4b9c458732450ec42578b5642ac53e312092acf8c0bfce140ada5ca1ac556f79"}, + {file = "wrapt-1.13.3-cp38-cp38-win_amd64.whl", hash = "sha256:7dde79d007cd6dfa65afe404766057c2409316135cb892be4b1c768e3f3a11cb"}, + {file = "wrapt-1.13.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:981da26722bebb9247a0601e2922cedf8bb7a600e89c852d063313102de6f2cb"}, + {file = "wrapt-1.13.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:705e2af1f7be4707e49ced9153f8d72131090e52be9278b5dbb1498c749a1e32"}, + {file = "wrapt-1.13.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:25b1b1d5df495d82be1c9d2fad408f7ce5ca8a38085e2da41bb63c914baadff7"}, + {file = "wrapt-1.13.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:77416e6b17926d953b5c666a3cb718d5945df63ecf922af0ee576206d7033b5e"}, + {file = "wrapt-1.13.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:865c0b50003616f05858b22174c40ffc27a38e67359fa1495605f96125f76640"}, + {file = "wrapt-1.13.3-cp39-cp39-win32.whl", hash = "sha256:0a017a667d1f7411816e4bf214646d0ad5b1da2c1ea13dec6c162736ff25a374"}, + {file = "wrapt-1.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:81bd7c90d28a4b2e1df135bfbd7c23aee3050078ca6441bead44c42483f9ebfb"}, + {file = "wrapt-1.13.3.tar.gz", hash = "sha256:1fea9cd438686e6682271d36f3481a9f3636195578bab9ca3382e2f5f01fc185"}, +] +zipp = [ + {file = "zipp-3.7.0-py3-none-any.whl", hash = "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"}, + {file = "zipp-3.7.0.tar.gz", hash = "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d"}, +] From 465e2859a40fe8b33f37f6cf8085833f8ad65b21 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Tue, 8 Mar 2022 11:35:13 +0100 Subject: [PATCH 60/74] Allow numba in benchmarks, fix bench_ad --- benchmarks/eko/benchmark_ad.py | 13 +++++-------- pyproject.toml | 8 +++++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/benchmarks/eko/benchmark_ad.py b/benchmarks/eko/benchmark_ad.py index 9b0ac352e..b220cae5a 100644 --- a/benchmarks/eko/benchmark_ad.py +++ b/benchmarks/eko/benchmark_ad.py @@ -14,7 +14,6 @@ def benchmark_melling_g3_pegasus(): check_melling_g3_pegasus(N) -@pytest.mark.isolated def check_melling_g3_pegasus(N): S1 = h.harmonic_S1(N) N1 = N + 1.0 @@ -40,25 +39,23 @@ def check_melling_g3_pegasus(N): - 0.3174 * (zeta2 - S15 / N5) / N5 + 0.0699 * (zeta2 - S16 / N6) / N6 ) - np.testing.assert_allclose(h.mellin_g3(N), SPMOM) @pytest.mark.isolated def benchmark_gamma_ns_1_pegasus(): - for N in range(10): + # remember that singlet has pole at N=1 + for N in [2, 3, 4, 1 + 1j, 1 - 1j, 2 + 1j, 3 + 1j]: for NF in [3, 4, 5]: - check_gamma_ns_1_pegasus(N, NF) + check_gamma_1_pegasus(N, NF) -@pytest.mark.isolated -def check_gamma_ns_1_pegasus(N, NF): - # pylint: disable=line-too-long,too-many-locals,too-many-statements +def check_gamma_1_pegasus(N, NF): # Test against pegasus implementation ZETA2 = h.zeta2 ZETA3 = h.zeta3 - N = np.random.rand(1) + np.random.rand(1) * 1j + # N = np.random.rand(1) + np.random.rand(1) * 1j S1 = h.harmonic_S1(N) S2 = h.harmonic_S2(N) diff --git a/pyproject.toml b/pyproject.toml index 839941f5c..1a2f29375 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,8 +76,10 @@ ekonav = "ekomark.navigator:launch_navigator" [tool.poe.tasks] test = "pytest tests" bench = "pytest benchmarks" -bench-iso = "pytest benchmarks -m isolated" -bench-run = "pytest benchmarks -m 'not isolated'" +bench-iso.cmd = "pytest benchmarks -m isolated" +bench-iso.env.NUMBA_DISABLE_JIT.default = "0" +bench-run.cmd = "pytest benchmarks -m 'not isolated'" +bench-run.env.NUMBA_DISABLE_JIT.default = "0" lint = "pylint src/**/*.py -E" lint-warnings = "pylint src/**/*.py --exit-zero" sandbox = "python benchmarks/sandbox.py" @@ -101,7 +103,7 @@ addopts = [ '--cov-report=xml', '--strict-markers', ] -env = ["NUMBA_DISABLE_JIT=1"] +env = ["D:NUMBA_DISABLE_JIT=1"] markers = ["isolated: marks benchmarks as isolated"] [tool.pylint.master] From fe7f3281bbff40b10759132a63c8ffa49eb22a24 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Tue, 8 Mar 2022 11:56:32 +0100 Subject: [PATCH 61/74] Fix bench runner sandbox cache --- src/ekomark/benchmark/runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ekomark/benchmark/runner.py b/src/ekomark/benchmark/runner.py index 1f4ced08b..40fd3455a 100644 --- a/src/ekomark/benchmark/runner.py +++ b/src/ekomark/benchmark/runner.py @@ -72,7 +72,7 @@ def run_me(self, theory, ocard, _pdf): if self.sandbox: rerun = True ops_id = f"o{ocard['hash'][:6]}_t{theory['hash'][:6]}" - path = f"{banana_cfg.cfg['paths']['database'].parents[0]}/{ops_id}.yaml" + path = f"{banana_cfg.cfg['paths']['database'].parents[0]}/{ops_id}.tar" if os.path.exists(path): rerun = False From 42fb1b904825a4d9726c5aa58c8acc7ec41fdb62 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Tue, 8 Mar 2022 12:03:24 +0100 Subject: [PATCH 62/74] Improve Int.Disp. doc (drop defaults) --- src/eko/interpolation.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/eko/interpolation.py b/src/eko/interpolation.py index a30617072..bb0ade7b0 100644 --- a/src/eko/interpolation.py +++ b/src/eko/interpolation.py @@ -510,19 +510,15 @@ def from_dict(cls, operators_card, mode_N=True): * - Name - Type - - default - description * - ``interpolation_xgrid`` - :py:obj:`list(float)` - - [required] - the interpolation grid * - ``interpolation_polynomial_degree`` - :py:obj:`int` - - ``4`` - polynomial degree of the interpolating function * - ``interpolation_is_log`` - :py:obj:`bool` - - ``True`` - use logarithmic interpolation? Parameters From a0b5017aacdf7ba0b23f420a1e50e25fe8b30549 Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Tue, 8 Mar 2022 12:05:47 +0100 Subject: [PATCH 63/74] Fix sphinx errors --- doc/Makefile | 2 +- doc/source/code/Operators.rst | 4 ++-- doc/source/code/Utilities.rst | 1 + doc/source/development/ekomark.rst | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index 57aadc8d8..45cf7008b 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -10,7 +10,7 @@ BUILDDIR = build EKODIR = ../src/eko EKOOUT = $(SOURCEDIR)/modules/eko EKOMARKDIR = ../src/ekomark -EKOMARKOUT = ./source/development/ekomark +EKOMARKOUT = $(SOURCEDIR)/development/ekomark TODOOUTFILE = ./source/development/code_todos.rst diff --git a/doc/source/code/Operators.rst b/doc/source/code/Operators.rst index 80f48003f..c58a64b37 100644 --- a/doc/source/code/Operators.rst +++ b/doc/source/code/Operators.rst @@ -55,7 +55,7 @@ The classes are nested as follows: * is the connection of the :class:`~eko.evolution_operator.Operator` between the different flavor bases * is initialized with the 3-dimensional :ref:`theory/FlavorSpace:Operator Anomalous Dimension Basis` - * does recombine the operator in the :ref:`theory/FlavorSpace:Operator Intrinsic Evolution Basis` + * does recombine the operator in the :ref:`theory/FlavorSpace:Operator Intrinsic QCD Evolution Basis` (see :doc:`Matching Conditions `) * exports the operators to :ref:`theory/FlavorSpace:Operator Flavor Basis` in a :class:`~numpy.ndarray` @@ -63,4 +63,4 @@ The classes are nested as follows: * represents a single operator in Mellin space for a given element of the :ref:`theory/FlavorSpace:Operator Bases` * inside :class:`~eko.evolution_operator.Operator` they are in :ref:`theory/FlavorSpace:Operator Anomalous Dimension Basis` - * inside :class:`~eko.evolution_operator.physical.PhysicalOperator` they are in :ref:`theory/FlavorSpace:Operator Intrinsic Evolution Basis` + * inside :class:`~eko.evolution_operator.physical.PhysicalOperator` they are in :ref:`theory/FlavorSpace:Operator Intrinsic QCD Evolution Basis` diff --git a/doc/source/code/Utilities.rst b/doc/source/code/Utilities.rst index 367db3083..639869ed6 100644 --- a/doc/source/code/Utilities.rst +++ b/doc/source/code/Utilities.rst @@ -55,6 +55,7 @@ Apart from the :doc:`operator ` classes, `eko` also provides some uti - :class:`eko.strong_coupling.StrongCoupling`: Implementation of the :ref:`theory/pQCD:strong coupling` +.. .. include:: IO-tabs/StrongCoupling.rst - :class:`eko.interpolation.InterpolatorDispatcher`: Implementation of the :doc:`../theory/Interpolation` diff --git a/doc/source/development/ekomark.rst b/doc/source/development/ekomark.rst index 9a9d99b4d..5a8630645 100644 --- a/doc/source/development/ekomark.rst +++ b/doc/source/development/ekomark.rst @@ -30,7 +30,7 @@ Ekomark is composed by four subpackages: * ``plot`` containing all the scripts to produce the output plots. -The banana configuration is loaded from ``banana_cfg.py`` file. +The banana configuration is loaded from ``banana/cfg.py`` file. To run Ekomark see the section of the available :doc:`runners`. Furthermore Ekomark provides also a python interpreter called `ekonavigator` to inspect the cached benchmark results. From f533c594f256c27653f7254657c86af12dc4fb96 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Tue, 8 Mar 2022 12:22:54 +0100 Subject: [PATCH 64/74] Fix bench runner sandbox load --- src/ekomark/benchmark/runner.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ekomark/benchmark/runner.py b/src/ekomark/benchmark/runner.py index 40fd3455a..40ccab8a7 100644 --- a/src/ekomark/benchmark/runner.py +++ b/src/ekomark/benchmark/runner.py @@ -87,8 +87,7 @@ def run_me(self, theory, ocard, _pdf): else: # load print(f"Using cached eko data: {os.path.relpath(path,os.getcwd())}") - with open(path, encoding="utf-8") as o: - out = eko.output.Output.load_yaml(o) + out = eko.output.Output.load_tar(path) if self.plot_operator: From 959024c7ffe6f2bf026169745e1dacbb19492027 Mon Sep 17 00:00:00 2001 From: Felix Hekhorn Date: Tue, 8 Mar 2022 12:49:29 +0100 Subject: [PATCH 65/74] Add ekobox to doc --- doc/.gitignore | 1 + doc/Makefile | 6 +++++- doc/source/conf.py | 5 +++++ doc/source/index.rst | 1 + doc/source/shared/abbreviations.rst | 4 ++++ 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/.gitignore b/doc/.gitignore index 3025cff24..625cc76e2 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -3,6 +3,7 @@ source/development/code_todos.rst # Ignore auto generated module references source/modules source/development/ekomark +source/development/ekobox # ignore temporary build files _build/ # Ignore generated sphinx-bibtex file diff --git a/doc/Makefile b/doc/Makefile index 45cf7008b..846f711e3 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -11,6 +11,8 @@ EKODIR = ../src/eko EKOOUT = $(SOURCEDIR)/modules/eko EKOMARKDIR = ../src/ekomark EKOMARKOUT = $(SOURCEDIR)/development/ekomark +EKOBOXKDIR = ../src/ekobox +EKOBOXKOUT = $(SOURCEDIR)/development/ekobox TODOOUTFILE = ./source/development/code_todos.rst @@ -35,7 +37,9 @@ clean: rm -rf _build cleanall: clean clean-todos - rm -rf $(SOURCEDIR)/modules + rm -rf $(EKOOUT) + rm -rf $(EKOMARKOUT) + rm -rf $(EKOBOXKOUT) # TODOs todos: diff --git a/doc/source/conf.py b/doc/source/conf.py index efc04dbf3..f5452b4d7 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -328,6 +328,11 @@ def run_apidoc(_): package = here.parents[1] / "src" / "ekomark" main(["--module-first", "-o", str(docs_dest), str(package)]) (docs_dest / "modules.rst").unlink() + # 'ekobox' + docs_dest = here / "development" / "ekobox" + package = here.parents[1] / "src" / "ekobox" + main(["--module-first", "-o", str(docs_dest), str(package)]) + (docs_dest / "modules.rst").unlink() def setup(app): diff --git a/doc/source/index.rst b/doc/source/index.rst index f0c78d36f..adaa99ab6 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -58,4 +58,5 @@ EKO is ... development/Benchmarks.rst development/ekomark.rst + development/ekobox/ekobox.rst development/code_todos diff --git a/doc/source/shared/abbreviations.rst b/doc/source/shared/abbreviations.rst index f1bc7b8b4..017ce001f 100644 --- a/doc/source/shared/abbreviations.rst +++ b/doc/source/shared/abbreviations.rst @@ -94,3 +94,7 @@ .. |T| raw:: html + + +.. |API| replace:: + :abbr:`API (Application Program Interface)` From 0674f20880bbe48d0d4db79c8bb94803de4938d6 Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Tue, 8 Mar 2022 13:06:26 +0100 Subject: [PATCH 66/74] Move ekobox location in docs --- doc/.gitignore | 2 +- doc/Makefile | 2 +- doc/source/code/genpdf.rst | 75 +++++++++++++++++++++++++++++++++++ doc/source/code/interface.rst | 9 +++++ doc/source/conf.py | 22 ++++------ doc/source/index.rst | 2 +- src/ekobox/genpdf/cli.py | 2 +- 7 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 doc/source/code/genpdf.rst create mode 100644 doc/source/code/interface.rst diff --git a/doc/.gitignore b/doc/.gitignore index 625cc76e2..d60bb3d69 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -3,7 +3,7 @@ source/development/code_todos.rst # Ignore auto generated module references source/modules source/development/ekomark -source/development/ekobox +source/code/ekobox # ignore temporary build files _build/ # Ignore generated sphinx-bibtex file diff --git a/doc/Makefile b/doc/Makefile index 846f711e3..3954fb760 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -12,7 +12,7 @@ EKOOUT = $(SOURCEDIR)/modules/eko EKOMARKDIR = ../src/ekomark EKOMARKOUT = $(SOURCEDIR)/development/ekomark EKOBOXKDIR = ../src/ekobox -EKOBOXKOUT = $(SOURCEDIR)/development/ekobox +EKOBOXKOUT = $(SOURCEDIR)/code/ekobox TODOOUTFILE = ./source/development/code_todos.rst diff --git a/doc/source/code/genpdf.rst b/doc/source/code/genpdf.rst new file mode 100644 index 000000000..551dee766 --- /dev/null +++ b/doc/source/code/genpdf.rst @@ -0,0 +1,75 @@ +genpdf +====== + +We provide also a console script called ``genpdf`` that is able +to generate and install a custom |PDF| set in the `lhapdf` format. +In particular, the command ``genpdf install [NAME]`` simply +install the |PDF| called ``[NAME]`` in the lhapdf folder and +the ``genpdf generate [NAME]`` command generates the custom |PDF| +and saves it as ``[NAME]`` in the current directory. +Notice that the argument ``[NAME]`` is the only mandatory one. + +The custom |PDF| can be generated in three different ways which +are accessible trough the option ``-p [PARENT]`` (the complete spelling +is ``genpdf generate [NAME] -p [PARENT]``): + + 1. If ``[PARENT]`` is the name of an available |PDF|, it is used as parent + |PDF| and thus copied to generate the new custom PDF. + 2. If ``[PARENT]`` is "toylh" or "toy", the **toy** |PDF| is used as parent. + 3. If the option ``-p [PARENT]`` is not used, the |PDF| is + generated using **x(1-x)** for all the flavors. + +Trough the use of the argument +``[LABEL]`` (``genpdf generate [NAME] [LABEL] [OPTIONS]``) it is also possible +to specify a set of flavors (expressed in |pid| basis) or a set of +**evolution basis components** on which filtering the custom |PDF|. +In this way the specified set is kept in the final |PDF|, while the rest +is discarded. + +In the case of custom |PDF| generated starting from a parent |PDF|, +it is possible to generate all the members trough the flag ``-m``. If this +flag is not used, only the *zero* member is generated (together with the *info* +file of course). Using the flag ``-m`` when the custom |PDF| is generated +either using the **toy** |PDF| or the **x(1-x)** function, has no effects. + +In order to automatically install the custom |PDF| in the lhapdf folder +at generation time (so without using ``genpdf install [NAME]`` after the +generation), it is possible to use the ``-i`` flag. + + +We also provide an API with some additional features and possibilities +such as generating a |PDF| with a custom function for every |pid| +(through a ``dict`` structure) and filtering custom combination of +flavors - see :mod:`here ` for details. + +Examples +-------- + +.. code-block:: bash + + $ genpdf generate gonly 21 + +This will generate the custom PDF using the debug x(1-x) PDF as parent +and then it will keep only the gluon. + +.. code-block:: bash + + $ genpdf install gonly + +This will install the previous PDF in the lhapdf folder. + +.. code-block:: bash + + $ genpdf generate Sonly S -p toy -i + +This will generate the custom PDF using the toy PDF as parent and then +it will keep only the singlet combination. The generated PDF is also +automatically installed in the lhapdf folder. + +.. code-block:: bash + + $ genpdf generate Vonly V -p CT10 -m + +This will generate the custom PDF using the CT10 PDF set as parent +(if available) and it will keep only the valence combination. Moreover +it will generate all the members of the parent PDF. diff --git a/doc/source/code/interface.rst b/doc/source/code/interface.rst new file mode 100644 index 000000000..18f9c42b6 --- /dev/null +++ b/doc/source/code/interface.rst @@ -0,0 +1,9 @@ +Interface +========= + + +.. toctree:: + :maxdepth: 1 + + ekobox/ekobox.rst + genpdf.rst diff --git a/doc/source/conf.py b/doc/source/conf.py index f5452b4d7..40754819e 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -319,20 +319,14 @@ def run_apidoc(_): sys.path.append(str(here.parent)) # 'eko' - docs_dest = here / "modules" / "eko" - package = here.parents[1] / "src" / "eko" - main(["--module-first", "-o", str(docs_dest), str(package)]) - (docs_dest / "modules.rst").unlink() - # 'ekomark' - docs_dest = here / "development" / "ekomark" - package = here.parents[1] / "src" / "ekomark" - main(["--module-first", "-o", str(docs_dest), str(package)]) - (docs_dest / "modules.rst").unlink() - # 'ekobox' - docs_dest = here / "development" / "ekobox" - package = here.parents[1] / "src" / "ekobox" - main(["--module-first", "-o", str(docs_dest), str(package)]) - (docs_dest / "modules.rst").unlink() + for pkg, docs_dest in dict( + eko=here / "modules" / "eko", + ekomark=here / "development" / "ekomark", + ekobox=here / "code" / "ekobox", + ).items(): + package = here.parents[1] / "src" / pkg + main(["--module-first", "-o", str(docs_dest), str(package)]) + (docs_dest / "modules.rst").unlink() def setup(app): diff --git a/doc/source/index.rst b/doc/source/index.rst index adaa99ab6..e724727d5 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -46,6 +46,7 @@ EKO is ... :hidden: code/IO + code/interface API code/Operators code/Utilities @@ -58,5 +59,4 @@ EKO is ... development/Benchmarks.rst development/ekomark.rst - development/ekobox/ekobox.rst development/code_todos diff --git a/src/ekobox/genpdf/cli.py b/src/ekobox/genpdf/cli.py index e60bd259e..02e2c62c8 100644 --- a/src/ekobox/genpdf/cli.py +++ b/src/ekobox/genpdf/cli.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ -This module defines the CLI - see :doc:`here ` +This module defines the CLI - see :doc:`here ` """ import click From 503695fc535c2d17c858b9765b82669f8761d8aa Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 8 Mar 2022 13:12:51 +0100 Subject: [PATCH 67/74] Drop old IO-tabs --- doc/source/code/IO-tabs/InterpolatorDispatcher.rst | 6 ------ doc/source/code/IO-tabs/ThresholdConfig.rst | 10 ---------- doc/source/code/Utilities.rst | 6 ------ 3 files changed, 22 deletions(-) delete mode 100644 doc/source/code/IO-tabs/InterpolatorDispatcher.rst delete mode 100644 doc/source/code/IO-tabs/ThresholdConfig.rst diff --git a/doc/source/code/IO-tabs/InterpolatorDispatcher.rst b/doc/source/code/IO-tabs/InterpolatorDispatcher.rst deleted file mode 100644 index 2d98736d1..000000000 --- a/doc/source/code/IO-tabs/InterpolatorDispatcher.rst +++ /dev/null @@ -1,6 +0,0 @@ -InterpolatorDispatcher parameters: - -- :obj:`list(float)` ``interpolation_xgrid`` the interpolation grid; **Required** -- :obj:`int` ``interpolation_polynomial_degree`` polynomial degree of the interpolating function; **Required** -- :obj:`bool` ``log`` use logarithmic interpolation? -- :obj:`bool` ``mode_N`` if true compiles the function on N, otherwise compiles x diff --git a/doc/source/code/IO-tabs/ThresholdConfig.rst b/doc/source/code/IO-tabs/ThresholdConfig.rst deleted file mode 100644 index 3d14c2688..000000000 --- a/doc/source/code/IO-tabs/ThresholdConfig.rst +++ /dev/null @@ -1,10 +0,0 @@ -ThresholdConfig parameters: - -- :obj:`list(float)`: **Required** - - :obj:`float` ``mc`` charm mass squared in GeV; - - :obj:`float` ``mb`` bottom mass squared in GeV; - - :obj:`float` ``mt`` top mass squared in GeV; -- :obj:`float` ``q2_ref`` reference scale squared in GeV; -- :obj:`int` ``nf_ref`` number of active flavors at the reference scale -- :obj`list(float)`: list of ratios between masses and matching thresholds squared -- :obj:`int` ``max_nf`` maximum number of active flavors diff --git a/doc/source/code/Utilities.rst b/doc/source/code/Utilities.rst index 367db3083..1d064e212 100644 --- a/doc/source/code/Utilities.rst +++ b/doc/source/code/Utilities.rst @@ -8,8 +8,6 @@ Apart from the :doc:`operator ` classes, `eko` also provides some uti - Implementation of the flavor number scheme and the quark thresholds both for the :class:`eko.strong_coupling.StrongCoupling` and the :doc:`operators <../theory/Matching>` - .. include:: IO-tabs/ThresholdConfig.rst - When running in |VFNS| it is important to specify the number of flavors active at each given scale, since the evolution path can be different depending of the chosen setting. This path is determined by :meth:`eko.thresholds.ThresholdsAtlas.path`. @@ -55,8 +53,4 @@ Apart from the :doc:`operator ` classes, `eko` also provides some uti - :class:`eko.strong_coupling.StrongCoupling`: Implementation of the :ref:`theory/pQCD:strong coupling` - .. include:: IO-tabs/StrongCoupling.rst - - :class:`eko.interpolation.InterpolatorDispatcher`: Implementation of the :doc:`../theory/Interpolation` - - .. include:: IO-tabs/InterpolatorDispatcher.rst From be261d9042c988e9de23cc88215434848e4eade7 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 8 Mar 2022 13:13:40 +0100 Subject: [PATCH 68/74] some suggested fixes in benchmarks --- benchmarks/apfel_bench.py | 10 +++++----- benchmarks/eko/benchmark_msbar_evolution.py | 8 +++----- benchmarks/pegasus_bench.py | 8 ++++---- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/benchmarks/apfel_bench.py b/benchmarks/apfel_bench.py index a111ccac9..68f087233 100644 --- a/benchmarks/apfel_bench.py +++ b/benchmarks/apfel_bench.py @@ -68,7 +68,7 @@ def benchmark_plain(self, pto): cartesian_product(th), operators.build(operators.apfel_config), ["ToyLH"] ) - def benchmark_sv(self, pto, scheme): + def benchmark_sv(self, pto, svmode): """Scale Variation""" th = self.vfns_theory.copy() @@ -77,7 +77,7 @@ def benchmark_sv(self, pto, scheme): "PTO": [pto], "XIR": [1 / np.sqrt(2.0)], "fact_to_ren_scale_ratio": [np.sqrt(2.0)], - "ModSV": [scheme], + "ModSV": [svmode], "EScaleVar": [0], "nfref": [4], } @@ -159,7 +159,7 @@ def benchmark_plain(self, pto): cartesian_product(th), operators.build(operators.apfel_config), ["ToyLH"] ) - def benchmark_sv(self, pto, scheme): + def benchmark_sv(self, pto, svmode): """Scale Variation""" ts = [] @@ -169,7 +169,7 @@ def benchmark_sv(self, pto, scheme): "PTO": [pto], "XIR": [np.sqrt(0.5)], "fact_to_ren_scale_ratio": [np.sqrt(2.0)], - "ModSV": [scheme], + "ModSV": [svmode], "EScaleVar": [0], } ) @@ -180,7 +180,7 @@ def benchmark_sv(self, pto, scheme): "PTO": [pto], "XIR": [np.sqrt(2.0)], "fact_to_ren_scale_ratio": [np.sqrt(0.5)], - "ModSV": [scheme], + "ModSV": [svmode], "EScaleVar": [0], } ) diff --git a/benchmarks/eko/benchmark_msbar_evolution.py b/benchmarks/eko/benchmark_msbar_evolution.py index 9de1a7f53..da8db85e4 100644 --- a/benchmarks/eko/benchmark_msbar_evolution.py +++ b/benchmarks/eko/benchmark_msbar_evolution.py @@ -44,8 +44,7 @@ class BenchmarkMSbar: def benchmark_APFEL_msbar_evolution(self): theory = copy.deepcopy(theory_dict) - Q2s = np.power([1, 96, 150], 2) - nfs = [3, 5, 5] + bench_values = dict(zip(np.power([1, 96, 150], 2), [3, 5, 5])) theory.update( { "mc": 1.4, @@ -120,7 +119,7 @@ def benchmark_APFEL_msbar_evolution(self): hqm_scheme=theory["HQ"], ) my_vals = [] - for nf_to, Q2 in zip(nfs, Q2s): + for Q2, nf_to in bench_values.items(): my_masses = [] for n in [3, 4, 5]: my_masses.append( @@ -153,7 +152,7 @@ def benchmark_APFEL_msbar_evolution(self): apfel.InitializeAPFEL() # collect apfel masses apfel_vals_cur = [] - for Q2 in Q2s: + for Q2 in bench_values: masses = [] for n in [4, 5, 6]: masses.append(apfel.HeavyQuarkMass(n, np.sqrt(Q2))) @@ -201,7 +200,6 @@ def benchmark_APFEL_msbar_solution(self): ) apfel.SetRenFacRatio(theory_dict["fact_to_ren_scale_ratio"]) apfel.InitializeAPFEL() - apfel.EnableWelcomeMessage(1) # check myself to APFEL np.testing.assert_allclose( apfel_vals, np.sqrt(np.array(my_masses)), rtol=4e-4 diff --git a/benchmarks/pegasus_bench.py b/benchmarks/pegasus_bench.py index 3a40a0bc0..498ba322f 100644 --- a/benchmarks/pegasus_bench.py +++ b/benchmarks/pegasus_bench.py @@ -75,7 +75,7 @@ def benchmark_plain(self, pto): cartesian_product(th), operators.build(operators.pegasus_config), ["ToyLH"] ) - def benchmark_sv(self, pto, scheme): + def benchmark_sv(self, pto, svmode): """Scale Variation""" th = self.zm_theory.copy() @@ -83,7 +83,7 @@ def benchmark_sv(self, pto, scheme): { "PTO": [pto], "fact_to_ren_scale_ratio": [np.sqrt(0.5), np.sqrt(2.0)], - "ModSV": [scheme], + "ModSV": [svmode], } ) self.run( @@ -124,7 +124,7 @@ def benchmark_plain(self, pto): cartesian_product(th), operators.build(operators.pegasus_config), ["ToyLH"] ) - def benchmark_sv(self, pto, scheme): + def benchmark_sv(self, pto, svmode): """Scale Variation""" th = self.ffns_theory.copy() @@ -132,7 +132,7 @@ def benchmark_sv(self, pto, scheme): { "PTO": [pto], "fact_to_ren_scale_ratio": [np.sqrt(0.5), np.sqrt(2.0)], - "ModSV": [scheme], + "ModSV": [svmode], } ) self.run( From fa9255d9112a278cb1a8d6f7e5bb3861222311d7 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 8 Mar 2022 13:32:24 +0100 Subject: [PATCH 69/74] separate is_downward path and flavor shift --- src/eko/evolution_operator/grid.py | 7 ++++--- src/eko/msbar_masses.py | 5 +++-- src/eko/strong_coupling.py | 3 ++- src/eko/thresholds.py | 26 +++++++++++++++++++------- tests/eko/test_thresholds.py | 12 ++++++------ 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py index 750edb8de..bea651f1c 100644 --- a/src/eko/evolution_operator/grid.py +++ b/src/eko/evolution_operator/grid.py @@ -11,7 +11,7 @@ import numpy as np -from eko.thresholds import is_downward_path +from eko.thresholds import flavor_shift, is_downward_path from .. import basis_rotation as br from .. import matching_conditions, member @@ -166,7 +166,8 @@ def get_threshold_operators(self, path): # The base area is always that of the reference q thr_ops = [] # is_downward point to smaller nf - is_downward, shift = is_downward_path(path) + is_downward = is_downward_path(path) + shift = flavor_shift(is_downward) for seg in path[:-1]: new_op_key = seg.tuple ome = OperatorMatrixElement(self.config, self.managers, is_downward) @@ -243,7 +244,7 @@ def generate(self, q2): ) operator.compute() intrinsic_range = self.config["intrinsic_range"] - is_downward, _ = is_downward_path(path) + is_downward = is_downward_path(path) if is_downward: intrinsic_range = [4, 5, 6] final_op = physical.PhysicalOperator.ad_to_evol_map( diff --git a/src/eko/msbar_masses.py b/src/eko/msbar_masses.py index cf2260752..9b984704d 100644 --- a/src/eko/msbar_masses.py +++ b/src/eko/msbar_masses.py @@ -10,7 +10,7 @@ from .beta import b, beta from .gamma import gamma from .strong_coupling import StrongCoupling, invert_matching_coeffs -from .thresholds import ThresholdsAtlas, is_downward_path +from .thresholds import ThresholdsAtlas, flavor_shift, is_downward_path def ker_exact(a0, a1, order, nf): @@ -304,7 +304,8 @@ def evolve( strong_coupling.thresholds.thresholds_ratios, ) path = thr_atlas.path(q2_to, nf_to) - is_downward, shift = is_downward_path(path) + is_downward = is_downward_path(path) + shift = flavor_shift(is_downward) ev_mass = 1.0 for k, seg in enumerate(path): diff --git a/src/eko/strong_coupling.py b/src/eko/strong_coupling.py index 711579685..0642ecdef 100644 --- a/src/eko/strong_coupling.py +++ b/src/eko/strong_coupling.py @@ -371,7 +371,8 @@ def a_s( # Set up the path to follow in order to go from q2_0 to q2_ref final_as = self.as_ref path = self.thresholds.path(scale_to, nf_to) - is_downward, shift = thresholds.is_downward_path(path) + is_downward = thresholds.is_downward_path(path) + shift = thresholds.flavor_shift(is_downward) # as a default assume mu_F^2 = mu_R^2 if fact_scale is None: diff --git a/src/eko/thresholds.py b/src/eko/thresholds.py index b2e03c96a..f3f173cb0 100644 --- a/src/eko/thresholds.py +++ b/src/eko/thresholds.py @@ -276,13 +276,25 @@ def is_downward_path(path): Returns ------- is_downward: bool - True is number of flavor is decreasing + True for a downward path + """ + if len(path) == 1: + return path[0].is_downward_q2 + return path[1].nf < path[0].nf + + +def flavor_shift(is_downward): + """ + Determine the shift to number of light flavors + + Parameters + ---------- + is_downward: bool + True for a downward path + + Returns + ------- shift: 3, 4 shift to number of light flavors """ - if len(path) == 1: - is_downward = path[0].is_downward_q2 - else: - is_downward = path[1].nf < path[0].nf - shift = 4 if is_downward else 3 - return is_downward, shift + return 4 if is_downward else 3 diff --git a/tests/eko/test_thresholds.py b/tests/eko/test_thresholds.py index 803591bfc..99eefb312 100644 --- a/tests/eko/test_thresholds.py +++ b/tests/eko/test_thresholds.py @@ -5,7 +5,7 @@ import numpy as np import pytest -from eko.thresholds import PathSegment, ThresholdsAtlas, is_downward_path +from eko.thresholds import PathSegment, ThresholdsAtlas, flavor_shift, is_downward_path class TestPathSegment: @@ -199,7 +199,7 @@ def test_errors(self): ) -def test_is_downward_path(): +def test_downward_path(): thr_atlas = ThresholdsAtlas( masses=np.power([2, 3, 4], 2), q2_ref=91**2, @@ -209,11 +209,11 @@ def test_is_downward_path(): q2_to = 5**2 path_3 = thr_atlas.path(q2_to, nf_to=3) # path_3 is downward in q2 - is_downward, shift = is_downward_path(path_3) + is_downward = is_downward_path(path_3) assert is_downward is True - assert shift == 4 + assert flavor_shift(is_downward) == 4 # path_6 is downward in q2, but forward in nf path_6 = thr_atlas.path(q2_to, nf_to=6) - is_downward, shift = is_downward_path(path_6) + is_downward = is_downward_path(path_6) assert is_downward is False - assert shift == 3 + assert flavor_shift(is_downward) == 3 From c90e6fd8eb447640c629855391584aaf2b409a48 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 8 Mar 2022 13:38:01 +0100 Subject: [PATCH 70/74] move test sv to proper folder --- tests/{ => eko}/test_sv_expanded.py | 0 tests/{ => eko}/test_sv_exponentiated.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/{ => eko}/test_sv_expanded.py (100%) rename tests/{ => eko}/test_sv_exponentiated.py (100%) diff --git a/tests/test_sv_expanded.py b/tests/eko/test_sv_expanded.py similarity index 100% rename from tests/test_sv_expanded.py rename to tests/eko/test_sv_expanded.py diff --git a/tests/test_sv_exponentiated.py b/tests/eko/test_sv_exponentiated.py similarity index 100% rename from tests/test_sv_exponentiated.py rename to tests/eko/test_sv_exponentiated.py From 9800f22f8eb39b3bfd5fcdee2422b1ff75f1611c Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 8 Mar 2022 14:03:25 +0100 Subject: [PATCH 71/74] some suggested imporvements in docs --- doc/source/code/Utilities.rst | 25 ++++++++++++++----------- doc/source/theory/pQCD.rst | 18 ++++++++++-------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/doc/source/code/Utilities.rst b/doc/source/code/Utilities.rst index 1d064e212..814fe775e 100644 --- a/doc/source/code/Utilities.rst +++ b/doc/source/code/Utilities.rst @@ -18,11 +18,11 @@ Apart from the :doc:`operator ` classes, `eko` also provides some uti .. code-block:: - ThresholdsAtlas [0.00e+00 - 4.00e+00 - 9.00e+00 - 16.00e+00 - inf], ref=49.000000000000001 @ 3 + ThresholdsAtlas [0.00e+00 - 4.00e+00 - 9.00e+00 - 16.00e+00 - inf], ref=64.000000000000001 @ 3 In this case some possible paths are: - - a path to ``Q=7`` with ``nf=6`` which is given by the following list of :class:`eko.thresholds.PathSegment` : + - a path to ``q2_to=49`` with ``nf=6`` which is given by the following list of :class:`eko.thresholds.PathSegment` : .. code-block:: @@ -31,24 +31,27 @@ Apart from the :doc:`operator ` classes, `eko` also provides some uti and it's determined according to the list of heavy quark thresholds. This path is default option when the argument ``nf_to`` is not given. - - A path to ``Q=7`` enforcing ``nf=3`` which will simply contain a single :class:`eko.thresholds.PathSegment`: + - A path to ``q2_to=49`` enforcing ``nf=4``: .. code-block:: - [PathSegment(64 -> 49, nf=3)] + [PathSegment(64 -> 4, nf=3), PathSegment(4 -> 49, nf=4)] - - A path to ``Q=7`` enforcing ``nf=4``: + - A path to ``q2_to=49`` enforcing ``nf=3`` which will simply contain a single :class:`eko.thresholds.PathSegment`: .. code-block:: - [PathSegment(64 -> 4, nf=3), PathSegment(4 -> 49, nf=4)] + [PathSegment(64 -> 49, nf=3)] + - As first step, you always go back to the closest matching scale (closest in ``nf``), + In the first two cases as first step, you go back to the closest matching scale (closest in ``nf``), running in ``nf=3``, since that is what has been specified in the boundary conditions. - Then you are back in the normal flow, and you cross all the other thresholds going according to the prescription given - by the :class:``eko.thresholds.ThresholdAtlas``. - You can noticed that :meth:`eko.thresholds.ThresholdsAtlas.path` are always ordered according to `nf` and not `Q2` scales. - This property is used in |VFNS| to determine if a path is backward or not modifying the way the different patches are matched. + Then you are back in the flavor flow, and you cross all the other thresholds going according to the prescription given + by the :class:`eko.thresholds.ThresholdAtlas`. + While in the third example you go directly to the final scale, since there is no matching scale in the middle. + You can notice that :meth:`eko.thresholds.ThresholdsAtlas.path` are always ordered according to `nf` and not `Q2` scales. + This property is used in |VFNS| to determine if the matchings are done for an increasing or decreasing number of + light flavors. - :class:`eko.strong_coupling.StrongCoupling`: Implementation of the :ref:`theory/pQCD:strong coupling` diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index 417839c22..3df4a29cf 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -47,7 +47,7 @@ In particular, the matching involved in the change from :math:`n_f` to :math:`n_ is presented in equation 3.1 of :cite:`Schroder:2005hy` for |MSbar| masses, while the same expression for POLE masses is reported in Appendix A. For this reason the boundary conditions of :class:`eko.strong_coupling.StrongCoupling` -can be specified at `scale_ref` along with ``nf_ref`` and, the computed result can +can be specified at ``scale_ref`` along with ``nf_ref`` and, the computed result can depend on the number of flavors at the target scale, see :meth:`eko.strong_coupling.StrongCoupling.a_s` An example how the evolution path is determined is given :doc:`here`. @@ -102,7 +102,7 @@ This method provides many advantages: * the same procedure can be used for any perturbative process, since the scale dependence of the strong coupling :math:`a_s(\mu^2)` and of PDFs is universal; -However there is no unique principle to determine the specific range of the scale variation; +However, there is no unique prescription to determine the specific range of the scale variation, the most used prescription specify to vary the factor :math:`\mu_F/\mu_R` in the range: :math:`1/2 \le \mu_F/\mu_R \le 2`. @@ -126,15 +126,17 @@ evolution, always evaluating the strong coupling at :math:`\mu_R^2`. the scale variation is applied to the whole |PDF| set: .. math :: - & \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) = \tilde{\mathbf{K}}(a_s) \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) \\ - & \tilde{\mathbf{K}}(a_s) = 1 - k \gamma + \frac{1}{2} k^2 \left ( \gamma^{2} - \beta \frac{\partial \gamma}{\partial a_s} \right ) + \frac{1}{6} k^3 \left [ - \beta \frac{\partial}{\partial a_s} \left( \beta \frac{\partial \gamma}{\partial a_s} \right) + 3 \beta \frac{\partial \gamma}{\partial a_s} \gamma - \gamma^3 \right ] + \mathcal{O}(k^4) + \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) & = \tilde{\mathbf{K}}(a_s) \tilde{\mathbf{E}}(a_s \leftarrow a_s^0) \\ + \tilde{\mathbf{K}}(a_s) & = 1 - k \gamma + \frac{1}{2} k^2 \left ( \gamma^{2} - \beta \frac{\partial \gamma}{\partial a_s} \right ) \\ + & + \frac{1}{6} k^3 \left [ - \beta \frac{\partial}{\partial a_s} \left( \beta \frac{\partial \gamma}{\partial a_s} \right) + 3 \beta \frac{\partial \gamma}{\partial a_s} \gamma - \gamma^3 \right ] + \mathcal{O}(k^4) where scale variation kernel is expanded consistently order by order in :math:`a_s`, leading to: .. math :: \tilde{\mathbf{K}}(a_s) \approx & 1 - a_s k \gamma^{(0)} + a_s^2 \left [ - k \gamma^{(1)} + \frac{1}{2} k^2 \gamma^{(0)} (\beta_0 + \gamma^{(0)}) \right ] \\ - & + a_s^3 \left [ -k \gamma^{(2)} + \frac{1}{2} k^2 \left(\beta_1 \gamma^{(0)} + 2 \gamma^{(1)} (\beta_0 + \gamma^{(0)} ) \right) - \frac{1}{6} k^3 \gamma^{(0)} \left(2 \beta_0^2 + 3 \beta_0 \gamma^{(0)}+\gamma^{(0),2} \right) \right] + \mathcal{O}(a^4) + & + a_s^3 \left [ -k \gamma^{(2)} + \frac{1}{2} k^2 \left(\beta_1 \gamma^{(0)} + 2 \gamma^{(1)} (\beta_0 + \gamma^{(0)} ) \right) \right. \\ + & \left. - \frac{1}{6} k^3 \gamma^{(0)} \left(2 \beta_0^2 + 3 \beta_0 \gamma^{(0)}+\gamma^{(0),2} \right) \right] + \mathcal{O}(a^4) In this way the dependence of the |EKO| on :math:`k` is factorized outside the unvaried evolution kernel. @@ -149,11 +151,11 @@ This happens because :math:`\beta \approx \mathcal{O}(a_s^2)`, :math:`\gamma \ap and the contribution proportional to :math:`\mathcal{O}(k^n)` is originated by the `n-th` derivative in :math:`\gamma` :cite:`AbdulKhalek:2019ihb`. -Furthermore the distance between the varied |EKO| and the unvaried one will decrease increasing -the perturbative order in :math:`a_s` +Furthermore the distance between the varied |EKO| and the unvaried one will decrease while +keeping higher order terms in :math:`a_s` Notice that in principle the two methods should be equivalent, especially for fully -linearized solutions (``ModEv=truncated,ev_op_max_iterations=1``), +linearized solutions (``ModEv=truncated``,``ev_op_iterations=1``), where the difference depends only on the perturbative expansion in :math:`a_s`. However, in our implementation this is not exactly true; since the integral of :math:`-\frac{\gamma(a_s)}{\beta(a_s)}` is evaluated before From 529777e1d1a86126241d7255ef2982382918568e Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 8 Mar 2022 14:13:47 +0100 Subject: [PATCH 72/74] remove some unnecessary else after return --- doc/source/conf.py | 7 +++---- src/eko/kernels/singlet.py | 9 +++------ src/eko/mellin.py | 6 ++---- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 40754819e..706b6937b 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -305,10 +305,9 @@ def process_numba_docstring( """Recover the docstring under numba, as the numba.njit decorator doesn't repeat the __doc__""" if not isinstance(obj, nb.core.registry.CPUDispatcher): return - else: - original = obj.py_func - orig_sig = inspect.signature(original) - lines = orig_sig.__doc__ + original = obj.py_func + orig_sig = inspect.signature(original) + lines = orig_sig.__doc__ # https://github.com/readthedocs/readthedocs.org/issues/1139#issuecomment-312626491 diff --git a/src/eko/kernels/singlet.py b/src/eko/kernels/singlet.py index a55fac2c8..aa5d19f33 100644 --- a/src/eko/kernels/singlet.py +++ b/src/eko/kernels/singlet.py @@ -532,12 +532,9 @@ def dispatcher( # pylint: disable=too-many-return-statements elif method == "decompose-exact": if order == 1: return nlo_decompose_exact(gamma_singlet, a1, a0, nf) - else: - return nnlo_decompose_exact(gamma_singlet, a1, a0, nf) + return nnlo_decompose_exact(gamma_singlet, a1, a0, nf) elif method == "decompose-expanded": if order == 1: return nlo_decompose_expanded(gamma_singlet, a1, a0, nf) - else: - return nnlo_decompose_expanded(gamma_singlet, a1, a0, nf) - else: - raise NotImplementedError("Selected method is not implemented") + return nnlo_decompose_expanded(gamma_singlet, a1, a0, nf) + raise NotImplementedError("Selected method is not implemented") diff --git a/src/eko/mellin.py b/src/eko/mellin.py index e718b7457..c7a717590 100644 --- a/src/eko/mellin.py +++ b/src/eko/mellin.py @@ -166,8 +166,7 @@ def edge_path(t, m, c, phi): """ if t < 0.5: # turning point: path is not differentiable in this point return c + (0.5 - t) * m * np.exp(complex(0, -phi)) - else: - return c + (t - 0.5) * m * np.exp(complex(0, +phi)) + return c + (t - 0.5) * m * np.exp(complex(0, +phi)) @nb.njit("c16(f8,f8,f8,f8)", cache=True) @@ -196,8 +195,7 @@ def edge_jac(t, m, _c, phi): """ if t < 0.5: # turning point: jacobian is not continuous here return -m * np.exp(complex(0, -phi)) - else: - return +m * np.exp(complex(0, phi)) + return +m * np.exp(complex(0, phi)) spec = [ From 4f2d37a2161be0eb698632591119c21e80828cf9 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 8 Mar 2022 14:18:52 +0100 Subject: [PATCH 73/74] fix benchmark_APFEL_fact_to_ren_lha_settings style --- benchmarks/eko/benchmark_strong_coupling.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/benchmarks/eko/benchmark_strong_coupling.py b/benchmarks/eko/benchmark_strong_coupling.py index 26852a5a1..39bbbd517 100644 --- a/benchmarks/eko/benchmark_strong_coupling.py +++ b/benchmarks/eko/benchmark_strong_coupling.py @@ -833,6 +833,7 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self): assert path_3[1].nf < path_3[0].nf assert path_3[1].q2_from < path_3[0].q2_from + apfel_val_ref = 0.03478112968976964 if use_APFEL: # run apfel apfel.CleanUp() @@ -857,9 +858,10 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self): apfel_val = apfel.AlphaQCD( np.sqrt(Q2) / theory_dict["fact_to_ren_scale_ratio"] ) / (4.0 * np.pi) - else: - apfel_val = 0.03478112968976964 + # check APFEL cached value + np.testing.assert_allclose(apfel_val_ref, apfel_val) + # check myself to APFEL - np.testing.assert_allclose(apfel_val, my_val, rtol=0.03) - np.testing.assert_allclose(apfel_val, my_val_4) + np.testing.assert_allclose(apfel_val_ref, my_val, rtol=0.03) + np.testing.assert_allclose(apfel_val_ref, my_val_4) np.testing.assert_allclose(my_val, my_val_3) From 1456443ee95ed4e885ae5f30262764485bd9e9f5 Mon Sep 17 00:00:00 2001 From: giacomomagni Date: Tue, 8 Mar 2022 15:15:42 +0100 Subject: [PATCH 74/74] expand thr atlas example --- doc/source/code/Utilities.rst | 31 ++++++++++++++++++++++++------- doc/source/theory/pQCD.rst | 2 +- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/doc/source/code/Utilities.rst b/doc/source/code/Utilities.rst index 814fe775e..2c7a6b83e 100644 --- a/doc/source/code/Utilities.rst +++ b/doc/source/code/Utilities.rst @@ -11,16 +11,33 @@ Apart from the :doc:`operator ` classes, `eko` also provides some uti When running in |VFNS| it is important to specify the number of flavors active at each given scale, since the evolution path can be different depending of the chosen setting. This path is determined by :meth:`eko.thresholds.ThresholdsAtlas.path`. - Let us consider an example to better illustrate how it works. - Imagine to have a boundary condition ``q2_ref=64, nf_ref=3`` and would like to evolve your object (|PDF| or :math:`a_s`) to a lower - scale (say ``Q=7``) but giving different number of active flavors to the final state and having set the heavy quarks mass thresholds - at: ``mc=2, mb=3, mt=4``. + Let us consider two examples to better illustrate how it works. + Imagine to have a boundary condition ``q2_ref=1``, ``nf_ref=3`` with heavy quarks mass thresholds + at: ``mc=2``, ``mb=3``, ``mt=4`` and would like to evolve your object (|PDF| or :math:`a_s`) to an higher + scale (say ``q2_to=49``). The corresponding ``ThresholdsAtlas`` will look like: + + .. code-block:: + + ThresholdsAtlas [0.00e+00 - 4.00e+00 - 9.00e+00 - 16.00e+00 - inf], ref=1.000000000000001 @ 3 + + and the evolution path will be given by: + + .. code-block:: + + [PathSegment(1 -> 4, nf=3), PathSegment(4 -> 9, nf=4), PathSegment(9 -> 16, nf=5), PathSegment(16 -> 49, nf=6)] + + where automatically the number of flavors active in each :class:`eko.thresholds.PathSegment` is determined according with the + specified thresholds scales. + + However some more complicated situations can arise when the boundary conditions are not given with the same prescription + of the :class:`eko.thresholds.ThresholdAtlas`. Let's now consider as boundary condition ``q2_ref=64`` with ``nf_ref=3``: .. code-block:: ThresholdsAtlas [0.00e+00 - 4.00e+00 - 9.00e+00 - 16.00e+00 - inf], ref=64.000000000000001 @ 3 - In this case some possible paths are: + Again we would like to evolve to ``q2_to=49`` but now giving a different number of active flavors to the final scale. + Some possible paths are: - a path to ``q2_to=49`` with ``nf=6`` which is given by the following list of :class:`eko.thresholds.PathSegment` : @@ -44,12 +61,12 @@ Apart from the :doc:`operator ` classes, `eko` also provides some uti [PathSegment(64 -> 49, nf=3)] - In the first two cases as first step, you go back to the closest matching scale (closest in ``nf``), + In the first two cases as first step, you go back to the closest matching scale (closest in `nf`), running in ``nf=3``, since that is what has been specified in the boundary conditions. Then you are back in the flavor flow, and you cross all the other thresholds going according to the prescription given by the :class:`eko.thresholds.ThresholdAtlas`. While in the third example you go directly to the final scale, since there is no matching scale in the middle. - You can notice that :meth:`eko.thresholds.ThresholdsAtlas.path` are always ordered according to `nf` and not `Q2` scales. + You can notice that :meth:`eko.thresholds.ThresholdsAtlas.path` are always ordered according to `nf` and not `q2` scales. This property is used in |VFNS| to determine if the matchings are done for an increasing or decreasing number of light flavors. diff --git a/doc/source/theory/pQCD.rst b/doc/source/theory/pQCD.rst index 3df4a29cf..2611c9876 100644 --- a/doc/source/theory/pQCD.rst +++ b/doc/source/theory/pQCD.rst @@ -155,7 +155,7 @@ Furthermore the distance between the varied |EKO| and the unvaried one will decr keeping higher order terms in :math:`a_s` Notice that in principle the two methods should be equivalent, especially for fully -linearized solutions (``ModEv=truncated``,``ev_op_iterations=1``), +linearized solutions (``ModEv=truncated``, ``ev_op_iterations=1``), where the difference depends only on the perturbative expansion in :math:`a_s`. However, in our implementation this is not exactly true; since the integral of :math:`-\frac{\gamma(a_s)}{\beta(a_s)}` is evaluated before