From bb523b4cf7553bc393e7b58e7f064c138f075c41 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 21 Jul 2023 16:06:35 +0200
Subject: [PATCH 01/67] Add mypy
---
.pre-commit-config.yaml | 7 +++++++
benchmarks/__init__.py | 0
benchmarks/ekobox/__init__.py | 0
pyproject.toml | 7 +++++++
4 files changed, 14 insertions(+)
create mode 100644 benchmarks/__init__.py
create mode 100644 benchmarks/ekobox/__init__.py
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 7ebbb534b..0a34b041f 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -42,6 +42,13 @@ repos:
args: ["--add-ignore=D107,D105"]
additional_dependencies:
- toml
+ - repo: https://github.com/pre-commit/mirrors-mypy
+ rev: v1.4.1
+ hooks:
+ - id: mypy
+ additional_dependencies: [types-PyYAML]
+ pass_filenames: false
+ args: [".", "--ignore-missing-imports"]
- repo: https://github.com/pre-commit/pre-commit
rev: v3.3.3
hooks:
diff --git a/benchmarks/__init__.py b/benchmarks/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/benchmarks/ekobox/__init__.py b/benchmarks/ekobox/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/pyproject.toml b/pyproject.toml
index 31be6cb0c..1f7d239c5 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -171,3 +171,10 @@ max-args = 10
[tool.pydocstyle]
convention = "numpy"
+
+[tool.mypy]
+exclude = [
+ 'extras/',
+ 'benchmarks/env',
+ 'doc/',
+]
From 103567c5c3a508bb57a4a615e4cf5f794ada9c5d Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 21 Jul 2023 16:39:43 +0200
Subject: [PATCH 02/67] Restrict mypy and start fixing
---
.pre-commit-config.yaml | 2 +-
pyproject.toml | 7 -------
src/eko/couplings.py | 5 +++--
src/eko/evolution_operator/__init__.py | 3 ++-
src/eko/evolution_operator/grid.py | 4 ++--
src/eko/quantities/couplings.py | 3 +--
6 files changed, 9 insertions(+), 15 deletions(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 0a34b041f..a8dc75857 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -48,7 +48,7 @@ repos:
- id: mypy
additional_dependencies: [types-PyYAML]
pass_filenames: false
- args: [".", "--ignore-missing-imports"]
+ args: ["--ignore-missing-imports", "src/"]
- repo: https://github.com/pre-commit/pre-commit
rev: v3.3.3
hooks:
diff --git a/pyproject.toml b/pyproject.toml
index 1f7d239c5..31be6cb0c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -171,10 +171,3 @@ max-args = 10
[tool.pydocstyle]
convention = "numpy"
-
-[tool.mypy]
-exclude = [
- 'extras/',
- 'benchmarks/env',
- 'doc/',
-]
diff --git a/src/eko/couplings.py b/src/eko/couplings.py
index b0d39a070..1b3620032 100644
--- a/src/eko/couplings.py
+++ b/src/eko/couplings.py
@@ -8,10 +8,11 @@
"""
import logging
-from typing import Iterable, List
+from typing import Dict, Iterable, List, Tuple
import numba as nb
import numpy as np
+import numpy.typing as npt
import scipy
from . import constants, matchings
@@ -474,7 +475,7 @@ def assert_positive(name, var):
self.decoupled_running,
)
# cache
- self.cache = {}
+ self.cache: Dict[Tuple[float, float, int, float, float], npt.NDArray] = {}
@property
def mu2_ref(self):
diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py
index eab3c64de..6a49551a5 100644
--- a/src/eko/evolution_operator/__init__.py
+++ b/src/eko/evolution_operator/__init__.py
@@ -8,6 +8,7 @@
import os
import time
from multiprocessing import Pool
+from typing import Dict, Tuple
import numba as nb
import numpy as np
@@ -617,7 +618,7 @@ def __init__(
# TODO make 'cut' external parameter?
self._mellin_cut = mellin_cut
self.is_threshold = is_threshold
- self.op_members = {}
+ self.op_members: Dict[Tuple[int, int], OpMember] = {}
self.order = tuple(config["order"])
self.alphaem_running = self.managers["couplings"].alphaem_running
if self.log_label == "Evolution":
diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py
index ca8a46d51..ad97f6e42 100644
--- a/src/eko/evolution_operator/grid.py
+++ b/src/eko/evolution_operator/grid.py
@@ -6,7 +6,7 @@
"""
import logging
from dataclasses import astuple
-from typing import Dict, List, Optional
+from typing import Any, Dict, List, Optional
import numpy as np
import numpy.typing as npt
@@ -61,7 +61,7 @@ def __init__(
interpol_dispatcher: InterpolatorDispatcher,
):
# check
- config = {}
+ config: Dict[str, Any] = {}
config["order"] = order
config["intrinsic_range"] = intrinsic_flavors
config["xif2"] = xif**2
diff --git a/src/eko/quantities/couplings.py b/src/eko/quantities/couplings.py
index 449abab38..01b11d138 100644
--- a/src/eko/quantities/couplings.py
+++ b/src/eko/quantities/couplings.py
@@ -1,7 +1,6 @@
"""Types and quantities related to theory couplings."""
import dataclasses
import enum
-from typing import Optional
from ..io.dictlike import DictLike
from ..io.types import FlavorsNumber, LinearScale, ReferenceRunning, Scalar
@@ -22,7 +21,7 @@ class CouplingsInfo(DictLike):
alphaem: Coupling
scale: LinearScale
max_num_flavs: FlavorsNumber
- num_flavs_ref: Optional[FlavorsNumber]
+ num_flavs_ref: FlavorsNumber
r"""Number of active flavors at strong coupling reference scale.
I.e. :math:`n_{f,\text{ref}}(\mu^2_{\text{ref}})`, formerly called
From e7b6e9360390e0224664b2faf6e21f9327f15a12 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 21 Jul 2023 16:58:36 +0200
Subject: [PATCH 03/67] Start fixing tests for num_flavs_ref=None
---
tests/eko/quantities/test_couplings.py | 2 +-
tests/eko/test_couplings.py | 28 ++++++++++++++------------
2 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/tests/eko/quantities/test_couplings.py b/tests/eko/quantities/test_couplings.py
index 0a3b97415..00ccae9d1 100644
--- a/tests/eko/quantities/test_couplings.py
+++ b/tests/eko/quantities/test_couplings.py
@@ -3,7 +3,7 @@
def test_couplings_ref():
scale = 90.0
- d = dict(alphas=0.1, alphaem=0.01, scale=scale, max_num_flavs=6, num_flavs_ref=None)
+ d = dict(alphas=0.1, alphaem=0.01, scale=scale, max_num_flavs=6, num_flavs_ref=5)
couplings = CouplingsInfo.from_dict(d)
assert couplings.scale == scale
assert not couplings.em_running
diff --git a/tests/eko/test_couplings.py b/tests/eko/test_couplings.py
index 62110da16..646a56448 100644
--- a/tests/eko/test_couplings.py
+++ b/tests/eko/test_couplings.py
@@ -54,7 +54,7 @@ def test_init(self):
alphas=alpharef[0],
alphaem=alpharef[1],
scale=muref,
- num_flavs_ref=None,
+ num_flavs_ref=5,
max_num_flavs=6,
)
)
@@ -152,18 +152,19 @@ def test_ref(self):
(0, np.inf, np.inf),
(2, 4, 175),
]
+ nfrefs = (3, 4, 5)
alpharef = (0.118, 0.00781)
muref = 91.0
- couplings = CouplingsInfo.from_dict(
- dict(
- alphas=alpharef[0],
- alphaem=alpharef[1],
- scale=muref,
- num_flavs_ref=None,
- max_num_flavs=6,
+ for thresh_setup, nfref in zip(thresh_setups, nfrefs):
+ couplings = CouplingsInfo.from_dict(
+ dict(
+ alphas=alpharef[0],
+ alphaem=alpharef[1],
+ scale=muref,
+ num_flavs_ref=nfref,
+ max_num_flavs=6,
+ )
)
- )
- for thresh_setup in thresh_setups:
for order_s in [1, 2, 3, 4]:
for order_em in [0, 1, 2]:
for evmod in CouplingEvolutionMethod:
@@ -220,9 +221,10 @@ def test_exact(self):
(0, np.inf, np.inf),
(2, 4, 175),
]
+ nfrefs = (3, 4, 5)
alpharef = np.array([0.118, 0.00781])
muref = 91.0
- for thresh_setup in thresh_setups:
+ for thresh_setup, nfref in zip(thresh_setups, nfrefs):
for qcd in range(1, 4 + 1):
for qed in range(2 + 1):
for em_running in [
@@ -235,7 +237,7 @@ def test_exact(self):
alphas=alpharef[0],
alphaem=alpharef[1],
scale=muref,
- num_flavs_ref=None,
+ num_flavs_ref=nfref,
max_num_flavs=6,
em_running=em_running,
)
@@ -298,7 +300,7 @@ def benchmark_expanded_n3lo(self):
alphas=alpharef[0],
alphaem=alpharef[1],
scale=muref,
- num_flavs_ref=None,
+ num_flavs_ref=5,
max_num_flavs=6,
)
m2c = 2
From bbfc166bd1e8a8fefaaf1e4c6c0e4907a5af3ca8 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 21 Jul 2023 17:28:05 +0200
Subject: [PATCH 04/67] Apply more mypy fixes
---
src/eko/evolution_operator/__init__.py | 4 ++--
.../operator_matrix_element.py | 3 ++-
src/eko/io/inventory.py | 4 ++--
src/eko/io/struct.py | 22 +++++++++----------
src/eko/msbar_masses.py | 2 +-
5 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py
index 6a49551a5..4251c5a4e 100644
--- a/src/eko/evolution_operator/__init__.py
+++ b/src/eko/evolution_operator/__init__.py
@@ -604,8 +604,8 @@ class Operator(sv.ModeMixin):
log_label = "Evolution"
# complete list of possible evolution operators labels
- full_labels = br.full_labels
- full_labels_qed = br.full_unified_labels
+ full_labels = list(br.full_labels)
+ full_labels_qed = list(br.full_unified_labels)
def __init__(
self, config, managers, segment: Segment, mellin_cut=5e-2, is_threshold=False
diff --git a/src/eko/evolution_operator/operator_matrix_element.py b/src/eko/evolution_operator/operator_matrix_element.py
index 5696ead19..809279c77 100644
--- a/src/eko/evolution_operator/operator_matrix_element.py
+++ b/src/eko/evolution_operator/operator_matrix_element.py
@@ -3,6 +3,7 @@
import copy
import functools
import logging
+from typing import List, Tuple
import numba as nb
import numpy as np
@@ -208,7 +209,7 @@ class OperatorMatrixElement(Operator):
(br.matching_hminus_pid, br.matching_hminus_pid),
]
# still valid in QED since Sdelta and Vdelta matchings are diagonal
- full_labels_qed = copy.deepcopy(full_labels)
+ full_labels_qed: List[Tuple[int, int]] = copy.deepcopy(full_labels)
def __init__(self, config, managers, nf, q2, is_backward, L, is_msbar):
super().__init__(config, managers, Segment(q2, q2, nf))
diff --git a/src/eko/io/inventory.py b/src/eko/io/inventory.py
index efdd2e9b0..d22046c76 100644
--- a/src/eko/io/inventory.py
+++ b/src/eko/io/inventory.py
@@ -2,7 +2,7 @@
import base64
from dataclasses import asdict, dataclass, field
from pathlib import Path
-from typing import Dict, Generic, Optional, Type, TypeVar
+from typing import Dict, Generic, Literal, Optional, Type, TypeVar
import yaml
@@ -10,7 +10,7 @@
from .items import Header, Operator
NBYTES = 8
-ENDIANNESS = "little"
+ENDIANNESS: Literal["little", "big"] = "little"
HEADER_EXT = ".yaml"
ARRAY_EXT = [".npy", ".npz"]
diff --git a/src/eko/io/struct.py b/src/eko/io/struct.py
index fecba3c57..3185c71ef 100644
--- a/src/eko/io/struct.py
+++ b/src/eko/io/struct.py
@@ -373,17 +373,17 @@ def open(cls, path: os.PathLike, mode="r"):
raise ValueError(f"Unknown file mode: {mode}")
tmpdir = pathlib.Path(tempfile.mkdtemp(prefix=TEMP_PREFIX))
- if load:
- cls.load(path, tmpdir)
- metadata = Metadata.load(tmpdir)
- opened = cls(
- **inventories(tmpdir, access),
- metadata=metadata,
- access=access,
- )
- opened.operators.sync()
- else:
- opened = Builder(path=tmpdir, access=access)
+ if not load:
+ return Builder(path=tmpdir, access=access)
+ # load existing instead
+ cls.load(path, tmpdir)
+ metadata = Metadata.load(tmpdir)
+ opened: EKO = cls(
+ **inventories(tmpdir, access),
+ metadata=metadata,
+ access=access,
+ )
+ opened.operators.sync()
return opened
diff --git a/src/eko/msbar_masses.py b/src/eko/msbar_masses.py
index 356a81019..c72893fc3 100644
--- a/src/eko/msbar_masses.py
+++ b/src/eko/msbar_masses.py
@@ -395,7 +395,7 @@ def sc(thr_masses):
heavy_quarks = quark_names[3:]
hq_idxs = np.arange(0, 3)
if nf_ref > 4:
- heavy_quarks = reversed(heavy_quarks)
+ heavy_quarks = str(reversed(heavy_quarks))
hq_idxs = reversed(hq_idxs)
# loop on heavy quarks and compute the msbar masses
From 2d8d8bf55c6be567701a6db02dc66948d667595b Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 21 Jul 2023 17:55:27 +0200
Subject: [PATCH 05/67] Apply more mypy fixes 2
---
src/eko/evolution_operator/__init__.py | 5 ++++-
src/eko/evolution_operator/grid.py | 11 +++++------
src/eko/msbar_masses.py | 2 +-
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py
index 4251c5a4e..0f9c52c4f 100644
--- a/src/eko/evolution_operator/__init__.py
+++ b/src/eko/evolution_operator/__init__.py
@@ -579,6 +579,9 @@ def quad_ker_qed(
return ker
+OPMEMBERS = Dict[Tuple[int, int], OpMember]
+
+
class Operator(sv.ModeMixin):
"""Internal representation of a single EKO.
@@ -618,7 +621,7 @@ def __init__(
# TODO make 'cut' external parameter?
self._mellin_cut = mellin_cut
self.is_threshold = is_threshold
- self.op_members: Dict[Tuple[int, int], OpMember] = {}
+ self.op_members: OPMEMBERS = {}
self.order = tuple(config["order"])
self.alphaem_running = self.managers["couplings"].alphaem_running
if self.log_label == "Evolution":
diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py
index ad97f6e42..af478be9e 100644
--- a/src/eko/evolution_operator/grid.py
+++ b/src/eko/evolution_operator/grid.py
@@ -5,7 +5,6 @@
"""
import logging
-from dataclasses import astuple
from typing import Any, Dict, List, Optional
import numpy as np
@@ -17,9 +16,9 @@
from ..interpolation import InterpolatorDispatcher
from ..io.runcards import Configs, Debug
from ..io.types import EvolutionPoint as EPoint
-from ..io.types import Order
+from ..io.types import Order, SquaredScale
from ..matchings import Atlas, Segment, flavor_shift, is_downward_path
-from . import Operator, flavors, matching_condition, physical
+from . import OPMEMBERS, Operator, flavors, matching_condition, physical
from .operator_matrix_element import OperatorMatrixElement
logger = logging.getLogger(__name__)
@@ -95,8 +94,8 @@ def __init__(
couplings=couplings,
interpol_dispatcher=interpol_dispatcher,
)
- self._threshold_operators = {}
- self._matching_operators = {}
+ self._threshold_operators: Dict[Segment, Operator] = {}
+ self._matching_operators: Dict[SquaredScale, OPMEMBERS] = {}
def get_threshold_operators(self, path: List[Segment]) -> List[Operator]:
"""Generate the threshold operators.
@@ -118,7 +117,7 @@ def get_threshold_operators(self, path: List[Segment]) -> List[Operator]:
is_downward = is_downward_path(path)
shift = flavor_shift(is_downward)
for seg in path[:-1]:
- new_op_key = astuple(seg)
+ new_op_key = seg
kthr = self.config["thresholds_ratios"][seg.nf - shift]
ome = OperatorMatrixElement(
self.config,
diff --git a/src/eko/msbar_masses.py b/src/eko/msbar_masses.py
index c72893fc3..f13582110 100644
--- a/src/eko/msbar_masses.py
+++ b/src/eko/msbar_masses.py
@@ -395,7 +395,7 @@ def sc(thr_masses):
heavy_quarks = quark_names[3:]
hq_idxs = np.arange(0, 3)
if nf_ref > 4:
- heavy_quarks = str(reversed(heavy_quarks))
+ heavy_quarks = "".join([e for e in reversed(heavy_quarks)])
hq_idxs = reversed(hq_idxs)
# loop on heavy quarks and compute the msbar masses
From 494da3c0ccd3d081cc3e345f39e96457b0fd46a3 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 21 Jul 2023 18:02:56 +0200
Subject: [PATCH 06/67] Rename OpMembers
---
src/eko/evolution_operator/__init__.py | 4 ++--
src/eko/evolution_operator/grid.py | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py
index 0f9c52c4f..d079bed3d 100644
--- a/src/eko/evolution_operator/__init__.py
+++ b/src/eko/evolution_operator/__init__.py
@@ -579,7 +579,7 @@ def quad_ker_qed(
return ker
-OPMEMBERS = Dict[Tuple[int, int], OpMember]
+OpMembers = Dict[Tuple[int, int], OpMember]
class Operator(sv.ModeMixin):
@@ -621,7 +621,7 @@ def __init__(
# TODO make 'cut' external parameter?
self._mellin_cut = mellin_cut
self.is_threshold = is_threshold
- self.op_members: OPMEMBERS = {}
+ self.op_members: OpMembers = {}
self.order = tuple(config["order"])
self.alphaem_running = self.managers["couplings"].alphaem_running
if self.log_label == "Evolution":
diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py
index af478be9e..5035b22b2 100644
--- a/src/eko/evolution_operator/grid.py
+++ b/src/eko/evolution_operator/grid.py
@@ -18,7 +18,7 @@
from ..io.types import EvolutionPoint as EPoint
from ..io.types import Order, SquaredScale
from ..matchings import Atlas, Segment, flavor_shift, is_downward_path
-from . import OPMEMBERS, Operator, flavors, matching_condition, physical
+from . import Operator, OpMembers, flavors, matching_condition, physical
from .operator_matrix_element import OperatorMatrixElement
logger = logging.getLogger(__name__)
@@ -95,7 +95,7 @@ def __init__(
interpol_dispatcher=interpol_dispatcher,
)
self._threshold_operators: Dict[Segment, Operator] = {}
- self._matching_operators: Dict[SquaredScale, OPMEMBERS] = {}
+ self._matching_operators: Dict[SquaredScale, OpMembers] = {}
def get_threshold_operators(self, path: List[Segment]) -> List[Operator]:
"""Generate the threshold operators.
From 48ac90e43ae60e37af173d5db15f36e2caf0f2fb Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 21 Jul 2023 18:22:05 +0200
Subject: [PATCH 07/67] Fix mypy in io/legacy
---
src/eko/io/legacy.py | 32 +++++++++++++++++++++-----------
1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/src/eko/io/legacy.py b/src/eko/io/legacy.py
index 1df9941b1..c7799d0fb 100644
--- a/src/eko/io/legacy.py
+++ b/src/eko/io/legacy.py
@@ -12,15 +12,19 @@
import numpy as np
import yaml
-from eko.interpolation import XGrid
-from eko.io.runcards import flavored_mugrid
-from eko.quantities.heavy_quarks import HeavyInfo, HeavyQuarkMasses, MatchingRatios
-
+from ..interpolation import XGrid
+from ..io.runcards import flavored_mugrid
+from ..quantities.heavy_quarks import (
+ HeavyInfo,
+ HeavyQuarkMasses,
+ MatchingRatios,
+ QuarkMassScheme,
+)
from . import raw
from .dictlike import DictLike
from .struct import EKO, Operator
from .types import EvolutionPoint as EPoint
-from .types import RawCard
+from .types import RawCard, ReferenceRunning
def load_tar(source: os.PathLike, dest: os.PathLike, errors: bool = False):
@@ -38,8 +42,8 @@ def load_tar(source: os.PathLike, dest: os.PathLike, errors: bool = False):
whether to load also errors (default ``False``)
"""
- with tempfile.TemporaryDirectory() as tmpdir:
- tmpdir = pathlib.Path(tmpdir)
+ with tempfile.TemporaryDirectory() as tmpdirr:
+ tmpdir = pathlib.Path(tmpdirr)
with tarfile.open(source, "r") as tar:
raw.safe_extractall(tar, tmpdir)
@@ -92,10 +96,16 @@ def from_old(cls, old: RawCard):
"""Load from old metadata."""
heavy = HeavyInfo(
num_flavs_init=4,
- num_flavs_max_pdf=None,
- intrinsic_flavors=None,
- masses=HeavyQuarkMasses([1.51, 4.92, 172.5]),
- masses_scheme=None,
+ num_flavs_max_pdf=5,
+ intrinsic_flavors=[],
+ masses=HeavyQuarkMasses(
+ [
+ ReferenceRunning([1.51, np.inf]),
+ ReferenceRunning([4.92, np.inf]),
+ ReferenceRunning([172.5, np.inf]),
+ ]
+ ),
+ masses_scheme=QuarkMassScheme.POLE,
matching_ratios=MatchingRatios([1.0, 1.0, 1.0]),
)
return cls(heavy=heavy)
From bab8cf2c44ab4ab79947b65b786f36a308424d03 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 21 Jul 2023 18:44:40 +0200
Subject: [PATCH 08/67] Fix mypy in box/{genpdf,apply}
---
src/ekobox/apply.py | 46 +++++++++++++++++++++--------------
src/ekobox/genpdf/__init__.py | 6 ++---
2 files changed, 31 insertions(+), 21 deletions(-)
diff --git a/src/ekobox/apply.py b/src/ekobox/apply.py
index c392ffe78..5e62b4a06 100644
--- a/src/ekobox/apply.py
+++ b/src/ekobox/apply.py
@@ -1,10 +1,14 @@
"""Apply operator evolution to PDF set."""
+from dataclasses import dataclass
+from typing import Dict, Optional, Union
+
import numpy as np
from eko import basis_rotation as br
from eko import interpolation
from eko.io import EKO
+from eko.io.types import EvolutionPoint
def apply_pdf(
@@ -48,6 +52,14 @@ def apply_pdf(
CONTRACTION = "ajbk,bk"
+@dataclass
+class PdfResult:
+ """Helper class to collect PDF results."""
+
+ pdfs: Dict[Union[int, str], float]
+ errors: Optional[Dict[Union[int, str], float]] = None
+
+
def apply_pdf_flavor(
eko: EKO, lhapdf_like, targetgrid=None, flavor_rotation=None, qed=False
):
@@ -83,36 +95,33 @@ def apply_pdf_flavor(
)
# build output
- out_grid = {}
+ out_grid: Dict[EvolutionPoint, PdfResult] = {}
for ep, elem in eko.items():
pdf_final = np.einsum(CONTRACTION, elem.operator, pdfs, optimize="optimal")
if elem.error is not None:
error_final = np.einsum(CONTRACTION, elem.error, pdfs, optimize="optimal")
else:
error_final = None
- out_grid[ep] = {
- "pdfs": dict(zip(eko.bases.targetpids, pdf_final)),
- "errors": None,
- }
+ out_grid[ep] = PdfResult(dict(zip(eko.bases.targetpids, pdf_final)))
if error_final is not None:
- out_grid[ep]["errors"] = dict(zip(eko.bases.targetpids, error_final))
+ out_grid[ep].errors = dict(zip(eko.bases.targetpids, error_final))
# rotate to evolution basis
if flavor_rotation is not None:
for q2, op in out_grid.items():
pdf = flavor_rotation @ np.array(
- [op["pdfs"][pid] for pid in br.flavor_basis_pids]
+ [op.pdfs[pid] for pid in br.flavor_basis_pids]
)
if not qed:
evol_basis = br.evol_basis
else:
evol_basis = br.unified_evol_basis
- op["pdfs"] = dict(zip(evol_basis, pdf))
- if op["errors"] is not None:
+ op.pdfs = dict(zip(evol_basis, pdf))
+ if op.errors is not None:
errors = flavor_rotation @ np.array(
- [op["errors"][pid] for pid in br.flavor_basis_pids]
+ [op.errors[pid] for pid in br.flavor_basis_pids]
)
- op["errors"] = dict(zip(evol_basis, errors))
+ op.errors = dict(zip(evol_basis, errors))
# rotate/interpolate to target grid
if targetgrid is not None:
@@ -124,11 +133,12 @@ def apply_pdf_flavor(
rot = b.get_interpolation(targetgrid)
for evpdf in out_grid.values():
- for pdf_label in evpdf["pdfs"]:
- evpdf["pdfs"][pdf_label] = np.matmul(rot, evpdf["pdfs"][pdf_label])
- if evpdf["errors"] is not None:
- evpdf["errors"][pdf_label] = np.matmul(
- rot, evpdf["errors"][pdf_label]
- )
-
+ for pdf_label in evpdf.pdfs:
+ evpdf.pdfs[pdf_label] = np.matmul(rot, evpdf.pdfs[pdf_label])
+ if evpdf.errors is not None:
+ evpdf.errors[pdf_label] = np.matmul(rot, evpdf.errors[pdf_label])
+ # cast back to be backward compatible
+ real_out_grid = {}
+ for ep, res in out_grid.items():
+ real_out_grid[ep] = {"pdfs": res.pdfs, "errors": res.errors}
return out_grid
diff --git a/src/ekobox/genpdf/__init__.py b/src/ekobox/genpdf/__init__.py
index af94a410e..5c88b9b7c 100644
--- a/src/ekobox/genpdf/__init__.py
+++ b/src/ekobox/genpdf/__init__.py
@@ -16,7 +16,7 @@
def take_data(
- parent_pdf_set: Optional[Union[str, dict]] = None,
+ parent_pdf_set=None,
members: bool = False,
xgrid: Optional[List[float]] = None,
evolgrid: Optional[List[EPoint]] = None,
@@ -62,7 +62,7 @@ def take_data(
all_blocks.append(
[
generate_block(
- toylh.xfxQ2, xgrid, sorted_q2grid, br.flavor_basis_pids
+ toylh.xfxQ2, xgrid, sorted_q2grid, list(br.flavor_basis_pids)
)
]
)
@@ -86,7 +86,7 @@ def take_data(
else parent_pdf_set[pid](x, Q2),
xgrid,
sorted_q2grid,
- br.flavor_basis_pids,
+ list(br.flavor_basis_pids),
)
]
)
From e61c8e6bf73f5ed60982a915a2ac75ed2eb26f84 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 24 Jul 2023 13:11:04 +0200
Subject: [PATCH 09/67] Fix ekomark/plots
---
src/ekomark/plots.py | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/ekomark/plots.py b/src/ekomark/plots.py
index 92a155de3..90602a0c1 100644
--- a/src/ekomark/plots.py
+++ b/src/ekomark/plots.py
@@ -1,6 +1,7 @@
"""Plotting tools to show the evolved PDF and the computed operators."""
import io
import pprint
+from typing import Dict, List, Tuple
import matplotlib.pyplot as plt
import numpy as np
@@ -230,7 +231,7 @@ def save_operators_to_pdf(path, theory, ops, me: EKO, skip_pdfs, change_lab=Fals
"""
ops_names = list(me.bases.targetpids)
if np.allclose(ops_names, br.rotate_flavor_to_evolution):
- ops_names = br.evol_basis_pids
+ ops_names = list(br.evol_basis_pids)
else:
raise ValueError("Can not reconstruct PDF names")
ops_id = f"o{ops['hash'][:6]}_t{theory['hash'][:6]}"
@@ -244,16 +245,16 @@ def save_operators_to_pdf(path, theory, ops, me: EKO, skip_pdfs, change_lab=Fals
# plot the operators
# it's necessary to reshuffle the eko output
- for mu2 in me.mu2grid:
- results = me[mu2].operator
- errors = me[mu2].error
+ for ep, op in me.items():
+ results = op.operator
+ errors = op.error
# loop on pids
for label_out, res, res_err in zip(ops_names, results, errors):
if label_out in skip_pdfs:
continue
- new_op = {}
- new_op_err = {}
+ new_op: Dict[Tuple[int, ...], List[float]] = {}
+ new_op_err: Dict[Tuple[int, ...], List[float]] = {}
# loop on xgrid point
for j in range(len(me.xgrid)):
# loop on pid in
@@ -279,7 +280,7 @@ def save_operators_to_pdf(path, theory, ops, me: EKO, skip_pdfs, change_lab=Fals
fig = None
try:
fig = plot_operator(
- f"Operator ({lab_in};{lab_out}) µ_F^2 = {mu2} GeV^2",
+ f"Operator ({lab_in};{lab_out}) µ_F^2 = {ep[0]} GeV^2, nf = {ep[1]}",
new_op[label_in],
new_op_err[label_in],
)
From e40a71812bc954a5c6c90edc2b6d6e3378e8ac7e Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 24 Jul 2023 14:50:08 +0200
Subject: [PATCH 10/67] Fix ekobox/cli
---
src/ekobox/cli/inspect.py | 2 +-
src/ekobox/cli/run.py | 16 ++++++++--------
src/ekobox/cli/runcards.py | 4 +++-
3 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/src/ekobox/cli/inspect.py b/src/ekobox/cli/inspect.py
index f37f09cce..06f6588ed 100644
--- a/src/ekobox/cli/inspect.py
+++ b/src/ekobox/cli/inspect.py
@@ -27,7 +27,7 @@ def subcommand(ctx, path: pathlib.Path):
@click.pass_obj
def sub_mu2(operator: EKO):
"""Check operator's mu2grid."""
- rich.print_json(data=operator.mu2grid.tolist())
+ rich.print_json(data=operator.mu2grid)
@subcommand.command("cards")
diff --git a/src/ekobox/cli/run.py b/src/ekobox/cli/run.py
index 16e11c5fd..db88167e4 100644
--- a/src/ekobox/cli/run.py
+++ b/src/ekobox/cli/run.py
@@ -52,11 +52,11 @@ def subcommand(paths: Sequence[pathlib.Path]):
else:
output = operator.parent / OUTPUT
- theory = yaml.safe_load(theory.read_text(encoding="utf-8"))
- if "order" in theory:
- theory = TheoryCard.from_dict(theory)
- operator = yaml.safe_load(operator.read_text(encoding="utf-8"))
- if "configs" in operator:
- operator = OperatorCard.from_dict(operator)
-
- eko.solve(theory, operator, path=output)
+ tc = yaml.safe_load(theory.read_text(encoding="utf-8"))
+ if "order" in tc:
+ tc = TheoryCard.from_dict(tc)
+ oc = yaml.safe_load(operator.read_text(encoding="utf-8"))
+ if "configs" in oc:
+ oc = OperatorCard.from_dict(oc)
+
+ eko.solve(tc, oc, path=output)
diff --git a/src/ekobox/cli/runcards.py b/src/ekobox/cli/runcards.py
index 1ad7d91d4..7fc46f1ef 100644
--- a/src/ekobox/cli/runcards.py
+++ b/src/ekobox/cli/runcards.py
@@ -2,6 +2,8 @@
import logging
import pathlib
+import numpy as np
+
from .. import cards
from . import library as lib
from .base import command
@@ -34,6 +36,6 @@ def sub_example(destination: pathlib.Path):
cards.dump(theory.raw, path=destination / "theory.yaml")
operator = cards.example.operator()
operator.mu0 = 1.65
- operator.mu2grid = [1e5]
+ operator.mugrid = [(np.sqrt(1e5), 5)]
cards.dump(operator.raw, path=destination / "operator.yaml")
_logger.info(f"Runcards generated to '{destination}'")
From 9271ebc5950b188376c16f8bc163baea93ba8a8a Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 24 Jul 2023 15:13:25 +0200
Subject: [PATCH 11/67] Make managers class
---
src/eko/evolution_operator/__init__.py | 10 +++++-----
src/eko/evolution_operator/grid.py | 18 ++++++++++++++----
.../operator_matrix_element.py | 2 +-
src/eko/runner/parts.py | 9 +++++----
tests/eko/evolution_operator/test_init.py | 8 +++++++-
5 files changed, 32 insertions(+), 15 deletions(-)
diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py
index d079bed3d..fea8d15fe 100644
--- a/src/eko/evolution_operator/__init__.py
+++ b/src/eko/evolution_operator/__init__.py
@@ -623,7 +623,7 @@ def __init__(
self.is_threshold = is_threshold
self.op_members: OpMembers = {}
self.order = tuple(config["order"])
- self.alphaem_running = self.managers["couplings"].alphaem_running
+ self.alphaem_running = self.managers.couplings.alphaem_running
if self.log_label == "Evolution":
self.a = self.compute_a()
self.compute_aem_list()
@@ -645,7 +645,7 @@ def xif2(self):
@property
def int_disp(self):
"""Return the interpolation dispatcher."""
- return self.managers["interpol_dispatcher"]
+ return self.managers.interpolator
@property
def grid_size(self):
@@ -668,7 +668,7 @@ def mu2(self):
def compute_a(self):
"""Return the computed values for :math:`a_s` and :math:`a_{em}`."""
- coupling = self.managers["couplings"]
+ coupling = self.managers.couplings
a0 = coupling.a(
self.mu2[0],
nf_to=self.nf,
@@ -708,7 +708,7 @@ def compute_aem_list(self):
as1 = self.a_s[1]
aem0 = self.a_em[0]
aem1 = self.a_em[1]
- q2ref = self.managers["couplings"].mu2_ref
+ q2ref = self.managers.couplings.mu2_ref
delta_from = abs(self.q2_from - q2ref)
delta_to = abs(self.q2_to - q2ref)
# I compute the values in aem_list starting from the mu2
@@ -719,7 +719,7 @@ def compute_aem_list(self):
else:
a_start = np.array([as0, aem0])
mu2_start = self.q2_from
- couplings = self.managers["couplings"]
+ couplings = self.managers.couplings
mu2_steps = utils.geomspace(self.q2_from, self.q2_to, 1 + ev_op_iterations)
mu2_l = mu2_steps[0]
self.as_list = np.array(
diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py
index 5035b22b2..1180697a6 100644
--- a/src/eko/evolution_operator/grid.py
+++ b/src/eko/evolution_operator/grid.py
@@ -5,6 +5,7 @@
"""
import logging
+from dataclasses import dataclass
from typing import Any, Dict, List, Optional
import numpy as np
@@ -27,6 +28,15 @@
"""In particular, only the ``operator`` and ``error`` fields are expected."""
+@dataclass(frozen=True)
+class Managers:
+ """Set of steering objects."""
+
+ atlas: Atlas
+ couplings: Couplings
+ interpolator: InterpolatorDispatcher
+
+
class OperatorGrid(sv.ModeMixin):
"""Collection of evolution operators for several scales.
@@ -89,10 +99,10 @@ def __init__(
self.config = config
self.q2_grid = mu2grid
- self.managers = dict(
- thresholds_config=atlas,
+ self.managers = Managers(
+ atlas=atlas,
couplings=couplings,
- interpol_dispatcher=interpol_dispatcher,
+ interpolator=interpol_dispatcher,
)
self._threshold_operators: Dict[Segment, Operator] = {}
self._matching_operators: Dict[SquaredScale, OpMembers] = {}
@@ -153,7 +163,7 @@ def generate(self, q2: EPoint) -> OpDict:
"""
# The lists of areas as produced by the thresholds
- path = self.managers["thresholds_config"].path(q2)
+ path = self.managers.atlas.path(q2)
# Prepare the path for the composition of the operator
thr_ops = self.get_threshold_operators(path)
# we start composing with the highest operator ...
diff --git a/src/eko/evolution_operator/operator_matrix_element.py b/src/eko/evolution_operator/operator_matrix_element.py
index 809279c77..8966a62b9 100644
--- a/src/eko/evolution_operator/operator_matrix_element.py
+++ b/src/eko/evolution_operator/operator_matrix_element.py
@@ -306,7 +306,7 @@ def a_s(self):
Note that here you need to use :math:`a_s^{n_f+1}`
"""
- sc = self.managers["couplings"]
+ sc = self.managers.couplings
return sc.a_s(
self.q2_from
* (self.xif2 if self.sv_mode == sv.Modes.exponentiated else 1.0),
diff --git a/src/eko/runner/parts.py b/src/eko/runner/parts.py
index e385b8f49..9f97a6de5 100644
--- a/src/eko/runner/parts.py
+++ b/src/eko/runner/parts.py
@@ -16,13 +16,14 @@
from ..evolution_operator import matching_condition
from ..evolution_operator import operator_matrix_element as ome
from ..evolution_operator import physical
+from ..evolution_operator.grid import Managers
from ..io import EKO
from ..io.items import Evolution, Matching, Operator
from ..quantities.heavy_quarks import QuarkMassScheme
from . import commons
-def managers(eko: EKO) -> dict:
+def managers(eko: EKO) -> Managers:
"""Collect managers for operator computation.
.. todo::
@@ -32,10 +33,10 @@ def managers(eko: EKO) -> dict:
"""
tcard = eko.theory_card
ocard = eko.operator_card
- return dict(
- thresholds_config=commons.atlas(tcard, ocard),
+ return Managers(
+ atlas=commons.atlas(tcard, ocard),
couplings=commons.couplings(tcard, ocard),
- interpol_dispatcher=commons.interpolator(ocard),
+ interpolator=commons.interpolator(ocard),
)
diff --git a/tests/eko/evolution_operator/test_init.py b/tests/eko/evolution_operator/test_init.py
index 642de5bb7..92a335f79 100644
--- a/tests/eko/evolution_operator/test_init.py
+++ b/tests/eko/evolution_operator/test_init.py
@@ -1,4 +1,5 @@
import os
+from dataclasses import dataclass
import numpy as np
import pytest
@@ -201,7 +202,12 @@ def compute(self, a_ref, nf, scale_from, scale_to):
return a_ref
-fake_managers = {"couplings": FakeCoupling()}
+@dataclass(frozen=True)
+class FakeManagers:
+ couplings: FakeCoupling
+
+
+fake_managers = FakeManagers(couplings=FakeCoupling())
class TestOperator:
From 80b85f157476f258798ec5c2d4eab2b1aec99471 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 24 Jul 2023 15:16:27 +0200
Subject: [PATCH 12/67] Use backported return in apply
---
src/ekobox/apply.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ekobox/apply.py b/src/ekobox/apply.py
index 5e62b4a06..ace0ccca1 100644
--- a/src/ekobox/apply.py
+++ b/src/ekobox/apply.py
@@ -141,4 +141,4 @@ def apply_pdf_flavor(
real_out_grid = {}
for ep, res in out_grid.items():
real_out_grid[ep] = {"pdfs": res.pdfs, "errors": res.errors}
- return out_grid
+ return real_out_grid
From 34c68a57a9587829a7c593563f5feaf83ecbc5fe Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 24 Jul 2023 15:28:48 +0200
Subject: [PATCH 13/67] Fix eko/io/legacy masses usage
---
src/eko/io/legacy.py | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/eko/io/legacy.py b/src/eko/io/legacy.py
index c7799d0fb..d580f7373 100644
--- a/src/eko/io/legacy.py
+++ b/src/eko/io/legacy.py
@@ -26,6 +26,10 @@
from .types import EvolutionPoint as EPoint
from .types import RawCard, ReferenceRunning
+_MC = 1.51
+_MB = 4.92
+_MT = 172.5
+
def load_tar(source: os.PathLike, dest: os.PathLike, errors: bool = False):
"""Load tar representation from file.
@@ -63,7 +67,7 @@ def load_tar(source: os.PathLike, dest: os.PathLike, errors: bool = False):
if op5 is None:
op5 = metaold["mu2grid"]
grid = op5to4(
- flavored_mugrid(op5, theory.heavy.masses, theory.heavy.matching_ratios), arrays
+ flavored_mugrid(op5, [_MC, _MB, _MT], theory.heavy.matching_ratios), arrays
)
with EKO.create(dest) as builder:
@@ -100,9 +104,9 @@ def from_old(cls, old: RawCard):
intrinsic_flavors=[],
masses=HeavyQuarkMasses(
[
- ReferenceRunning([1.51, np.inf]),
- ReferenceRunning([4.92, np.inf]),
- ReferenceRunning([172.5, np.inf]),
+ ReferenceRunning([_MC, np.inf]),
+ ReferenceRunning([_MB, np.inf]),
+ ReferenceRunning([_MT, np.inf]),
]
),
masses_scheme=QuarkMassScheme.POLE,
@@ -134,7 +138,7 @@ def from_old(cls, old: RawCard):
mu2list = old["mu2grid"]
mu2grid = np.array(mu2list)
evolgrid = flavored_mugrid(
- np.sqrt(mu2grid).tolist(), [1.51, 4.92, 172.5], [1, 1, 1]
+ np.sqrt(mu2grid).tolist(), [_MC, _MB, _MT], [1, 1, 1]
)
xgrid = XGrid(old["interpolation_xgrid"])
From d6d17340b4c2592d8a5680bbf106f93f77476961 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 24 Jul 2023 15:55:08 +0200
Subject: [PATCH 14/67] Fix remaining mypy errors
---
src/eko/io/struct.py | 6 ++++--
src/eko/runner/operators.py | 4 +++-
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/eko/io/struct.py b/src/eko/io/struct.py
index 3185c71ef..ce4679871 100644
--- a/src/eko/io/struct.py
+++ b/src/eko/io/struct.py
@@ -272,7 +272,7 @@ def approx(
Raises
------
ValueError
- if multiple values are find in the neighbourhood
+ if multiple values are found in the neighbourhood
"""
eps = np.array([ep_ for ep_ in self if ep_[1] == ep[1]])
@@ -280,7 +280,9 @@ def approx(
close = eps[np.isclose(ep[0], mu2s, rtol=rtol, atol=atol)]
if len(close) == 1:
- return tuple(close[0])
+ found = close[0]
+ assert isinstance(found[0], float)
+ return (found[0], int(found[1]))
if len(close) == 0:
return None
raise ValueError(f"Multiple values of Q2 have been found close to {ep}")
diff --git a/src/eko/runner/operators.py b/src/eko/runner/operators.py
index 5a0a219c7..bfc4ce407 100644
--- a/src/eko/runner/operators.py
+++ b/src/eko/runner/operators.py
@@ -16,7 +16,9 @@ def retrieve(
elements = []
for head in headers:
inv = parts if isinstance(head, Evolution) else parts_matching
- elements.append(inv[head])
+ op = inv[head]
+ assert isinstance(op, Operator)
+ elements.append(op)
return elements
From b9cfc9e5914287b550fb75e01443197dba3b870b Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 24 Jul 2023 18:11:01 +0200
Subject: [PATCH 15/67] Change manipulate act on Operator
---
src/eko/io/manipulate.py | 212 +++++++++---------------
src/ekomark/benchmark/runner.py | 13 +-
src/ekomark/plots.py | 30 ++--
tests/eko/io/test_manipulate.py | 274 ++++++++++----------------------
4 files changed, 180 insertions(+), 349 deletions(-)
diff --git a/src/eko/io/manipulate.py b/src/eko/io/manipulate.py
index e9cc89538..1372e9e14 100644
--- a/src/eko/io/manipulate.py
+++ b/src/eko/io/manipulate.py
@@ -1,7 +1,8 @@
-"""Manipulate output generate by EKO."""
+"""Manipulate operators."""
+import copy
import logging
import warnings
-from typing import Callable, Optional, Union
+from typing import Callable, Optional
import numpy as np
import numpy.typing as npt
@@ -9,7 +10,7 @@
from .. import basis_rotation as br
from .. import interpolation
from ..interpolation import XGrid
-from .struct import EKO, Operator
+from .struct import Operator
logger = logging.getLogger(__name__)
@@ -18,10 +19,8 @@
SIMGRID_ROTATION = "ij,ajbk,kl->aibl"
"""Simultaneous grid rotation contraction indices."""
-Basis = Union[XGrid, npt.NDArray]
-
-def rotation(new: Optional[Basis], old: Basis, check: Callable, compute: Callable):
+def rotation(new: Optional[XGrid], old: XGrid, check: Callable, compute: Callable):
"""Define grid rotation.
This function returns the new grid to be assigned and the rotation computed,
@@ -61,81 +60,66 @@ def xgrid_compute_rotation(new: XGrid, old: XGrid, interpdeg: int, swap: bool =
def xgrid_reshape(
- eko: EKO,
+ elem: Operator,
+ xgrid: XGrid,
+ interpdeg: int,
targetgrid: Optional[XGrid] = None,
inputgrid: Optional[XGrid] = None,
-):
- """Reinterpolate operators on output and/or input grids.
+) -> Operator:
+ """Reinterpolate the operator on output and/or input grid(s).
Target corresponds to the output PDF.
-
- The operation is in-place.
-
"""
- eko.assert_permissions(write=True)
-
# calling with no arguments is an error
if targetgrid is None and inputgrid is None:
raise ValueError("Nor inputgrid nor targetgrid was given")
- interpdeg = eko.operator_card.configs.interpolation_polynomial_degree
check = xgrid_check
crot = xgrid_compute_rotation
# construct matrices
newtarget, targetrot = rotation(
targetgrid,
- eko.bases.targetgrid,
+ xgrid,
check,
lambda new, old: crot(new, old, interpdeg),
)
newinput, inputrot = rotation(
inputgrid,
- eko.bases.inputgrid,
+ xgrid,
check,
lambda new, old: crot(new, old, interpdeg, swap=True),
)
-
# after the checks: if there is still nothing to do, skip
if targetrot is None and inputrot is None:
logger.debug("Nothing done.")
- return
- # if no rotation is done, the grids are not modified
- if targetrot is not None:
- eko.bases.targetgrid = newtarget
- if inputrot is not None:
- eko.bases.inputgrid = newinput
+ return copy.deepcopy(elem)
# build new grid
- for ep, elem in eko.items():
- assert elem is not None
-
- operands = [elem.operator]
- operands_errs = [elem.error]
+ operands = [elem.operator]
+ operands_errs = [elem.error]
- if targetrot is not None and inputrot is None:
- contraction = TARGETGRID_ROTATION
- elif inputrot is not None and targetrot is None:
- contraction = INPUTGRID_ROTATION
- else:
- contraction = SIMGRID_ROTATION
+ if targetrot is not None and inputrot is None:
+ contraction = TARGETGRID_ROTATION
+ elif inputrot is not None and targetrot is None:
+ contraction = INPUTGRID_ROTATION
+ else:
+ contraction = SIMGRID_ROTATION
- if targetrot is not None:
- operands.insert(0, targetrot)
- operands_errs.insert(0, targetrot)
- if inputrot is not None:
- operands.append(inputrot)
- operands_errs.append(inputrot)
-
- new_operator = np.einsum(contraction, *operands, optimize="optimal")
- if elem.error is not None:
- new_error = np.einsum(contraction, *operands_errs, optimize="optimal")
- else:
- new_error = None
+ if targetrot is not None:
+ operands.insert(0, targetrot)
+ operands_errs.insert(0, targetrot)
+ if inputrot is not None:
+ operands.append(inputrot)
+ operands_errs.append(inputrot)
- eko[ep] = Operator(operator=new_operator, error=new_error)
+ new_operator = np.einsum(contraction, *operands, optimize="optimal")
+ if elem.error is not None:
+ new_error = np.einsum(contraction, *operands_errs, optimize="optimal")
+ else:
+ new_error = None
- eko.update()
+ return Operator(operator=new_operator, error=new_error)
TARGETPIDS_ROTATION = "ca,ajbk->cjbk"
@@ -145,107 +129,85 @@ def xgrid_reshape(
def flavor_reshape(
- eko: EKO,
+ elem: Operator,
targetpids: Optional[npt.NDArray] = None,
inputpids: Optional[npt.NDArray] = None,
- update: bool = True,
):
- """Change the operators to have in the output targetpids and/or in the input inputpids.
-
- The operation is in-place.
+ """Change the operator to have in the output targetpids and/or in the input inputpids.
Parameters
----------
- eko :
+ elem :
the operator to be rotated
targetpids :
target rotation specified in the flavor basis
inputpids :
input rotation specified in the flavor basis
- update :
- update :class:`~eko.io.struct.EKO` metadata after writing
"""
- eko.assert_permissions(write=True)
-
# calling with no arguments is an error
if targetpids is None and inputpids is None:
raise ValueError("Nor inputpids nor targetpids was given")
# now check to the current status
if targetpids is not None and np.allclose(
- targetpids, np.eye(len(eko.bases.targetpids))
+ targetpids, np.eye(elem.operator.shape[0])
):
targetpids = None
warnings.warn("The new targetpids is close to current basis")
- if inputpids is not None and np.allclose(
- inputpids, np.eye(len(eko.bases.inputpids))
- ):
+ if inputpids is not None and np.allclose(inputpids, np.eye(elem.operator.shape[2])):
inputpids = None
warnings.warn("The new inputpids is close to current basis")
# after the checks: if there is still nothing to do, skip
if targetpids is None and inputpids is None:
logger.debug("Nothing done.")
- return
+ return copy.deepcopy(elem)
# flip input around
if inputpids is not None:
inv_inputpids = np.linalg.inv(inputpids)
# build new grid
- for q2, elem in eko.items():
- ops = elem.operator
- errs = elem.error
- if targetpids is not None and inputpids is None:
- ops = np.einsum(TARGETPIDS_ROTATION, targetpids, ops, optimize="optimal")
- errs = (
- np.einsum(TARGETPIDS_ROTATION, targetpids, errs, optimize="optimal")
- if errs is not None
- else None
- )
- elif inputpids is not None and targetpids is None:
- ops = np.einsum(INPUTPIDS_ROTATION, ops, inv_inputpids, optimize="optimal")
- errs = (
- np.einsum(INPUTPIDS_ROTATION, errs, inv_inputpids, optimize="optimal")
- if errs is not None
- else None
- )
- else:
- ops = np.einsum(
- SIMPIDS_ROTATION, targetpids, ops, inv_inputpids, optimize="optimal"
- )
- errs = (
- np.einsum(
- SIMPIDS_ROTATION,
- targetpids,
- errs,
- inv_inputpids,
- optimize="optimal",
- )
- if errs is not None
- else None
+ ops = elem.operator
+ errs = elem.error
+ if targetpids is not None and inputpids is None:
+ ops = np.einsum(TARGETPIDS_ROTATION, targetpids, ops, optimize="optimal")
+ errs = (
+ np.einsum(TARGETPIDS_ROTATION, targetpids, errs, optimize="optimal")
+ if errs is not None
+ else None
+ )
+ elif inputpids is not None and targetpids is None:
+ ops = np.einsum(INPUTPIDS_ROTATION, ops, inv_inputpids, optimize="optimal")
+ errs = (
+ np.einsum(INPUTPIDS_ROTATION, errs, inv_inputpids, optimize="optimal")
+ if errs is not None
+ else None
+ )
+ else:
+ ops = np.einsum(
+ SIMPIDS_ROTATION, targetpids, ops, inv_inputpids, optimize="optimal"
+ )
+ errs = (
+ np.einsum(
+ SIMPIDS_ROTATION,
+ targetpids,
+ errs,
+ inv_inputpids,
+ optimize="optimal",
)
+ if errs is not None
+ else None
+ )
- eko[q2] = Operator(operator=ops, error=errs)
-
- # drop PIDs - keeping them int nevertheless
- # there is no meaningful way to set them in general, after rotation
- if inputpids is not None:
- eko.bases.inputpids = np.array([0] * len(eko.bases.inputpids))
- if targetpids is not None:
- eko.bases.targetpids = np.array([0] * len(eko.bases.targetpids))
-
- if update:
- eko.update()
+ return Operator(operator=ops, error=errs)
-def to_evol(eko: EKO, source: bool = True, target: bool = False):
+def to_evol(elem: Operator, source: bool = True, target: bool = False):
"""Rotate the operator into evolution basis.
- This assigns also the pids. The operation is in-place.
-
Parameters
----------
- eko :
+ elem :
the operator to be rotated
source :
rotate on the input tensor
@@ -256,27 +218,15 @@ def to_evol(eko: EKO, source: bool = True, target: bool = False):
# rotate
inputpids = br.rotate_flavor_to_evolution if source else None
targetpids = br.rotate_flavor_to_evolution if target else None
- # prevent metadata update, since flavor_reshape has not enough information
- # to determine inpupids and targetpids, and they will be updated after the
- # call
- flavor_reshape(eko, inputpids=inputpids, targetpids=targetpids, update=False)
- # assign pids
- if source:
- eko.bases.inputpids = inputpids
- if target:
- eko.bases.targetpids = targetpids
-
- eko.update()
+ return flavor_reshape(elem, inputpids=inputpids, targetpids=targetpids)
-def to_uni_evol(eko: EKO, source: bool = True, target: bool = False):
+def to_uni_evol(elem: Operator, source: bool = True, target: bool = False):
"""Rotate the operator into evolution basis.
- This assigns also the pids. The operation is in-place.
-
Parameters
----------
- eko :
+ elem :
the operator to be rotated
source :
rotate on the input tensor
@@ -287,14 +237,4 @@ def to_uni_evol(eko: EKO, source: bool = True, target: bool = False):
# rotate
inputpids = br.rotate_flavor_to_unified_evolution if source else None
targetpids = br.rotate_flavor_to_unified_evolution if target else None
- # prevent metadata update, since flavor_reshape has not enough information
- # to determine inpupids and targetpids, and they will be updated after the
- # call
- flavor_reshape(eko, inputpids=inputpids, targetpids=targetpids, update=False)
- # assign pids
- if source:
- eko.bases.inputpids = inputpids
- if target:
- eko.bases.targetpids = targetpids
-
- eko.update()
+ return flavor_reshape(elem, inputpids=inputpids, targetpids=targetpids)
diff --git a/src/ekomark/benchmark/runner.py b/src/ekomark/benchmark/runner.py
index 8c07e7153..b1e9fc579 100644
--- a/src/ekomark/benchmark/runner.py
+++ b/src/ekomark/benchmark/runner.py
@@ -13,7 +13,6 @@
import eko
from eko import EKO
from eko import basis_rotation as br
-from eko.io import manipulate
from ekobox import apply
from .. import pdfname
@@ -116,22 +115,14 @@ def run_me(self, theory, ocard, _pdf):
os.makedirs(output_path)
# rotating to evolution basis if requested
with EKO.edit(path) as out_copy:
- change_lab = False
- if self.rotate_to_evolution_basis:
- qed = theory["QED"] > 0
- if not qed:
- manipulate.to_evol(out_copy, source=True, target=True)
- else:
- manipulate.to_uni_evol(out_copy, source=True, target=True)
- change_lab = True
-
save_operators_to_pdf(
output_path,
theory,
ocard,
out_copy,
self.skip_pdfs(theory),
- change_lab,
+ self.rotate_to_evolution_basis,
+ theory["QED"] > 0,
)
else:
# else we always rerun
diff --git a/src/ekomark/plots.py b/src/ekomark/plots.py
index 92a155de3..5c300f996 100644
--- a/src/ekomark/plots.py
+++ b/src/ekomark/plots.py
@@ -9,6 +9,7 @@
from matplotlib.colors import LogNorm
from eko import basis_rotation as br
+from eko.io import manipulate
from eko.io.struct import EKO
@@ -209,7 +210,15 @@ def plot_operator(var_name, op, op_err, log_operator=True, abs_operator=True):
return fig
-def save_operators_to_pdf(path, theory, ops, me: EKO, skip_pdfs, change_lab=False):
+def save_operators_to_pdf(
+ path,
+ theory,
+ ops,
+ me: EKO,
+ skip_pdfs,
+ rotate_to_evolution_basis: bool,
+ qed: bool = False,
+):
"""Output all operator heatmaps to PDF.
Parameters
@@ -228,11 +237,7 @@ def save_operators_to_pdf(path, theory, ops, me: EKO, skip_pdfs, change_lab=Fals
set whether to rename the labels
"""
- ops_names = list(me.bases.targetpids)
- if np.allclose(ops_names, br.rotate_flavor_to_evolution):
- ops_names = br.evol_basis_pids
- else:
- raise ValueError("Can not reconstruct PDF names")
+ ops_names = br.evol_basis_pids if rotate_to_evolution_basis else br.evol_basis_pids
ops_id = f"o{ops['hash'][:6]}_t{theory['hash'][:6]}"
path = f"{path}/{ops_id}.pdf"
print(f"Plotting operators plots to {path}")
@@ -244,9 +249,16 @@ def save_operators_to_pdf(path, theory, ops, me: EKO, skip_pdfs, change_lab=Fals
# plot the operators
# it's necessary to reshuffle the eko output
- for mu2 in me.mu2grid:
- results = me[mu2].operator
- errors = me[mu2].error
+ for mu2, op in me.items():
+ change_lab = False
+ if rotate_to_evolution_basis:
+ if not qed:
+ op = manipulate.to_evol(op, source=True, target=True)
+ else:
+ op = manipulate.to_uni_evol(op, source=True, target=True)
+ change_lab = True
+ results = op.operator
+ errors = op.error
# loop on pids
for label_out, res, res_err in zip(ops_names, results, errors):
diff --git a/tests/eko/io/test_manipulate.py b/tests/eko/io/test_manipulate.py
index 3431d93ce..56ceafc0f 100644
--- a/tests/eko/io/test_manipulate.py
+++ b/tests/eko/io/test_manipulate.py
@@ -1,5 +1,3 @@
-import pathlib
-
import numpy as np
import pytest
@@ -21,235 +19,125 @@ def chk_keys(a, b):
class TestManipulate:
- def test_xgrid_reshape(self, eko_factory: EKOFactory, tmp_path: pathlib.Path):
+ def test_xgrid_reshape(self):
# create object
- muout = 10.0
- mu2out = muout**2
- epout = (mu2out, 5)
+ interpdeg = 1
xg = interpolation.XGrid(np.geomspace(1e-5, 1.0, 21))
- eko_factory.operator.mugrid = [(muout, 5)]
- eko_factory.operator.xgrid = xg
- o1 = eko_factory.get()
+ xgp = interpolation.XGrid(np.geomspace(1e-5, 1.0, 11))
lpids = 2
- o1[epout] = eko.io.Operator(
+ o1 = eko.io.Operator(
operator=eko_identity([1, lpids, len(xg), lpids, len(xg)])[0]
)
- xgp = interpolation.XGrid(np.geomspace(1e-5, 1.0, 11))
# only target
- otpath = tmp_path / "ot.tar"
- o1.deepcopy(otpath)
- with EKO.edit(otpath) as ot:
- manipulate.xgrid_reshape(ot, xgp)
- chk_keys(o1.raw, ot.raw)
- assert ot[epout].operator.shape == (lpids, len(xgp), lpids, len(xg))
- ottpath = tmp_path / "ott.tar"
- o1.deepcopy(ottpath)
- with EKO.edit(ottpath) as ott:
- with pytest.warns(Warning):
- manipulate.xgrid_reshape(ott, xg)
- chk_keys(o1.raw, ott.raw)
- np.testing.assert_allclose(ott[epout].operator, o1[epout].operator)
+ ot = manipulate.xgrid_reshape(o1, xg, interpdeg, xgp)
+ assert ot.operator.shape == (lpids, len(xgp), lpids, len(xg))
+ ott = manipulate.xgrid_reshape(ot, xgp, interpdeg, xg)
+ # when blowing up again a line 0 ... 0 0 1 0 0 ... 0 becomes
+ # 0 ... 0 0.5 0 0.5 0 ... 0 instead
+ np.testing.assert_allclose(
+ np.sum(ott.operator, axis=3), np.sum(o1.operator, axis=3)
+ )
# only input
- oipath = tmp_path / "oi.tar"
- o1.deepcopy(oipath)
- with EKO.edit(oipath) as oi:
- manipulate.xgrid_reshape(oi, inputgrid=xgp)
- assert oi[epout].operator.shape == (lpids, len(xg), lpids, len(xgp))
- chk_keys(o1.raw, oi.raw)
- oiipath = tmp_path / "oii.tar"
- o1.deepcopy(oiipath)
- with EKO.edit(oiipath) as oii:
- with pytest.warns(Warning):
- manipulate.xgrid_reshape(oii, inputgrid=xg)
- chk_keys(o1.raw, oii.raw)
- np.testing.assert_allclose(oii[epout].operator, o1[epout].operator)
+ oi = manipulate.xgrid_reshape(o1, xg, interpdeg, inputgrid=xgp)
+ assert oi.operator.shape == (lpids, len(xg), lpids, len(xgp))
+ oii = manipulate.xgrid_reshape(oi, xgp, interpdeg, inputgrid=xg)
+ np.testing.assert_allclose(
+ np.sum(oii.operator, axis=3), np.sum(o1.operator, axis=3)
+ )
+ with pytest.warns(Warning):
+ oiii = manipulate.xgrid_reshape(oii, xg, interpdeg, inputgrid=xg)
+ np.testing.assert_allclose(oiii.operator, oii.operator)
# both
- oitpath = tmp_path / "oit.tar"
- o1.deepcopy(oitpath)
- with EKO.edit(oitpath) as oit:
- manipulate.xgrid_reshape(oit, xgp, xgp)
- chk_keys(o1.raw, oit.raw)
- op = eko_identity([1, 2, len(xgp), 2, len(xgp)])
- np.testing.assert_allclose(oit[epout].operator, op[0], atol=1e-10)
-
+ oit = manipulate.xgrid_reshape(o1, xg, interpdeg, xgp, xgp)
+ op = eko_identity([1, 2, len(xgp), 2, len(xgp)])
+ np.testing.assert_allclose(oit.operator, op[0], atol=1e-10)
# op error handling
- ep2 = (25, 5)
- o1[ep2] = eko.io.Operator(
+ o1e = eko.io.Operator(
operator=eko_identity([1, lpids, len(xg), lpids, len(xg)])[0],
error=0.1 * eko_identity([1, lpids, len(xg), lpids, len(xg)])[0],
)
- ot2path = tmp_path / "ot2.tar"
- o1.deepcopy(ot2path)
- with EKO.edit(ot2path) as ot2:
- manipulate.xgrid_reshape(ot2, xgp)
- chk_keys(o1.raw, ot2.raw)
- assert ot2[ep2].operator.shape == (lpids, len(xgp), lpids, len(xg))
- assert ot2[epout].error is None
- assert ot2[ep2].error is not None
+ assert ot.error is None
+ assert oi.error is None
+ ot2 = manipulate.xgrid_reshape(o1e, xg, interpdeg, xgp)
+ assert ot2.error is not None
# Python error
- with pytest.raises(ValueError):
- manipulate.xgrid_reshape(o1)
+ with pytest.raises(ValueError, match="Nor inputgrid nor targetgrid"):
+ manipulate.xgrid_reshape(o1, xg, interpdeg)
- def test_reshape_io(self, eko_factory: EKOFactory, tmp_path):
- eko_factory.path = tmp_path / "eko.tar"
- eko_factory.operator.configs.interpolation_polynomial_degree = 1
- # create object
- o1 = eko_factory.get()
- lpids = len(o1.bases.pids)
- path_copy = tmp_path / "eko_copy.tar"
- o1.deepcopy(path_copy)
- newxgrid = interpolation.XGrid([0.1, 1.0])
- inputpids = np.eye(lpids)
- inputpids[:2, :2] = np.array([[1, -1], [1, 1]])
- with EKO.edit(path_copy) as o2:
- manipulate.xgrid_reshape(o2, newxgrid, newxgrid)
- manipulate.flavor_reshape(o2, inputpids=inputpids)
- # reload
- with EKO.read(path_copy) as o3:
- chk_keys(o1.raw, o3.raw)
- np.testing.assert_allclose(o3.bases.inputgrid.raw, newxgrid.raw)
- np.testing.assert_allclose(o3.bases.targetgrid.raw, newxgrid.raw)
- # since we use a general rotation, the inputpids are erased,
- # leaving just as many zeros as PIDs, as placeholders for missing
- # values
- np.testing.assert_allclose(o3.bases.inputpids, [0] * len(o3.bases.pids))
- # these has to be unchanged
- np.testing.assert_allclose(o3.bases.targetpids, o3.bases.pids)
-
- def test_flavor_reshape(self, eko_factory: EKOFactory, tmp_path: pathlib.Path):
+ def test_flavor_reshape(self):
# create object
xg = interpolation.XGrid(np.geomspace(1e-5, 1.0, 21))
- muout = 10.0
- mu2out = muout**2
- epout = (mu2out, 5)
- eko_factory.operator.xgrid = xg
- eko_factory.operator.mugrid = [(muout, 5)]
- o1 = eko_factory.get()
- lpids = len(o1.bases.pids)
+ lpids = len(br.flavor_basis_pids)
lx = len(xg)
- o1[epout] = eko.io.Operator(
+ o1 = eko.io.Operator(
operator=eko_identity([1, lpids, lx, lpids, lx])[0],
error=None,
)
- # only target
- target_r = np.eye(lpids)
- target_r[:2, :2] = np.array([[1, -1], [1, 1]])
- tpath = tmp_path / "ot.tar"
- ttpath = tmp_path / "ott.tar"
- o1.deepcopy(tpath)
- with EKO.edit(tpath) as ot:
- manipulate.flavor_reshape(ot, target_r)
- chk_keys(o1.raw, ot.raw)
- assert ot[epout].operator.shape == (lpids, len(xg), lpids, len(xg))
- ot.deepcopy(ttpath)
- with EKO.edit(ttpath) as ott:
- manipulate.flavor_reshape(ott, np.linalg.inv(target_r))
- np.testing.assert_allclose(ott[epout].operator, o1[epout].operator)
- with pytest.warns(Warning):
- manipulate.flavor_reshape(ott, np.eye(lpids))
- chk_keys(o1.raw, ott.raw)
- np.testing.assert_allclose(ott[epout].operator, o1[epout].operator)
# only input
input_r = np.eye(lpids)
input_r[:2, :2] = np.array([[1, -1], [1, 1]])
- ipath = tmp_path / "oi.tar"
- iipath = tmp_path / "oii.tar"
- o1.deepcopy(ipath)
- with EKO.edit(ipath) as oi:
- manipulate.flavor_reshape(oi, inputpids=input_r)
- chk_keys(o1.raw, oi.raw)
- assert oi[epout].operator.shape == (lpids, len(xg), lpids, len(xg))
- oi.deepcopy(iipath)
- with EKO.edit(iipath) as oii:
- manipulate.flavor_reshape(oii, inputpids=np.linalg.inv(input_r))
- np.testing.assert_allclose(oii[epout].operator, o1[epout].operator)
- with pytest.warns(Warning):
- manipulate.flavor_reshape(oii, inputpids=np.eye(lpids))
- chk_keys(o1.raw, oii.raw)
- np.testing.assert_allclose(oii[epout].operator, o1[epout].operator)
+ oi = manipulate.flavor_reshape(o1, inputpids=input_r)
+ assert oi.operator.shape == (lpids, len(xg), lpids, len(xg))
+ oii = manipulate.flavor_reshape(oi, inputpids=np.linalg.inv(input_r))
+ np.testing.assert_allclose(oii.operator, o1.operator)
+ with pytest.warns(Warning):
+ oiii = manipulate.flavor_reshape(oii, inputpids=np.eye(lpids))
+ np.testing.assert_allclose(oiii.operator, oii.operator)
+
+ # only target
+ target_r = np.eye(lpids)
+ target_r[:2, :2] = np.array([[1, -1], [1, 1]])
+ ot = manipulate.flavor_reshape(o1, target_r)
+ assert ot.operator.shape == (lpids, len(xg), lpids, len(xg))
+ ott = manipulate.flavor_reshape(ot, np.linalg.inv(target_r))
+ np.testing.assert_allclose(ott.operator, o1.operator)
+ with pytest.warns(Warning):
+ ottt = manipulate.flavor_reshape(ott, np.eye(lpids))
+ np.testing.assert_allclose(ottt.operator, ott.operator)
# both
- itpath = tmp_path / "oit.tar"
- o1.deepcopy(itpath)
- with EKO.edit(itpath) as oit:
- manipulate.flavor_reshape(oit, target_r, input_r)
- chk_keys(o1.raw, oit.raw)
- op = eko_identity([1, lpids, len(xg), lpids, len(xg)]).copy()
- np.testing.assert_allclose(oit[epout].operator, op[0], atol=1e-10)
+ oit = manipulate.flavor_reshape(o1, target_r, input_r)
+ op = eko_identity([1, lpids, len(xg), lpids, len(xg)]).copy()
+ np.testing.assert_allclose(oit.operator, op[0], atol=1e-10)
# error
- fpath = tmp_path / "fail.tar"
- o1.deepcopy(fpath)
- with pytest.raises(ValueError):
- with EKO.edit(fpath) as of:
- manipulate.flavor_reshape(of)
+ with pytest.raises(ValueError, match="Nor inputpids nor targetpids"):
+ manipulate.flavor_reshape(o1)
- def test_to_evol(self, eko_factory: EKOFactory, tmp_path):
+ def test_to_evol(self):
self._test_to_all_evol(
- eko_factory,
- tmp_path,
manipulate.to_evol,
br.rotate_flavor_to_evolution,
- br.flavor_basis_pids,
)
- def test_to_uni_evol(self, eko_factory: EKOFactory, tmp_path):
+ def test_to_uni_evol(self):
self._test_to_all_evol(
- eko_factory,
- tmp_path,
manipulate.to_uni_evol,
br.rotate_flavor_to_unified_evolution,
- br.flavor_basis_pids,
)
- def _test_to_all_evol(
- self, eko_factory: EKOFactory, tmp_path, to_evol_fnc, rot_matrix, pids
- ):
- xgrid = interpolation.XGrid([0.5, 1.0])
- mu_out = 2.0
- mu2_out = mu_out**2
- nfout = 4
- epout = (mu2_out, nfout)
- eko_factory.operator.mu0 = float(np.sqrt(1.0))
- eko_factory.operator.mugrid = [(mu_out, nfout)]
- eko_factory.operator.xgrid = xgrid
- eko_factory.operator.configs.interpolation_polynomial_degree = 1
- eko_factory.operator.configs.interpolation_is_log = False
- eko_factory.operator.configs.ev_op_max_order = (2, 0)
- eko_factory.operator.configs.ev_op_iterations = 1
- eko_factory.operator.configs.inversion_method = runcards.InversionMethod.EXACT
- o00 = eko_factory.get()
- o01_path = tmp_path / "o01.tar"
- o00.deepcopy(o01_path)
- with EKO.edit(o01_path) as o01:
- to_evol_fnc(o01)
- o10_path = tmp_path / "o10.tar"
- o00.deepcopy(o10_path)
- with EKO.edit(o10_path) as o10:
- to_evol_fnc(o10, False, True)
- o11_path = tmp_path / "o11.tar"
- o00.deepcopy(o11_path)
- with EKO.edit(o11_path) as o11:
- to_evol_fnc(o11, True, True)
- chk_keys(o00.raw, o11.raw)
-
- with EKO.edit(o01_path) as o01:
- with EKO.edit(o10_path) as o10:
- with EKO.read(o11_path) as o11:
- # check the input rotated one
- np.testing.assert_allclose(o01.bases.inputpids, rot_matrix)
- np.testing.assert_allclose(o01.bases.targetpids, pids)
- # rotate also target
- to_evol_fnc(o01, False, True)
- np.testing.assert_allclose(o01[epout].operator, o11[epout].operator)
- chk_keys(o00.raw, o01.raw)
- # check the target rotated one
- np.testing.assert_allclose(o10.bases.inputpids, pids)
- np.testing.assert_allclose(o10.bases.targetpids, rot_matrix)
- # rotate also input
- to_evol_fnc(o10)
- np.testing.assert_allclose(o10[epout].operator, o11[epout].operator)
- chk_keys(o00.raw, o10.raw)
+ def _test_to_all_evol(self, to_evol_fnc, rot_matrix):
+ # create object
+ xg = interpolation.XGrid(np.geomspace(1e-5, 1.0, 21))
+ lpids = len(br.flavor_basis_pids)
+ lx = len(xg)
+ o = eko.io.Operator(
+ operator=eko_identity([1, lpids, lx, lpids, lx])[0],
+ error=None,
+ )
+
+ # do it once
+ o01 = to_evol_fnc(o, True, False)
+ o10 = to_evol_fnc(o, False, True)
+ o11 = to_evol_fnc(o, True, True)
+
+ # do also the other one
+ np.testing.assert_allclose(
+ to_evol_fnc(o01, False, True).operator, o11.operator, atol=1e-15
+ )
+ np.testing.assert_allclose(
+ to_evol_fnc(o10, True, False).operator, o11.operator, atol=1e-15
+ )
From 6e0f434b9c1792dad9c79bed9e013e2a5b5cdd1d Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Tue, 25 Jul 2023 16:11:22 +0200
Subject: [PATCH 16/67] Remove init from benchmarks
---
benchmarks/__init__.py | 0
benchmarks/ekobox/__init__.py | 0
2 files changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 benchmarks/__init__.py
delete mode 100644 benchmarks/ekobox/__init__.py
diff --git a/benchmarks/__init__.py b/benchmarks/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/benchmarks/ekobox/__init__.py b/benchmarks/ekobox/__init__.py
deleted file mode 100644
index e69de29bb..000000000
From 4699064f9e4c5e368e148f1afb9614e0e9908689 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 31 Jul 2023 11:26:54 +0200
Subject: [PATCH 17/67] Address review comments
---
src/eko/io/manipulate.py | 12 ++++++------
src/ekomark/plots.py | 11 +++++------
2 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/src/eko/io/manipulate.py b/src/eko/io/manipulate.py
index 1372e9e14..72f3a641b 100644
--- a/src/eko/io/manipulate.py
+++ b/src/eko/io/manipulate.py
@@ -23,7 +23,7 @@
def rotation(new: Optional[XGrid], old: XGrid, check: Callable, compute: Callable):
"""Define grid rotation.
- This function returns the new grid to be assigned and the rotation computed,
+ This function returns the necessary rotation,
if the checks for a non-trivial new grid are passed.
However, the check and the computation are delegated respectively to the
@@ -31,13 +31,13 @@ def rotation(new: Optional[XGrid], old: XGrid, check: Callable, compute: Callabl
"""
if new is None:
- return old, None
+ return None
if check(new, old):
warnings.warn("The new grid is close to the current one")
- return old, None
+ return None
- return new, compute(new, old)
+ return compute(new, old)
def xgrid_check(new: Optional[XGrid], old: XGrid):
@@ -78,13 +78,13 @@ def xgrid_reshape(
crot = xgrid_compute_rotation
# construct matrices
- newtarget, targetrot = rotation(
+ targetrot = rotation(
targetgrid,
xgrid,
check,
lambda new, old: crot(new, old, interpdeg),
)
- newinput, inputrot = rotation(
+ inputrot = rotation(
inputgrid,
xgrid,
check,
diff --git a/src/ekomark/plots.py b/src/ekomark/plots.py
index 5c300f996..2e74586c6 100644
--- a/src/ekomark/plots.py
+++ b/src/ekomark/plots.py
@@ -233,9 +233,10 @@ def save_operators_to_pdf(
DGLAP result
skip_pdfs : list
PDF to skip
- change_lab : bool
- set whether to rename the labels
-
+ rotate_to_evolution_basis : bool
+ plot operators in evolution basis
+ qed : bool
+ plot operators in unified evolution basis, if the former is active
"""
ops_names = br.evol_basis_pids if rotate_to_evolution_basis else br.evol_basis_pids
ops_id = f"o{ops['hash'][:6]}_t{theory['hash'][:6]}"
@@ -250,13 +251,11 @@ def save_operators_to_pdf(
# plot the operators
# it's necessary to reshuffle the eko output
for mu2, op in me.items():
- change_lab = False
if rotate_to_evolution_basis:
if not qed:
op = manipulate.to_evol(op, source=True, target=True)
else:
op = manipulate.to_uni_evol(op, source=True, target=True)
- change_lab = True
results = op.operator
errors = op.error
@@ -283,7 +282,7 @@ def save_operators_to_pdf(
continue
lab_in = label_in
lab_out = label_out
- if change_lab:
+ if rotate_to_evolution_basis:
index_in = br.evol_basis_pids.index(label_in)
index_out = br.evol_basis_pids.index(label_out)
lab_in = br.evol_basis[index_in]
From 0ee166af669a0fbd50e48c4415ee4bd07cdd814d Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 31 Jul 2023 11:51:39 +0200
Subject: [PATCH 18/67] Add missing typ hints
---
src/eko/io/manipulate.py | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/src/eko/io/manipulate.py b/src/eko/io/manipulate.py
index 72f3a641b..c54883fdd 100644
--- a/src/eko/io/manipulate.py
+++ b/src/eko/io/manipulate.py
@@ -20,7 +20,9 @@
"""Simultaneous grid rotation contraction indices."""
-def rotation(new: Optional[XGrid], old: XGrid, check: Callable, compute: Callable):
+def rotation(
+ new: Optional[XGrid], old: XGrid, check: Callable, compute: Callable
+) -> npt.NDArray:
"""Define grid rotation.
This function returns the necessary rotation,
@@ -40,12 +42,14 @@ def rotation(new: Optional[XGrid], old: XGrid, check: Callable, compute: Callabl
return compute(new, old)
-def xgrid_check(new: Optional[XGrid], old: XGrid):
+def xgrid_check(new: Optional[XGrid], old: XGrid) -> bool:
"""Check validity of new xgrid."""
return new is not None and len(new) == len(old) and np.allclose(new.raw, old.raw)
-def xgrid_compute_rotation(new: XGrid, old: XGrid, interpdeg: int, swap: bool = False):
+def xgrid_compute_rotation(
+ new: XGrid, old: XGrid, interpdeg: int, swap: bool = False
+) -> npt.NDArray:
"""Compute rotation from old to new xgrid.
By default, the roation is computed for a target xgrid. Whether the function
@@ -132,7 +136,7 @@ def flavor_reshape(
elem: Operator,
targetpids: Optional[npt.NDArray] = None,
inputpids: Optional[npt.NDArray] = None,
-):
+) -> Operator:
"""Change the operator to have in the output targetpids and/or in the input inputpids.
Parameters
@@ -202,7 +206,7 @@ def flavor_reshape(
return Operator(operator=ops, error=errs)
-def to_evol(elem: Operator, source: bool = True, target: bool = False):
+def to_evol(elem: Operator, source: bool = True, target: bool = False) -> Operator:
"""Rotate the operator into evolution basis.
Parameters
@@ -221,7 +225,7 @@ def to_evol(elem: Operator, source: bool = True, target: bool = False):
return flavor_reshape(elem, inputpids=inputpids, targetpids=targetpids)
-def to_uni_evol(elem: Operator, source: bool = True, target: bool = False):
+def to_uni_evol(elem: Operator, source: bool = True, target: bool = False) -> Operator:
"""Rotate the operator into evolution basis.
Parameters
From 054e4b2a9c9d9b9ceeaee8aea42963aa5b5c6242 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 31 Jul 2023 12:47:10 +0200
Subject: [PATCH 19/67] Drop max_num_flavs
---
benchmarks/eko/benchmark_evol_to_unity.py | 1 -
benchmarks/eko/benchmark_strong_coupling.py | 63 ++++++++++---------
benchmarks/ekobox/benchmark_evol_pdf.py | 1 -
doc/source/overview/tutorials/alpha_s.ipynb | 7 +--
doc/source/overview/tutorials/pdf.ipynb | 1 -
extras/n3lo_bench/splitting_function_utils.py | 1 -
src/eko/io/runcards.py | 1 -
src/eko/quantities/couplings.py | 1 -
src/ekobox/cards.py | 1 -
tests/eko/kernels/test_kernels_QEDns.py | 1 -
tests/eko/quantities/test_couplings.py | 2 +-
tests/eko/test_couplings.py | 5 --
12 files changed, 37 insertions(+), 48 deletions(-)
diff --git a/benchmarks/eko/benchmark_evol_to_unity.py b/benchmarks/eko/benchmark_evol_to_unity.py
index 41bc4b4d0..893de5de3 100644
--- a/benchmarks/eko/benchmark_evol_to_unity.py
+++ b/benchmarks/eko/benchmark_evol_to_unity.py
@@ -20,7 +20,6 @@ def update_cards(theory: TheoryCard, operator: OperatorCard):
alphas=0.35,
alphaem=0.007496,
scale=float(np.sqrt(2)),
- max_num_flavs=6,
num_flavs_ref=None,
)
theory.heavy.num_flavs_init = 4
diff --git a/benchmarks/eko/benchmark_strong_coupling.py b/benchmarks/eko/benchmark_strong_coupling.py
index d13a264bd..80f65cf72 100644
--- a/benchmarks/eko/benchmark_strong_coupling.py
+++ b/benchmarks/eko/benchmark_strong_coupling.py
@@ -8,7 +8,7 @@
from eko.couplings import Couplings
from eko.io.runcards import TheoryCard
from eko.quantities.couplings import CouplingEvolutionMethod, CouplingsInfo
-from eko.quantities.heavy_quarks import QuarkMassScheme
+from eko.quantities.heavy_quarks import FlavorsNumber, QuarkMassScheme
# try to load LHAPDF - if not available, we'll use the cached values
try:
@@ -35,16 +35,12 @@
use_PEGASUS = False
-def ref_couplings(
- ref_values,
- ref_scale: float,
-) -> CouplingsInfo:
+def ref_couplings(ref_values, ref_scale: float, ref_nf: FlavorsNumber) -> CouplingsInfo:
return CouplingsInfo(
alphas=ref_values[0],
alphaem=ref_values[1],
scale=ref_scale,
- max_num_flavs=6,
- num_flavs_ref=None,
+ num_flavs_ref=ref_nf,
)
@@ -54,11 +50,11 @@ def test_a_s(self):
"""Tests the value of alpha_s (for now only at LO)
for a given set of parameters
"""
- # TODO @JCM: we need a source for this!
+ # source: JCM
known_val = 0.0091807954
ref_mu2 = 90
ask_q2 = 125
- ref = ref_couplings([0.1181, 0.007496], np.sqrt(ref_mu2))
+ ref = ref_couplings([0.1181, 0.007496], np.sqrt(ref_mu2), 5)
as_FFNS_LO = Couplings(
couplings=ref,
order=(1, 0),
@@ -80,7 +76,7 @@ def benchmark_LHA_paper(self):
# LO - FFNS
# note that the LO-FFNS value reported in :cite:`Giele:2002hx`
# was corrected in :cite:`Dittmar:2005ed`
- coupling_ref = ref_couplings([0.35, 0.007496], np.sqrt(2))
+ coupling_ref = ref_couplings([0.35, 0.007496], np.sqrt(2), 4)
as_FFNS_LO = Couplings(
couplings=coupling_ref,
order=(1, 0),
@@ -141,7 +137,7 @@ def benchmark_APFEL_ffns(self):
threshold_holder = matchings.Atlas.ffns(nf, 0.0)
for order in [1, 2, 3]:
as_FFNS = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf),
order=(order, 0),
method=CouplingEvolutionMethod.EXPANDED,
masses=threshold_holder.walls[1:-1],
@@ -212,8 +208,7 @@ def benchmark_pegasus_ffns(self):
}
# collect my values
threshold_holder = matchings.Atlas.ffns(nf, 0.0)
- couplings = ref_couplings(coupling_ref, scale_ref)
- couplings.max_num_flavs = 4
+ couplings = ref_couplings(coupling_ref, scale_ref, nf)
for order in [1, 2, 3, 4]:
as_FFNS = Couplings(
couplings=couplings,
@@ -259,6 +254,7 @@ def benchmark_APFEL_vfns(self):
Q2s = [1, 2**2, 3**2, 90**2, 100**2]
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 91.0
+ nf_ref = 5
threshold_list = np.power([2, 4, 175], 2)
apfel_vals_dict = {
1: np.array(
@@ -292,7 +288,7 @@ def benchmark_APFEL_vfns(self):
# collect my values
for order in [1, 2, 3]:
as_VFNS = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf_ref),
order=(order, 0),
method=CouplingEvolutionMethod.EXPANDED,
masses=threshold_list,
@@ -339,8 +335,9 @@ def benchmark_APFEL_vfns_fact_to_ren(self):
]
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 91.0
+ nf_ref = 5
fact_to_ren_lin_list = [0.567, 2.34]
- threshold_list = np.power([2, 2 * 4, 2 * 92], 2)
+ masses_list = np.power([2, 2 * 4, 2 * 92], 2)
apfel_vals_dict_list = [
{
1: np.array(
@@ -437,10 +434,10 @@ def benchmark_APFEL_vfns_fact_to_ren(self):
# collect my values
for order in [1, 2, 3]:
as_VFNS = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf_ref),
order=(order, 0),
method=CouplingEvolutionMethod.EXACT,
- masses=threshold_list.tolist(),
+ masses=masses_list.tolist(),
hqm_scheme=QuarkMassScheme.POLE,
thresholds_ratios=np.array([1.0, 1.0, 1.0]) / fact_to_ren_lin**2,
)
@@ -457,7 +454,7 @@ def benchmark_APFEL_vfns_fact_to_ren(self):
apfel.SetAlphaEvolution("exact")
apfel.SetAlphaQCDRef(coupling_ref[0], scale_ref)
apfel.SetVFNS()
- apfel.SetPoleMasses(*np.sqrt(threshold_list))
+ apfel.SetPoleMasses(*np.sqrt(masses_list))
apfel.SetRenFacRatio(1.0 / fact_to_ren_lin)
apfel.InitializeAPFEL()
# collect a_s
@@ -468,12 +465,18 @@ def benchmark_APFEL_vfns_fact_to_ren(self):
)
np.testing.assert_allclose(apfel_vals, np.array(apfel_vals_cur))
# check myself to APFEL
- np.testing.assert_allclose(apfel_vals, np.array(my_vals), rtol=2.5e-5)
+ np.testing.assert_allclose(
+ apfel_vals,
+ np.array(my_vals),
+ rtol=2.5e-5,
+ err_msg=f"{order=},{fact_to_ren_lin=}",
+ )
def benchmark_APFEL_vfns_threshold(self):
Q2s = np.power([30, 96, 150], 2)
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 91.0
+ nf_ref = 4
threshold_list = np.power([30, 95, 240], 2)
thresholds_ratios = [2.34**2, 1.0**2, 0.5**2]
apfel_vals_dict = {
@@ -487,7 +490,7 @@ def benchmark_APFEL_vfns_threshold(self):
# collect my values
for order in [2, 3]:
as_VFNS = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf_ref),
order=(order, 0),
method=CouplingEvolutionMethod.EXPANDED,
masses=threshold_list.tolist(),
@@ -496,7 +499,6 @@ def benchmark_APFEL_vfns_threshold(self):
)
my_vals = []
for Q2 in Q2s:
- print(Q2)
my_vals.append(as_VFNS.a(Q2)[0])
# get APFEL numbers - if available else use cache
apfel_vals = apfel_vals_dict[order]
@@ -516,7 +518,6 @@ def benchmark_APFEL_vfns_threshold(self):
apfel_vals_cur = []
for Q2 in Q2s:
apfel_vals_cur.append(apfel.AlphaQCD(np.sqrt(Q2)) / (4.0 * np.pi))
- print(apfel_vals_cur)
np.testing.assert_allclose(apfel_vals, np.array(apfel_vals_cur))
# check myself to APFEL
np.testing.assert_allclose(apfel_vals, np.array(my_vals))
@@ -525,6 +526,7 @@ def benchmark_APFEL_vfns_msbar(self):
Q2s = np.power([3, 96, 150], 2)
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 91.0
+ nf_ref = 5
Q2m = np.power([2.0, 4.0, 175], 2)
m2s = np.power((1.4, 4.0, 175), 2)
apfel_vals_dict = {
@@ -538,7 +540,7 @@ def benchmark_APFEL_vfns_msbar(self):
# collect my values
for order in [2, 3]:
as_VFNS = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf_ref),
order=(order, 0),
method=CouplingEvolutionMethod.EXPANDED,
masses=m2s.tolist(),
@@ -586,7 +588,7 @@ def benchmark_lhapdf_ffns_lo(self):
# collect my values
threshold_holder = matchings.Atlas.ffns(nf, 0.0)
as_FFNS_LO = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf),
order=(1, 0),
method=CouplingEvolutionMethod.EXACT,
masses=threshold_holder.walls[1:-1],
@@ -629,8 +631,9 @@ def benchmark_apfel_exact(self):
Q2s = [1e1, 1e2, 1e3, 1e4]
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 90
+ nf = 3
# collect my values
- threshold_holder = matchings.Atlas.ffns(3, 0.0)
+ threshold_holder = matchings.Atlas.ffns(nf, 0.0)
# LHAPDF cache
apfel_vals_dict = {
1: np.array(
@@ -660,7 +663,7 @@ def benchmark_apfel_exact(self):
}
for order in range(1, 3 + 1):
sc = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf),
order=(order, 0),
method=CouplingEvolutionMethod.EXACT,
masses=threshold_holder.walls[1:-1],
@@ -696,8 +699,9 @@ def benchmark_lhapdf_exact(self):
Q2s = [1e1, 1e2, 1e3, 1e4]
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 90
+ nf = 3
# collect my values
- threshold_holder = matchings.Atlas.ffns(3, 0.0)
+ threshold_holder = matchings.Atlas.ffns(nf, 0.0)
# LHAPDF cache
lhapdf_vals_dict = {
1: np.array(
@@ -735,7 +739,7 @@ def benchmark_lhapdf_exact(self):
}
for order in range(1, 4 + 1):
sc = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf),
order=(order, 0),
method=CouplingEvolutionMethod.EXACT,
masses=threshold_holder.walls[1:-1],
@@ -766,6 +770,7 @@ def benchmark_lhapdf_zmvfns_lo(self):
Q2s = [1, 1e1, 1e2, 1e3, 1e4]
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 900
+ nf_ref = 5
m2c = 2.0
m2b = 25.0
m2t = 1500.0
@@ -785,7 +790,7 @@ def benchmark_lhapdf_zmvfns_lo(self):
# collect my values
as_VFNS_LO = Couplings(
- couplings=ref_couplings(coupling_ref, np.sqrt(scale_ref)),
+ couplings=ref_couplings(coupling_ref, np.sqrt(scale_ref), nf_ref),
order=(1, 0),
method=CouplingEvolutionMethod.EXACT,
masses=threshold_list,
diff --git a/benchmarks/ekobox/benchmark_evol_pdf.py b/benchmarks/ekobox/benchmark_evol_pdf.py
index 3a9dc0f4a..2a9aa8ea9 100644
--- a/benchmarks/ekobox/benchmark_evol_pdf.py
+++ b/benchmarks/ekobox/benchmark_evol_pdf.py
@@ -23,7 +23,6 @@ def benchmark_evolve_single_member(
theory.couplings.alphas = 0.118000
theory.couplings.scale = 91.1876
theory.couplings.alphaem = 0.007496
- theory.couplings.max_num_flavs = 3
theory.heavy.num_flavs_max_pdf = 3
theory.heavy.masses.c.value = 1.3
theory.heavy.masses.b.value = 4.75
diff --git a/doc/source/overview/tutorials/alpha_s.ipynb b/doc/source/overview/tutorials/alpha_s.ipynb
index a9d75c0ca..d8954900d 100644
--- a/doc/source/overview/tutorials/alpha_s.ipynb
+++ b/doc/source/overview/tutorials/alpha_s.ipynb
@@ -40,7 +40,7 @@
"\n",
"# set the (alpha_s, alpha_em) reference values\n",
"couplings_ref = CouplingsInfo(\n",
- " alphas=0.118, alphaem=0.007496252, scale=91.0, num_flavs_ref=None, max_num_flavs=5\n",
+ " alphas=0.118, alphaem=0.007496252, scale=91.0, num_flavs_ref=5\n",
")\n",
"\n",
"# set heavy quark masses and their threshold ratios\n",
@@ -105,13 +105,10 @@
}
],
"metadata": {
- "interpreter": {
- "hash": "0a84ba3ac8703c04e87bc503a7d00188dfd591ad56130da93c406115a1e4a408"
- },
"kernelspec": {
"display_name": "eko-KkPVjVhh-py3.10",
"language": "python",
- "name": "eko-kkpvjvhh-py3.10"
+ "name": "python3"
},
"language_info": {
"codemirror_mode": {
diff --git a/doc/source/overview/tutorials/pdf.ipynb b/doc/source/overview/tutorials/pdf.ipynb
index 4607ef891..9da9ead26 100644
--- a/doc/source/overview/tutorials/pdf.ipynb
+++ b/doc/source/overview/tutorials/pdf.ipynb
@@ -371,7 +371,6 @@
"th_card.couplings.alphas = 0.130000 # reference value of alpha_s\n",
"th_card.couplings.scale = 91.1876 # the reference scale at which alpha_s is provided\n",
"th_card.couplings.num_flavs_ref = 5 # the number of flavors active at the alpha_s reference scale\n",
- "th_card.couplings.max_num_flavs = 5 # the maximum number of flavors active in the alpha_s evolution\n",
"th_card.couplings.num_flavs_init = 3 # the number of flavors active at the reference scale\n",
"th_card.num_flavs_max_pdf = 5 # the maximum number of flavors active in the pdf evolution."
]
diff --git a/extras/n3lo_bench/splitting_function_utils.py b/extras/n3lo_bench/splitting_function_utils.py
index 6917e6bd8..db06f5c72 100644
--- a/extras/n3lo_bench/splitting_function_utils.py
+++ b/extras/n3lo_bench/splitting_function_utils.py
@@ -104,7 +104,6 @@ def compute_a_s(q2=None, xif2=1.0, nf=None, order=(4, 0)):
alphas=0.1181,
alphaem=0.007496,
scale=91.00,
- max_num_flavs=6,
num_flavs_ref=5,
)
sc = Couplings(
diff --git a/src/eko/io/runcards.py b/src/eko/io/runcards.py
index 41aef9445..6f1b585b0 100644
--- a/src/eko/io/runcards.py
+++ b/src/eko/io/runcards.py
@@ -185,7 +185,6 @@ def new_theory(self):
em_running=em_running,
scale=old["Qref"],
num_flavs_ref=old["nfref"],
- max_num_flavs=old["MaxNfAs"],
)
new["heavy"] = {
"num_flavs_init": nf_default(old["Q0"] ** 2.0, default_atlas(ms, ks))
diff --git a/src/eko/quantities/couplings.py b/src/eko/quantities/couplings.py
index 01b11d138..f80420a9c 100644
--- a/src/eko/quantities/couplings.py
+++ b/src/eko/quantities/couplings.py
@@ -20,7 +20,6 @@ class CouplingsInfo(DictLike):
alphas: Coupling
alphaem: Coupling
scale: LinearScale
- max_num_flavs: FlavorsNumber
num_flavs_ref: FlavorsNumber
r"""Number of active flavors at strong coupling reference scale.
diff --git a/src/ekobox/cards.py b/src/ekobox/cards.py
index 474e7d931..e68a8ce63 100644
--- a/src/ekobox/cards.py
+++ b/src/ekobox/cards.py
@@ -15,7 +15,6 @@
alphaem=0.007496252,
scale=91.2,
num_flavs_ref=5,
- max_num_flavs=6,
),
heavy=dict(
num_flavs_init=4,
diff --git a/tests/eko/kernels/test_kernels_QEDns.py b/tests/eko/kernels/test_kernels_QEDns.py
index e84956084..b85a3f013 100644
--- a/tests/eko/kernels/test_kernels_QEDns.py
+++ b/tests/eko/kernels/test_kernels_QEDns.py
@@ -121,7 +121,6 @@ def test_zero_true_gamma():
alphaem=alpharef[1],
scale=muref,
num_flavs_ref=5,
- max_num_flavs=6,
)
)
evmod = CouplingEvolutionMethod.EXACT
diff --git a/tests/eko/quantities/test_couplings.py b/tests/eko/quantities/test_couplings.py
index 00ccae9d1..83bef709c 100644
--- a/tests/eko/quantities/test_couplings.py
+++ b/tests/eko/quantities/test_couplings.py
@@ -3,7 +3,7 @@
def test_couplings_ref():
scale = 90.0
- d = dict(alphas=0.1, alphaem=0.01, scale=scale, max_num_flavs=6, num_flavs_ref=5)
+ d = dict(alphas=0.1, alphaem=0.01, scale=scale, num_flavs_ref=5)
couplings = CouplingsInfo.from_dict(d)
assert couplings.scale == scale
assert not couplings.em_running
diff --git a/tests/eko/test_couplings.py b/tests/eko/test_couplings.py
index 646a56448..10535cbcb 100644
--- a/tests/eko/test_couplings.py
+++ b/tests/eko/test_couplings.py
@@ -55,7 +55,6 @@ def test_init(self):
alphaem=alpharef[1],
scale=muref,
num_flavs_ref=5,
- max_num_flavs=6,
)
)
order = (1, 0)
@@ -162,7 +161,6 @@ def test_ref(self):
alphaem=alpharef[1],
scale=muref,
num_flavs_ref=nfref,
- max_num_flavs=6,
)
)
for order_s in [1, 2, 3, 4]:
@@ -197,7 +195,6 @@ def test_ref_copy_e841b0dfdee2f31d9ccc1ecee4d9d1a6f6624313(self):
alphaem=alpharef[1],
scale=muref,
num_flavs_ref=3, # reference nf is needed to force the matching
- max_num_flavs=6,
)
)
sc = Couplings(
@@ -238,7 +235,6 @@ def test_exact(self):
alphaem=alpharef[1],
scale=muref,
num_flavs_ref=nfref,
- max_num_flavs=6,
em_running=em_running,
)
)
@@ -301,7 +297,6 @@ def benchmark_expanded_n3lo(self):
alphaem=alpharef[1],
scale=muref,
num_flavs_ref=5,
- max_num_flavs=6,
)
m2c = 2
m2b = 25
From cfc7ee53bd807c5377263fd1024e313d4d5f8315 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 31 Jul 2023 12:58:29 +0200
Subject: [PATCH 20/67] Drop num_flavs_max_pdf
---
benchmarks/ekobox/benchmark_evol_pdf.py | 1 -
doc/source/overview/tutorials/pdf.ipynb | 3 +--
src/eko/io/legacy.py | 1 -
src/eko/io/runcards.py | 1 -
src/eko/quantities/heavy_quarks.py | 2 --
src/ekobox/cards.py | 1 -
tests/eko/test_quantities.py | 1 -
7 files changed, 1 insertion(+), 9 deletions(-)
diff --git a/benchmarks/ekobox/benchmark_evol_pdf.py b/benchmarks/ekobox/benchmark_evol_pdf.py
index 2a9aa8ea9..c85083604 100644
--- a/benchmarks/ekobox/benchmark_evol_pdf.py
+++ b/benchmarks/ekobox/benchmark_evol_pdf.py
@@ -23,7 +23,6 @@ def benchmark_evolve_single_member(
theory.couplings.alphas = 0.118000
theory.couplings.scale = 91.1876
theory.couplings.alphaem = 0.007496
- theory.heavy.num_flavs_max_pdf = 3
theory.heavy.masses.c.value = 1.3
theory.heavy.masses.b.value = 4.75
theory.heavy.masses.t.value = 172
diff --git a/doc/source/overview/tutorials/pdf.ipynb b/doc/source/overview/tutorials/pdf.ipynb
index 9da9ead26..0719d9d63 100644
--- a/doc/source/overview/tutorials/pdf.ipynb
+++ b/doc/source/overview/tutorials/pdf.ipynb
@@ -371,8 +371,7 @@
"th_card.couplings.alphas = 0.130000 # reference value of alpha_s\n",
"th_card.couplings.scale = 91.1876 # the reference scale at which alpha_s is provided\n",
"th_card.couplings.num_flavs_ref = 5 # the number of flavors active at the alpha_s reference scale\n",
- "th_card.couplings.num_flavs_init = 3 # the number of flavors active at the reference scale\n",
- "th_card.num_flavs_max_pdf = 5 # the maximum number of flavors active in the pdf evolution."
+ "th_card.heavy.num_flavs_init = 3 # the number of flavors active at the reference scale"
]
},
{
diff --git a/src/eko/io/legacy.py b/src/eko/io/legacy.py
index d580f7373..cb7b24644 100644
--- a/src/eko/io/legacy.py
+++ b/src/eko/io/legacy.py
@@ -100,7 +100,6 @@ def from_old(cls, old: RawCard):
"""Load from old metadata."""
heavy = HeavyInfo(
num_flavs_init=4,
- num_flavs_max_pdf=5,
intrinsic_flavors=[],
masses=HeavyQuarkMasses(
[
diff --git a/src/eko/io/runcards.py b/src/eko/io/runcards.py
index 6f1b585b0..c66e48dc4 100644
--- a/src/eko/io/runcards.py
+++ b/src/eko/io/runcards.py
@@ -190,7 +190,6 @@ def new_theory(self):
"num_flavs_init": nf_default(old["Q0"] ** 2.0, default_atlas(ms, ks))
if old["nf0"] is None
else old["nf0"],
- "num_flavs_max_pdf": old["MaxNfPdf"],
"matching_ratios": self.heavies("k%sThr", old),
"masses_scheme": old["HQ"],
}
diff --git a/src/eko/quantities/heavy_quarks.py b/src/eko/quantities/heavy_quarks.py
index df0285649..ab0ece64a 100644
--- a/src/eko/quantities/heavy_quarks.py
+++ b/src/eko/quantities/heavy_quarks.py
@@ -96,8 +96,6 @@ class HeavyInfo(DictLike):
I.e. :math:`n_{f,\text{ref}}(\mu^2_0)`, formerly called ``nf0``.
"""
- num_flavs_max_pdf: FlavorsNumber
- """Maximum number of quark PDFs."""
intrinsic_flavors: IntrinsicFlavors
"""List of intrinsic quark PDFs."""
masses: HeavyQuarkMasses
diff --git a/src/ekobox/cards.py b/src/ekobox/cards.py
index e68a8ce63..a69b32ad6 100644
--- a/src/ekobox/cards.py
+++ b/src/ekobox/cards.py
@@ -18,7 +18,6 @@
),
heavy=dict(
num_flavs_init=4,
- num_flavs_max_pdf=6,
intrinsic_flavors=[4],
masses=[ReferenceRunning([mq, nan]) for mq in (2.0, 4.5, 173.07)],
masses_scheme="POLE",
diff --git a/tests/eko/test_quantities.py b/tests/eko/test_quantities.py
index 0c2628b30..8fd6c298f 100644
--- a/tests/eko/test_quantities.py
+++ b/tests/eko/test_quantities.py
@@ -34,7 +34,6 @@ def test_HeavyQuarks():
def test_HeavyInfo():
i = hq.HeavyInfo(
num_flavs_init=4,
- num_flavs_max_pdf=6,
intrinsic_flavors=[4, 5],
masses=hq.HeavyQuarkMasses(
[
From 8b3899d02dd80e6ea4dc31a0c517ac7785bcc3d8 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 31 Jul 2023 19:13:24 +0200
Subject: [PATCH 21/67] Start dropping intrinsic
---
benchmarks/eko/benchmark_evol_to_unity.py | 1 -
src/eko/evolution_operator/grid.py | 8 +-
.../evolution_operator/matching_condition.py | 48 +++++-----
.../operator_matrix_element.py | 8 +-
src/eko/evolution_operator/physical.py | 23 ++---
src/eko/io/legacy.py | 1 -
src/eko/io/runcards.py | 5 -
src/eko/io/types.py | 1 -
src/eko/quantities/heavy_quarks.py | 10 +-
src/eko/runner/legacy.py | 2 -
src/eko/runner/managed.py | 2 -
src/eko/runner/parts.py | 40 ++------
src/ekobox/cards.py | 1 -
.../test_matching_condition.py | 91 +++++--------------
tests/eko/evolution_operator/test_physical.py | 36 +++-----
tests/eko/io/test_runcards.py | 1 -
tests/eko/test_quantities.py | 1 -
17 files changed, 80 insertions(+), 199 deletions(-)
diff --git a/benchmarks/eko/benchmark_evol_to_unity.py b/benchmarks/eko/benchmark_evol_to_unity.py
index 893de5de3..d269db202 100644
--- a/benchmarks/eko/benchmark_evol_to_unity.py
+++ b/benchmarks/eko/benchmark_evol_to_unity.py
@@ -23,7 +23,6 @@ def update_cards(theory: TheoryCard, operator: OperatorCard):
num_flavs_ref=None,
)
theory.heavy.num_flavs_init = 4
- theory.heavy.intrinsic_flavors = [4, 5]
theory.heavy.masses.c.value = 1.0
theory.heavy.masses.b.value = 4.75
theory.heavy.masses.t.value = 173.0
diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py
index 1180697a6..382ece751 100644
--- a/src/eko/evolution_operator/grid.py
+++ b/src/eko/evolution_operator/grid.py
@@ -60,7 +60,6 @@ def __init__(
masses: List[float],
mass_scheme,
thresholds_ratios: List[float],
- intrinsic_flavors: list,
xif: float,
n3lo_ad_variation: tuple,
configs: Configs,
@@ -72,7 +71,6 @@ def __init__(
# check
config: Dict[str, Any] = {}
config["order"] = order
- config["intrinsic_range"] = intrinsic_flavors
config["xif2"] = xif**2
config["HQ"] = mass_scheme
config["ModSV"] = configs.scvar_method
@@ -171,16 +169,15 @@ def generate(self, q2: EPoint) -> OpDict:
operator.compute()
is_downward = is_downward_path(path)
- intrinsic_range = [4, 5, 6] if is_downward else self.config["intrinsic_range"]
qed = self.config["order"][1] > 0
final_op = physical.PhysicalOperator.ad_to_evol_map(
- operator.op_members, operator.nf, operator.q2_to, intrinsic_range, qed
+ operator.op_members, operator.nf, operator.q2_to, qed
)
# and multiply the lower ones from the right
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, qed
+ op.op_members, op.nf, op.q2_to, qed
)
# join with the basis rotation, since matching requires c+ (or likewise)
@@ -189,7 +186,6 @@ def generate(self, q2: EPoint) -> OpDict:
self._matching_operators[op.q2_to],
nf_match,
op.q2_to,
- intrinsic_range=intrinsic_range,
qed=qed,
)
if is_downward:
diff --git a/src/eko/evolution_operator/matching_condition.py b/src/eko/evolution_operator/matching_condition.py
index 059617fbf..e84ef4d2e 100644
--- a/src/eko/evolution_operator/matching_condition.py
+++ b/src/eko/evolution_operator/matching_condition.py
@@ -20,7 +20,6 @@ def split_ad_to_evol_map(
op_members,
nf,
q2_thr,
- intrinsic_range,
qed=False,
):
"""
@@ -35,8 +34,6 @@ def split_ad_to_evol_map(
number of active flavors *below* the threshold
q2_thr: float
threshold value
- intrinsic_range : list
- list of intrinsic quark pids
qed : bool
activate qed
"""
@@ -78,27 +75,26 @@ def split_ad_to_evol_map(
)
# intrinsic matching
- if len(intrinsic_range) != 0:
- op_id = member.OpMember.id_like(op_members[(200, 200)])
- for intr_fl in intrinsic_range:
- ihq = br.quark_names[intr_fl - 1] # find name
- if intr_fl > nf + 1:
- # keep the higher quarks as they are
- m[f"{ihq}+.{ihq}+"] = op_id.copy()
- m[f"{ihq}-.{ihq}-"] = op_id.copy()
- elif intr_fl == nf + 1:
- # match the missing contribution from h+ and h-
- m.update(
- {
- f"{ihq}+.{ihq}+": op_members[
- (br.matching_hplus_pid, br.matching_hplus_pid)
- ],
- f"S.{ihq}+": op_members[(100, br.matching_hplus_pid)],
- f"g.{ihq}+": op_members[(21, br.matching_hplus_pid)],
- f"{ihq}-.{ihq}-": op_members[
- (br.matching_hminus_pid, br.matching_hminus_pid)
- ],
- # f"V.{ihq}-": op_members[(200, br.matching_hminus_pid)],
- }
- )
+ op_id = member.OpMember.id_like(op_members[(200, 200)])
+ for intr_fl in [4, 5, 6]:
+ ihq = br.quark_names[intr_fl - 1] # find name
+ if intr_fl > nf + 1:
+ # keep the higher quarks as they are
+ m[f"{ihq}+.{ihq}+"] = op_id.copy()
+ m[f"{ihq}-.{ihq}-"] = op_id.copy()
+ elif intr_fl == nf + 1:
+ # match the missing contribution from h+ and h-
+ m.update(
+ {
+ f"{ihq}+.{ihq}+": op_members[
+ (br.matching_hplus_pid, br.matching_hplus_pid)
+ ],
+ f"S.{ihq}+": op_members[(100, br.matching_hplus_pid)],
+ f"g.{ihq}+": op_members[(21, br.matching_hplus_pid)],
+ f"{ihq}-.{ihq}-": op_members[
+ (br.matching_hminus_pid, br.matching_hminus_pid)
+ ],
+ # f"V.{ihq}-": op_members[(200, br.matching_hminus_pid)],
+ }
+ )
return cls.promote_names(m, q2_thr)
diff --git a/src/eko/evolution_operator/operator_matrix_element.py b/src/eko/evolution_operator/operator_matrix_element.py
index 8966a62b9..b45e06c81 100644
--- a/src/eko/evolution_operator/operator_matrix_element.py
+++ b/src/eko/evolution_operator/operator_matrix_element.py
@@ -214,10 +214,6 @@ class OperatorMatrixElement(Operator):
def __init__(self, config, managers, nf, q2, is_backward, L, is_msbar):
super().__init__(config, managers, Segment(q2, q2, nf))
self.backward_method = config["backward_inversion"] if is_backward else None
- if is_backward:
- self.is_intrinsic = True
- else:
- self.is_intrinsic = bool(len(config["intrinsic_range"]) != 0)
self.L = L
self.is_msbar = is_msbar
# Note for the moment only QCD matching is implemented
@@ -238,7 +234,7 @@ def labels(self):
logger.warning("%s: skipping non-singlet sector", self.log_label)
else:
labels.append((200, 200))
- if self.is_intrinsic or self.backward_method is not None:
+ if self.backward_method is not None:
# intrinsic labels, which are not zero at NLO
labels.append((br.matching_hminus_pid, br.matching_hminus_pid))
# These contributions are always 0 for the moment
@@ -254,7 +250,7 @@ def labels(self):
(br.matching_hplus_pid, 100),
]
)
- if self.is_intrinsic or self.backward_method is not None:
+ if self.backward_method is not None:
labels.extend(
[
(21, br.matching_hplus_pid),
diff --git a/src/eko/evolution_operator/physical.py b/src/eko/evolution_operator/physical.py
index c963e2a26..6a5138d25 100644
--- a/src/eko/evolution_operator/physical.py
+++ b/src/eko/evolution_operator/physical.py
@@ -22,7 +22,7 @@ class PhysicalOperator(member.OperatorBase):
"""
@classmethod
- def ad_to_evol_map(cls, op_members, nf, q2_final, intrinsic_range, qed=False):
+ def ad_to_evol_map(cls, op_members, nf, q2_final, qed=False):
"""
Obtain map between the 3-dimensional anomalous dimension basis and the 4-dimensional evolution basis.
@@ -34,8 +34,6 @@ def ad_to_evol_map(cls, op_members, nf, q2_final, intrinsic_range, qed=False):
operator members in anomalous dimension basis
nf : int
number of active light flavors
- intrinsic_range : sequence
- intrinsic heavy flavors
qed : bool
activate qed
@@ -93,15 +91,14 @@ def ad_to_evol_map(cls, op_members, nf, q2_final, intrinsic_range, qed=False):
m["Tu8.Tu8"] = op_members[(br.non_singlet_pids_map["ns+u"], 0)]
m["Vu8.Vu8"] = op_members[(br.non_singlet_pids_map["ns-u"], 0)]
# deal with intrinsic heavy quark PDFs
- if intrinsic_range is not None:
- hqfl = "cbt"
- op_id = member.OpMember.id_like(op_members[(21, 21)])
- for intr_fl in intrinsic_range:
- if intr_fl <= nf: # light quarks are not intrinsic
- continue
- hq = hqfl[intr_fl - 4] # find name
- # intrinsic means no evolution, i.e. they are evolving with the identity
- m[f"{hq}+.{hq}+"] = op_id.copy()
- m[f"{hq}-.{hq}-"] = op_id.copy()
+ hqfl = "cbt"
+ op_id = member.OpMember.id_like(op_members[(21, 21)])
+ for intr_fl in [4, 5, 6]:
+ if intr_fl <= nf: # light quarks are not intrinsic
+ continue
+ hq = hqfl[intr_fl - 4] # find name
+ # intrinsic means no evolution, i.e. they are evolving with the identity
+ m[f"{hq}+.{hq}+"] = op_id.copy()
+ m[f"{hq}-.{hq}-"] = op_id.copy()
# map key to MemberName
return cls.promote_names(m, q2_final)
diff --git a/src/eko/io/legacy.py b/src/eko/io/legacy.py
index cb7b24644..8491a6acc 100644
--- a/src/eko/io/legacy.py
+++ b/src/eko/io/legacy.py
@@ -100,7 +100,6 @@ def from_old(cls, old: RawCard):
"""Load from old metadata."""
heavy = HeavyInfo(
num_flavs_init=4,
- intrinsic_flavors=[],
masses=HeavyQuarkMasses(
[
ReferenceRunning([_MC, np.inf]),
diff --git a/src/eko/io/runcards.py b/src/eko/io/runcards.py
index c66e48dc4..d5c8c36e8 100644
--- a/src/eko/io/runcards.py
+++ b/src/eko/io/runcards.py
@@ -193,11 +193,6 @@ def new_theory(self):
"matching_ratios": self.heavies("k%sThr", old),
"masses_scheme": old["HQ"],
}
- intrinsic = []
- for idx, q in enumerate(hq.FLAVORS):
- if old.get(f"i{q}".upper()) == 1:
- intrinsic.append(idx + 4)
- new["heavy"]["intrinsic_flavors"] = intrinsic
if old["HQ"] == "POLE":
new["heavy"]["masses"] = [[m, nan] for m in ms]
elif old["HQ"] == "MSBAR":
diff --git a/src/eko/io/types.py b/src/eko/io/types.py
index 5573bafbb..b92628116 100644
--- a/src/eko/io/types.py
+++ b/src/eko/io/types.py
@@ -22,7 +22,6 @@
Order = Tuple[int, int]
FlavorsNumber = int
FlavorIndex = int
-IntrinsicFlavors = typing.List[FlavorIndex]
N3LOAdVariation = typing.Tuple[int, int, int, int]
# Evolution coordinates
diff --git a/src/eko/quantities/heavy_quarks.py b/src/eko/quantities/heavy_quarks.py
index ab0ece64a..3b081a03d 100644
--- a/src/eko/quantities/heavy_quarks.py
+++ b/src/eko/quantities/heavy_quarks.py
@@ -6,13 +6,7 @@
import numpy as np
from ..io.dictlike import DictLike
-from ..io.types import (
- FlavorsNumber,
- IntrinsicFlavors,
- LinearScale,
- ReferenceRunning,
- SquaredScale,
-)
+from ..io.types import FlavorsNumber, LinearScale, ReferenceRunning, SquaredScale
FLAVORS = "cbt"
@@ -96,8 +90,6 @@ class HeavyInfo(DictLike):
I.e. :math:`n_{f,\text{ref}}(\mu^2_0)`, formerly called ``nf0``.
"""
- intrinsic_flavors: IntrinsicFlavors
- """List of intrinsic quark PDFs."""
masses: HeavyQuarkMasses
"""List of heavy quark masses."""
masses_scheme: QuarkMassScheme
diff --git a/src/eko/runner/legacy.py b/src/eko/runner/legacy.py
index c964c3415..76d6f1a8a 100644
--- a/src/eko/runner/legacy.py
+++ b/src/eko/runner/legacy.py
@@ -44,7 +44,6 @@ def __init__(
"""
new_theory, new_operator = runcards.update(theory_card, operators_card)
- new_theory.heavy.intrinsic_flavors = [4, 5, 6]
# Store inputs
self.path = path
@@ -69,7 +68,6 @@ def __init__(
masses=masses,
mass_scheme=new_theory.heavy.masses_scheme.value,
thresholds_ratios=new_theory.heavy.squared_ratios,
- intrinsic_flavors=new_theory.heavy.intrinsic_flavors,
xif=new_theory.xif,
configs=new_operator.configs,
debug=new_operator.debug,
diff --git a/src/eko/runner/managed.py b/src/eko/runner/managed.py
index c353decde..dc253e2ea 100644
--- a/src/eko/runner/managed.py
+++ b/src/eko/runner/managed.py
@@ -20,8 +20,6 @@
def solve(theory: TheoryCard, operator: OperatorCard, path: Path):
"""Solve DGLAP equations in terms of evolution kernel operators (EKO)."""
- theory.heavy.intrinsic_flavors = [4, 5, 6]
-
with EKO.create(path) as builder:
eko = builder.load_cards(theory, operator).build() # pylint: disable=E1101
diff --git a/src/eko/runner/parts.py b/src/eko/runner/parts.py
index 9f97a6de5..22a2ff9ca 100644
--- a/src/eko/runner/parts.py
+++ b/src/eko/runner/parts.py
@@ -40,32 +40,6 @@ def managers(eko: EKO) -> Managers:
)
-def blowup_info(eko: EKO) -> dict:
- """Prepare common information to blow up to flavor basis.
-
- Note
- ----
- ``intrinsic_range`` is a fully deprecated feature, here and anywhere else,
- since a full range is already always used for backward evolution, and it is
- not harmful to use it also for forward.
-
- Indeed, the only feature of non-intrinsic evolution is to absorb a
- non-trivial boundary condition when an intrinsic PDF is defined.
- But to achieve this, is sufficient to not specify any intrinsic boundary
- condition at all, while if something is there, it is intuitive enough that
- it will be consistently evolved.
-
- Moreover, since two different behavior are applied for the forward and
- backward evolution, the intrinsic range is a "non-local" function, since it
- does not depend only on the evolution segment, but also on the previous
- evolution history (to determine if evolution is backward in flavor,
- irrespectively of happening for an increasing or decreasing interval in
- scale at fixed flavor).
-
- """
- return dict(intrinsic_range=[4, 5, 6], qed=eko.theory_card.order[1] > 0)
-
-
def evolve_configs(eko: EKO) -> dict:
"""Create configs for :class:`Operator`.
@@ -99,10 +73,10 @@ def evolve(eko: EKO, recipe: Evolution) -> Operator:
)
op.compute()
- binfo = blowup_info(eko)
+ qed = eko.theory_card.order[1] > 0
res, err = physical.PhysicalOperator.ad_to_evol_map(
- op.op_members, op.nf, op.q2_to, **binfo
- ).to_flavor_basis_tensor(qed=binfo["qed"])
+ op.op_members, op.nf, op.q2_to, qed
+ ).to_flavor_basis_tensor(qed)
return Operator(res, err)
@@ -120,7 +94,6 @@ def matching_configs(eko: EKO) -> dict:
return dict(
**evolve_configs(eko),
backward_inversion=ocard.configs.inversion_method,
- intrinsic_range=tcard.heavy.intrinsic_flavors,
)
@@ -148,11 +121,10 @@ def match(eko: EKO, recipe: Matching) -> Operator:
eko.theory_card.heavy.masses_scheme is QuarkMassScheme.MSBAR,
)
op.compute()
-
- binfo = blowup_info(eko)
+ qed = eko.theory_card.order[1] > 0
nf_match = op.nf - 1 if recipe.inverse else op.nf
res, err = matching_condition.MatchingCondition.split_ad_to_evol_map(
- op.op_members, nf_match, recipe.scale, **binfo
- ).to_flavor_basis_tensor(qed=binfo["qed"])
+ op.op_members, nf_match, recipe.scale, qed
+ ).to_flavor_basis_tensor(qed)
return Operator(res, err)
diff --git a/src/ekobox/cards.py b/src/ekobox/cards.py
index a69b32ad6..482e65faf 100644
--- a/src/ekobox/cards.py
+++ b/src/ekobox/cards.py
@@ -18,7 +18,6 @@
),
heavy=dict(
num_flavs_init=4,
- intrinsic_flavors=[4],
masses=[ReferenceRunning([mq, nan]) for mq in (2.0, 4.5, 173.07)],
masses_scheme="POLE",
matching_ratios=[1.0, 1.0, 1.0],
diff --git a/tests/eko/evolution_operator/test_matching_condition.py b/tests/eko/evolution_operator/test_matching_condition.py
index 8cbd6b537..bb6aeebbc 100644
--- a/tests/eko/evolution_operator/test_matching_condition.py
+++ b/tests/eko/evolution_operator/test_matching_condition.py
@@ -22,12 +22,6 @@ def mkOME(self):
(br.matching_hplus_pid, 21),
(200, 200),
(br.matching_hminus_pid, 200),
- ]:
- ome.update({key: mkOM(self.shape)})
- return ome
-
- def update_intrinsic_OME(self, ome):
- for key in [
(br.matching_hplus_pid, br.matching_hplus_pid),
(br.matching_hminus_pid, br.matching_hminus_pid),
(200, br.matching_hminus_pid),
@@ -35,10 +29,11 @@ def update_intrinsic_OME(self, ome):
(21, br.matching_hplus_pid),
]:
ome.update({key: mkOM(self.shape)})
+ return ome
def test_split_ad_to_evol_map(self):
ome = self.mkOME()
- a = MatchingCondition.split_ad_to_evol_map(ome, 3, 1, [])
+ a = MatchingCondition.split_ad_to_evol_map(ome, 3, 1)
triv_keys = [
"V.V",
"T3.T3",
@@ -55,6 +50,14 @@ def test_split_ad_to_evol_map(self):
"c+.S",
"c+.g",
# "c-.V",
+ "S.c+",
+ "g.c+",
+ "c+.c+",
+ "c-.c-",
+ "b+.b+",
+ "b-.b-",
+ "t+.t+",
+ "t-.t-",
]
assert sorted(str(k) for k in a.op_members.keys()) == sorted(
[*triv_keys, *keys3]
@@ -63,36 +66,8 @@ def test_split_ad_to_evol_map(self):
a.op_members[member.MemberName("V.V")].value,
ome[(200, 200)].value,
)
- # # if alpha is zero, nothing non-trivial should happen
- b = MatchingCondition.split_ad_to_evol_map(ome, 3, 1, [])
- assert sorted(str(k) for k in b.op_members.keys()) == sorted(
- [*triv_keys, *keys3]
- )
- # assert_almost_equal(
- # b.op_members[member.MemberName("V.V")].value,
- # np.eye(self.shape[0]),
- # )
- # nf=3 + IC
- self.update_intrinsic_OME(ome)
- c = MatchingCondition.split_ad_to_evol_map(ome, 3, 1, [4])
- assert sorted(str(k) for k in c.op_members.keys()) == sorted(
- [*triv_keys, *keys3, "S.c+", "g.c+", "c+.c+", "c-.c-"]
- )
- assert_almost_equal(
- c.op_members[member.MemberName("V.V")].value,
- b.op_members[member.MemberName("V.V")].value,
- )
- # nf=3 + IB
- d = MatchingCondition.split_ad_to_evol_map(ome, 3, 1, [5])
- assert sorted(str(k) for k in d.op_members.keys()) == sorted(
- [*triv_keys, *keys3, "b+.b+", "b-.b-"]
- )
- assert_almost_equal(
- d.op_members[member.MemberName("b+.b+")].value,
- np.eye(self.shape[0]),
- )
# nf=4 + IB
- d = MatchingCondition.split_ad_to_evol_map(ome, 4, 1, [5])
+ d = MatchingCondition.split_ad_to_evol_map(ome, 4, 1)
assert sorted(str(k) for k in d.op_members.keys()) == sorted(
[
*triv_keys,
@@ -106,6 +81,8 @@ def test_split_ad_to_evol_map(self):
"b+.b+",
# "b-.V",
"b-.b-",
+ "t+.t+",
+ "t-.t-",
]
)
assert_almost_equal(
@@ -127,7 +104,7 @@ def test_split_ad_to_evol_map(self):
def test_split_ad_to_evol_map_qed(self):
ome = self.mkOME()
- a = MatchingCondition.split_ad_to_evol_map(ome, 3, 1, [], qed=True)
+ a = MatchingCondition.split_ad_to_evol_map(ome, 3, 1, qed=True)
triv_keys = [
"ph.ph",
"S.S",
@@ -144,7 +121,15 @@ def test_split_ad_to_evol_map_qed(self):
keys3 = [
"c+.S",
"c+.g",
+ "S.c+",
+ "g.c+",
+ "c+.c+",
+ "c-.c-",
# "c-.V",
+ "b+.b+",
+ "b-.b-",
+ "t+.t+",
+ "t-.t-",
]
assert sorted(str(k) for k in a.op_members.keys()) == sorted(
[*triv_keys, *keys3]
@@ -153,36 +138,8 @@ def test_split_ad_to_evol_map_qed(self):
a.op_members[member.MemberName("V.V")].value,
ome[(200, 200)].value,
)
- # # if alpha is zero, nothing non-trivial should happen
- b = MatchingCondition.split_ad_to_evol_map(ome, 3, 1, [], qed=True)
- assert sorted(str(k) for k in b.op_members.keys()) == sorted(
- [*triv_keys, *keys3]
- )
- # assert_almost_equal(
- # b.op_members[member.MemberName("V.V")].value,
- # np.eye(self.shape[0]),
- # )
- # nf=3 + IC
- self.update_intrinsic_OME(ome)
- c = MatchingCondition.split_ad_to_evol_map(ome, 3, 1, [4], qed=True)
- assert sorted(str(k) for k in c.op_members.keys()) == sorted(
- [*triv_keys, *keys3, "S.c+", "g.c+", "c+.c+", "c-.c-"]
- )
- assert_almost_equal(
- c.op_members[member.MemberName("V.V")].value,
- b.op_members[member.MemberName("V.V")].value,
- )
- # nf=3 + IB
- d = MatchingCondition.split_ad_to_evol_map(ome, 3, 1, [5], qed=True)
- assert sorted(str(k) for k in d.op_members.keys()) == sorted(
- [*triv_keys, *keys3, "b+.b+", "b-.b-"]
- )
- assert_almost_equal(
- d.op_members[member.MemberName("b+.b+")].value,
- np.eye(self.shape[0]),
- )
# nf=4 + IB
- d = MatchingCondition.split_ad_to_evol_map(ome, 4, 1, [5], qed=True)
+ d = MatchingCondition.split_ad_to_evol_map(ome, 4, 1, qed=True)
assert sorted(str(k) for k in d.op_members.keys()) == sorted(
[
*triv_keys,
@@ -196,6 +153,8 @@ def test_split_ad_to_evol_map_qed(self):
"b+.b+",
# "b-.V",
"b-.b-",
+ "t+.t+",
+ "t-.t-",
]
)
assert_almost_equal(
diff --git a/tests/eko/evolution_operator/test_physical.py b/tests/eko/evolution_operator/test_physical.py
index b4a9936b6..fb74fb617 100644
--- a/tests/eko/evolution_operator/test_physical.py
+++ b/tests/eko/evolution_operator/test_physical.py
@@ -221,27 +221,21 @@ def mk_op_members(shape=(2, 2), qed=False):
return om
-def get_ad_to_evol_map(nf, intrinsic_range=None, qed=False):
+def get_ad_to_evol_map(nf, qed=False):
oms = mk_op_members(qed=qed)
- m = PhysicalOperator.ad_to_evol_map(oms, nf, 1, intrinsic_range, qed)
+ m = PhysicalOperator.ad_to_evol_map(oms, nf, 1, qed)
return sorted(map(str, m.op_members.keys()))
def test_ad_to_evol_map():
triv_ops = ("S.S", "S.g", "g.S", "g.g", "V.V", "V3.V3", "T3.T3", "V8.V8", "T8.T8")
# nf=3
- assert sorted(triv_ops) == get_ad_to_evol_map(3)
- # nf=3 + IC
- assert sorted([*triv_ops, "c+.c+", "c-.c-"]) == get_ad_to_evol_map(3, [4])
- # nf=3 + IC + IB
assert sorted(
- [*triv_ops, "c+.c+", "c-.c-", "b+.b+", "b-.b-"]
- ) == get_ad_to_evol_map(3, [4, 5])
- # nf=4 + IC(non-existant) + IB
- ks = sorted([*triv_ops, "V15.V15", "T15.T15", "b+.b+", "b-.b-"])
- assert ks == get_ad_to_evol_map(4, [4, 5])
- # nf=4 + IB
- assert ks == get_ad_to_evol_map(4, [5])
+ [*triv_ops, "c+.c+", "c-.c-", "b+.b+", "b-.b-", "t+.t+", "t-.t-"]
+ ) == get_ad_to_evol_map(3)
+ # nf=4
+ ks = sorted([*triv_ops, "V15.V15", "T15.T15", "b+.b+", "b-.b-", "t+.t+", "t-.t-"])
+ assert ks == get_ad_to_evol_map(4)
# nf=6
assert sorted(
[*triv_ops, "T15.T15", "V15.V15", "T24.T24", "V24.V24", "T35.T35", "V35.V35"]
@@ -274,18 +268,12 @@ def test_ad_to_evol_map_qed():
"Td3.Td3",
)
# nf=3
- assert sorted(triv_ops) == get_ad_to_evol_map(3, qed=True)
- # nf=3 + IC
- assert sorted([*triv_ops, "c+.c+", "c-.c-"]) == get_ad_to_evol_map(3, [4], qed=True)
- # nf=3 + IC + IB
assert sorted(
- [*triv_ops, "c+.c+", "c-.c-", "b+.b+", "b-.b-"]
- ) == get_ad_to_evol_map(3, [4, 5], qed=True)
- # nf=4 + IC(non-existant) + IB
- ks = sorted([*triv_ops, "Vu3.Vu3", "Tu3.Tu3", "b+.b+", "b-.b-"])
- assert ks == get_ad_to_evol_map(4, [4, 5], qed=True)
- # nf=4 + IB
- assert ks == get_ad_to_evol_map(4, [5], qed=True)
+ [*triv_ops, "c+.c+", "c-.c-", "b+.b+", "b-.b-", "t+.t+", "t-.t-"]
+ ) == get_ad_to_evol_map(3, True)
+ # nf=4
+ ks = sorted([*triv_ops, "Vu3.Vu3", "Tu3.Tu3", "b+.b+", "b-.b-", "t+.t+", "t-.t-"])
+ assert ks == get_ad_to_evol_map(4, True)
# nf=6
assert sorted(
[*triv_ops, "Tu3.Tu3", "Vu3.Vu3", "Td8.Td8", "Vd8.Vd8", "Tu8.Tu8", "Vu8.Vu8"]
diff --git a/tests/eko/io/test_runcards.py b/tests/eko/io/test_runcards.py
index 6af37edcb..0a391047b 100644
--- a/tests/eko/io/test_runcards.py
+++ b/tests/eko/io/test_runcards.py
@@ -100,7 +100,6 @@ def test_runcards_quarkmass():
tc["IC"] = 1
oc = copy.deepcopy(operator_card)
nt, no = rc.update(tc, oc)
- assert nt.heavy.intrinsic_flavors == [4]
for _, scale in nt.heavy.masses:
assert np.isnan(scale)
m2s = rc.masses(nt, no.configs.evolution_method)
diff --git a/tests/eko/test_quantities.py b/tests/eko/test_quantities.py
index 8fd6c298f..f9dcb9203 100644
--- a/tests/eko/test_quantities.py
+++ b/tests/eko/test_quantities.py
@@ -34,7 +34,6 @@ def test_HeavyQuarks():
def test_HeavyInfo():
i = hq.HeavyInfo(
num_flavs_init=4,
- intrinsic_flavors=[4, 5],
masses=hq.HeavyQuarkMasses(
[
hq.QuarkMassRef([2.0, nan]),
From 7279e86333bf09043c8c161144561f6074b3c230 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Tue, 1 Aug 2023 11:40:59 +0200
Subject: [PATCH 22/67] Compute always intrinsic in ome
---
.../operator_matrix_element.py | 24 +++++++++----------
tests/eko/evolution_operator/test_ome.py | 1 +
2 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/src/eko/evolution_operator/operator_matrix_element.py b/src/eko/evolution_operator/operator_matrix_element.py
index b45e06c81..fc0518aa1 100644
--- a/src/eko/evolution_operator/operator_matrix_element.py
+++ b/src/eko/evolution_operator/operator_matrix_element.py
@@ -234,11 +234,10 @@ def labels(self):
logger.warning("%s: skipping non-singlet sector", self.log_label)
else:
labels.append((200, 200))
- if self.backward_method is not None:
- # intrinsic labels, which are not zero at NLO
- labels.append((br.matching_hminus_pid, br.matching_hminus_pid))
- # These contributions are always 0 for the moment
- # labels.extend([(200, br.matching_hminus_pid), (br.matching_hminus_pid, 200)])
+ # intrinsic labels, which are not zero at NLO
+ labels.append((br.matching_hminus_pid, br.matching_hminus_pid))
+ # These contributions are always 0 for the moment
+ # labels.extend([(200, br.matching_hminus_pid), (br.matching_hminus_pid, 200)])
# same for singlet
if self.config["debug_skip_singlet"]:
logger.warning("%s: skipping singlet sector", self.log_label)
@@ -250,14 +249,13 @@ def labels(self):
(br.matching_hplus_pid, 100),
]
)
- if self.backward_method is not None:
- labels.extend(
- [
- (21, br.matching_hplus_pid),
- (100, br.matching_hplus_pid),
- (br.matching_hplus_pid, br.matching_hplus_pid),
- ]
- )
+ labels.extend(
+ [
+ (21, br.matching_hplus_pid),
+ (100, br.matching_hplus_pid),
+ (br.matching_hplus_pid, br.matching_hplus_pid),
+ ]
+ )
return labels
def quad_ker(self, label, logx, areas):
diff --git a/tests/eko/evolution_operator/test_ome.py b/tests/eko/evolution_operator/test_ome.py
index b844290c9..c90563269 100644
--- a/tests/eko/evolution_operator/test_ome.py
+++ b/tests/eko/evolution_operator/test_ome.py
@@ -338,6 +338,7 @@ def test_labels(self, theory_ffns, operator_card, tmp_path: pathlib.Path):
path = tmp_path / "eko.tar"
for skip_singlet in [True, False]:
for skip_ns in [True, False]:
+ operator_card.configs.inversion_method = "exact"
operator_card.debug.skip_singlet = skip_singlet
operator_card.debug.skip_non_singlet = skip_ns
path.unlink(missing_ok=True)
From da9fbc42da4ee62823f80031efba037a0e9e8642 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Tue, 1 Aug 2023 12:08:15 +0200
Subject: [PATCH 23/67] Move eko.io.runcards.update
---
src/eko/io/runcards.py | 22 --------
src/eko/runner/legacy.py | 4 +-
src/ekomark/data/__init__.py | 28 ++++++++++
tests/eko/io/test_runcards.py | 88 ------------------------------
tests/ekomark/data/__init__.py | 0
tests/ekomark/data/test_init.py | 96 +++++++++++++++++++++++++++++++++
6 files changed, 127 insertions(+), 111 deletions(-)
create mode 100644 tests/ekomark/data/__init__.py
create mode 100644 tests/ekomark/data/test_init.py
diff --git a/src/eko/io/runcards.py b/src/eko/io/runcards.py
index d5c8c36e8..8a6261bf2 100644
--- a/src/eko/io/runcards.py
+++ b/src/eko/io/runcards.py
@@ -255,28 +255,6 @@ def new_operator(self):
return OperatorCard.from_dict(new)
-def update(theory: Union[RawCard, TheoryCard], operator: Union[RawCard, OperatorCard]):
- """Update legacy runcards.
-
- This function is mainly defined for compatibility with the old interface.
- Prefer direct usage of :class:`Legacy` in new code.
-
- Consecutive applications of this function yield identical results::
-
- cards = update(theory, operator)
- assert update(*cards) == cards
-
- """
- if isinstance(theory, TheoryCard) or isinstance(operator, OperatorCard):
- # if one is not a dict, both have to be new cards
- assert isinstance(theory, TheoryCard)
- assert isinstance(operator, OperatorCard)
- return theory, operator
-
- cards = Legacy(theory, operator)
- return cards.new_theory, cards.new_operator
-
-
def default_atlas(masses: list, matching_ratios: list):
r"""Create default landscape.
diff --git a/src/eko/runner/legacy.py b/src/eko/runner/legacy.py
index 76d6f1a8a..5de53ceb7 100644
--- a/src/eko/runner/legacy.py
+++ b/src/eko/runner/legacy.py
@@ -3,6 +3,8 @@
import os
from typing import Union
+from ekomark.data import update_runcards
+
from ..evolution_operator.grid import OperatorGrid
from ..io import EKO, Operator, runcards
from ..io.types import RawCard
@@ -43,7 +45,7 @@ def __init__(
path where to store the computed operator
"""
- new_theory, new_operator = runcards.update(theory_card, operators_card)
+ new_theory, new_operator = update_runcards(theory_card, operators_card)
# Store inputs
self.path = path
diff --git a/src/ekomark/data/__init__.py b/src/ekomark/data/__init__.py
index 797409204..b6242845b 100644
--- a/src/ekomark/data/__init__.py
+++ b/src/ekomark/data/__init__.py
@@ -1 +1,29 @@
"""EKO database configuration."""
+from typing import Union
+
+from eko.io.runcards import Legacy, OperatorCard, TheoryCard
+from eko.io.types import RawCard
+
+
+def update_runcards(
+ theory: Union[RawCard, TheoryCard], operator: Union[RawCard, OperatorCard]
+):
+ """Update legacy runcards.
+
+ This function is mainly defined for compatibility with the old interface.
+ Prefer direct usage of :class:`Legacy` in new code.
+
+ Consecutive applications of this function yield identical results::
+
+ cards = update(theory, operator)
+ assert update(*cards) == cards
+
+ """
+ if isinstance(theory, TheoryCard) or isinstance(operator, OperatorCard):
+ # if one is not a dict, both have to be new cards
+ assert isinstance(theory, TheoryCard)
+ assert isinstance(operator, OperatorCard)
+ return theory, operator
+
+ cards = Legacy(theory, operator)
+ return cards.new_theory, cards.new_operator
diff --git a/tests/eko/io/test_runcards.py b/tests/eko/io/test_runcards.py
index 0a391047b..465a1abf6 100644
--- a/tests/eko/io/test_runcards.py
+++ b/tests/eko/io/test_runcards.py
@@ -1,14 +1,11 @@
-import copy
from io import StringIO
import numpy as np
import pytest
import yaml
-from banana.data.theories import default_card as theory_card
from eko.io import runcards as rc
from eko.io.bases import Bases
-from ekomark.data.operators import default_card as operator_card
def test_flavored_mu2grid():
@@ -31,48 +28,6 @@ def test_flavored_mu2grid():
assert t == tuple(l)
-def test_runcards_opcard():
- # check conversion
- tc = copy.deepcopy(theory_card)
- oc = copy.deepcopy(operator_card)
- tc["Q0"] = 2.0
- # mugrid
- oc["mugrid"] = [2.0, 10.0]
- _nt, no = rc.update(tc, oc)
- assert isinstance(no, rc.OperatorCard)
- assert len(no.evolgrid) == len(oc["mugrid"])
- assert len(no.mu2grid) == len(no.evolgrid)
- assert no.evolgrid[0][-1] == 4
- assert no.evolgrid[1][-1] == 5
- np.testing.assert_allclose(no.mu0, tc["Q0"])
- np.testing.assert_allclose(no.mu20, tc["Q0"] ** 2.0)
- assert len(no.pids) == 14
- check_dumpable(no)
- del oc["mugrid"]
- # or mu2grid
- oc["mu2grid"] = [9.0, 30.0, 32.0]
- _nt, no = rc.update(tc, oc)
- assert isinstance(no, rc.OperatorCard)
- assert len(no.evolgrid) == len(oc["mu2grid"])
- assert len(no.mu2grid) == len(no.evolgrid)
- assert no.evolgrid[0][-1] == 4
- assert no.evolgrid[1][-1] == 5
- assert no.evolgrid[2][-1] == 5
- check_dumpable(no)
- del oc["mu2grid"]
- # or Q2grid
- oc["Q2grid"] = [15.0, 130.0, 140.0, 1e5]
- _nt, no = rc.update(tc, oc)
- assert isinstance(no, rc.OperatorCard)
- assert len(no.evolgrid) == len(oc["Q2grid"])
- assert len(no.mu2grid) == len(no.evolgrid)
- assert no.evolgrid[0][-1] == 4
- assert no.evolgrid[1][-1] == 5
- assert no.evolgrid[2][-1] == 5
- assert no.evolgrid[3][-1] == 6
- check_dumpable(no)
-
-
def check_dumpable(no):
"""Check we can write and read to yaml."""
so = StringIO()
@@ -81,49 +36,6 @@ def check_dumpable(no):
noo = yaml.safe_load(so)
-def test_runcards_ekomark():
- # check conversion
- tc = copy.deepcopy(theory_card)
- oc = copy.deepcopy(operator_card)
- nt, no = rc.update(tc, oc)
- assert isinstance(nt, rc.TheoryCard)
- assert isinstance(no, rc.OperatorCard)
- # check is idempotent
- nnt, nno = rc.update(nt, no)
- assert nnt == nt
- assert nno == no
-
-
-def test_runcards_quarkmass():
- tc = copy.deepcopy(theory_card)
- tc["nfref"] = 5
- tc["IC"] = 1
- oc = copy.deepcopy(operator_card)
- nt, no = rc.update(tc, oc)
- for _, scale in nt.heavy.masses:
- assert np.isnan(scale)
- m2s = rc.masses(nt, no.configs.evolution_method)
- raw = rc.Legacy.heavies("m%s", tc)
- raw2 = np.power(raw, 2.0)
- np.testing.assert_allclose(m2s, raw2)
- tc["HQ"] = "MSBAR"
- tc["Qmc"] = raw[0] * 1.1
- tc["Qmb"] = raw[1] * 1.1
- tc["Qmt"] = raw[2] * 0.9
- nt, no = rc.update(tc, oc)
- for _, scale in nt.heavy.masses:
- assert not np.isnan(scale)
- m2s = rc.masses(nt, no.configs.evolution_method)
- for m1, m2 in zip(m2s, raw2):
- assert not np.isclose(m1, m2)
- tc["HQ"] = "Blub"
- with pytest.raises(ValueError, match="mass scheme"):
- _nt, _no = rc.update(tc, oc)
- nt.heavy.masses_scheme = "Bla"
- with pytest.raises(ValueError, match="mass scheme"):
- _ms = rc.masses(nt, no.configs.evolution_method)
-
-
def test_legacy_fallback():
assert rc.Legacy.fallback(1, 2, 3) == 1
assert rc.Legacy.fallback(None, 2, 3) == 2
diff --git a/tests/ekomark/data/__init__.py b/tests/ekomark/data/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/ekomark/data/test_init.py b/tests/ekomark/data/test_init.py
new file mode 100644
index 000000000..7d39dca43
--- /dev/null
+++ b/tests/ekomark/data/test_init.py
@@ -0,0 +1,96 @@
+import copy
+
+import numpy as np
+import pytest
+from banana.data.theories import default_card as theory_card
+
+from eko.io import runcards as rc
+from ekomark.data import update_runcards
+from ekomark.data.operators import default_card as operator_card
+
+from ...eko.io.test_runcards import check_dumpable
+
+
+def test_runcards_opcard():
+ # check conversion
+ tc = copy.deepcopy(theory_card)
+ oc = copy.deepcopy(operator_card)
+ tc["Q0"] = 2.0
+ # mugrid
+ oc["mugrid"] = [2.0, 10.0]
+ _nt, no = update_runcards(tc, oc)
+ assert isinstance(no, rc.OperatorCard)
+ assert len(no.evolgrid) == len(oc["mugrid"])
+ assert len(no.mu2grid) == len(no.evolgrid)
+ assert no.evolgrid[0][-1] == 4
+ assert no.evolgrid[1][-1] == 5
+ np.testing.assert_allclose(no.mu0, tc["Q0"])
+ np.testing.assert_allclose(no.mu20, tc["Q0"] ** 2.0)
+ assert len(no.pids) == 14
+ check_dumpable(no)
+ del oc["mugrid"]
+ # or mu2grid
+ oc["mu2grid"] = [9.0, 30.0, 32.0]
+ _nt, no = update_runcards(tc, oc)
+ assert isinstance(no, rc.OperatorCard)
+ assert len(no.evolgrid) == len(oc["mu2grid"])
+ assert len(no.mu2grid) == len(no.evolgrid)
+ assert no.evolgrid[0][-1] == 4
+ assert no.evolgrid[1][-1] == 5
+ assert no.evolgrid[2][-1] == 5
+ check_dumpable(no)
+ del oc["mu2grid"]
+ # or Q2grid
+ oc["Q2grid"] = [15.0, 130.0, 140.0, 1e5]
+ _nt, no = update_runcards(tc, oc)
+ assert isinstance(no, rc.OperatorCard)
+ assert len(no.evolgrid) == len(oc["Q2grid"])
+ assert len(no.mu2grid) == len(no.evolgrid)
+ assert no.evolgrid[0][-1] == 4
+ assert no.evolgrid[1][-1] == 5
+ assert no.evolgrid[2][-1] == 5
+ assert no.evolgrid[3][-1] == 6
+ check_dumpable(no)
+
+
+def test_runcards_ekomark():
+ # check conversion
+ tc = copy.deepcopy(theory_card)
+ oc = copy.deepcopy(operator_card)
+ nt, no = update_runcards(tc, oc)
+ assert isinstance(nt, rc.TheoryCard)
+ assert isinstance(no, rc.OperatorCard)
+ # check is idempotent
+ nnt, nno = update_runcards(nt, no)
+ assert nnt == nt
+ assert nno == no
+
+
+def test_runcards_quarkmass():
+ tc = copy.deepcopy(theory_card)
+ tc["nfref"] = 5
+ tc["IC"] = 1
+ oc = copy.deepcopy(operator_card)
+ nt, no = update_runcards(tc, oc)
+ for _, scale in nt.heavy.masses:
+ assert np.isnan(scale)
+ m2s = rc.masses(nt, no.configs.evolution_method)
+ raw = rc.Legacy.heavies("m%s", tc)
+ raw2 = np.power(raw, 2.0)
+ np.testing.assert_allclose(m2s, raw2)
+ tc["HQ"] = "MSBAR"
+ tc["Qmc"] = raw[0] * 1.1
+ tc["Qmb"] = raw[1] * 1.1
+ tc["Qmt"] = raw[2] * 0.9
+ nt, no = update_runcards(tc, oc)
+ for _, scale in nt.heavy.masses:
+ assert not np.isnan(scale)
+ m2s = rc.masses(nt, no.configs.evolution_method)
+ for m1, m2 in zip(m2s, raw2):
+ assert not np.isclose(m1, m2)
+ tc["HQ"] = "Blub"
+ with pytest.raises(ValueError, match="mass scheme"):
+ _nt, _no = update_runcards(tc, oc)
+ nt.heavy.masses_scheme = "Bla"
+ with pytest.raises(ValueError, match="mass scheme"):
+ _ms = rc.masses(nt, no.configs.evolution_method)
From 1c448ffd6dd84b665a73b9a8b895c40b27b7d16e Mon Sep 17 00:00:00 2001
From: Alessandro Candido
Date: Tue, 1 Aug 2023 12:20:18 +0200
Subject: [PATCH 24/67] Define higher level interfaces for improved runners
creation
---
src/eko/runner/managed.py | 13 +++++--------
src/eko/runner/operators.py | 9 +++++++++
src/eko/runner/recipes.py | 15 ++++++++++++---
3 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/src/eko/runner/managed.py b/src/eko/runner/managed.py
index c353decde..b21882d92 100644
--- a/src/eko/runner/managed.py
+++ b/src/eko/runner/managed.py
@@ -15,7 +15,7 @@
from ..io.items import Evolution, Matching, Target
from ..io.runcards import OperatorCard, TheoryCard
from ..io.struct import EKO
-from . import commons, operators, parts, recipes
+from . import operators, parts, recipes
def solve(theory: TheoryCard, operator: OperatorCard, path: Path):
@@ -24,11 +24,7 @@ def solve(theory: TheoryCard, operator: OperatorCard, path: Path):
with EKO.create(path) as builder:
eko = builder.load_cards(theory, operator).build() # pylint: disable=E1101
-
- atlas = commons.atlas(eko.theory_card, eko.operator_card)
-
- recs = recipes.create(eko.operator_card.evolgrid, atlas)
- eko.load_recipes(recs)
+ recipes.create(eko)
for recipe in eko.recipes:
assert isinstance(recipe, Evolution)
@@ -42,8 +38,9 @@ def solve(theory: TheoryCard, operator: OperatorCard, path: Path):
del eko.parts_matching[recipe]
for ep in operator.evolgrid:
- headers = recipes.elements(ep, atlas)
- parts_ = operators.retrieve(headers, eko.parts, eko.parts_matching)
+ parts_ = operators.retrieve(
+ operators.parts(ep, eko), eko.parts, eko.parts_matching
+ )
target = Target.from_ep(ep)
eko.operators[target] = operators.join(parts_)
# flush the memory
diff --git a/src/eko/runner/operators.py b/src/eko/runner/operators.py
index 5a0a219c7..2ccbd1013 100644
--- a/src/eko/runner/operators.py
+++ b/src/eko/runner/operators.py
@@ -7,6 +7,9 @@
from ..io.inventory import Inventory
from ..io.items import Evolution, Operator, Recipe
+from ..io.struct import EKO
+from ..io.types import EvolutionPoint
+from . import commons, recipes
def retrieve(
@@ -91,3 +94,9 @@ def join(elements: List[Operator]) -> Operator:
"""
return reduce(dotop, reversed(elements))
+
+
+def parts(ep: EvolutionPoint, eko: EKO) -> List[Recipe]:
+ """Determine parts required for the given evolution point operator."""
+ atlas = commons.atlas(eko.theory_card, eko.operator_card)
+ return recipes._elements(ep, atlas)
diff --git a/src/eko/runner/recipes.py b/src/eko/runner/recipes.py
index 7a09554cb..9c0b11170 100644
--- a/src/eko/runner/recipes.py
+++ b/src/eko/runner/recipes.py
@@ -2,11 +2,13 @@
from typing import List
from ..io.items import Evolution, Matching, Recipe
+from ..io.struct import EKO
from ..io.types import EvolutionPoint as EPoint
from ..matchings import Atlas, Segment
+from . import commons
-def elements(ep: EPoint, atlas: Atlas) -> List[Recipe]:
+def _elements(ep: EPoint, atlas: Atlas) -> List[Recipe]:
"""Determine recipes to compute a given operator."""
recipes = []
@@ -26,10 +28,17 @@ def elements(ep: EPoint, atlas: Atlas) -> List[Recipe]:
return recipes
-def create(evolgrid: List[EPoint], atlas: Atlas) -> List[Recipe]:
+def _create(evolgrid: List[EPoint], atlas: Atlas) -> List[Recipe]:
"""Create all associated recipes."""
recipes = []
for ep in evolgrid:
- recipes.extend(elements(ep, atlas))
+ recipes.extend(_elements(ep, atlas))
return list(set(recipes))
+
+
+def create(eko: EKO):
+ """Create and load all associated recipes."""
+ atlas = commons.atlas(eko.theory_card, eko.operator_card)
+ recs = _create(eko.operator_card.evolgrid, atlas)
+ eko.load_recipes(recs)
From e7268e927f08abb85d908ffd664f940315725856 Mon Sep 17 00:00:00 2001
From: Alessandro Candido
Date: Tue, 1 Aug 2023 12:31:23 +0200
Subject: [PATCH 25/67] Fix recipes unit tests
---
tests/eko/runner/test_recipes.py | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/tests/eko/runner/test_recipes.py b/tests/eko/runner/test_recipes.py
index 59b1a8855..20988f1c7 100644
--- a/tests/eko/runner/test_recipes.py
+++ b/tests/eko/runner/test_recipes.py
@@ -4,26 +4,26 @@
from eko.io.types import EvolutionPoint
from eko.matchings import Atlas
from eko.quantities.heavy_quarks import MatchingScales
-from eko.runner.recipes import create, elements
+from eko.runner.recipes import _create, _elements
SCALES = MatchingScales([10.0, 20.0, 30.0])
ATLAS = Atlas(SCALES, (50.0, 5))
def test_elements():
- onestep = elements((60.0, 5), ATLAS)
+ onestep = _elements((60.0, 5), ATLAS)
assert len(onestep) == 1
assert isinstance(onestep[0], Evolution)
assert not onestep[0].cliff
- backandforth = elements((60.0, 6), ATLAS)
+ backandforth = _elements((60.0, 6), ATLAS)
assert len(backandforth) == 3
assert isinstance(backandforth[0], Evolution)
assert backandforth[0].cliff
assert isinstance(backandforth[1], Matching)
assert not backandforth[1].inverse
- down = elements((5.0, 3), ATLAS)
+ down = _elements((5.0, 3), ATLAS)
assert all([isinstance(el, Evolution) for i, el in enumerate(down) if i % 2 == 0])
assert all([isinstance(el, Matching) for i, el in enumerate(down) if i % 2 == 1])
@@ -31,13 +31,13 @@ def test_elements():
def test_create():
evolgrid: List[EvolutionPoint] = [(60.0, 5)]
- recs = create(evolgrid, ATLAS)
+ recs = _create(evolgrid, ATLAS)
assert len(recs) == 1
evolgrid.append((60.0, 6))
- recs = create(evolgrid, ATLAS)
+ recs = _create(evolgrid, ATLAS)
assert len(recs) == 1 + 3
evolgrid.append((70.0, 6))
- recs = create(evolgrid, ATLAS)
+ recs = _create(evolgrid, ATLAS)
assert len(recs) == 1 + 3 + 1
From 075febb13fd5f3340c9094885ed7762413493896 Mon Sep 17 00:00:00 2001
From: Alessandro Candido
Date: Tue, 1 Aug 2023 12:39:31 +0200
Subject: [PATCH 26/67] Fix runner conftest
---
tests/eko/runner/conftest.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/eko/runner/conftest.py b/tests/eko/runner/conftest.py
index a1516b2a7..6c513e3eb 100644
--- a/tests/eko/runner/conftest.py
+++ b/tests/eko/runner/conftest.py
@@ -28,7 +28,7 @@ def identity(neweko: EKO):
@pytest.fixture
def ekoparts(neweko: EKO, identity: Operator):
atlas = commons.atlas(neweko.theory_card, neweko.operator_card)
- neweko.load_recipes(recipes.create(neweko.operator_card.evolgrid, atlas))
+ neweko.load_recipes(recipes._create(neweko.operator_card.evolgrid, atlas))
for rec in neweko.recipes:
neweko.parts[rec] = identity
From ac406cd3c0f956654a5f679e95fec0073bb55c00 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Tue, 1 Aug 2023 12:40:16 +0200
Subject: [PATCH 27/67] Use EPoint in couplings
---
benchmarks/eko/benchmark_evol_to_unity.py | 3 +--
benchmarks/eko/benchmark_msbar_evolution.py | 3 +--
benchmarks/eko/benchmark_strong_coupling.py | 8 +++-----
benchmarks/ekobox/benchmark_evol_pdf.py | 4 ++--
doc/source/overview/tutorials/alpha_s.ipynb | 2 +-
doc/source/overview/tutorials/pdf.ipynb | 3 +--
extras/n3lo_bench/splitting_function_utils.py | 3 +--
src/eko/couplings.py | 6 +++---
src/eko/io/runcards.py | 3 +--
src/eko/msbar_masses.py | 4 ++--
src/eko/quantities/couplings.py | 10 ++--------
src/ekobox/cards.py | 3 +--
src/ekobox/info_file.py | 2 +-
tests/eko/kernels/test_kernels_QEDns.py | 3 +--
tests/eko/quantities/test_couplings.py | 4 ++--
tests/eko/runner/test_legacy.py | 2 +-
tests/eko/test_couplings.py | 17 ++++++-----------
tests/eko/test_msbar_masses.py | 3 +--
18 files changed, 31 insertions(+), 52 deletions(-)
diff --git a/benchmarks/eko/benchmark_evol_to_unity.py b/benchmarks/eko/benchmark_evol_to_unity.py
index d269db202..5e864b3b5 100644
--- a/benchmarks/eko/benchmark_evol_to_unity.py
+++ b/benchmarks/eko/benchmark_evol_to_unity.py
@@ -19,8 +19,7 @@ def update_cards(theory: TheoryCard, operator: OperatorCard):
theory.couplings = CouplingsInfo(
alphas=0.35,
alphaem=0.007496,
- scale=float(np.sqrt(2)),
- num_flavs_ref=None,
+ scale=(float(np.sqrt(2)), 4),
)
theory.heavy.num_flavs_init = 4
theory.heavy.masses.c.value = 1.0
diff --git a/benchmarks/eko/benchmark_msbar_evolution.py b/benchmarks/eko/benchmark_msbar_evolution.py
index 6286e15ad..86e0e361e 100644
--- a/benchmarks/eko/benchmark_msbar_evolution.py
+++ b/benchmarks/eko/benchmark_msbar_evolution.py
@@ -20,9 +20,8 @@
def update_theory(theory: TheoryCard):
theory.order = (3, 0)
- theory.couplings.scale = 91
+ theory.couplings.ref = (91, 5)
theory.couplings.alphaem = 0.007496
- theory.couplings.num_flavs_ref = 5
theory.heavy.masses_scheme = QuarkMassScheme.MSBAR
theory.heavy.masses.c = QuarkMassRef([1.5, 18])
theory.heavy.masses.b = QuarkMassRef([4.1, 20])
diff --git a/benchmarks/eko/benchmark_strong_coupling.py b/benchmarks/eko/benchmark_strong_coupling.py
index 80f65cf72..3f94bd036 100644
--- a/benchmarks/eko/benchmark_strong_coupling.py
+++ b/benchmarks/eko/benchmark_strong_coupling.py
@@ -39,8 +39,7 @@ def ref_couplings(ref_values, ref_scale: float, ref_nf: FlavorsNumber) -> Coupli
return CouplingsInfo(
alphas=ref_values[0],
alphaem=ref_values[1],
- scale=ref_scale,
- num_flavs_ref=ref_nf,
+ ref=(ref_scale, ref_nf),
)
@@ -841,9 +840,8 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self, theory_card: TheoryCard):
theory = theory_card
theory.order = (3, 0)
theory.couplings.alphas = 0.35
- theory.couplings.scale = float(np.sqrt(2))
theory.couplings.alphaem = 0.007496
- theory.couplings.num_flavs_ref = 4
+ theory.couplings.ref = (float(np.sqrt(2)), 4)
theory.heavy.num_flavs_init = 3
theory.xif = np.sqrt(1.0 / 2.0)
theory.heavy.masses.c.value = np.sqrt(2.0)
@@ -886,7 +884,7 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self, theory_card: TheoryCard):
apfel.SetTheory("QCD")
apfel.SetPerturbativeOrder(theory.order[0] - 1)
apfel.SetAlphaEvolution("exact")
- apfel.SetAlphaQCDRef(theory.couplings.alphas, theory.couplings.scale)
+ apfel.SetAlphaQCDRef(theory.couplings.alphas, theory.couplings.ref[0])
apfel.SetVFNS()
apfel.SetPoleMasses(qmasses.c.value, qmasses.b.value, qmasses.t.value)
apfel.SetMassMatchingScales(
diff --git a/benchmarks/ekobox/benchmark_evol_pdf.py b/benchmarks/ekobox/benchmark_evol_pdf.py
index c85083604..5d198b3ff 100644
--- a/benchmarks/ekobox/benchmark_evol_pdf.py
+++ b/benchmarks/ekobox/benchmark_evol_pdf.py
@@ -21,7 +21,7 @@ def benchmark_evolve_single_member(
theory = theory_card
theory.order = (1, 0)
theory.couplings.alphas = 0.118000
- theory.couplings.scale = 91.1876
+ theory.couplings.ref = (91.1876, 5)
theory.couplings.alphaem = 0.007496
theory.heavy.masses.c.value = 1.3
theory.heavy.masses.b.value = 4.75
@@ -47,7 +47,7 @@ def benchmark_evolve_single_member(
ev_pdf = lhapdf.mkPDF("EvPDF", 0)
assert info["XMin"] == op.xgrid.raw[0]
assert info["SetDesc"] == "MyEvolvedPDF"
- assert info["MZ"] == theory.couplings.scale
+ assert info["MZ"] == theory.couplings.ref[0]
assert info["Debug"] == "Debug"
xgrid = op.xgrid.raw
for idx, mu2 in enumerate(op.mu2grid):
diff --git a/doc/source/overview/tutorials/alpha_s.ipynb b/doc/source/overview/tutorials/alpha_s.ipynb
index d8954900d..327eb39c9 100644
--- a/doc/source/overview/tutorials/alpha_s.ipynb
+++ b/doc/source/overview/tutorials/alpha_s.ipynb
@@ -40,7 +40,7 @@
"\n",
"# set the (alpha_s, alpha_em) reference values\n",
"couplings_ref = CouplingsInfo(\n",
- " alphas=0.118, alphaem=0.007496252, scale=91.0, num_flavs_ref=5\n",
+ " alphas=0.118, alphaem=0.007496252, ref=(91.0, 5)\n",
")\n",
"\n",
"# set heavy quark masses and their threshold ratios\n",
diff --git a/doc/source/overview/tutorials/pdf.ipynb b/doc/source/overview/tutorials/pdf.ipynb
index 0719d9d63..2cc2f688b 100644
--- a/doc/source/overview/tutorials/pdf.ipynb
+++ b/doc/source/overview/tutorials/pdf.ipynb
@@ -369,8 +369,7 @@
"th_card.orders = (1,0) # QCD LO\n",
"th_card.heavy.masses = HeavyQuarks([QuarkMassRef([1.3,nan]), QuarkMassRef([4.75,nan]), QuarkMassRef([172.,nan])]) # quark mass\n",
"th_card.couplings.alphas = 0.130000 # reference value of alpha_s\n",
- "th_card.couplings.scale = 91.1876 # the reference scale at which alpha_s is provided\n",
- "th_card.couplings.num_flavs_ref = 5 # the number of flavors active at the alpha_s reference scale\n",
+ "th_card.couplings.ref = (91.1876,5) # the reference scale together with the number of flavors at which alpha_s is provided\n",
"th_card.heavy.num_flavs_init = 3 # the number of flavors active at the reference scale"
]
},
diff --git a/extras/n3lo_bench/splitting_function_utils.py b/extras/n3lo_bench/splitting_function_utils.py
index db06f5c72..7368e24b1 100644
--- a/extras/n3lo_bench/splitting_function_utils.py
+++ b/extras/n3lo_bench/splitting_function_utils.py
@@ -103,8 +103,7 @@ def compute_a_s(q2=None, xif2=1.0, nf=None, order=(4, 0)):
ref = CouplingsInfo(
alphas=0.1181,
alphaem=0.007496,
- scale=91.00,
- num_flavs_ref=5,
+ ref=(91.00, 5),
)
sc = Couplings(
couplings=ref,
diff --git a/src/eko/couplings.py b/src/eko/couplings.py
index 1b3620032..3bf21b11d 100644
--- a/src/eko/couplings.py
+++ b/src/eko/couplings.py
@@ -435,7 +435,7 @@ def assert_positive(name, var):
assert_positive("alpha_s_ref", couplings.alphas)
assert_positive("alpha_em_ref", couplings.alphaem)
- assert_positive("scale_ref", couplings.scale)
+ assert_positive("scale_ref", couplings.ref[0])
if order[0] not in [1, 2, 3, 4]:
raise NotImplementedError("a_s beyond N3LO is not implemented")
if order[1] not in [0, 1, 2]:
@@ -445,7 +445,7 @@ def assert_positive(name, var):
raise ValueError(f"Unknown method {method.value}")
self.method = method.value
- nf_ref = couplings.num_flavs_ref
+ nf_ref = couplings.ref[1]
scheme_name = hqm_scheme.name
self.alphaem_running = couplings.em_running
self.decoupled_running = False
@@ -454,7 +454,7 @@ def assert_positive(name, var):
self.a_ref = np.array(couplings.values) / 4.0 / np.pi # convert to a_s and a_em
matching_scales = (np.array(masses) * np.array(thresholds_ratios)).tolist()
self.thresholds_ratios = list(thresholds_ratios)
- self.atlas = matchings.Atlas(matching_scales, (couplings.scale**2, nf_ref))
+ self.atlas = matchings.Atlas(matching_scales, (couplings.ref[0] ** 2, nf_ref))
self.hqm_scheme = scheme_name
logger.info(
"Strong Coupling: a_s(µ_R^2=%f)%s=%f=%f/(4π)",
diff --git a/src/eko/io/runcards.py b/src/eko/io/runcards.py
index 8a6261bf2..3d8413d1b 100644
--- a/src/eko/io/runcards.py
+++ b/src/eko/io/runcards.py
@@ -183,8 +183,7 @@ def new_theory(self):
alphas=old["alphas"],
alphaem=alphaem,
em_running=em_running,
- scale=old["Qref"],
- num_flavs_ref=old["nfref"],
+ ref=(old["Qref"], old["nfref"]),
)
new["heavy"] = {
"num_flavs_init": nf_default(old["Q0"] ** 2.0, default_atlas(ms, ks))
diff --git a/src/eko/msbar_masses.py b/src/eko/msbar_masses.py
index f13582110..5edac4c46 100644
--- a/src/eko/msbar_masses.py
+++ b/src/eko/msbar_masses.py
@@ -377,8 +377,8 @@ def compute(
"""
# TODO: sketch in the docs how the MSbar computation works with a figure.
- mu2_ref = couplings.scale**2
- nf_ref: FlavorsNumber = couplings.num_flavs_ref
+ mu2_ref = couplings.ref[0] ** 2
+ nf_ref: FlavorsNumber = couplings.ref[1]
masses = np.concatenate((np.zeros(nf_ref - 3), np.full(6 - nf_ref, np.inf)))
def sc(thr_masses):
diff --git a/src/eko/quantities/couplings.py b/src/eko/quantities/couplings.py
index f80420a9c..3a5ab96ef 100644
--- a/src/eko/quantities/couplings.py
+++ b/src/eko/quantities/couplings.py
@@ -3,6 +3,7 @@
import enum
from ..io.dictlike import DictLike
+from ..io.types import EvolutionPoint as EPoint
from ..io.types import FlavorsNumber, LinearScale, ReferenceRunning, Scalar
Coupling = Scalar
@@ -19,14 +20,7 @@ class CouplingsInfo(DictLike):
alphas: Coupling
alphaem: Coupling
- scale: LinearScale
- num_flavs_ref: FlavorsNumber
- r"""Number of active flavors at strong coupling reference scale.
-
- I.e. :math:`n_{f,\text{ref}}(\mu^2_{\text{ref}})`, formerly called
- ``nfref``.
-
- """
+ ref: EPoint
em_running: bool = False
@property
diff --git a/src/ekobox/cards.py b/src/ekobox/cards.py
index 482e65faf..3d4e346aa 100644
--- a/src/ekobox/cards.py
+++ b/src/ekobox/cards.py
@@ -13,8 +13,7 @@
couplings=dict(
alphas=0.118,
alphaem=0.007496252,
- scale=91.2,
- num_flavs_ref=5,
+ ref=(91.2, 5),
),
heavy=dict(
num_flavs_init=4,
diff --git a/src/ekobox/info_file.py b/src/ekobox/info_file.py
index 2f99d8377..35f2cfcae 100644
--- a/src/ekobox/info_file.py
+++ b/src/ekobox/info_file.py
@@ -48,7 +48,7 @@ def build(
template_info["OrderQCD"] = theory_card.order[0] - 1
template_info["QMin"] = round(math.sqrt(operators_card.mu2grid[0]), 4)
template_info["QMax"] = round(math.sqrt(operators_card.mu2grid[-1]), 4)
- template_info["MZ"] = theory_card.couplings.scale
+ template_info["MZ"] = theory_card.couplings.ref[0]
template_info["MUp"] = 0.0
template_info["MDown"] = 0.0
template_info["MStrange"] = 0.0
diff --git a/tests/eko/kernels/test_kernels_QEDns.py b/tests/eko/kernels/test_kernels_QEDns.py
index b85a3f013..2e710c722 100644
--- a/tests/eko/kernels/test_kernels_QEDns.py
+++ b/tests/eko/kernels/test_kernels_QEDns.py
@@ -119,8 +119,7 @@ def test_zero_true_gamma():
dict(
alphas=alpharef[0],
alphaem=alpharef[1],
- scale=muref,
- num_flavs_ref=5,
+ ref=(muref, 5),
)
)
evmod = CouplingEvolutionMethod.EXACT
diff --git a/tests/eko/quantities/test_couplings.py b/tests/eko/quantities/test_couplings.py
index 83bef709c..e4d194d5b 100644
--- a/tests/eko/quantities/test_couplings.py
+++ b/tests/eko/quantities/test_couplings.py
@@ -3,7 +3,7 @@
def test_couplings_ref():
scale = 90.0
- d = dict(alphas=0.1, alphaem=0.01, scale=scale, num_flavs_ref=5)
+ d = dict(alphas=0.1, alphaem=0.01, ref=(scale, 5))
couplings = CouplingsInfo.from_dict(d)
- assert couplings.scale == scale
+ assert couplings.ref[0] == scale
assert not couplings.em_running
diff --git a/tests/eko/runner/test_legacy.py b/tests/eko/runner/test_legacy.py
index 60395acc5..1828285c3 100644
--- a/tests/eko/runner/test_legacy.py
+++ b/tests/eko/runner/test_legacy.py
@@ -36,7 +36,7 @@ class FakeEM(enum.Enum):
eko.runner.legacy.Runner(theory_card, operator_card, path=path)
# MSbar scheme
theory_card.heavy.masses_scheme = QuarkMassScheme.MSBAR
- theory_card.couplings.num_flavs_ref = 5
+ theory_card.couplings.ref = (91.0, 5)
theory_card.heavy.masses.c.scale = 2
theory_card.heavy.masses.b.scale = 4.5
theory_card.heavy.masses.t.scale = 173.07
diff --git a/tests/eko/test_couplings.py b/tests/eko/test_couplings.py
index 10535cbcb..7468051be 100644
--- a/tests/eko/test_couplings.py
+++ b/tests/eko/test_couplings.py
@@ -53,8 +53,7 @@ def test_init(self):
dict(
alphas=alpharef[0],
alphaem=alpharef[1],
- scale=muref,
- num_flavs_ref=5,
+ ref=(muref, 5),
)
)
order = (1, 0)
@@ -107,7 +106,7 @@ def test_init(self):
)
with pytest.raises(ValueError):
coup3 = copy.deepcopy(couplings)
- coup3.scale = 0
+ coup3.ref = (0.0, 5)
Couplings(
coup3,
order,
@@ -159,8 +158,7 @@ def test_ref(self):
dict(
alphas=alpharef[0],
alphaem=alpharef[1],
- scale=muref,
- num_flavs_ref=nfref,
+ ref=(muref, nfref),
)
)
for order_s in [1, 2, 3, 4]:
@@ -193,8 +191,7 @@ def test_ref_copy_e841b0dfdee2f31d9ccc1ecee4d9d1a6f6624313(self):
dict(
alphas=alpharef[0],
alphaem=alpharef[1],
- scale=muref,
- num_flavs_ref=3, # reference nf is needed to force the matching
+ ref=(muref, 3), # reference nf is needed to force the matching
)
)
sc = Couplings(
@@ -233,8 +230,7 @@ def test_exact(self):
dict(
alphas=alpharef[0],
alphaem=alpharef[1],
- scale=muref,
- num_flavs_ref=nfref,
+ ref=(muref, nfref),
em_running=em_running,
)
)
@@ -295,8 +291,7 @@ def benchmark_expanded_n3lo(self):
couplings = CouplingsInfo(
alphas=alpharef[0],
alphaem=alpharef[1],
- scale=muref,
- num_flavs_ref=5,
+ ref=(muref, 5),
)
m2c = 2
m2b = 25
diff --git a/tests/eko/test_msbar_masses.py b/tests/eko/test_msbar_masses.py
index b0c102ef8..edfd243ab 100644
--- a/tests/eko/test_msbar_masses.py
+++ b/tests/eko/test_msbar_masses.py
@@ -15,9 +15,8 @@ def theory_card(theory_card: TheoryCard):
th = theory_card
th.order = (3, 0)
th.couplings.alphas = 0.1180
- th.couplings.scale = 91.0
th.couplings.alphaem = 0.00781
- th.couplings.num_flavs_ref = 5
+ th.couplings.ref = (91.0, 5)
th.heavy.masses = HeavyQuarkMasses(
[QuarkMassRef(val) for val in [(2.0, 2.1), (4.0, 4.1), (175.0, 174.9)]]
)
From 45ae33043c33435ae5231e34785d1572cd774fe7 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Tue, 1 Aug 2023 15:04:11 +0200
Subject: [PATCH 28/67] Fix couplings ref ep in benchmarks
---
benchmarks/eko/benchmark_evol_to_unity.py | 2 +-
benchmarks/eko/benchmark_msbar_evolution.py | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/benchmarks/eko/benchmark_evol_to_unity.py b/benchmarks/eko/benchmark_evol_to_unity.py
index 5e864b3b5..561721f6f 100644
--- a/benchmarks/eko/benchmark_evol_to_unity.py
+++ b/benchmarks/eko/benchmark_evol_to_unity.py
@@ -19,7 +19,7 @@ def update_cards(theory: TheoryCard, operator: OperatorCard):
theory.couplings = CouplingsInfo(
alphas=0.35,
alphaem=0.007496,
- scale=(float(np.sqrt(2)), 4),
+ ref=(float(np.sqrt(2)), 4),
)
theory.heavy.num_flavs_init = 4
theory.heavy.masses.c.value = 1.0
diff --git a/benchmarks/eko/benchmark_msbar_evolution.py b/benchmarks/eko/benchmark_msbar_evolution.py
index 86e0e361e..c0e849e64 100644
--- a/benchmarks/eko/benchmark_msbar_evolution.py
+++ b/benchmarks/eko/benchmark_msbar_evolution.py
@@ -148,7 +148,7 @@ def benchmark_APFEL_msbar_evolution(
apfel.SetTheory("QCD")
apfel.SetPerturbativeOrder(order - 1)
apfel.SetAlphaEvolution(method)
- apfel.SetAlphaQCDRef(coupl.alphas, coupl.scale)
+ apfel.SetAlphaQCDRef(coupl.alphas, coupl.ref[0])
apfel.SetVFNS()
apfel.SetMSbarMasses(
qmasses.c.value, qmasses.b.value, qmasses.t.value
@@ -216,7 +216,7 @@ def benchmark_APFEL_msbar_solution(
apfel.SetTheory("QCD")
apfel.SetPerturbativeOrder(order - 1)
apfel.SetAlphaEvolution("exact")
- apfel.SetAlphaQCDRef(coupl.alphas, coupl.scale)
+ apfel.SetAlphaQCDRef(coupl.alphas, coupl.ref[0])
apfel.SetVFNS()
apfel.SetMSbarMasses(qmasses.c.value, qmasses.b.value, qmasses.t.value)
apfel.SetMassScaleReference(
From 0f94cdc66171c769c14dbd77052efdc44ea4f029 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Tue, 1 Aug 2023 15:38:24 +0200
Subject: [PATCH 29/67] Use EPoint for PDF boundary
---
benchmarks/eko/benchmark_evol_to_unity.py | 3 +--
benchmarks/eko/benchmark_strong_coupling.py | 1 -
benchmarks/ekobox/benchmark_evol_pdf.py | 4 ++--
doc/source/overview/tutorials/pdf.ipynb | 5 ++---
src/eko/io/legacy.py | 7 +++----
src/eko/io/runcards.py | 22 ++++++++++-----------
src/eko/io/struct.py | 2 +-
src/eko/quantities/heavy_quarks.py | 6 ------
src/eko/runner/commons.py | 2 +-
src/ekobox/cards.py | 3 +--
src/ekobox/cli/runcards.py | 2 +-
src/ekobox/info_file.py | 4 +++-
src/ekobox/utils.py | 2 +-
tests/eko/evolution_operator/test_grid.py | 2 +-
tests/eko/io/test_manipulate.py | 2 +-
tests/eko/test_quantities.py | 1 -
tests/ekobox/test_cards.py | 8 ++++----
tests/ekobox/test_evol_pdf.py | 2 +-
tests/ekobox/test_info_file.py | 2 +-
tests/ekobox/test_utils.py | 7 +++----
tests/ekomark/data/test_init.py | 2 +-
21 files changed, 39 insertions(+), 50 deletions(-)
diff --git a/benchmarks/eko/benchmark_evol_to_unity.py b/benchmarks/eko/benchmark_evol_to_unity.py
index 561721f6f..c466d00d8 100644
--- a/benchmarks/eko/benchmark_evol_to_unity.py
+++ b/benchmarks/eko/benchmark_evol_to_unity.py
@@ -21,11 +21,10 @@ def update_cards(theory: TheoryCard, operator: OperatorCard):
alphaem=0.007496,
ref=(float(np.sqrt(2)), 4),
)
- theory.heavy.num_flavs_init = 4
theory.heavy.masses.c.value = 1.0
theory.heavy.masses.b.value = 4.75
theory.heavy.masses.t.value = 173.0
- operator.mu0 = float(np.sqrt(2))
+ operator.init = (float(np.sqrt(2)), 4)
operator.mugrid = [(10, 5)]
operator.xgrid = XGrid(np.linspace(1e-1, 1, 30))
operator.configs.interpolation_polynomial_degree = 1
diff --git a/benchmarks/eko/benchmark_strong_coupling.py b/benchmarks/eko/benchmark_strong_coupling.py
index 3f94bd036..1d1cd7219 100644
--- a/benchmarks/eko/benchmark_strong_coupling.py
+++ b/benchmarks/eko/benchmark_strong_coupling.py
@@ -842,7 +842,6 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self, theory_card: TheoryCard):
theory.couplings.alphas = 0.35
theory.couplings.alphaem = 0.007496
theory.couplings.ref = (float(np.sqrt(2)), 4)
- theory.heavy.num_flavs_init = 3
theory.xif = np.sqrt(1.0 / 2.0)
theory.heavy.masses.c.value = np.sqrt(2.0)
theory.heavy.masses.b.value = 4.5
diff --git a/benchmarks/ekobox/benchmark_evol_pdf.py b/benchmarks/ekobox/benchmark_evol_pdf.py
index 5d198b3ff..a0ddcaac4 100644
--- a/benchmarks/ekobox/benchmark_evol_pdf.py
+++ b/benchmarks/ekobox/benchmark_evol_pdf.py
@@ -27,7 +27,7 @@ def benchmark_evolve_single_member(
theory.heavy.masses.b.value = 4.75
theory.heavy.masses.t.value = 172
op = operator_card
- op.mu0 = 5.0
+ op.init = (5.0, 4)
op.mugrid = mugrid
# lhapdf import (maybe i have to dump with a x*), do plots)
with lhapdf_path(test_pdf):
@@ -74,7 +74,7 @@ def benchmark_evolve_more_members(
theory = theory_card
theory.order = (1, 0)
op = operator_card
- op.mu0 = 1.0
+ op.init = (1.0, 3)
op.mugrid = [(10.0, 5), (100.0, 5)]
op.xgrid = XGrid([1e-7, 0.01, 0.1, 0.2, 0.3])
with lhapdf_path(test_pdf):
diff --git a/doc/source/overview/tutorials/pdf.ipynb b/doc/source/overview/tutorials/pdf.ipynb
index 2cc2f688b..923520f59 100644
--- a/doc/source/overview/tutorials/pdf.ipynb
+++ b/doc/source/overview/tutorials/pdf.ipynb
@@ -361,7 +361,7 @@
"op_card = example.operator()\n",
"op_card.xgrid = eko.interpolation.XGrid(make_grid(30, 30)) # x grid\n",
"op_card.mugrid = [(float(q),5) for q in np.geomspace(5., 100, 5)] # Q2 grid\n",
- "op_card.mu0 = 1.295000 # starting point for the evolution \n",
+ "op_card.init = (1.295000,3) # starting point for the evolution \n",
"\n",
"# setup the theory card - this can be mostly inferred from the PDF's .info file\n",
"\n",
@@ -369,8 +369,7 @@
"th_card.orders = (1,0) # QCD LO\n",
"th_card.heavy.masses = HeavyQuarks([QuarkMassRef([1.3,nan]), QuarkMassRef([4.75,nan]), QuarkMassRef([172.,nan])]) # quark mass\n",
"th_card.couplings.alphas = 0.130000 # reference value of alpha_s\n",
- "th_card.couplings.ref = (91.1876,5) # the reference scale together with the number of flavors at which alpha_s is provided\n",
- "th_card.heavy.num_flavs_init = 3 # the number of flavors active at the reference scale"
+ "th_card.couplings.ref = (91.1876,5) # the reference scale together with the number of flavors at which alpha_s is provided"
]
},
{
diff --git a/src/eko/io/legacy.py b/src/eko/io/legacy.py
index 8491a6acc..3bee940ac 100644
--- a/src/eko/io/legacy.py
+++ b/src/eko/io/legacy.py
@@ -99,7 +99,6 @@ class PseudoTheory(DictLike):
def from_old(cls, old: RawCard):
"""Load from old metadata."""
heavy = HeavyInfo(
- num_flavs_init=4,
masses=HeavyQuarkMasses(
[
ReferenceRunning([_MC, np.inf]),
@@ -122,7 +121,7 @@ class PseudoOperator(DictLike):
"""
- mu20: float
+ init: EPoint
evolgrid: List[EPoint]
xgrid: XGrid
configs: dict
@@ -130,7 +129,7 @@ class PseudoOperator(DictLike):
@classmethod
def from_old(cls, old: RawCard):
"""Load from old metadata."""
- mu20 = float(old["q2_ref"])
+ mu0 = float(np.sqrt(float(old["q2_ref"])))
mu2list = old.get("Q2grid")
if mu2list is None:
mu2list = old["mu2grid"]
@@ -146,7 +145,7 @@ def from_old(cls, old: RawCard):
interpolation_is_log=old.get("interpolation_is_log"),
)
- return cls(mu20=mu20, evolgrid=evolgrid, xgrid=xgrid, configs=configs)
+ return cls(init=(mu0, 4), evolgrid=evolgrid, xgrid=xgrid, configs=configs)
ARRAY_SUFFIX = ".npy.lz4"
diff --git a/src/eko/io/runcards.py b/src/eko/io/runcards.py
index 3d8413d1b..8ab9beeff 100644
--- a/src/eko/io/runcards.py
+++ b/src/eko/io/runcards.py
@@ -95,7 +95,7 @@ class Configs(DictLike):
class OperatorCard(DictLike):
"""Operator Card info."""
- mu0: float
+ init: EPoint
"""Initial scale."""
mugrid: List[EPoint]
xgrid: interpolation.XGrid
@@ -115,7 +115,7 @@ class OperatorCard(DictLike):
@property
def mu20(self):
"""Squared value of initial scale."""
- return self.mu0**2
+ return self.init[0] ** 2
@property
def mu2grid(self) -> npt.NDArray:
@@ -186,9 +186,6 @@ def new_theory(self):
ref=(old["Qref"], old["nfref"]),
)
new["heavy"] = {
- "num_flavs_init": nf_default(old["Q0"] ** 2.0, default_atlas(ms, ks))
- if old["nf0"] is None
- else old["nf0"],
"matching_ratios": self.heavies("k%sThr", old),
"masses_scheme": old["HQ"],
}
@@ -212,17 +209,20 @@ def new_operator(self):
old_th = self.theory
new = {}
- new["mu0"] = old_th["Q0"]
+ ms = self.heavies("m%s", old_th)
+ ks = self.heavies("k%sThr", old_th)
+ new["init"] = (
+ old_th["Q0"],
+ nf_default(old_th["Q0"] ** 2.0, default_atlas(ms, ks))
+ if old_th["nf0"] is None
+ else old_th["nf0"],
+ )
if "mugrid" in old:
mugrid = old["mugrid"]
else:
mu2grid = old["Q2grid"] if "Q2grid" in old else old["mu2grid"]
mugrid = np.sqrt(mu2grid).tolist()
- new["mugrid"] = flavored_mugrid(
- mugrid,
- list(self.heavies("m%s", old_th)),
- list(self.heavies("k%sThr", old_th)),
- )
+ new["mugrid"] = flavored_mugrid(mugrid, list(ms), list(ks))
new["configs"] = {}
evmod = old_th["ModEv"]
diff --git a/src/eko/io/struct.py b/src/eko/io/struct.py
index ce4679871..783e82f51 100644
--- a/src/eko/io/struct.py
+++ b/src/eko/io/struct.py
@@ -552,7 +552,7 @@ def build(self) -> EKO:
self.access.open = True
metadata = Metadata(
_path=self.path,
- origin=(self.operator.mu20, self.theory.heavy.num_flavs_init),
+ origin=(self.operator.init[0] ** 2, self.operator.init[1]),
bases=Bases(xgrid=self.operator.xgrid),
)
InternalPaths(self.path).bootstrap(
diff --git a/src/eko/quantities/heavy_quarks.py b/src/eko/quantities/heavy_quarks.py
index 3b081a03d..fe20fc53c 100644
--- a/src/eko/quantities/heavy_quarks.py
+++ b/src/eko/quantities/heavy_quarks.py
@@ -84,12 +84,6 @@ class HeavyInfo(DictLike):
"""
- num_flavs_init: FlavorsNumber
- r"""Number of active flavors at fitting scale.
-
- I.e. :math:`n_{f,\text{ref}}(\mu^2_0)`, formerly called ``nf0``.
-
- """
masses: HeavyQuarkMasses
"""List of heavy quark masses."""
masses_scheme: QuarkMassScheme
diff --git a/src/eko/runner/commons.py b/src/eko/runner/commons.py
index c27b4c8a2..05a1d8dd3 100644
--- a/src/eko/runner/commons.py
+++ b/src/eko/runner/commons.py
@@ -32,7 +32,7 @@ def atlas(theory: TheoryCard, operator: OperatorCard) -> Atlas:
# TODO: cache result
masses = runcards.masses(theory, operator.configs.evolution_method)
matching_scales = np.power(theory.heavy.matching_ratios, 2.0) * np.array(masses)
- return Atlas(matching_scales.tolist(), (operator.mu20, theory.heavy.num_flavs_init))
+ return Atlas(matching_scales.tolist(), (operator.mu20, operator.init[1]))
def couplings(theory: TheoryCard, operator: OperatorCard) -> Couplings:
diff --git a/src/ekobox/cards.py b/src/ekobox/cards.py
index 3d4e346aa..d56e50da0 100644
--- a/src/ekobox/cards.py
+++ b/src/ekobox/cards.py
@@ -16,7 +16,6 @@
ref=(91.2, 5),
),
heavy=dict(
- num_flavs_init=4,
masses=[ReferenceRunning([mq, nan]) for mq in (2.0, 4.5, 173.07)],
masses_scheme="POLE",
matching_ratios=[1.0, 1.0, 1.0],
@@ -26,7 +25,7 @@
)
_operator = dict(
- mu0=1.65,
+ init=(1.65, 4),
mugrid=[(100.0, 5)],
xgrid=np.geomspace(1e-7, 1.0, 50).tolist(),
configs=dict(
diff --git a/src/ekobox/cli/runcards.py b/src/ekobox/cli/runcards.py
index 7fc46f1ef..c5511add5 100644
--- a/src/ekobox/cli/runcards.py
+++ b/src/ekobox/cli/runcards.py
@@ -35,7 +35,7 @@ def sub_example(destination: pathlib.Path):
theory.order = (1, 0)
cards.dump(theory.raw, path=destination / "theory.yaml")
operator = cards.example.operator()
- operator.mu0 = 1.65
+ operator.init = (1.65, 4)
operator.mugrid = [(np.sqrt(1e5), 5)]
cards.dump(operator.raw, path=destination / "operator.yaml")
_logger.info(f"Runcards generated to '{destination}'")
diff --git a/src/ekobox/info_file.py b/src/ekobox/info_file.py
index 35f2cfcae..3d4ca2634 100644
--- a/src/ekobox/info_file.py
+++ b/src/ekobox/info_file.py
@@ -35,7 +35,9 @@ def build(
info file in lhapdf format
"""
template_info = copy.deepcopy(load.template_info)
- template_info["SetDesc"] = "Evolved PDF from " + str(operators_card.mu0) + " GeV"
+ template_info["SetDesc"] = (
+ "Evolved PDF from " + str(operators_card.init[0]) + " GeV"
+ )
template_info["Authors"] = ""
template_info["FlavorScheme"] = "variable"
template_info.update(info_update)
diff --git a/src/ekobox/utils.py b/src/ekobox/utils.py
index 095e605e9..4dc151e96 100644
--- a/src/ekobox/utils.py
+++ b/src/ekobox/utils.py
@@ -37,7 +37,7 @@ def ekos_product(
# another kind of output which includes the theory and operator runcards)
ep_match = eko_ini.approx(
- (eko_fin.operator_card.mu0**2, eko_fin.theory_card.heavy.num_flavs_init),
+ (eko_fin.operator_card.init[0] ** 2, eko_fin.operator_card.init[1]),
rtol=rtol,
atol=atol,
)
diff --git a/tests/eko/evolution_operator/test_grid.py b/tests/eko/evolution_operator/test_grid.py
index 804388db6..01754578a 100644
--- a/tests/eko/evolution_operator/test_grid.py
+++ b/tests/eko/evolution_operator/test_grid.py
@@ -72,7 +72,7 @@ def test_mod_expanded(theory_card, theory_ffns, operator_card, tmp_path: pathlib
else:
theory = theory_card
theory.order = (1, 0)
- theory.heavy.num_flavs_init = nf0
+ operator_card.init = (operator_card.init[0], nf0)
path.unlink(missing_ok=True)
opgrid = legacy.Runner(theory, operator_card, path=path).op_grid
opg = opgrid.compute()
diff --git a/tests/eko/io/test_manipulate.py b/tests/eko/io/test_manipulate.py
index 3431d93ce..08b38e23d 100644
--- a/tests/eko/io/test_manipulate.py
+++ b/tests/eko/io/test_manipulate.py
@@ -213,7 +213,7 @@ def _test_to_all_evol(
mu2_out = mu_out**2
nfout = 4
epout = (mu2_out, nfout)
- eko_factory.operator.mu0 = float(np.sqrt(1.0))
+ eko_factory.operator.init = (float(np.sqrt(1.0)), 3)
eko_factory.operator.mugrid = [(mu_out, nfout)]
eko_factory.operator.xgrid = xgrid
eko_factory.operator.configs.interpolation_polynomial_degree = 1
diff --git a/tests/eko/test_quantities.py b/tests/eko/test_quantities.py
index f9dcb9203..d3c412a25 100644
--- a/tests/eko/test_quantities.py
+++ b/tests/eko/test_quantities.py
@@ -33,7 +33,6 @@ def test_HeavyQuarks():
def test_HeavyInfo():
i = hq.HeavyInfo(
- num_flavs_init=4,
masses=hq.HeavyQuarkMasses(
[
hq.QuarkMassRef([2.0, nan]),
diff --git a/tests/ekobox/test_cards.py b/tests/ekobox/test_cards.py
index 1a35e137e..00ef0e4c3 100644
--- a/tests/ekobox/test_cards.py
+++ b/tests/ekobox/test_cards.py
@@ -10,14 +10,14 @@ def test_generate_ocard():
mu0 = 1.65
mugrid = [(10.0, 6), (100.0, 5)]
op = cards.example.operator()
- op.mu0 = mu0
+ op.init = (mu0, 4)
op.mugrid = mugrid
assert pytest.approx(op.mugrid) == mugrid
assert pytest.approx(op.mu2grid) == np.array([mu**2 for mu, _ in mugrid])
assert op.configs.interpolation_polynomial_degree == 4
mugrid1 = [100.0, 5]
op = cards.example.operator()
- op.mu0 = mu0
+ op.init = (mu0, 4)
op.mugrid = mugrid1
op.configs.interpolation_polynomial_degree = 2
op.configs.interpolation_is_log = False
@@ -35,7 +35,7 @@ def test_dump_load_op_card(tmp_path, cd):
path1 = tmp_path / "debug_op.yaml"
path2 = tmp_path / "debug_op_two.yaml"
op = cards.example.operator()
- op.mu0 = mu0
+ op.init = (mu0, 4)
cards.dump(op.raw, path1)
cards.dump(op.raw, path2)
op_loaded = cards.load(path1)
@@ -52,7 +52,7 @@ def test_generate_theory_card():
assert theory.order[0] == 2
rawt = cards.example.raw_theory()
assert isinstance(rawt, dict)
- assert theory.heavy.num_flavs_init == rawt["heavy"]["num_flavs_init"]
+ assert theory.heavy.masses.c[0] == rawt["heavy"]["masses"][0][0]
def containsnan(obj) -> bool:
diff --git a/tests/ekobox/test_evol_pdf.py b/tests/ekobox/test_evol_pdf.py
index 1c51dfdad..8e51c6e43 100644
--- a/tests/ekobox/test_evol_pdf.py
+++ b/tests/ekobox/test_evol_pdf.py
@@ -9,7 +9,7 @@
def init_cards():
op = cards.example.operator()
- op.mu0 = 1.65
+ op.init = (1.65, 4)
op.xgrid = XGrid([0.1, 0.5, 1.0])
op.configs.interpolation_polynomial_degree = 1
theory = cards.example.theory()
diff --git a/tests/ekobox/test_info_file.py b/tests/ekobox/test_info_file.py
index 64af8eb93..ac50a2253 100644
--- a/tests/ekobox/test_info_file.py
+++ b/tests/ekobox/test_info_file.py
@@ -10,7 +10,7 @@ def test_build():
theory.order = (2, 0)
theory.couplings.alphas = 0.2
op = cards.example.operator()
- op.mu0 = 1.0
+ op.init = (1.0, 3)
op.mugrid = [(10.0, 5), (100.0, 5)]
info = info_file.build(
theory, op, 4, info_update={"SetDesc": "Prova", "NewArg": 15.3, "MTop": 1.0}
diff --git a/tests/ekobox/test_utils.py b/tests/ekobox/test_utils.py
index 557db679c..1233d1d91 100644
--- a/tests/ekobox/test_utils.py
+++ b/tests/ekobox/test_utils.py
@@ -16,10 +16,9 @@ def test_ekos_product(tmp_path):
theory = cards.example.theory()
theory.order = (1, 0)
- theory.heavy.num_flavs_init = 5
op1 = cards.example.operator()
- op1.mu0 = mu01
+ op1.init = (mu01, 5)
op1.mugrid = mugrid1
op1.xgrid = xgrid
op1.configs.interpolation_polynomial_degree = 1
@@ -28,13 +27,13 @@ def test_ekos_product(tmp_path):
mugrid2 = [(8.0, 5), (10.0, 5), (12.0, 5)]
op2 = cards.example.operator()
- op2.mu0 = mu0
+ op2.init = (mu0, 5)
op2.mugrid = mugrid2
op2.xgrid = xgrid
op2.configs.interpolation_polynomial_degree = 1
op_err = copy.deepcopy(op2)
- op_err.mu0 = mu01
+ op_err.init = (mu01, 5)
mu2first = (mugrid2[0][0] ** 2, mugrid2[0][1])
diff --git a/tests/ekomark/data/test_init.py b/tests/ekomark/data/test_init.py
index 7d39dca43..278a06181 100644
--- a/tests/ekomark/data/test_init.py
+++ b/tests/ekomark/data/test_init.py
@@ -24,7 +24,7 @@ def test_runcards_opcard():
assert len(no.mu2grid) == len(no.evolgrid)
assert no.evolgrid[0][-1] == 4
assert no.evolgrid[1][-1] == 5
- np.testing.assert_allclose(no.mu0, tc["Q0"])
+ np.testing.assert_allclose(no.init[0], tc["Q0"])
np.testing.assert_allclose(no.mu20, tc["Q0"] ** 2.0)
assert len(no.pids) == 14
check_dumpable(no)
From 0d7a459d01b57fcbe34e0875f2e59a1d31373a76 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Tue, 1 Aug 2023 16:00:20 +0200
Subject: [PATCH 30/67] Fix benchmark_APFEL_vfns_fact_to_ren
---
benchmarks/eko/benchmark_strong_coupling.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/benchmarks/eko/benchmark_strong_coupling.py b/benchmarks/eko/benchmark_strong_coupling.py
index 1d1cd7219..d60bd28b0 100644
--- a/benchmarks/eko/benchmark_strong_coupling.py
+++ b/benchmarks/eko/benchmark_strong_coupling.py
@@ -334,7 +334,7 @@ def benchmark_APFEL_vfns_fact_to_ren(self):
]
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 91.0
- nf_ref = 5
+ nf_refs = (5, 6)
fact_to_ren_lin_list = [0.567, 2.34]
masses_list = np.power([2, 2 * 4, 2 * 92], 2)
apfel_vals_dict_list = [
@@ -427,8 +427,8 @@ def benchmark_APFEL_vfns_fact_to_ren(self):
),
},
]
- for fact_to_ren_lin, apfel_vals_dict in zip(
- fact_to_ren_lin_list, apfel_vals_dict_list
+ for fact_to_ren_lin, apfel_vals_dict, nf_ref in zip(
+ fact_to_ren_lin_list, apfel_vals_dict_list, nf_refs
):
# collect my values
for order in [1, 2, 3]:
From ba0a0cad21957dd112ee37c37adba2a50d59b486 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Tue, 1 Aug 2023 16:22:42 +0200
Subject: [PATCH 31/67] Update notebooks
---
doc/source/overview/tutorials/alpha_s.ipynb | 12 +-
doc/source/overview/tutorials/dglap.ipynb | 15 +--
doc/source/overview/tutorials/output.ipynb | 8 +-
doc/source/overview/tutorials/pdf.ipynb | 130 ++++++++++----------
4 files changed, 78 insertions(+), 87 deletions(-)
diff --git a/doc/source/overview/tutorials/alpha_s.ipynb b/doc/source/overview/tutorials/alpha_s.ipynb
index 327eb39c9..f9cc5a240 100644
--- a/doc/source/overview/tutorials/alpha_s.ipynb
+++ b/doc/source/overview/tutorials/alpha_s.ipynb
@@ -39,12 +39,10 @@
"from eko.quantities.heavy_quarks import MatchingScales, QuarkMassScheme\n",
"\n",
"# set the (alpha_s, alpha_em) reference values\n",
- "couplings_ref = CouplingsInfo(\n",
- " alphas=0.118, alphaem=0.007496252, ref=(91.0, 5)\n",
- ")\n",
+ "couplings_ref = CouplingsInfo(alphas=0.118, alphaem=0.007496252, ref=(91.0, 5))\n",
"\n",
"# set heavy quark masses and their threshold ratios\n",
- "heavy_quark_masses = np.power([1.51, 4.92, 172.0],2)\n",
+ "heavy_quark_masses = np.power([1.51, 4.92, 172.0], 2)\n",
"thresholds_ratios = np.array([1.0, 1.0, 1.0])\n",
"\n",
"# set (QCD,QED) perturbative order\n",
@@ -88,9 +86,9 @@
}
],
"source": [
- "target_scale = 10.0 ** 2\n",
+ "target_scale = 10.0**2\n",
"a_s = sc.a_s(target_scale)\n",
- "print(\"The value of alpha_s at Q^2=100 GeV^2 is: \", 4. * np.pi * a_s)"
+ "print(\"The value of alpha_s at Q^2=100 GeV^2 is: \", 4.0 * np.pi * a_s)"
]
},
{
@@ -106,7 +104,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "eko-KkPVjVhh-py3.10",
+ "display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
diff --git a/doc/source/overview/tutorials/dglap.ipynb b/doc/source/overview/tutorials/dglap.ipynb
index 0e271a00c..98cb4a6e1 100644
--- a/doc/source/overview/tutorials/dglap.ipynb
+++ b/doc/source/overview/tutorials/dglap.ipynb
@@ -68,7 +68,7 @@
"th_card = example.theory()\n",
"op_card = example.operator()\n",
"# here we replace the grid with a very minimal one, to speed up the example\n",
- "op_card.xgrid = [1e-3, 1e-2, 1e-1, 5e-1, 1.]"
+ "op_card.xgrid = [1e-3, 1e-2, 1e-1, 5e-1, 1.0]"
]
},
{
@@ -91,14 +91,9 @@
"{'order': [1, 0],\n",
" 'couplings': {'alphas': 0.118,\n",
" 'alphaem': 0.007496252,\n",
- " 'scale': 91.2,\n",
- " 'max_num_flavs': 6,\n",
- " 'num_flavs_ref': 5,\n",
+ " 'ref': [91.2, 5],\n",
" 'em_running': False},\n",
- " 'heavy': {'num_flavs_init': 4,\n",
- " 'num_flavs_max_pdf': 6,\n",
- " 'intrinsic_flavors': [4],\n",
- " 'masses': [[2.0, nan], [4.5, nan], [173.07, nan]],\n",
+ " 'heavy': {'masses': [[2.0, nan], [4.5, nan], [173.07, nan]],\n",
" 'masses_scheme': 'pole',\n",
" 'matching_ratios': [1.0, 1.0, 1.0]},\n",
" 'xif': 1.0,\n",
@@ -123,7 +118,7 @@
{
"data": {
"text/plain": [
- "{'mu0': 1.65,\n",
+ "{'init': [1.65, 4],\n",
" 'mugrid': [[100.0, 5]],\n",
" 'xgrid': [0.001, 0.01, 0.1, 0.5, 1.0],\n",
" 'configs': {'evolution_method': 'iterate-exact',\n",
@@ -174,7 +169,7 @@
"id": "880aadcf-8f87-4918-a0bc-09581d0d3579",
"metadata": {},
"source": [
- "The actual result is a complicate EKO object, we will discuss it in a separate tutorial.\n",
+ "The actual result is a complicate EKO object, which we will discuss it in a separate tutorial.\n",
"\n",
"You have just run your first DGLAP calculation!"
]
diff --git a/doc/source/overview/tutorials/output.ipynb b/doc/source/overview/tutorials/output.ipynb
index 47345ac35..1cfe9f071 100644
--- a/doc/source/overview/tutorials/output.ipynb
+++ b/doc/source/overview/tutorials/output.ipynb
@@ -34,7 +34,7 @@
"id": "2f8f0666-c6ab-40f6-86f5-15773f205b51",
"metadata": {},
"source": [
- "We can access the operator, by using the `open` method (similar to python's `open`):"
+ "We can access the operator, by using the `read` method:"
]
},
{
@@ -76,8 +76,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "TheoryCard(order=(1, 0), couplings=CouplingsInfo(alphas=0.118, alphaem=0.007496252, scale=91.2, max_num_flavs=6, num_flavs_ref=5, em_running=False), heavy=HeavyInfo(num_flavs_init=4, num_flavs_max_pdf=6, intrinsic_flavors=[4, 5, 6], masses=[[2.0, nan], [4.5, nan], [173.07, nan]], masses_scheme=, matching_ratios=[1.0, 1.0, 1.0]), xif=1.0, n3lo_ad_variation=(0, 0, 0, 0))\n",
- "OperatorCard(mu0=1.65, mugrid=[(100.0, 5)], xgrid=, configs=Configs(evolution_method=, ev_op_max_order=(10, 0), ev_op_iterations=10, scvar_method=None, inversion_method=None, interpolation_polynomial_degree=4, interpolation_is_log=True, polarized=False, time_like=False, n_integration_cores=0), debug=Debug(skip_singlet=False, skip_non_singlet=False), eko_version='0.0.0')\n"
+ "TheoryCard(order=(1, 0), couplings=CouplingsInfo(alphas=0.118, alphaem=0.007496252, ref=(91.2, 5), em_running=False), heavy=HeavyInfo(masses=[[2.0, nan], [4.5, nan], [173.07, nan]], masses_scheme=, matching_ratios=[1.0, 1.0, 1.0]), xif=1.0, n3lo_ad_variation=(0, 0, 0, 0))\n",
+ "OperatorCard(init=(1.65, 4), mugrid=[(100.0, 5)], xgrid=, configs=Configs(evolution_method=, ev_op_max_order=(10, 0), ev_op_iterations=10, scvar_method=None, inversion_method=None, interpolation_polynomial_degree=4, interpolation_is_log=True, polarized=False, time_like=False, n_integration_cores=0), debug=Debug(skip_singlet=False, skip_non_singlet=False), eko_version='0.0.0')\n"
]
}
],
@@ -143,7 +143,7 @@
],
"source": [
"with eko.EKO.read(\"./myeko.tar\") as evolution_operator:\n",
- " with evolution_operator.operator((10000.,5)) as op:\n",
+ " with evolution_operator.operator((10000.0, 5)) as op:\n",
" print(f\"operator: {op.operator.shape}\")\n",
" print(f\"error: {op.error.shape}\")"
]
diff --git a/doc/source/overview/tutorials/pdf.ipynb b/doc/source/overview/tutorials/pdf.ipynb
index 923520f59..bfc6ad3ad 100644
--- a/doc/source/overview/tutorials/pdf.ipynb
+++ b/doc/source/overview/tutorials/pdf.ipynb
@@ -13,9 +13,9 @@
"id": "3e0dcd0f",
"metadata": {},
"source": [
- "## Method 1: Using apply_pdf\n",
+ "## Method 1: Using `apply_pdf`\n",
"\n",
- "In this first part we will compute the eko and subsequently apply the initial PDF \"manually\" calling a dedicated function. "
+ "In this first part, we compute the eko and subsequently apply the initial PDF \"manually\" calling a dedicated function. "
]
},
{
@@ -52,6 +52,7 @@
"import pathlib\n",
"import eko\n",
"from banana import toy\n",
+ "\n",
"pdf = toy.mkPDF(\"\", 0)"
]
},
@@ -71,6 +72,7 @@
"outputs": [],
"source": [
"from ekobox.apply import apply_pdf\n",
+ "\n",
"with eko.EKO.read(\"./myeko.tar\") as evolution_operator:\n",
" evolved_pdfs = apply_pdf(evolution_operator, pdf)"
]
@@ -92,7 +94,7 @@
{
"data": {
"text/plain": [
- "dict_keys([10000.0])"
+ "dict_keys([(10000.0, 5)])"
]
},
"execution_count": 3,
@@ -134,7 +136,7 @@
}
],
"source": [
- "evolved_pdfs[10000.0][\"pdfs\"][21]"
+ "evolved_pdfs[(10000.0, 5)][\"pdfs\"][21]"
]
},
{
@@ -150,7 +152,7 @@
"id": "e925d2c9",
"metadata": {},
"source": [
- "## Method 2: Using evolve_pdfs\n",
+ "## Method 2: Using `evolve_pdfs`\n",
"\n",
"In this second part we illustrate how to get (and install) directly a LHAPDF set evolved with eko. "
]
@@ -171,6 +173,7 @@
"outputs": [],
"source": [
"from banana import toy\n",
+ "\n",
"pdf = toy.mkPDF(\"\", 0)"
]
},
@@ -195,10 +198,10 @@
"th_card = example.theory()\n",
"op_card = example.operator()\n",
"# here we replace the grid with a very minimal one, to speed up the example\n",
- "op_card.xgrid = eko.interpolation.XGrid([1e-3, 1e-2, 1e-1, 5e-1, 1.])\n",
- "op_card.mugrid = [(10.,5), (100.,5)]\n",
+ "op_card.xgrid = eko.interpolation.XGrid([1e-3, 1e-2, 1e-1, 5e-1, 1.0])\n",
+ "op_card.mugrid = [(10.0, 5), (100.0, 5)]\n",
"# set QCD LO evolution\n",
- "th_card.orders = (1,0)"
+ "th_card.orders = (1, 0)"
]
},
{
@@ -236,16 +239,10 @@
],
"source": [
"from ekobox.evol_pdf import evolve_pdfs\n",
+ "\n",
"path = pathlib.Path(\"./myeko2.tar\")\n",
"path.unlink(missing_ok=True)\n",
- "evolve_pdfs(\n",
- " [pdf],\n",
- " th_card,\n",
- " op_card,\n",
- " install=True,\n",
- " name=\"Evolved_PDF\",\n",
- " store_path=path\n",
- ")"
+ "evolve_pdfs([pdf], th_card, op_card, install=True, name=\"Evolved_PDF\", store_path=path)"
]
},
{
@@ -273,6 +270,7 @@
],
"source": [
"import lhapdf\n",
+ "\n",
"evolved_pdf = lhapdf.mkPDF(\"Evolved_PDF\", 0)"
]
},
@@ -300,12 +298,12 @@
}
],
"source": [
- "pid = 21 # gluon pid\n",
- "Q2 = 89.10 # Q^2 in Gev^2\n",
- "x = 0.01 # momentum fraction \n",
+ "pid = 21 # gluon pid\n",
+ "Q2 = 89.10 # Q^2 in Gev^2\n",
+ "x = 0.01 # momentum fraction\n",
"\n",
"# check that the particle is present\n",
- "print(\"has gluon?\",evolved_pdf.hasFlavor(pid))\n",
+ "print(\"has gluon?\", evolved_pdf.hasFlavor(pid))\n",
"# now do the lookup\n",
"xg = evolved_pdf.xfxQ2(pid, x, Q2)\n",
"print(f\"xg(x={x}, Q2={Q2}) = {xg}\")"
@@ -352,24 +350,28 @@
"import lhapdf\n",
"from ekobox.cards import example\n",
"from eko.interpolation import make_grid\n",
- "from eko.quantities.heavy_quarks import QuarkMassRef,HeavyQuarks\n",
+ "from eko.quantities.heavy_quarks import QuarkMassRef, HeavyQuarks\n",
"\n",
"# get the PDF object\n",
"ct14llo = lhapdf.mkPDF(\"CT14llo\")\n",
"\n",
"# setup the operator card\n",
"op_card = example.operator()\n",
- "op_card.xgrid = eko.interpolation.XGrid(make_grid(30, 30)) # x grid\n",
- "op_card.mugrid = [(float(q),5) for q in np.geomspace(5., 100, 5)] # Q2 grid\n",
- "op_card.init = (1.295000,3) # starting point for the evolution \n",
+ "op_card.xgrid = eko.interpolation.XGrid(make_grid(30, 30)) # x grid\n",
+ "op_card.mugrid = [(float(q), 5) for q in np.geomspace(5.0, 100, 5)] # Q2 grid\n",
+ "op_card.init = (1.295000, 3) # starting point for the evolution\n",
"\n",
"# setup the theory card - this can be mostly inferred from the PDF's .info file\n",
- "\n",
"th_card = example.theory()\n",
- "th_card.orders = (1,0) # QCD LO\n",
- "th_card.heavy.masses = HeavyQuarks([QuarkMassRef([1.3,nan]), QuarkMassRef([4.75,nan]), QuarkMassRef([172.,nan])]) # quark mass\n",
- "th_card.couplings.alphas = 0.130000 # reference value of alpha_s\n",
- "th_card.couplings.ref = (91.1876,5) # the reference scale together with the number of flavors at which alpha_s is provided"
+ "th_card.orders = (1, 0) # QCD LO\n",
+ "th_card.heavy.masses = HeavyQuarks(\n",
+ " [QuarkMassRef([1.3, nan]), QuarkMassRef([4.75, nan]), QuarkMassRef([172.0, nan])]\n",
+ ") # quark mass\n",
+ "th_card.couplings.alphas = 0.130000 # reference value of alpha_s\n",
+ "th_card.couplings.ref = (\n",
+ " 91.1876,\n",
+ " 5,\n",
+ ") # the reference scale together with the number of flavors at which alpha_s is provided"
]
},
{
@@ -403,15 +405,11 @@
],
"source": [
"from ekobox.evol_pdf import evolve_pdfs\n",
+ "\n",
"path = pathlib.Path(\"./myeko_ct14llo.tar\")\n",
"path.unlink(missing_ok=True)\n",
"evolve_pdfs(\n",
- " [ct14llo],\n",
- " th_card,\n",
- " op_card,\n",
- " install=True,\n",
- " name=\"my_ct14llo\",\n",
- " store_path=path\n",
+ " [ct14llo], th_card, op_card, install=True, name=\"my_ct14llo\", store_path=path\n",
")"
]
},
@@ -435,33 +433,33 @@
"output_type": "stream",
"text": [
"LHAPDF 6.4.0 loading /home/felix/local/share/LHAPDF/my_ct14llo/my_ct14llo_0000.dat\n",
+ "my_ct14llo PDF set, member #0, version 1\n",
" x Q2 ct14llo my_ct14llo relative_diff\n",
- "0 0.000010 25.000000 7.635785e+01 7.630461e+01 0.000697\n",
- "1 0.000173 25.000000 3.194273e+01 3.192092e+01 0.000683\n",
- "2 0.003000 25.000000 1.081843e+01 1.081086e+01 0.000701\n",
- "3 0.051962 25.000000 1.958956e+00 1.958632e+00 0.000166\n",
- "4 0.900000 25.000000 1.922415e-05 1.955026e-05 -0.016963\n",
- "5 0.000010 111.803399 1.333957e+02 1.332985e+02 0.000729\n",
- "6 0.000173 111.803399 4.777286e+01 4.773664e+01 0.000758\n",
- "7 0.003000 111.803399 1.341028e+01 1.339967e+01 0.000791\n",
- "8 0.051962 111.803399 1.978216e+00 1.978130e+00 0.000044\n",
- "9 0.900000 111.803399 6.644805e-06 6.753652e-06 -0.016381\n",
- "10 0.000010 500.000000 1.967032e+02 1.965456e+02 0.000801\n",
- "11 0.000173 500.000000 6.291393e+01 6.286095e+01 0.000842\n",
- "12 0.003000 500.000000 1.542347e+01 1.540996e+01 0.000876\n",
- "13 0.051962 500.000000 1.947465e+00 1.947391e+00 0.000038\n",
- "14 0.900000 500.000000 2.929060e-06 2.977306e-06 -0.016471\n",
- "15 0.000010 2236.067977 2.633266e+02 2.631109e+02 0.000819\n",
- "16 0.000173 2236.067977 7.708540e+01 7.701938e+01 0.000856\n",
- "17 0.003000 2236.067977 1.700410e+01 1.698928e+01 0.000872\n",
- "18 0.051962 2236.067977 1.893923e+00 1.893971e+00 -0.000025\n",
- "19 0.900000 2236.067977 1.544450e-06 1.570997e-06 -0.017189\n",
- "20 0.000010 10000.000000 3.314097e+02 3.311351e+02 0.000829\n",
- "21 0.000173 10000.000000 9.023010e+01 9.015279e+01 0.000857\n",
- "22 0.003000 10000.000000 1.825934e+01 1.824402e+01 0.000839\n",
- "23 0.051962 10000.000000 1.830992e+00 1.831183e+00 -0.000104\n",
- "24 0.900000 10000.000000 9.288458e-07 9.447927e-07 -0.017169\n",
- "my_ct14llo PDF set, member #0, version 1\n"
+ "0 0.000010 25.000000 7.635785e+01 7.630719e+01 0.000663\n",
+ "1 0.000173 25.000000 3.194273e+01 3.192239e+01 0.000637\n",
+ "2 0.003000 25.000000 1.081843e+01 1.081160e+01 0.000632\n",
+ "3 0.051962 25.000000 1.958956e+00 1.958820e+00 0.000069\n",
+ "4 0.900000 25.000000 1.922415e-05 1.955440e-05 -0.017179\n",
+ "5 0.000010 111.803399 1.333957e+02 1.333028e+02 0.000697\n",
+ "6 0.000173 111.803399 4.777286e+01 4.773855e+01 0.000718\n",
+ "7 0.003000 111.803399 1.341028e+01 1.340044e+01 0.000734\n",
+ "8 0.051962 111.803399 1.978216e+00 1.978292e+00 -0.000038\n",
+ "9 0.900000 111.803399 6.644805e-06 6.756354e-06 -0.016787\n",
+ "10 0.000010 500.000000 1.967032e+02 1.965517e+02 0.000770\n",
+ "11 0.000173 500.000000 6.291393e+01 6.286327e+01 0.000805\n",
+ "12 0.003000 500.000000 1.542347e+01 1.541073e+01 0.000826\n",
+ "13 0.051962 500.000000 1.947465e+00 1.947532e+00 -0.000034\n",
+ "14 0.900000 500.000000 2.929060e-06 2.979511e-06 -0.017224\n",
+ "15 0.000010 2236.067977 2.633266e+02 2.631189e+02 0.000789\n",
+ "16 0.000173 2236.067977 7.708540e+01 7.702204e+01 0.000822\n",
+ "17 0.003000 2236.067977 1.700410e+01 1.699004e+01 0.000827\n",
+ "18 0.051962 2236.067977 1.893923e+00 1.894094e+00 -0.000090\n",
+ "19 0.900000 2236.067977 1.544450e-06 1.572860e-06 -0.018395\n",
+ "20 0.000010 10000.000000 3.314097e+02 3.311450e+02 0.000799\n",
+ "21 0.000173 10000.000000 9.023010e+01 9.015576e+01 0.000824\n",
+ "22 0.003000 10000.000000 1.825934e+01 1.824477e+01 0.000798\n",
+ "23 0.051962 10000.000000 1.830992e+00 1.831291e+00 -0.000163\n",
+ "24 0.900000 10000.000000 9.288458e-07 9.463689e-07 -0.018866\n"
]
}
],
@@ -471,15 +469,15 @@
"# load evolved pdf\n",
"my_ct14llo = lhapdf.mkPDF(\"my_ct14llo\", 0)\n",
"\n",
- "pid = 21 # gluon pid\n",
+ "pid = 21 # gluon pid\n",
"\n",
"# collect data\n",
- "log = {\"x\": [], \"Q2\" : [], \"ct14llo\": [], \"my_ct14llo\": [], \"relative_diff\": []} \n",
- "for q in np.geomspace(5., 100, 5):\n",
- " q2 = q**2.\n",
+ "log = {\"x\": [], \"Q2\": [], \"ct14llo\": [], \"my_ct14llo\": [], \"relative_diff\": []}\n",
+ "for q in np.geomspace(5.0, 100, 5):\n",
+ " q2 = q**2.0\n",
" for x in np.geomspace(1e-5, 0.9, 5):\n",
" value = ct14llo.xfxQ2(pid, x, q2)\n",
- " my_value = my_ct14llo.xfxQ2(pid, x, q2)\n",
+ " my_value = my_ct14llo.xfxQ2(pid, x, q2)\n",
" log[\"x\"].append(x)\n",
" log[\"Q2\"].append(q2)\n",
" log[\"ct14llo\"].append(value)\n",
From 3e2d12a4ff0a1013ce33cd07b193a2c52c9e4939 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Tue, 1 Aug 2023 17:06:34 +0200
Subject: [PATCH 32/67] Drop Bases
---
src/eko/io/bases.py | 117 ----------------------------------
src/eko/io/metadata.py | 8 +--
src/eko/io/struct.py | 12 +---
src/ekobox/apply.py | 12 ++--
tests/eko/io/test_bases.py | 83 ------------------------
tests/eko/io/test_metadata.py | 6 +-
tests/eko/io/test_runcards.py | 1 -
tests/eko/runner/__init__.py | 10 +--
tests/eko/runner/conftest.py | 3 +-
tests/ekobox/test_apply.py | 11 ++--
10 files changed, 27 insertions(+), 236 deletions(-)
delete mode 100644 src/eko/io/bases.py
delete mode 100644 tests/eko/io/test_bases.py
diff --git a/src/eko/io/bases.py b/src/eko/io/bases.py
deleted file mode 100644
index 97a28dc36..000000000
--- a/src/eko/io/bases.py
+++ /dev/null
@@ -1,117 +0,0 @@
-"""Operators bases."""
-from dataclasses import dataclass, fields
-from typing import Optional
-
-import numpy as np
-import numpy.typing as npt
-
-from .. import basis_rotation as br
-from .. import interpolation
-from .dictlike import DictLike
-
-
-@dataclass
-class Bases(DictLike):
- """Rotations related configurations.
-
- Here "Rotation" is intended in a broad sense: it includes both rotations in
- flavor space (labeled with suffix `pids`) and in :math:`x`-space (labeled
- with suffix `grid`).
- Rotations in :math:`x`-space correspond to reinterpolate the result on a
- different basis of polynomials.
-
- """
-
- xgrid: interpolation.XGrid
- """Internal momentum fraction grid."""
- _targetgrid: Optional[interpolation.XGrid] = None
- _inputgrid: Optional[interpolation.XGrid] = None
- _targetpids: Optional[npt.NDArray] = None
- _inputpids: Optional[npt.NDArray] = None
-
- def __post_init__(self):
- """Adjust types when loaded from serialized object."""
- for attr in ("xgrid", "_inputgrid", "_targetgrid"):
- value = getattr(self, attr)
- if value is None:
- continue
- if isinstance(value, (np.ndarray, list)):
- setattr(self, attr, interpolation.XGrid(value))
- elif not isinstance(value, interpolation.XGrid):
- setattr(self, attr, interpolation.XGrid.load(value))
-
- @property
- def pids(self):
- """Internal flavor basis, used for computation."""
- return np.array(br.flavor_basis_pids)
-
- @property
- def inputpids(self) -> npt.NDArray:
- """Provide pids expected on the input PDF."""
- if self._inputpids is None:
- return self.pids
- return self._inputpids
-
- @inputpids.setter
- def inputpids(self, value):
- self._inputpids = value
-
- @property
- def targetpids(self) -> npt.NDArray:
- """Provide pids corresponding to the output PDF."""
- if self._targetpids is None:
- return self.pids
- return self._targetpids
-
- @targetpids.setter
- def targetpids(self, value):
- self._targetpids = value
-
- @property
- def inputgrid(self) -> interpolation.XGrid:
- """Provide :math:`x`-grid expected on the input PDF."""
- if self._inputgrid is None:
- return self.xgrid
- return self._inputgrid
-
- @inputgrid.setter
- def inputgrid(self, value: interpolation.XGrid):
- self._inputgrid = value
-
- @property
- def targetgrid(self) -> interpolation.XGrid:
- """Provide :math:`x`-grid corresponding to the output PDF."""
- if self._targetgrid is None:
- return self.xgrid
- return self._targetgrid
-
- @targetgrid.setter
- def targetgrid(self, value: interpolation.XGrid):
- self._targetgrid = value
-
- @classmethod
- def from_dict(cls, dictionary: dict):
- """Deserialize rotation.
-
- Load from full state, but with public names.
-
- """
- d = dictionary.copy()
- for f in fields(cls):
- if f.name.startswith("_"):
- d[f.name] = d.pop(f.name[1:])
- return cls._from_dict(d)
-
- @property
- def raw(self):
- """Serialize rotation.
-
- Pass through interfaces, access internal values but with a public name.
-
- """
- d = self._raw()
- for key in d.copy():
- if key.startswith("_"):
- d[key[1:]] = d.pop(key)
-
- return d
diff --git a/src/eko/io/metadata.py b/src/eko/io/metadata.py
index 415b2dfa5..00f189ab4 100644
--- a/src/eko/io/metadata.py
+++ b/src/eko/io/metadata.py
@@ -8,7 +8,7 @@
import yaml
from .. import version as vmod
-from .bases import Bases
+from ..interpolation import XGrid
from .dictlike import DictLike
from .paths import InternalPaths
from .types import EvolutionPoint as EPoint
@@ -34,10 +34,8 @@ class Metadata(DictLike):
origin: EPoint
"""Inital scale."""
- bases: Bases
- """Manipulation information, describing the current status of the EKO (e.g.
- `inputgrid` and `targetgrid`).
- """
+ xgrid: XGrid
+ """Interpolation grid"""
# tagging information
_path: Optional[pathlib.Path] = None
"""Path to temporary dir."""
diff --git a/src/eko/io/struct.py b/src/eko/io/struct.py
index fecba3c57..dbbb231f9 100644
--- a/src/eko/io/struct.py
+++ b/src/eko/io/struct.py
@@ -16,7 +16,6 @@
from .. import interpolation
from . import exceptions, raw
from .access import AccessConfigs
-from .bases import Bases
from .inventory import Inventory
from .items import Evolution, Matching, Operator, Recipe, Target
from .metadata import Metadata
@@ -105,20 +104,15 @@ def paths(self) -> InternalPaths:
"""Accessor for internal paths."""
return InternalPaths(self.metadata.path)
- @property
- def bases(self) -> Bases:
- """Bases information."""
- return self.metadata.bases
-
@property
def xgrid(self) -> interpolation.XGrid:
"""Momentum fraction internal grid."""
- return self.bases.xgrid
+ return self.metadata.xgrid
@xgrid.setter
def xgrid(self, value: interpolation.XGrid):
"""Set `xgrid` value."""
- self.bases.xgrid = value
+ self.metadata.xgrid = value
self.update()
@property
@@ -551,7 +545,7 @@ def build(self) -> EKO:
metadata = Metadata(
_path=self.path,
origin=(self.operator.mu20, self.theory.heavy.num_flavs_init),
- bases=Bases(xgrid=self.operator.xgrid),
+ xgrid=self.operator.xgrid,
)
InternalPaths(self.path).bootstrap(
theory=self.theory.raw,
diff --git a/src/ekobox/apply.py b/src/ekobox/apply.py
index c392ffe78..5722a6ad6 100644
--- a/src/ekobox/apply.py
+++ b/src/ekobox/apply.py
@@ -74,12 +74,12 @@ def apply_pdf_flavor(
output PDFs and their associated errors for the computed mu2grid
"""
# create pdfs
- pdfs = np.zeros((len(eko.bases.inputpids), len(eko.bases.inputgrid)))
- for j, pid in enumerate(eko.bases.inputpids):
+ pdfs = np.zeros((len(br.flavor_basis_pids), len(eko.xgrid)))
+ for j, pid in enumerate(br.flavor_basis_pids):
if not lhapdf_like.hasFlavor(pid):
continue
pdfs[j] = np.array(
- [lhapdf_like.xfxQ2(pid, x, eko.mu20) / x for x in eko.bases.inputgrid.raw]
+ [lhapdf_like.xfxQ2(pid, x, eko.mu20) / x for x in eko.xgrid.raw]
)
# build output
@@ -91,11 +91,11 @@ def apply_pdf_flavor(
else:
error_final = None
out_grid[ep] = {
- "pdfs": dict(zip(eko.bases.targetpids, pdf_final)),
+ "pdfs": dict(zip(br.flavor_basis_pids, pdf_final)),
"errors": None,
}
if error_final is not None:
- out_grid[ep]["errors"] = dict(zip(eko.bases.targetpids, error_final))
+ out_grid[ep]["errors"] = dict(zip(br.flavor_basis_pids, error_final))
# rotate to evolution basis
if flavor_rotation is not None:
@@ -117,7 +117,7 @@ def apply_pdf_flavor(
# rotate/interpolate to target grid
if targetgrid is not None:
b = interpolation.InterpolatorDispatcher(
- xgrid=eko.bases.targetgrid,
+ xgrid=eko.xgrid,
polynomial_degree=eko.operator_card.configs.interpolation_polynomial_degree,
mode_N=False,
)
diff --git a/tests/eko/io/test_bases.py b/tests/eko/io/test_bases.py
deleted file mode 100644
index a0165243f..000000000
--- a/tests/eko/io/test_bases.py
+++ /dev/null
@@ -1,83 +0,0 @@
-from dataclasses import fields
-
-import numpy as np
-
-from eko import basis_rotation as br
-from eko import interpolation
-from eko.io.bases import Bases
-
-
-class TestBases:
- XGRID_TEST = [1e-3, 1e-2, 1e-1, 1.0]
-
- def test_serialization(self):
- rot = Bases(interpolation.XGrid(self.XGRID_TEST))
-
- d = rot.raw
- rot1 = rot.from_dict(d)
-
- for f in fields(Bases):
- assert getattr(rot, f.name) == getattr(rot1, f.name)
-
- assert d["targetgrid"] is None
- assert "_targetgrid" not in d
-
- def test_pids(self):
- rot = Bases(interpolation.XGrid(self.XGRID_TEST))
-
- # no check on correctness of value set
- rot.inputpids = [0, 1]
- # but the internal grid is unmodified
- assert len(rot.pids) == 14
- # and fallback implemented for unset external bases
- assert np.all(rot.targetpids == rot.pids)
-
- def test_grids(self):
- rot = Bases(interpolation.XGrid(self.XGRID_TEST))
-
- # no check on correctness of value set
- rot.inputgrid = interpolation.XGrid([0.1, 1])
- # but the internal grid is unmodified
- assert len(rot.xgrid) == len(self.XGRID_TEST)
- # and fallback implemented for unset external grids
- assert np.all(rot.targetgrid == rot.xgrid)
-
- def test_fallback(self):
- xg = interpolation.XGrid([0.1, 1.0])
- r = Bases(xgrid=xg)
- np.testing.assert_allclose(r.targetpids, r.pids)
- np.testing.assert_allclose(r.inputpids, r.pids)
- assert r.xgrid == xg
- assert r.targetgrid == xg
- assert r.inputgrid == xg
-
- def test_overwrite(self):
- tpids = np.array([3, 4] + list(br.flavor_basis_pids[2:]))
- ipids = np.array([5, 6] + list(br.flavor_basis_pids[2:]))
- xg = interpolation.XGrid([0.1, 1.0])
- txg = interpolation.XGrid([0.2, 1.0])
- ixg = interpolation.XGrid([0.3, 1.0])
- r = Bases(
- xgrid=xg,
- _targetgrid=txg,
- _inputgrid=ixg,
- _targetpids=tpids,
- _inputpids=ipids,
- )
- np.testing.assert_allclose(r.targetpids, tpids)
- np.testing.assert_allclose(r.inputpids, ipids)
- assert r.xgrid == xg
- assert r.targetgrid == txg
- assert r.inputgrid == ixg
-
- def test_init(self):
- xg = interpolation.XGrid([0.1, 1.0])
- txg = np.array([0.2, 1.0])
- ixg = {"grid": [0.3, 1.0], "log": True}
- r = Bases(xgrid=xg, _targetgrid=txg, _inputgrid=ixg)
- assert isinstance(r.xgrid, interpolation.XGrid)
- assert isinstance(r.targetgrid, interpolation.XGrid)
- assert isinstance(r.inputgrid, interpolation.XGrid)
- assert r.xgrid == xg
- assert r.targetgrid == interpolation.XGrid(txg)
- assert r.inputgrid == interpolation.XGrid.load(ixg)
diff --git a/tests/eko/io/test_metadata.py b/tests/eko/io/test_metadata.py
index a5651e0c8..fcfa8dd09 100644
--- a/tests/eko/io/test_metadata.py
+++ b/tests/eko/io/test_metadata.py
@@ -3,11 +3,11 @@
import pytest
import yaml
-from eko.io import bases, metadata, paths
+from eko.io import metadata, paths
def test_metadata(tmp_path, caplog):
- m = metadata.Metadata((1.0, 3), bases.Bases([0.1, 1.0]))
+ m = metadata.Metadata(origin=(1.0, 3), xgrid=[0.1, 1.0])
# errors
with caplog.at_level(logging.INFO):
m.update()
@@ -26,7 +26,7 @@ def test_metadata(tmp_path, caplog):
m.version = "0.0.0-a1~really1.0.0"
m.update()
# if I read back the thing should be what I set
- mn = metadata.Metadata((1.0, 3), bases.Bases([0.1, 1.0]))
+ mn = metadata.Metadata(origin=(1.0, 3), xgrid=[0.1, 1.0])
mm = metadata.Metadata.load(tmp_path)
assert m.path == tmp_path
assert mm.version != mn.version
diff --git a/tests/eko/io/test_runcards.py b/tests/eko/io/test_runcards.py
index 6af37edcb..4b4996336 100644
--- a/tests/eko/io/test_runcards.py
+++ b/tests/eko/io/test_runcards.py
@@ -7,7 +7,6 @@
from banana.data.theories import default_card as theory_card
from eko.io import runcards as rc
-from eko.io.bases import Bases
from ekomark.data.operators import default_card as operator_card
diff --git a/tests/eko/runner/__init__.py b/tests/eko/runner/__init__.py
index c8ec5b854..0e3ea68c0 100644
--- a/tests/eko/runner/__init__.py
+++ b/tests/eko/runner/__init__.py
@@ -1,19 +1,21 @@
import numpy as np
+from eko import basis_rotation as br
+
def check_shapes(o, txs, ixs, theory_card, operators_card):
- tpids = len(o.bases.targetpids)
- ipids = len(o.bases.inputpids)
+ tpids = len(br.flavor_basis_pids)
+ ipids = len(br.flavor_basis_pids)
op_shape = (tpids, len(txs), ipids, len(ixs))
# check output = input
np.testing.assert_allclose(o.xgrid.raw, operators_card.xgrid.raw)
# targetgrid and inputgrid in the opcard are now ignored, we are testing this
np.testing.assert_allclose(
- o.bases.targetgrid.raw,
+ o.xgrid.raw,
txs.raw,
)
- np.testing.assert_allclose(o.bases.inputgrid.raw, ixs.raw)
+ np.testing.assert_allclose(o.xgrid.raw, ixs.raw)
np.testing.assert_allclose(o.mu20, operators_card.mu20)
# check available operators
~o.operators
diff --git a/tests/eko/runner/conftest.py b/tests/eko/runner/conftest.py
index a1516b2a7..a2966c5e9 100644
--- a/tests/eko/runner/conftest.py
+++ b/tests/eko/runner/conftest.py
@@ -4,6 +4,7 @@
import pytest
from eko import EKO
+from eko import basis_rotation as br
from eko.io.items import Operator
from eko.io.runcards import OperatorCard, TheoryCard
from eko.runner import commons, recipes
@@ -21,7 +22,7 @@ def neweko(theory_card: TheoryCard, operator_card: OperatorCard, tmp_path: Path)
@pytest.fixture
def identity(neweko: EKO):
xs = len(neweko.xgrid.raw)
- flavs = len(neweko.bases.pids)
+ flavs = len(br.flavor_basis_pids)
return Operator(operator=np.eye(xs * flavs).reshape((xs, flavs, xs, flavs)))
diff --git a/tests/ekobox/test_apply.py b/tests/ekobox/test_apply.py
index 8fa23548f..70eb74adc 100644
--- a/tests/ekobox/test_apply.py
+++ b/tests/ekobox/test_apply.py
@@ -1,5 +1,6 @@
import numpy as np
+from eko import basis_rotation as br
from ekobox import apply
from tests.conftest import EKOFactory
@@ -12,13 +13,13 @@ def test_apply(self, eko_factory: EKOFactory, fake_pdf):
pdf_grid = apply.apply_pdf(eko, fake_pdf)
assert len(pdf_grid) == len(eko.evolgrid)
pdfs = pdf_grid[ep_out]["pdfs"]
- assert list(pdfs.keys()) == list(eko.bases.targetpids)
+ assert list(pdfs.keys()) == list(br.flavor_basis_pids)
# rotate to target_grid
target_grid = [0.75]
pdf_grid = apply.apply_pdf(eko, fake_pdf, target_grid)
assert len(pdf_grid) == 1
pdfs = pdf_grid[ep_out]["pdfs"]
- assert list(pdfs.keys()) == list(eko.bases.targetpids)
+ assert list(pdfs.keys()) == list(br.flavor_basis_pids)
def test_apply_flavor(self, eko_factory: EKOFactory, fake_pdf, monkeypatch):
eko = eko_factory.get()
@@ -27,12 +28,8 @@ def test_apply_flavor(self, eko_factory: EKOFactory, fake_pdf, monkeypatch):
monkeypatch.setattr(
"eko.basis_rotation.rotate_flavor_to_evolution", np.ones((14, 14))
)
- monkeypatch.setattr(
- "eko.basis_rotation.flavor_basis_pids",
- eko.bases.targetpids,
- )
fake_evol_basis = tuple(
- ["a", "b"] + [str(x) for x in range(len(eko.bases.pids) - 2)]
+ ["a", "b"] + [str(x) for x in range(len(br.flavor_basis_pids) - 2)]
)
monkeypatch.setattr("eko.basis_rotation.evol_basis", fake_evol_basis)
pdf_grid = apply.apply_pdf(eko, fake_pdf, rotate_to_evolution_basis=True)
From 7cf9e1b30d2f17553094e23db15775aabc8e9545 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Tue, 1 Aug 2023 17:57:50 +0200
Subject: [PATCH 33/67] Use correct types in LHA
---
benchmarks/lha_paper_bench.py | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/benchmarks/lha_paper_bench.py b/benchmarks/lha_paper_bench.py
index 9254307dc..f92755af9 100644
--- a/benchmarks/lha_paper_bench.py
+++ b/benchmarks/lha_paper_bench.py
@@ -12,19 +12,15 @@
register(__file__)
+_sqrt2 = float(np.sqrt(2.0))
+
base_theory = {
"ModEv": "EXA",
- "Q0": np.sqrt(
- 2.0
- ), # Eq. (30) :cite:`Giele:2002hx`, Eq. (4.53) :cite:`Dittmar:2005ed`
- "mc": np.sqrt(
- 2.0
- ), # Eq. (34) :cite:`Giele:2002hx`, Eq. (4.56) :cite:`Dittmar:2005ed`
+ "Q0": _sqrt2, # Eq. (30) :cite:`Giele:2002hx`, Eq. (4.53) :cite:`Dittmar:2005ed`
+ "mc": _sqrt2, # Eq. (34) :cite:`Giele:2002hx`, Eq. (4.56) :cite:`Dittmar:2005ed`
"mb": 4.5,
"mt": 175,
- "Qref": np.sqrt(
- 2.0
- ), # Eq. (32) :cite:`Giele:2002hx`,Eq. (4.53) :cite:`Dittmar:2005ed`
+ "Qref": _sqrt2, # Eq. (32) :cite:`Giele:2002hx`,Eq. (4.53) :cite:`Dittmar:2005ed`
"alphas": 0.35, # Eq. (4.55) :cite:`Dittmar:2005ed`
"alphaqed": 0.007496,
"QED": 0,
@@ -78,11 +74,11 @@ def sv_theories(self, pto):
"""
low = self.theory.copy()
low["PTO"] = pto
- low["XIF"] = np.sqrt(1.0 / 2.0)
+ low["XIF"] = 1.0 / _sqrt2
low["ModSV"] = "exponentiated"
high = self.theory.copy()
high["PTO"] = pto
- high["XIF"] = np.sqrt(2.0)
+ high["XIF"] = _sqrt2
high["ModSV"] = "exponentiated"
return [high, low]
@@ -301,7 +297,7 @@ def benchmark_sv(self, pto):
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)
+ low["XIR"] = _sqrt2
+ high["XIR"] = 1.0 / _sqrt2
self.run_lha([low, high])
From 50cd3aff60e7cd67ae7d7b3fbfff1ae0919ba329 Mon Sep 17 00:00:00 2001
From: Alessandro Candido
Date: Wed, 16 Aug 2023 16:01:34 +0200
Subject: [PATCH 34/67] Dismiss PathLike internal usage in struct
---
src/eko/io/struct.py | 41 +++++++++++++++--------------------------
1 file changed, 15 insertions(+), 26 deletions(-)
diff --git a/src/eko/io/struct.py b/src/eko/io/struct.py
index fecba3c57..7acd6af5e 100644
--- a/src/eko/io/struct.py
+++ b/src/eko/io/struct.py
@@ -2,12 +2,11 @@
import contextlib
import copy
import logging
-import os
-import pathlib
import shutil
import tarfile
import tempfile
from dataclasses import dataclass
+from pathlib import Path
from typing import List, Optional
import numpy as np
@@ -30,7 +29,7 @@
TEMP_PREFIX = "eko-"
-def inventories(path: pathlib.Path, access: AccessConfigs) -> dict:
+def inventories(path: Path, access: AccessConfigs) -> dict:
"""Set up empty inventories for object initialization."""
paths = InternalPaths(path)
return dict(
@@ -293,7 +292,7 @@ def unload(self):
# operator management
# -------------------
- def deepcopy(self, path: os.PathLike):
+ def deepcopy(self, path: Path):
"""Create a deep copy of current instance.
The managed on-disk object is copied as well, to the new ``path``
@@ -327,11 +326,11 @@ def deepcopy(self, path: os.PathLike):
self.unload()
new = copy.deepcopy(self)
- new.access.path = pathlib.Path(path)
+ new.access.path = path
new.access.readonly = False
new.access.open = True
- tmpdir = pathlib.Path(tempfile.mkdtemp(prefix=TEMP_PREFIX))
+ tmpdir = Path(tempfile.mkdtemp(prefix=TEMP_PREFIX))
new.metadata.path = tmpdir
# copy old dir to new dir
tmpdir.rmdir()
@@ -339,17 +338,8 @@ def deepcopy(self, path: os.PathLike):
new.close()
@staticmethod
- def load(tarpath: os.PathLike, dest: os.PathLike):
- """Load the content of archive in a target directory.
-
- Parameters
- ----------
- tarpath: os.PathLike
- the archive to extract
- tmppath: os.PathLike
- the destination directory
-
- """
+ def load(tarpath: Path, dest: Path):
+ """Load the content of archive in a target directory."""
try:
with tarfile.open(tarpath) as tar:
raw.safe_extractall(tar, dest)
@@ -357,9 +347,8 @@ def load(tarpath: os.PathLike, dest: os.PathLike):
raise exceptions.OutputNotTar(f"Not a valid tar archive: '{tarpath}'")
@classmethod
- def open(cls, path: os.PathLike, mode="r"):
+ def open(cls, path: Path, mode: str = "r"):
"""Open EKO object in the specified mode."""
- path = pathlib.Path(path)
access = AccessConfigs(path, readonly=False, open=True)
load = False
if mode == "r":
@@ -372,7 +361,7 @@ def open(cls, path: os.PathLike, mode="r"):
else:
raise ValueError(f"Unknown file mode: {mode}")
- tmpdir = pathlib.Path(tempfile.mkdtemp(prefix=TEMP_PREFIX))
+ tmpdir = Path(tempfile.mkdtemp(prefix=TEMP_PREFIX))
if load:
cls.load(path, tmpdir)
metadata = Metadata.load(tmpdir)
@@ -388,7 +377,7 @@ def open(cls, path: os.PathLike, mode="r"):
return opened
@classmethod
- def read(cls, path: os.PathLike):
+ def read(cls, path: Path):
"""Read the content of an EKO.
Type-safe alias for::
@@ -401,7 +390,7 @@ def read(cls, path: os.PathLike):
return eko
@classmethod
- def create(cls, path: os.PathLike):
+ def create(cls, path: Path):
"""Create a new EKO.
Type-safe alias for::
@@ -414,7 +403,7 @@ def create(cls, path: os.PathLike):
return builder
@classmethod
- def edit(cls, path: os.PathLike):
+ def edit(cls, path: Path):
"""Read from and write on existing EKO.
Type-safe alias for::
@@ -430,12 +419,12 @@ def __enter__(self):
"""Allow EKO to be used in :obj:`with` statements."""
return self
- def dump(self, archive: Optional[os.PathLike] = None):
+ def dump(self, archive: Optional[Path] = None):
"""Dump the current content to archive.
Parameters
----------
- archive: os.PathLike or None
+ archive: Path or None
path to archive, in general you should keep the default, that will
make use of the registered path (default: ``None``)
@@ -494,7 +483,7 @@ def raw(self) -> dict:
class Builder:
"""Build EKO instances."""
- path: pathlib.Path
+ path: Path
"""Path on disk to ."""
access: AccessConfigs
"""Access related configurations."""
From 3e1c57f3c28f8bbba25ee3b0fac901a67fd06613 Mon Sep 17 00:00:00 2001
From: Alessandro Candido
Date: Wed, 16 Aug 2023 17:26:50 +0200
Subject: [PATCH 35/67] Add test for open loading
---
tests/eko/io/test_struct.py | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/tests/eko/io/test_struct.py b/tests/eko/io/test_struct.py
index b7ff9877b..399018ddd 100644
--- a/tests/eko/io/test_struct.py
+++ b/tests/eko/io/test_struct.py
@@ -28,7 +28,7 @@ def test_new_error(self, tmp_path: pathlib.Path, theory_card, operator_card):
for args in [(None, None), (theory_card, None), (None, operator_card)]:
with pytest.raises(RuntimeError, match="missing"):
with struct.EKO.create(tmp_path / "Blub2.tar") as builder:
- eko = builder.load_cards(*args).build()
+ _ = builder.load_cards(*args).build()
def test_load_error(self, tmp_path):
# try to read from a non-tar path
@@ -184,3 +184,16 @@ def test_context_operator(self, eko_factory: EKOFactory):
assert isinstance(op, struct.Operator)
assert eko.operators.cache[Target.from_ep(ep)] is None
+
+ def test_load_opened(self, tmp_path: pathlib.Path, eko_factory: EKOFactory):
+ """Test the loading of an already opened EKO."""
+ eko = eko_factory.get()
+ eko.close()
+ # drop from cache to avoid double close by the fixture
+ eko_factory.cache = None
+
+ assert eko.access.path is not None
+ read_closed = EKO.read(eko.access.path, dest=tmp_path)
+ read_opened = EKO.read(tmp_path, extract=False)
+
+ assert read_closed.metadata == read_opened.metadata
From 44e6a3867bc101e12abd1425970b9a9cbc987e84 Mon Sep 17 00:00:00 2001
From: Alessandro Candido
Date: Wed, 16 Aug 2023 17:27:02 +0200
Subject: [PATCH 36/67] Implement open loading
The struct methods have been rearranged, to avoid increasing too much
the complexity, in particular for no special purpose
---
src/eko/io/access.py | 2 +-
src/eko/io/metadata.py | 2 +-
src/eko/io/struct.py | 109 +++++++++++++++++++++--------------------
3 files changed, 59 insertions(+), 54 deletions(-)
diff --git a/src/eko/io/access.py b/src/eko/io/access.py
index b8dec50a8..5a4d631c0 100644
--- a/src/eko/io/access.py
+++ b/src/eko/io/access.py
@@ -43,7 +43,7 @@ class ClosedOperator(RuntimeError, exceptions.OutputError):
class AccessConfigs:
"""Configurations specified during opening of an EKO."""
- path: Path
+ path: Optional[Path]
"""The path to the permanent object."""
readonly: bool
"Read-only flag"
diff --git a/src/eko/io/metadata.py b/src/eko/io/metadata.py
index 415b2dfa5..857f03b25 100644
--- a/src/eko/io/metadata.py
+++ b/src/eko/io/metadata.py
@@ -40,7 +40,7 @@ class Metadata(DictLike):
"""
# tagging information
_path: Optional[pathlib.Path] = None
- """Path to temporary dir."""
+ """Path to the open dir."""
version: str = vmod.__version__
"""Library version used to create the corresponding file."""
data_version: int = vmod.__data_version__
diff --git a/src/eko/io/struct.py b/src/eko/io/struct.py
index 7acd6af5e..c2e1daba7 100644
--- a/src/eko/io/struct.py
+++ b/src/eko/io/struct.py
@@ -338,8 +338,8 @@ def deepcopy(self, path: Path):
new.close()
@staticmethod
- def load(tarpath: Path, dest: Path):
- """Load the content of archive in a target directory."""
+ def extract(tarpath: Path, dest: Path):
+ """Extract the content of archive in a target directory."""
try:
with tarfile.open(tarpath) as tar:
raw.safe_extractall(tar, dest)
@@ -347,73 +347,77 @@ def load(tarpath: Path, dest: Path):
raise exceptions.OutputNotTar(f"Not a valid tar archive: '{tarpath}'")
@classmethod
- def open(cls, path: Path, mode: str = "r"):
- """Open EKO object in the specified mode."""
- access = AccessConfigs(path, readonly=False, open=True)
- load = False
- if mode == "r":
- load = True
- access.readonly = True
- elif mode in "w":
- pass
- elif mode in "a":
- load = True
- else:
- raise ValueError(f"Unknown file mode: {mode}")
+ def load(cls, path: Path):
+ """Load the EKO from disk information.
- tmpdir = Path(tempfile.mkdtemp(prefix=TEMP_PREFIX))
- if load:
- cls.load(path, tmpdir)
- metadata = Metadata.load(tmpdir)
- opened = cls(
- **inventories(tmpdir, access),
- metadata=metadata,
- access=access,
- )
- opened.operators.sync()
- else:
- opened = Builder(path=tmpdir, access=access)
+ Note
+ ----
+ No archive path is assigned to the :cls:`EKO` object, setting its
+ :attr:`EKO.access.path` to `None`.
+ If you want to properly load from an archive, use the :meth:`read`
+ constructor.
+
+ """
+ access = AccessConfigs(None, readonly=True, open=True)
+
+ metadata = Metadata.load(path)
+ loaded = cls(
+ **inventories(path, access),
+ metadata=metadata,
+ access=access,
+ )
+ loaded.operators.sync()
- return opened
+ return loaded
@classmethod
- def read(cls, path: Path):
- """Read the content of an EKO.
+ def read(
+ cls,
+ path: Path,
+ extract: bool = True,
+ dest: Optional[Path] = None,
+ readonly: bool = False,
+ ):
+ """Load an existing EKO.
+
+ If the `extract` attribute is `True` the EKO is loaded from its archived
+ format. Otherwise, the `path` is interpreted as the location of an
+ already extracted folder.
- Type-safe alias for::
- EKO.open(... , "r")
"""
- eko = cls.open(path, "r")
- assert isinstance(eko, EKO)
- return eko
+ if extract:
+ dir_ = Path(tempfile.mkdtemp(prefix=TEMP_PREFIX)) if dest is None else dest
+ cls.extract(path, dir_)
+ else:
+ dir_ = path
- @classmethod
- def create(cls, path: Path):
- """Create a new EKO.
+ loaded = cls.load(dir_)
- Type-safe alias for::
+ loaded.access.readonly = readonly
+ if extract:
+ loaded.access.path = path
- EKO.open(... , "w")
+ return loaded
- """
- builder = cls.open(path, "w")
- assert isinstance(builder, Builder)
+ @classmethod
+ def create(cls, path: Path):
+ """Create a new EKO."""
+ access = AccessConfigs(path, readonly=False, open=True)
+ builder = Builder(
+ path=Path(tempfile.mkdtemp(prefix=TEMP_PREFIX)), access=access
+ )
return builder
@classmethod
- def edit(cls, path: Path):
+ def edit(cls, *args, **kwargs):
"""Read from and write on existing EKO.
- Type-safe alias for::
-
- EKO.open(... , "a")
+ Alias of `EKO.read(..., readonly=False)`, see :meth:`read`.
"""
- eko = cls.open(path, "a")
- assert isinstance(eko, EKO)
- return eko
+ return cls.read(*args, readonly=False, **kwargs)
def __enter__(self):
"""Allow EKO to be used in :obj:`with` statements."""
@@ -463,7 +467,8 @@ def __exit__(self, exc_type: type, _exc_value, _traceback):
if exc_type is not None:
return
- self.close()
+ if self.access.path is not None:
+ self.close()
@property
def raw(self) -> dict:
@@ -484,7 +489,7 @@ class Builder:
"""Build EKO instances."""
path: Path
- """Path on disk to ."""
+ """Path on disk to the EKO."""
access: AccessConfigs
"""Access related configurations."""
From cb58d8db1f0881b1444d9bc92d55b9927fb86e9c Mon Sep 17 00:00:00 2001
From: Alessandro Candido
Date: Wed, 16 Aug 2023 17:30:32 +0200
Subject: [PATCH 37/67] Switch read-only default
---
src/eko/io/struct.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/eko/io/struct.py b/src/eko/io/struct.py
index c2e1daba7..d9da4bc35 100644
--- a/src/eko/io/struct.py
+++ b/src/eko/io/struct.py
@@ -376,7 +376,7 @@ def read(
path: Path,
extract: bool = True,
dest: Optional[Path] = None,
- readonly: bool = False,
+ readonly: bool = True,
):
"""Load an existing EKO.
From 38c3d1b0ecb00b1345a483991aa66e68e4343e38 Mon Sep 17 00:00:00 2001
From: Alessandro Candido
Date: Wed, 16 Aug 2023 17:58:12 +0200
Subject: [PATCH 38/67] Remove outdated test
---
extras/matching/check-matching.py | 2 +-
tests/eko/io/test_struct.py | 2 --
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/extras/matching/check-matching.py b/extras/matching/check-matching.py
index e080883cb..f83cc714b 100644
--- a/extras/matching/check-matching.py
+++ b/extras/matching/check-matching.py
@@ -121,7 +121,7 @@ def collect_data():
data = {}
pdf = toy.mkPDF("", 0)
for id in th_updates.keys():
- with eko.EKO.open(f"./eko_{id}.tar") as evolution_operator:
+ with eko.EKO.read(f"./eko_{id}.tar") as evolution_operator:
x = evolution_operator.metadata.rotations.targetgrid.raw
data[id] = {
mu2: el["pdfs"]
diff --git a/tests/eko/io/test_struct.py b/tests/eko/io/test_struct.py
index 399018ddd..2c50aac6d 100644
--- a/tests/eko/io/test_struct.py
+++ b/tests/eko/io/test_struct.py
@@ -36,8 +36,6 @@ def test_load_error(self, tmp_path):
no_tar_path.write_text("Blub", encoding="utf-8")
with pytest.raises(ValueError, match="tar"):
struct.EKO.read(no_tar_path)
- with pytest.raises(ValueError, match="file mode"):
- struct.EKO.open(no_tar_path, "ü")
def test_properties(self, eko_factory: EKOFactory):
mu = 10.0
From 394bb9f17a74a7b1cad74f475483626a8947246f Mon Sep 17 00:00:00 2001
From: Alessandro Candido
Date: Thu, 17 Aug 2023 16:09:26 +0200
Subject: [PATCH 39/67] Inline extract in load
---
src/eko/io/struct.py | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/src/eko/io/struct.py b/src/eko/io/struct.py
index d9da4bc35..11a0d6a30 100644
--- a/src/eko/io/struct.py
+++ b/src/eko/io/struct.py
@@ -337,15 +337,6 @@ def deepcopy(self, path: Path):
shutil.copytree(self.paths.root, new.paths.root)
new.close()
- @staticmethod
- def extract(tarpath: Path, dest: Path):
- """Extract the content of archive in a target directory."""
- try:
- with tarfile.open(tarpath) as tar:
- raw.safe_extractall(tar, dest)
- except tarfile.ReadError:
- raise exceptions.OutputNotTar(f"Not a valid tar archive: '{tarpath}'")
-
@classmethod
def load(cls, path: Path):
"""Load the EKO from disk information.
@@ -389,7 +380,8 @@ def read(
"""
if extract:
dir_ = Path(tempfile.mkdtemp(prefix=TEMP_PREFIX)) if dest is None else dest
- cls.extract(path, dir_)
+ with tarfile.open(path) as tar:
+ raw.safe_extractall(tar, dir_)
else:
dir_ = path
From 7ecb58e78c63099ac252cbc3fee9faa90c2ffde4 Mon Sep 17 00:00:00 2001
From: Alessandro Candido
Date: Thu, 17 Aug 2023 16:23:55 +0200
Subject: [PATCH 40/67] Restrict parts public API
---
src/eko/runner/managed.py | 4 +---
src/eko/runner/parts.py | 23 +++++++++++++----------
2 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/src/eko/runner/managed.py b/src/eko/runner/managed.py
index b21882d92..aacd249cf 100644
--- a/src/eko/runner/managed.py
+++ b/src/eko/runner/managed.py
@@ -12,7 +12,7 @@
"""
from pathlib import Path
-from ..io.items import Evolution, Matching, Target
+from ..io.items import Target
from ..io.runcards import OperatorCard, TheoryCard
from ..io.struct import EKO
from . import operators, parts, recipes
@@ -27,12 +27,10 @@ def solve(theory: TheoryCard, operator: OperatorCard, path: Path):
recipes.create(eko)
for recipe in eko.recipes:
- assert isinstance(recipe, Evolution)
eko.parts[recipe] = parts.evolve(eko, recipe)
# flush the memory
del eko.parts[recipe]
for recipe in eko.recipes_matching:
- assert isinstance(recipe, Matching)
eko.parts_matching[recipe] = parts.match(eko, recipe)
# flush the memory
del eko.parts_matching[recipe]
diff --git a/src/eko/runner/parts.py b/src/eko/runner/parts.py
index e385b8f49..1ad5bda72 100644
--- a/src/eko/runner/parts.py
+++ b/src/eko/runner/parts.py
@@ -22,7 +22,7 @@
from . import commons
-def managers(eko: EKO) -> dict:
+def _managers(eko: EKO) -> dict:
"""Collect managers for operator computation.
.. todo::
@@ -39,7 +39,7 @@ def managers(eko: EKO) -> dict:
)
-def blowup_info(eko: EKO) -> dict:
+def _blowup_info(eko: EKO) -> dict:
"""Prepare common information to blow up to flavor basis.
Note
@@ -65,7 +65,7 @@ def blowup_info(eko: EKO) -> dict:
return dict(intrinsic_range=[4, 5, 6], qed=eko.theory_card.order[1] > 0)
-def evolve_configs(eko: EKO) -> dict:
+def _evolution_configs(eko: EKO) -> dict:
"""Create configs for :class:`Operator`.
.. todo::
@@ -94,11 +94,14 @@ def evolve_configs(eko: EKO) -> dict:
def evolve(eko: EKO, recipe: Evolution) -> Operator:
"""Compute evolution in isolation."""
op = evop.Operator(
- evolve_configs(eko), managers(eko), recipe.as_atlas, is_threshold=recipe.cliff
+ _evolution_configs(eko),
+ _managers(eko),
+ recipe.as_atlas,
+ is_threshold=recipe.cliff,
)
op.compute()
- binfo = blowup_info(eko)
+ binfo = _blowup_info(eko)
res, err = physical.PhysicalOperator.ad_to_evol_map(
op.op_members, op.nf, op.q2_to, **binfo
).to_flavor_basis_tensor(qed=binfo["qed"])
@@ -106,7 +109,7 @@ def evolve(eko: EKO, recipe: Evolution) -> Operator:
return Operator(res, err)
-def matching_configs(eko: EKO) -> dict:
+def _matching_configs(eko: EKO) -> dict:
"""Create configs for :class:`OperatorMatrixElement`.
.. todo::
@@ -117,7 +120,7 @@ def matching_configs(eko: EKO) -> dict:
tcard = eko.theory_card
ocard = eko.operator_card
return dict(
- **evolve_configs(eko),
+ **_evolution_configs(eko),
backward_inversion=ocard.configs.inversion_method,
intrinsic_range=tcard.heavy.intrinsic_flavors,
)
@@ -138,8 +141,8 @@ def match(eko: EKO, recipe: Matching) -> Operator:
"""
kthr = eko.theory_card.heavy.squared_ratios[recipe.hq - 4]
op = ome.OperatorMatrixElement(
- matching_configs(eko),
- managers(eko),
+ _matching_configs(eko),
+ _managers(eko),
recipe.hq - 1,
recipe.scale,
recipe.inverse,
@@ -148,7 +151,7 @@ def match(eko: EKO, recipe: Matching) -> Operator:
)
op.compute()
- binfo = blowup_info(eko)
+ binfo = _blowup_info(eko)
nf_match = op.nf - 1 if recipe.inverse else op.nf
res, err = matching_condition.MatchingCondition.split_ad_to_evol_map(
op.op_members, nf_match, recipe.scale, **binfo
From d5d952c4970e03fb8c1b194d06e3805170e0f308 Mon Sep 17 00:00:00 2001
From: Alessandro Candido
Date: Thu, 17 Aug 2023 16:41:27 +0200
Subject: [PATCH 41/67] Restrict operators public API
---
src/eko/runner/managed.py | 7 ++-----
src/eko/runner/operators.py | 31 +++++++++++++++++-------------
tests/eko/runner/test_operators.py | 6 +++---
3 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/src/eko/runner/managed.py b/src/eko/runner/managed.py
index aacd249cf..2c3d2c313 100644
--- a/src/eko/runner/managed.py
+++ b/src/eko/runner/managed.py
@@ -36,12 +36,9 @@ def solve(theory: TheoryCard, operator: OperatorCard, path: Path):
del eko.parts_matching[recipe]
for ep in operator.evolgrid:
- parts_ = operators.retrieve(
- operators.parts(ep, eko), eko.parts, eko.parts_matching
- )
+ components = operators.retrieve(ep, eko)
target = Target.from_ep(ep)
- eko.operators[target] = operators.join(parts_)
+ eko.operators[target] = operators.join(components)
# flush the memory
del eko.parts
- del eko.parts_matching
del eko.operators[target]
diff --git a/src/eko/runner/operators.py b/src/eko/runner/operators.py
index 2ccbd1013..702c6479c 100644
--- a/src/eko/runner/operators.py
+++ b/src/eko/runner/operators.py
@@ -12,7 +12,7 @@
from . import commons, recipes
-def retrieve(
+def _retrieve(
headers: List[Recipe], parts: Inventory, parts_matching: Inventory
) -> List[Operator]:
"""Retrieve parts to be joined."""
@@ -24,7 +24,18 @@ def retrieve(
return elements
-def dot4(op1: npt.NDArray, op2: npt.NDArray) -> npt.NDArray:
+def _parts(ep: EvolutionPoint, eko: EKO) -> List[Recipe]:
+ """Determine parts required for the given evolution point operator."""
+ atlas = commons.atlas(eko.theory_card, eko.operator_card)
+ return recipes._elements(ep, atlas)
+
+
+def retrieve(ep: EvolutionPoint, eko: EKO) -> List[Operator]:
+ """Retrieve parts required for the given evolution point operator."""
+ return _retrieve(_parts(ep, eko), eko.parts, eko.parts_matching)
+
+
+def _dot4(op1: npt.NDArray, op2: npt.NDArray) -> npt.NDArray:
"""Dot product between rank 4 objects.
The product is performed considering them as matrices indexed by pairs, so
@@ -34,10 +45,10 @@ def dot4(op1: npt.NDArray, op2: npt.NDArray) -> npt.NDArray:
return np.einsum("aibj,bjck->aick", op1, op2)
-def dotop(op1: Operator, op2: Operator) -> Operator:
+def _dotop(op1: Operator, op2: Operator) -> Operator:
r"""Dot product between two operators.
- Essentially a wrapper of :func:`dot4`, applying linear error propagation,
+ Essentially a wrapper of :func:`_dot4`, applying linear error propagation,
if applicable.
Note
@@ -67,10 +78,10 @@ def dotop(op1: Operator, op2: Operator) -> Operator:
|da_i| \cdot |b_i| + |a_i| \cdot |db_i| + \mathcal{O}(d^2)
"""
- val = dot4(op1.operator, op2.operator)
+ val = _dot4(op1.operator, op2.operator)
if op1.error is not None and op2.error is not None:
- err = dot4(np.abs(op1.operator), np.abs(op2.error)) + dot4(
+ err = _dot4(np.abs(op1.operator), np.abs(op2.error)) + _dot4(
np.abs(op1.error), np.abs(op2.operator)
)
else:
@@ -93,10 +104,4 @@ def join(elements: List[Operator]) -> Operator:
consider if reversing the path...
"""
- return reduce(dotop, reversed(elements))
-
-
-def parts(ep: EvolutionPoint, eko: EKO) -> List[Recipe]:
- """Determine parts required for the given evolution point operator."""
- atlas = commons.atlas(eko.theory_card, eko.operator_card)
- return recipes._elements(ep, atlas)
+ return reduce(_dotop, reversed(elements))
diff --git a/tests/eko/runner/test_operators.py b/tests/eko/runner/test_operators.py
index 8721fca99..77811cf3a 100644
--- a/tests/eko/runner/test_operators.py
+++ b/tests/eko/runner/test_operators.py
@@ -2,18 +2,18 @@
from eko.io.items import Operator
from eko.io.struct import EKO
-from eko.runner.operators import join, retrieve
+from eko.runner.operators import _retrieve, join
def test_retrieve(ekoparts: EKO):
evhead, evop = next(iter(ekoparts.parts.cache.items()))
matchhead, matchop = next(iter(ekoparts.parts_matching.cache.items()))
- els = retrieve([evhead] * 5, ekoparts.parts, ekoparts.parts_matching)
+ els = _retrieve([evhead] * 5, ekoparts.parts, ekoparts.parts_matching)
assert len(els) == 5
assert all(isinstance(el, Operator) for el in els)
- els = retrieve(
+ els = _retrieve(
[evhead, matchhead, matchhead], ekoparts.parts, ekoparts.parts_matching
)
assert len(els) == 3
From 6a74792e1dab57b11d8084b2c9ee4e6e32d3c632 Mon Sep 17 00:00:00 2001
From: Alessandro Candido
Date: Thu, 17 Aug 2023 16:49:43 +0200
Subject: [PATCH 42/67] Update error type in struct opening test
---
tests/eko/io/test_struct.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/eko/io/test_struct.py b/tests/eko/io/test_struct.py
index 2c50aac6d..1370ccdb6 100644
--- a/tests/eko/io/test_struct.py
+++ b/tests/eko/io/test_struct.py
@@ -34,7 +34,7 @@ def test_load_error(self, tmp_path):
# try to read from a non-tar path
no_tar_path = tmp_path / "Blub.tar"
no_tar_path.write_text("Blub", encoding="utf-8")
- with pytest.raises(ValueError, match="tar"):
+ with pytest.raises(tarfile.ReadError):
struct.EKO.read(no_tar_path)
def test_properties(self, eko_factory: EKOFactory):
From e8c218e0d5e7c7e90ecfd40d22f6f9d58bd2d142 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Thu, 17 Aug 2023 17:26:56 +0200
Subject: [PATCH 43/67] Drop new_op_key variable in grid
---
src/eko/evolution_operator/grid.py | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py
index 1180697a6..9c0c6c1df 100644
--- a/src/eko/evolution_operator/grid.py
+++ b/src/eko/evolution_operator/grid.py
@@ -127,7 +127,6 @@ def get_threshold_operators(self, path: List[Segment]) -> List[Operator]:
is_downward = is_downward_path(path)
shift = flavor_shift(is_downward)
for seg in path[:-1]:
- new_op_key = seg
kthr = self.config["thresholds_ratios"][seg.nf - shift]
ome = OperatorMatrixElement(
self.config,
@@ -138,13 +137,13 @@ def get_threshold_operators(self, path: List[Segment]) -> List[Operator]:
np.log(kthr),
self.config["HQ"] == "MSBAR",
)
- if new_op_key not in self._threshold_operators:
+ if seg not in self._threshold_operators:
# Compute the operator and store it
logger.info("Prepare threshold operator")
op_th = Operator(self.config, self.managers, seg, is_threshold=True)
op_th.compute()
- self._threshold_operators[new_op_key] = op_th
- thr_ops.append(self._threshold_operators[new_op_key])
+ self._threshold_operators[seg] = op_th
+ thr_ops.append(self._threshold_operators[seg])
# Compute the matching conditions and store it
if seg.target not in self._matching_operators:
From 54d9e53401476339afc34bafc0b6718ca523a6b2 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Thu, 17 Aug 2023 17:32:28 +0200
Subject: [PATCH 44/67] Define couplings cache key type
---
src/eko/couplings.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/eko/couplings.py b/src/eko/couplings.py
index 1b3620032..5cd35ef2b 100644
--- a/src/eko/couplings.py
+++ b/src/eko/couplings.py
@@ -381,6 +381,10 @@ def couplings_expanded_fixed_alphaem(order, couplings_ref, nf, scale_from, scale
return np.array([res_as, aem])
+_CouplingsCacheKey = Tuple[float, float, int, float, float]
+"""Cache key containing (a0, a1, nf, scale_from, scale_to)."""
+
+
class Couplings:
r"""Compute the strong and electromagnetic coupling constants :math:`a_s, a_{em}`.
@@ -475,7 +479,7 @@ def assert_positive(name, var):
self.decoupled_running,
)
# cache
- self.cache: Dict[Tuple[float, float, int, float, float], npt.NDArray] = {}
+ self.cache: Dict[_CouplingsCacheKey, npt.NDArray] = {}
@property
def mu2_ref(self):
From 9b0d8048b98a708a6616e482b2ac955f6475cd30 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Thu, 17 Aug 2023 17:38:56 +0200
Subject: [PATCH 45/67] Define label type in apply
---
src/ekobox/apply.py | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/ekobox/apply.py b/src/ekobox/apply.py
index ace0ccca1..97d1a0168 100644
--- a/src/ekobox/apply.py
+++ b/src/ekobox/apply.py
@@ -51,13 +51,16 @@ def apply_pdf(
CONTRACTION = "ajbk,bk"
+_PdfLabel = Union[int, str]
+"""PDF identifier: either PID or label."""
+
@dataclass
class PdfResult:
"""Helper class to collect PDF results."""
- pdfs: Dict[Union[int, str], float]
- errors: Optional[Dict[Union[int, str], float]] = None
+ pdfs: Dict[_PdfLabel, float]
+ errors: Optional[Dict[_PdfLabel, float]] = None
def apply_pdf_flavor(
From 3b576005797436986452c2cab91c726d0d009328 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Thu, 17 Aug 2023 17:46:05 +0200
Subject: [PATCH 46/67] Cast labels in evop/Operator
---
src/eko/evolution_operator/__init__.py | 4 ++--
src/eko/evolution_operator/operator_matrix_element.py | 8 ++++----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py
index fea8d15fe..6e008e322 100644
--- a/src/eko/evolution_operator/__init__.py
+++ b/src/eko/evolution_operator/__init__.py
@@ -607,8 +607,8 @@ class Operator(sv.ModeMixin):
log_label = "Evolution"
# complete list of possible evolution operators labels
- full_labels = list(br.full_labels)
- full_labels_qed = list(br.full_unified_labels)
+ full_labels: Tuple[Tuple[int, int], ...] = br.full_labels
+ full_labels_qed: Tuple[Tuple[int, int], ...] = br.full_unified_labels
def __init__(
self, config, managers, segment: Segment, mellin_cut=5e-2, is_threshold=False
diff --git a/src/eko/evolution_operator/operator_matrix_element.py b/src/eko/evolution_operator/operator_matrix_element.py
index 8966a62b9..deb763499 100644
--- a/src/eko/evolution_operator/operator_matrix_element.py
+++ b/src/eko/evolution_operator/operator_matrix_element.py
@@ -3,7 +3,7 @@
import copy
import functools
import logging
-from typing import List, Tuple
+from typing import Tuple
import numba as nb
import numpy as np
@@ -196,7 +196,7 @@ class OperatorMatrixElement(Operator):
log_label = "Matching"
# complete list of possible matching operators labels
- full_labels = [
+ full_labels = (
*br.singlet_labels,
(br.matching_hplus_pid, 21),
(br.matching_hplus_pid, 100),
@@ -207,9 +207,9 @@ class OperatorMatrixElement(Operator):
(200, br.matching_hminus_pid),
(br.matching_hminus_pid, 200),
(br.matching_hminus_pid, br.matching_hminus_pid),
- ]
+ )
# still valid in QED since Sdelta and Vdelta matchings are diagonal
- full_labels_qed: List[Tuple[int, int]] = copy.deepcopy(full_labels)
+ full_labels_qed: Tuple[Tuple[int, int], ...] = copy.deepcopy(full_labels)
def __init__(self, config, managers, nf, q2, is_backward, L, is_msbar):
super().__init__(config, managers, Segment(q2, q2, nf))
From bbe955c54302f2ad3ee80cd65dec8bae2c4ccb78 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Thu, 17 Aug 2023 17:49:57 +0200
Subject: [PATCH 47/67] Update src/eko/runner/operators.py
Co-authored-by: Alessandro Candido
---
src/eko/runner/operators.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/eko/runner/operators.py b/src/eko/runner/operators.py
index bfc4ce407..19f53c243 100644
--- a/src/eko/runner/operators.py
+++ b/src/eko/runner/operators.py
@@ -17,7 +17,7 @@ def retrieve(
for head in headers:
inv = parts if isinstance(head, Evolution) else parts_matching
op = inv[head]
- assert isinstance(op, Operator)
+ assert op is not None
elements.append(op)
return elements
From 16e38092e5eeb42d43348bb07c1d3417e7747a14 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Thu, 17 Aug 2023 17:56:01 +0200
Subject: [PATCH 48/67] Introduce OperatorLabel type
---
src/eko/evolution_operator/__init__.py | 8 +++++---
src/eko/evolution_operator/operator_matrix_element.py | 3 +--
src/eko/io/types.py | 8 ++++----
3 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py
index 6e008e322..3681f0663 100644
--- a/src/eko/evolution_operator/__init__.py
+++ b/src/eko/evolution_operator/__init__.py
@@ -21,6 +21,7 @@
from .. import basis_rotation as br
from .. import interpolation, mellin
from .. import scale_variations as sv
+from ..io.types import OperatorLabel
from ..kernels import non_singlet as ns
from ..kernels import non_singlet_qed as qed_ns
from ..kernels import singlet as s
@@ -579,7 +580,8 @@ def quad_ker_qed(
return ker
-OpMembers = Dict[Tuple[int, int], OpMember]
+OpMembers = Dict[OperatorLabel, OpMember]
+"""Map of all operators."""
class Operator(sv.ModeMixin):
@@ -607,8 +609,8 @@ class Operator(sv.ModeMixin):
log_label = "Evolution"
# complete list of possible evolution operators labels
- full_labels: Tuple[Tuple[int, int], ...] = br.full_labels
- full_labels_qed: Tuple[Tuple[int, int], ...] = br.full_unified_labels
+ full_labels: Tuple[OperatorLabel, ...] = br.full_labels
+ full_labels_qed: Tuple[OperatorLabel, ...] = br.full_unified_labels
def __init__(
self, config, managers, segment: Segment, mellin_cut=5e-2, is_threshold=False
diff --git a/src/eko/evolution_operator/operator_matrix_element.py b/src/eko/evolution_operator/operator_matrix_element.py
index deb763499..7a5a3ce6c 100644
--- a/src/eko/evolution_operator/operator_matrix_element.py
+++ b/src/eko/evolution_operator/operator_matrix_element.py
@@ -3,7 +3,6 @@
import copy
import functools
import logging
-from typing import Tuple
import numba as nb
import numpy as np
@@ -209,7 +208,7 @@ class OperatorMatrixElement(Operator):
(br.matching_hminus_pid, br.matching_hminus_pid),
)
# still valid in QED since Sdelta and Vdelta matchings are diagonal
- full_labels_qed: Tuple[Tuple[int, int], ...] = copy.deepcopy(full_labels)
+ full_labels_qed = copy.deepcopy(full_labels)
def __init__(self, config, managers, nf, q2, is_backward, L, is_msbar):
super().__init__(config, managers, Segment(q2, q2, nf))
diff --git a/src/eko/io/types.py b/src/eko/io/types.py
index 5573bafbb..dc8c490c4 100644
--- a/src/eko/io/types.py
+++ b/src/eko/io/types.py
@@ -1,7 +1,6 @@
"""Common type definitions, only used for static analysis."""
import enum
-import typing
-from typing import Any, Dict, Generic, Tuple, TypeVar
+from typing import Any, Dict, Generic, List, Tuple, TypeVar
# Energy scales
# -------------
@@ -22,8 +21,9 @@
Order = Tuple[int, int]
FlavorsNumber = int
FlavorIndex = int
-IntrinsicFlavors = typing.List[FlavorIndex]
-N3LOAdVariation = typing.Tuple[int, int, int, int]
+IntrinsicFlavors = List[FlavorIndex]
+N3LOAdVariation = Tuple[int, int, int, int]
+OperatorLabel = Tuple[int, int]
# Evolution coordinates
# ---------------------
From c9cdc72dfc37932fda2ad91d8f17129cc2a4b3b1 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Thu, 17 Aug 2023 17:58:08 +0200
Subject: [PATCH 49/67] Remove list comprension in msbar
---
src/eko/msbar_masses.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/eko/msbar_masses.py b/src/eko/msbar_masses.py
index f13582110..ca4fd6731 100644
--- a/src/eko/msbar_masses.py
+++ b/src/eko/msbar_masses.py
@@ -395,7 +395,7 @@ def sc(thr_masses):
heavy_quarks = quark_names[3:]
hq_idxs = np.arange(0, 3)
if nf_ref > 4:
- heavy_quarks = "".join([e for e in reversed(heavy_quarks)])
+ heavy_quarks = "".join(reversed(heavy_quarks))
hq_idxs = reversed(hq_idxs)
# loop on heavy quarks and compute the msbar masses
From c946b3f21745c060aa29109c101ad090daa3a5c8 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Thu, 17 Aug 2023 18:25:27 +0200
Subject: [PATCH 50/67] Upgrade banana
---
poetry.lock | 1525 ++++++++++++++++++++++++++----------------------
pyproject.toml | 2 +-
2 files changed, 813 insertions(+), 714 deletions(-)
diff --git a/poetry.lock b/poetry.lock
index 53d012a61..9d5f9c818 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -38,14 +38,14 @@ files = [
[[package]]
name = "astroid"
-version = "2.15.5"
+version = "2.15.6"
description = "An abstract syntax tree for Python with inference support."
category = "dev"
optional = false
python-versions = ">=3.7.2"
files = [
- {file = "astroid-2.15.5-py3-none-any.whl", hash = "sha256:078e5212f9885fa85fbb0cf0101978a336190aadea6e13305409d099f71b2324"},
- {file = "astroid-2.15.5.tar.gz", hash = "sha256:1039262575027b441137ab4a62a793a9b43defb42c32d5670f38686207cd780f"},
+ {file = "astroid-2.15.6-py3-none-any.whl", hash = "sha256:389656ca57b6108f939cf5d2f9a2a825a3be50ba9d589670f393236e0a03b91c"},
+ {file = "astroid-2.15.6.tar.gz", hash = "sha256:903f024859b7c7687d7a7f3a3f73b17301f8e42dfd9cc9df9d4418172d3e2dbd"},
]
[package.dependencies]
@@ -139,14 +139,14 @@ files = [
[[package]]
name = "banana-hep"
-version = "0.6.9"
+version = "0.6.10"
description = "Benchmark QCD physics"
category = "main"
optional = true
python-versions = ">=3.8.0,<3.12"
files = [
- {file = "banana_hep-0.6.9-py3-none-any.whl", hash = "sha256:e857b777eb0f64b0bf5e0a2b7cc6afcb5680a60dc3bdd7ce9c34c4bf3b94828b"},
- {file = "banana_hep-0.6.9.tar.gz", hash = "sha256:0b9f5cd3e4e44d5c8117bab93c832784009feb6d87d5a874da0d47fc91ab0514"},
+ {file = "banana_hep-0.6.10-py3-none-any.whl", hash = "sha256:e50fcfad55220a9f14b3b3d056f5ba893e1ee2579f875a6786a0273e73f8b3f7"},
+ {file = "banana_hep-0.6.10.tar.gz", hash = "sha256:48c584bcb169de4769241ee34f5a067f9f719aaa64f512d3b9251bbe90e80002"},
]
[package.dependencies]
@@ -201,14 +201,14 @@ css = ["tinycss2 (>=1.1.0,<1.2)"]
[[package]]
name = "certifi"
-version = "2023.5.7"
+version = "2023.7.22"
description = "Python package for providing Mozilla's CA Bundle."
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
- {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"},
- {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"},
+ {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"},
+ {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"},
]
[[package]]
@@ -290,99 +290,99 @@ pycparser = "*"
[[package]]
name = "charset-normalizer"
-version = "3.1.0"
+version = "3.2.0"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "dev"
optional = false
python-versions = ">=3.7.0"
files = [
- {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"},
- {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"},
+ {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"},
+ {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"},
]
[[package]]
name = "click"
-version = "8.1.3"
+version = "8.1.6"
description = "Composable command line interface toolkit"
category = "main"
optional = true
python-versions = ">=3.7"
files = [
- {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
- {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
+ {file = "click-8.1.6-py3-none-any.whl", hash = "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"},
+ {file = "click-8.1.6.tar.gz", hash = "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd"},
]
[package.dependencies]
@@ -402,18 +402,18 @@ files = [
[[package]]
name = "comm"
-version = "0.1.3"
+version = "0.1.4"
description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc."
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
- {file = "comm-0.1.3-py3-none-any.whl", hash = "sha256:16613c6211e20223f215fc6d3b266a247b6e2641bf4e0a3ad34cb1aff2aa3f37"},
- {file = "comm-0.1.3.tar.gz", hash = "sha256:a61efa9daffcfbe66fd643ba966f846a624e4e6d6767eda9cf6e993aadaab93e"},
+ {file = "comm-0.1.4-py3-none-any.whl", hash = "sha256:6d52794cba11b36ed9860999cd10fd02d6b2eac177068fdd585e1e2f8a96e67a"},
+ {file = "comm-0.1.4.tar.gz", hash = "sha256:354e40a59c9dd6db50c5cc6b4acc887d82e9603787f83b68c01a80a923984d15"},
]
[package.dependencies]
-traitlets = ">=5.3"
+traitlets = ">=4"
[package.extras]
lint = ["black (>=22.6.0)", "mdformat (>0.7)", "mdformat-gfm (>=0.3.5)", "ruff (>=0.0.156)"]
@@ -496,72 +496,64 @@ test-no-images = ["pytest", "pytest-cov", "wurlitzer"]
[[package]]
name = "coverage"
-version = "7.2.7"
+version = "7.3.0"
description = "Code coverage measurement for Python"
category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"},
- {file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"},
- {file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"},
- {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"},
- {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"},
- {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"},
- {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"},
- {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"},
- {file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"},
- {file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"},
- {file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"},
- {file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"},
- {file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"},
- {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"},
- {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"},
- {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"},
- {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"},
- {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"},
- {file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"},
- {file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"},
- {file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"},
- {file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"},
- {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"},
- {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"},
- {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"},
- {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"},
- {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"},
- {file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"},
- {file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"},
- {file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"},
- {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"},
- {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"},
- {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"},
- {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"},
- {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"},
- {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"},
- {file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"},
- {file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"},
- {file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"},
- {file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"},
- {file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"},
- {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"},
- {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"},
- {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"},
- {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"},
- {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"},
- {file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"},
- {file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"},
- {file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"},
- {file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"},
- {file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"},
- {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"},
- {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"},
- {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"},
- {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"},
- {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"},
- {file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"},
- {file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"},
- {file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"},
- {file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"},
+ {file = "coverage-7.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db76a1bcb51f02b2007adacbed4c88b6dee75342c37b05d1822815eed19edee5"},
+ {file = "coverage-7.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c02cfa6c36144ab334d556989406837336c1d05215a9bdf44c0bc1d1ac1cb637"},
+ {file = "coverage-7.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:477c9430ad5d1b80b07f3c12f7120eef40bfbf849e9e7859e53b9c93b922d2af"},
+ {file = "coverage-7.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce2ee86ca75f9f96072295c5ebb4ef2a43cecf2870b0ca5e7a1cbdd929cf67e1"},
+ {file = "coverage-7.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68d8a0426b49c053013e631c0cdc09b952d857efa8f68121746b339912d27a12"},
+ {file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3eb0c93e2ea6445b2173da48cb548364f8f65bf68f3d090404080d338e3a689"},
+ {file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:90b6e2f0f66750c5a1178ffa9370dec6c508a8ca5265c42fbad3ccac210a7977"},
+ {file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:96d7d761aea65b291a98c84e1250cd57b5b51726821a6f2f8df65db89363be51"},
+ {file = "coverage-7.3.0-cp310-cp310-win32.whl", hash = "sha256:63c5b8ecbc3b3d5eb3a9d873dec60afc0cd5ff9d9f1c75981d8c31cfe4df8527"},
+ {file = "coverage-7.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:97c44f4ee13bce914272589b6b41165bbb650e48fdb7bd5493a38bde8de730a1"},
+ {file = "coverage-7.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:74c160285f2dfe0acf0f72d425f3e970b21b6de04157fc65adc9fd07ee44177f"},
+ {file = "coverage-7.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b543302a3707245d454fc49b8ecd2c2d5982b50eb63f3535244fd79a4be0c99d"},
+ {file = "coverage-7.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad0f87826c4ebd3ef484502e79b39614e9c03a5d1510cfb623f4a4a051edc6fd"},
+ {file = "coverage-7.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:13c6cbbd5f31211d8fdb477f0f7b03438591bdd077054076eec362cf2207b4a7"},
+ {file = "coverage-7.3.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fac440c43e9b479d1241fe9d768645e7ccec3fb65dc3a5f6e90675e75c3f3e3a"},
+ {file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3c9834d5e3df9d2aba0275c9f67989c590e05732439b3318fa37a725dff51e74"},
+ {file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4c8e31cf29b60859876474034a83f59a14381af50cbe8a9dbaadbf70adc4b214"},
+ {file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7a9baf8e230f9621f8e1d00c580394a0aa328fdac0df2b3f8384387c44083c0f"},
+ {file = "coverage-7.3.0-cp311-cp311-win32.whl", hash = "sha256:ccc51713b5581e12f93ccb9c5e39e8b5d4b16776d584c0f5e9e4e63381356482"},
+ {file = "coverage-7.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:887665f00ea4e488501ba755a0e3c2cfd6278e846ada3185f42d391ef95e7e70"},
+ {file = "coverage-7.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d000a739f9feed900381605a12a61f7aaced6beae832719ae0d15058a1e81c1b"},
+ {file = "coverage-7.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:59777652e245bb1e300e620ce2bef0d341945842e4eb888c23a7f1d9e143c446"},
+ {file = "coverage-7.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9737bc49a9255d78da085fa04f628a310c2332b187cd49b958b0e494c125071"},
+ {file = "coverage-7.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5247bab12f84a1d608213b96b8af0cbb30d090d705b6663ad794c2f2a5e5b9fe"},
+ {file = "coverage-7.3.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2ac9a1de294773b9fa77447ab7e529cf4fe3910f6a0832816e5f3d538cfea9a"},
+ {file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:85b7335c22455ec12444cec0d600533a238d6439d8d709d545158c1208483873"},
+ {file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:36ce5d43a072a036f287029a55b5c6a0e9bd73db58961a273b6dc11a2c6eb9c2"},
+ {file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:211a4576e984f96d9fce61766ffaed0115d5dab1419e4f63d6992b480c2bd60b"},
+ {file = "coverage-7.3.0-cp312-cp312-win32.whl", hash = "sha256:56afbf41fa4a7b27f6635bc4289050ac3ab7951b8a821bca46f5b024500e6321"},
+ {file = "coverage-7.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f297e0c1ae55300ff688568b04ff26b01c13dfbf4c9d2b7d0cb688ac60df479"},
+ {file = "coverage-7.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac0dec90e7de0087d3d95fa0533e1d2d722dcc008bc7b60e1143402a04c117c1"},
+ {file = "coverage-7.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:438856d3f8f1e27f8e79b5410ae56650732a0dcfa94e756df88c7e2d24851fcd"},
+ {file = "coverage-7.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1084393c6bda8875c05e04fce5cfe1301a425f758eb012f010eab586f1f3905e"},
+ {file = "coverage-7.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49ab200acf891e3dde19e5aa4b0f35d12d8b4bd805dc0be8792270c71bd56c54"},
+ {file = "coverage-7.3.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a67e6bbe756ed458646e1ef2b0778591ed4d1fcd4b146fc3ba2feb1a7afd4254"},
+ {file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8f39c49faf5344af36042b293ce05c0d9004270d811c7080610b3e713251c9b0"},
+ {file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7df91fb24c2edaabec4e0eee512ff3bc6ec20eb8dccac2e77001c1fe516c0c84"},
+ {file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:34f9f0763d5fa3035a315b69b428fe9c34d4fc2f615262d6be3d3bf3882fb985"},
+ {file = "coverage-7.3.0-cp38-cp38-win32.whl", hash = "sha256:bac329371d4c0d456e8d5f38a9b0816b446581b5f278474e416ea0c68c47dcd9"},
+ {file = "coverage-7.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:b859128a093f135b556b4765658d5d2e758e1fae3e7cc2f8c10f26fe7005e543"},
+ {file = "coverage-7.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fc0ed8d310afe013db1eedd37176d0839dc66c96bcfcce8f6607a73ffea2d6ba"},
+ {file = "coverage-7.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61260ec93f99f2c2d93d264b564ba912bec502f679793c56f678ba5251f0393"},
+ {file = "coverage-7.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97af9554a799bd7c58c0179cc8dbf14aa7ab50e1fd5fa73f90b9b7215874ba28"},
+ {file = "coverage-7.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3558e5b574d62f9c46b76120a5c7c16c4612dc2644c3d48a9f4064a705eaee95"},
+ {file = "coverage-7.3.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37d5576d35fcb765fca05654f66aa71e2808d4237d026e64ac8b397ffa66a56a"},
+ {file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:07ea61bcb179f8f05ffd804d2732b09d23a1238642bf7e51dad62082b5019b34"},
+ {file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:80501d1b2270d7e8daf1b64b895745c3e234289e00d5f0e30923e706f110334e"},
+ {file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4eddd3153d02204f22aef0825409091a91bf2a20bce06fe0f638f5c19a85de54"},
+ {file = "coverage-7.3.0-cp39-cp39-win32.whl", hash = "sha256:2d22172f938455c156e9af2612650f26cceea47dc86ca048fa4e0b2d21646ad3"},
+ {file = "coverage-7.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:60f64e2007c9144375dd0f480a54d6070f00bb1a28f65c408370544091c9bc9e"},
+ {file = "coverage-7.3.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:5492a6ce3bdb15c6ad66cb68a0244854d9917478877a25671d70378bdc8562d0"},
+ {file = "coverage-7.3.0.tar.gz", hash = "sha256:49dbb19cdcafc130f597d9e04a29d0a032ceedf729e41b181f51cd170e6ee865"},
]
[package.dependencies]
@@ -584,30 +576,30 @@ files = [
[[package]]
name = "debugpy"
-version = "1.6.7"
+version = "1.6.7.post1"
description = "An implementation of the Debug Adapter Protocol for Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "debugpy-1.6.7-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b3e7ac809b991006ad7f857f016fa92014445085711ef111fdc3f74f66144096"},
- {file = "debugpy-1.6.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3876611d114a18aafef6383695dfc3f1217c98a9168c1aaf1a02b01ec7d8d1e"},
- {file = "debugpy-1.6.7-cp310-cp310-win32.whl", hash = "sha256:33edb4afa85c098c24cc361d72ba7c21bb92f501104514d4ffec1fb36e09c01a"},
- {file = "debugpy-1.6.7-cp310-cp310-win_amd64.whl", hash = "sha256:ed6d5413474e209ba50b1a75b2d9eecf64d41e6e4501977991cdc755dc83ab0f"},
- {file = "debugpy-1.6.7-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:38ed626353e7c63f4b11efad659be04c23de2b0d15efff77b60e4740ea685d07"},
- {file = "debugpy-1.6.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279d64c408c60431c8ee832dfd9ace7c396984fd7341fa3116aee414e7dcd88d"},
- {file = "debugpy-1.6.7-cp37-cp37m-win32.whl", hash = "sha256:dbe04e7568aa69361a5b4c47b4493d5680bfa3a911d1e105fbea1b1f23f3eb45"},
- {file = "debugpy-1.6.7-cp37-cp37m-win_amd64.whl", hash = "sha256:f90a2d4ad9a035cee7331c06a4cf2245e38bd7c89554fe3b616d90ab8aab89cc"},
- {file = "debugpy-1.6.7-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:5224eabbbeddcf1943d4e2821876f3e5d7d383f27390b82da5d9558fd4eb30a9"},
- {file = "debugpy-1.6.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae1123dff5bfe548ba1683eb972329ba6d646c3a80e6b4c06cd1b1dd0205e9b"},
- {file = "debugpy-1.6.7-cp38-cp38-win32.whl", hash = "sha256:9cd10cf338e0907fdcf9eac9087faa30f150ef5445af5a545d307055141dd7a4"},
- {file = "debugpy-1.6.7-cp38-cp38-win_amd64.whl", hash = "sha256:aaf6da50377ff4056c8ed470da24632b42e4087bc826845daad7af211e00faad"},
- {file = "debugpy-1.6.7-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:0679b7e1e3523bd7d7869447ec67b59728675aadfc038550a63a362b63029d2c"},
- {file = "debugpy-1.6.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de86029696e1b3b4d0d49076b9eba606c226e33ae312a57a46dca14ff370894d"},
- {file = "debugpy-1.6.7-cp39-cp39-win32.whl", hash = "sha256:d71b31117779d9a90b745720c0eab54ae1da76d5b38c8026c654f4a066b0130a"},
- {file = "debugpy-1.6.7-cp39-cp39-win_amd64.whl", hash = "sha256:c0ff93ae90a03b06d85b2c529eca51ab15457868a377c4cc40a23ab0e4e552a3"},
- {file = "debugpy-1.6.7-py2.py3-none-any.whl", hash = "sha256:53f7a456bc50706a0eaabecf2d3ce44c4d5010e46dfc65b6b81a518b42866267"},
- {file = "debugpy-1.6.7.zip", hash = "sha256:c4c2f0810fa25323abfdfa36cbbbb24e5c3b1a42cb762782de64439c575d67f2"},
+ {file = "debugpy-1.6.7.post1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:903bd61d5eb433b6c25b48eae5e23821d4c1a19e25c9610205f5aeaccae64e32"},
+ {file = "debugpy-1.6.7.post1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d16882030860081e7dd5aa619f30dec3c2f9a421e69861125f83cc372c94e57d"},
+ {file = "debugpy-1.6.7.post1-cp310-cp310-win32.whl", hash = "sha256:eea8d8cfb9965ac41b99a61f8e755a8f50e9a20330938ad8271530210f54e09c"},
+ {file = "debugpy-1.6.7.post1-cp310-cp310-win_amd64.whl", hash = "sha256:85969d864c45f70c3996067cfa76a319bae749b04171f2cdeceebe4add316155"},
+ {file = "debugpy-1.6.7.post1-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:890f7ab9a683886a0f185786ffbda3b46495c4b929dab083b8c79d6825832a52"},
+ {file = "debugpy-1.6.7.post1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4ac7a4dba28801d184b7fc0e024da2635ca87d8b0a825c6087bb5168e3c0d28"},
+ {file = "debugpy-1.6.7.post1-cp37-cp37m-win32.whl", hash = "sha256:3370ef1b9951d15799ef7af41f8174194f3482ee689988379763ef61a5456426"},
+ {file = "debugpy-1.6.7.post1-cp37-cp37m-win_amd64.whl", hash = "sha256:65b28435a17cba4c09e739621173ff90c515f7b9e8ea469b92e3c28ef8e5cdfb"},
+ {file = "debugpy-1.6.7.post1-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:92b6dae8bfbd497c90596bbb69089acf7954164aea3228a99d7e43e5267f5b36"},
+ {file = "debugpy-1.6.7.post1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72f5d2ecead8125cf669e62784ef1e6300f4067b0f14d9f95ee00ae06fc7c4f7"},
+ {file = "debugpy-1.6.7.post1-cp38-cp38-win32.whl", hash = "sha256:f0851403030f3975d6e2eaa4abf73232ab90b98f041e3c09ba33be2beda43fcf"},
+ {file = "debugpy-1.6.7.post1-cp38-cp38-win_amd64.whl", hash = "sha256:3de5d0f97c425dc49bce4293df6a04494309eedadd2b52c22e58d95107e178d9"},
+ {file = "debugpy-1.6.7.post1-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:38651c3639a4e8bbf0ca7e52d799f6abd07d622a193c406be375da4d510d968d"},
+ {file = "debugpy-1.6.7.post1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:038c51268367c9c935905a90b1c2d2dbfe304037c27ba9d19fe7409f8cdc710c"},
+ {file = "debugpy-1.6.7.post1-cp39-cp39-win32.whl", hash = "sha256:4b9eba71c290852f959d2cf8a03af28afd3ca639ad374d393d53d367f7f685b2"},
+ {file = "debugpy-1.6.7.post1-cp39-cp39-win_amd64.whl", hash = "sha256:973a97ed3b434eab0f792719a484566c35328196540676685c975651266fccf9"},
+ {file = "debugpy-1.6.7.post1-py2.py3-none-any.whl", hash = "sha256:1093a5c541af079c13ac8c70ab8b24d1d35c8cacb676306cf11e57f699c02926"},
+ {file = "debugpy-1.6.7.post1.zip", hash = "sha256:fe87ec0182ef624855d05e6ed7e0b7cb1359d2ffa2a925f8ec2d22e98b75d0ca"},
]
[[package]]
@@ -655,14 +647,14 @@ pygments = ["pygments (>=2.2.0)"]
[[package]]
name = "dill"
-version = "0.3.6"
-description = "serialize all of python"
+version = "0.3.7"
+description = "serialize all of Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"},
- {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"},
+ {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"},
+ {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"},
]
[package.extras]
@@ -670,14 +662,14 @@ graph = ["objgraph (>=1.7.2)"]
[[package]]
name = "distlib"
-version = "0.3.6"
+version = "0.3.7"
description = "Distribution utilities"
category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"},
- {file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"},
+ {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"},
+ {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"},
]
[[package]]
@@ -694,14 +686,14 @@ files = [
[[package]]
name = "exceptiongroup"
-version = "1.1.1"
+version = "1.1.3"
description = "Backport of PEP 654 (exception groups)"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"},
- {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"},
+ {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"},
+ {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"},
]
[package.extras]
@@ -740,14 +732,14 @@ pyrepl = ">=0.8.2"
[[package]]
name = "fastjsonschema"
-version = "2.17.1"
+version = "2.18.0"
description = "Fastest Python implementation of JSON schema"
category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "fastjsonschema-2.17.1-py3-none-any.whl", hash = "sha256:4b90b252628ca695280924d863fe37234eebadc29c5360d322571233dc9746e0"},
- {file = "fastjsonschema-2.17.1.tar.gz", hash = "sha256:f4eeb8a77cef54861dbf7424ac8ce71306f12cbb086c45131bcba2c6a4f726e3"},
+ {file = "fastjsonschema-2.18.0-py3-none-any.whl", hash = "sha256:128039912a11a807068a7c87d0da36660afbfd7202780db26c4aa7153cfdc799"},
+ {file = "fastjsonschema-2.18.0.tar.gz", hash = "sha256:e820349dd16f806e4bd1467a138dced9def4bc7d6213a34295272a6cac95b5bd"},
]
[package.extras]
@@ -771,46 +763,46 @@ testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "p
[[package]]
name = "fonttools"
-version = "4.40.0"
+version = "4.42.0"
description = "Tools to manipulate font files"
category = "main"
optional = true
python-versions = ">=3.8"
files = [
- {file = "fonttools-4.40.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b802dcbf9bcff74672f292b2466f6589ab8736ce4dcf36f48eb994c2847c4b30"},
- {file = "fonttools-4.40.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f6e3fa3da923063c286320e728ba2270e49c73386e3a711aa680f4b0747d692"},
- {file = "fonttools-4.40.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fdf60f8a5c6bcce7d024a33f7e4bc7921f5b74e8ea13bccd204f2c8b86f3470"},
- {file = "fonttools-4.40.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91784e21a1a085fac07c6a407564f4a77feb471b5954c9ee55a4f9165151f6c1"},
- {file = "fonttools-4.40.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:05171f3c546f64d78569f10adc0de72561882352cac39ec7439af12304d8d8c0"},
- {file = "fonttools-4.40.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7449e5e306f3a930a8944c85d0cbc8429cba13503372a1a40f23124d6fb09b58"},
- {file = "fonttools-4.40.0-cp310-cp310-win32.whl", hash = "sha256:bae8c13abbc2511e9a855d2142c0ab01178dd66b1a665798f357da0d06253e0d"},
- {file = "fonttools-4.40.0-cp310-cp310-win_amd64.whl", hash = "sha256:425b74a608427499b0e45e433c34ddc350820b6f25b7c8761963a08145157a66"},
- {file = "fonttools-4.40.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:00ab569b2a3e591e00425023ade87e8fef90380c1dde61be7691cb524ca5f743"},
- {file = "fonttools-4.40.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:18ea64ac43e94c9e0c23d7a9475f1026be0e25b10dda8f236fc956188761df97"},
- {file = "fonttools-4.40.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:022c4a16b412293e7f1ce21b8bab7a6f9d12c4ffdf171fdc67122baddb973069"},
- {file = "fonttools-4.40.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:530c5d35109f3e0cea2535742d6a3bc99c0786cf0cbd7bb2dc9212387f0d908c"},
- {file = "fonttools-4.40.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5e00334c66f4e83535384cb5339526d01d02d77f142c23b2f97bd6a4f585497a"},
- {file = "fonttools-4.40.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb52c10fda31159c22c7ed85074e05f8b97da8773ea461706c273e31bcbea836"},
- {file = "fonttools-4.40.0-cp311-cp311-win32.whl", hash = "sha256:6a8d71b9a5c884c72741868e845c0e563c5d83dcaf10bb0ceeec3b4b2eb14c67"},
- {file = "fonttools-4.40.0-cp311-cp311-win_amd64.whl", hash = "sha256:15abb3d055c1b2dff9ce376b6c3db10777cb74b37b52b78f61657634fd348a0d"},
- {file = "fonttools-4.40.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14037c31138fbd21847ad5e5441dfdde003e0a8f3feb5812a1a21fd1c255ffbd"},
- {file = "fonttools-4.40.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:94c915f6716589f78bc00fbc14c5b8de65cfd11ee335d32504f1ef234524cb24"},
- {file = "fonttools-4.40.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37467cee0f32cada2ec08bc16c9c31f9b53ea54b2f5604bf25a1246b5f50593a"},
- {file = "fonttools-4.40.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56d4d85f5374b45b08d2f928517d1e313ea71b4847240398decd0ab3ebbca885"},
- {file = "fonttools-4.40.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8c4305b171b61040b1ee75d18f9baafe58bd3b798d1670078efe2c92436bfb63"},
- {file = "fonttools-4.40.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a954b90d1473c85a22ecf305761d9fd89da93bbd31dae86e7dea436ad2cb5dc9"},
- {file = "fonttools-4.40.0-cp38-cp38-win32.whl", hash = "sha256:1bc4c5b147be8dbc5df9cc8ac5e93ee914ad030fe2a201cc8f02f499db71011d"},
- {file = "fonttools-4.40.0-cp38-cp38-win_amd64.whl", hash = "sha256:8a917828dbfdb1cbe50cf40eeae6fbf9c41aef9e535649ed8f4982b2ef65c091"},
- {file = "fonttools-4.40.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:882983279bf39afe4e945109772c2ffad2be2c90983d6559af8b75c19845a80a"},
- {file = "fonttools-4.40.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c55f1b4109dbc3aeb496677b3e636d55ef46dc078c2a5e3f3db4e90f1c6d2907"},
- {file = "fonttools-4.40.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec468c022d09f1817c691cf884feb1030ef6f1e93e3ea6831b0d8144c06480d1"},
- {file = "fonttools-4.40.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d5adf4ba114f028fc3f5317a221fd8b0f4ef7a2e5524a2b1e0fd891b093791a"},
- {file = "fonttools-4.40.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aa83b3f151bc63970f39b2b42a06097c5a22fd7ed9f7ba008e618de4503d3895"},
- {file = "fonttools-4.40.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97d95b8301b62bdece1af943b88bcb3680fd385f88346a4a899ee145913b414a"},
- {file = "fonttools-4.40.0-cp39-cp39-win32.whl", hash = "sha256:1a003608400dd1cca3e089e8c94973c6b51a4fb1ef00ff6d7641617b9242e637"},
- {file = "fonttools-4.40.0-cp39-cp39-win_amd64.whl", hash = "sha256:7961575221e3da0841c75da53833272c520000d76f7f71274dbf43370f8a1065"},
- {file = "fonttools-4.40.0-py3-none-any.whl", hash = "sha256:200729d12461e2038700d31f0d49ad5a7b55855dec7525074979a06b46f88505"},
- {file = "fonttools-4.40.0.tar.gz", hash = "sha256:337b6e83d7ee73c40ea62407f2ce03b07c3459e213b6f332b94a69923b9e1cb9"},
+ {file = "fonttools-4.42.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9c456d1f23deff64ffc8b5b098718e149279abdea4d8692dba69172fb6a0d597"},
+ {file = "fonttools-4.42.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:150122ed93127a26bc3670ebab7e2add1e0983d30927733aec327ebf4255b072"},
+ {file = "fonttools-4.42.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48e82d776d2e93f88ca56567509d102266e7ab2fb707a0326f032fe657335238"},
+ {file = "fonttools-4.42.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58c1165f9b2662645de9b19a8c8bdd636b36294ccc07e1b0163856b74f10bafc"},
+ {file = "fonttools-4.42.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2d6dc3fa91414ff4daa195c05f946e6a575bd214821e26d17ca50f74b35b0fe4"},
+ {file = "fonttools-4.42.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fae4e801b774cc62cecf4a57b1eae4097903fced00c608d9e2bc8f84cd87b54a"},
+ {file = "fonttools-4.42.0-cp310-cp310-win32.whl", hash = "sha256:b8600ae7dce6ec3ddfb201abb98c9d53abbf8064d7ac0c8a0d8925e722ccf2a0"},
+ {file = "fonttools-4.42.0-cp310-cp310-win_amd64.whl", hash = "sha256:57b68eab183fafac7cd7d464a7bfa0fcd4edf6c67837d14fb09c1c20516cf20b"},
+ {file = "fonttools-4.42.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0a1466713e54bdbf5521f2f73eebfe727a528905ff5ec63cda40961b4b1eea95"},
+ {file = "fonttools-4.42.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3fb2a69870bfe143ec20b039a1c8009e149dd7780dd89554cc8a11f79e5de86b"},
+ {file = "fonttools-4.42.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae881e484702efdb6cf756462622de81d4414c454edfd950b137e9a7352b3cb9"},
+ {file = "fonttools-4.42.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27ec3246a088555629f9f0902f7412220c67340553ca91eb540cf247aacb1983"},
+ {file = "fonttools-4.42.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8ece1886d12bb36c48c00b2031518877f41abae317e3a55620d38e307d799b7e"},
+ {file = "fonttools-4.42.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:10dac980f2b975ef74532e2a94bb00e97a95b4595fb7f98db493c474d5f54d0e"},
+ {file = "fonttools-4.42.0-cp311-cp311-win32.whl", hash = "sha256:83b98be5d291e08501bd4fc0c4e0f8e6e05b99f3924068b17c5c9972af6fff84"},
+ {file = "fonttools-4.42.0-cp311-cp311-win_amd64.whl", hash = "sha256:e35bed436726194c5e6e094fdfb423fb7afaa0211199f9d245e59e11118c576c"},
+ {file = "fonttools-4.42.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c36c904ce0322df01e590ba814d5d69e084e985d7e4c2869378671d79662a7d4"},
+ {file = "fonttools-4.42.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d54e600a2bcfa5cdaa860237765c01804a03b08404d6affcd92942fa7315ffba"},
+ {file = "fonttools-4.42.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01cfe02416b6d416c5c8d15e30315cbcd3e97d1b50d3b34b0ce59f742ef55258"},
+ {file = "fonttools-4.42.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f81ed9065b4bd3f4f3ce8e4873cd6a6b3f4e92b1eddefde35d332c6f414acc3"},
+ {file = "fonttools-4.42.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:685a4dd6cf31593b50d6d441feb7781a4a7ef61e19551463e14ed7c527b86f9f"},
+ {file = "fonttools-4.42.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:329341ba3d86a36e482610db56b30705384cb23bd595eac8cbb045f627778e9d"},
+ {file = "fonttools-4.42.0-cp38-cp38-win32.whl", hash = "sha256:4655c480a1a4d706152ff54f20e20cf7609084016f1df3851cce67cef768f40a"},
+ {file = "fonttools-4.42.0-cp38-cp38-win_amd64.whl", hash = "sha256:6bd7e4777bff1dcb7c4eff4786998422770f3bfbef8be401c5332895517ba3fa"},
+ {file = "fonttools-4.42.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a9b55d2a3b360e0c7fc5bd8badf1503ca1c11dd3a1cd20f2c26787ffa145a9c7"},
+ {file = "fonttools-4.42.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0df8ef75ba5791e873c9eac2262196497525e3f07699a2576d3ab9ddf41cb619"},
+ {file = "fonttools-4.42.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd2363ea7728496827658682d049ffb2e98525e2247ca64554864a8cc945568"},
+ {file = "fonttools-4.42.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d40673b2e927f7cd0819c6f04489dfbeb337b4a7b10fc633c89bf4f34ecb9620"},
+ {file = "fonttools-4.42.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c8bf88f9e3ce347c716921804ef3a8330cb128284eb6c0b6c4b3574f3c580023"},
+ {file = "fonttools-4.42.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:703101eb0490fae32baf385385d47787b73d9ea55253df43b487c89ec767e0d7"},
+ {file = "fonttools-4.42.0-cp39-cp39-win32.whl", hash = "sha256:f0290ea7f9945174bd4dfd66e96149037441eb2008f3649094f056201d99e293"},
+ {file = "fonttools-4.42.0-cp39-cp39-win_amd64.whl", hash = "sha256:ae7df0ae9ee2f3f7676b0ff6f4ebe48ad0acaeeeaa0b6839d15dbf0709f2c5ef"},
+ {file = "fonttools-4.42.0-py3-none-any.whl", hash = "sha256:dfe7fa7e607f7e8b58d0c32501a3a7cac148538300626d1b930082c90ae7f6bd"},
+ {file = "fonttools-4.42.0.tar.gz", hash = "sha256:614b1283dca88effd20ee48160518e6de275ce9b5456a3134d5f235523fc5065"},
]
[package.extras]
@@ -927,14 +919,14 @@ files = [
[[package]]
name = "importlib-metadata"
-version = "6.6.0"
+version = "6.8.0"
description = "Read metadata from Python packages"
category = "main"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
- {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
+ {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"},
+ {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"},
]
[package.dependencies]
@@ -943,26 +935,26 @@ zipp = ">=0.5"
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
perf = ["ipython"]
-testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
+testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"]
[[package]]
name = "importlib-resources"
-version = "5.12.0"
+version = "6.0.1"
description = "Read resources from Python packages"
category = "main"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "importlib_resources-5.12.0-py3-none-any.whl", hash = "sha256:7b1deeebbf351c7578e09bf2f63fa2ce8b5ffec296e0d349139d43cca061a81a"},
- {file = "importlib_resources-5.12.0.tar.gz", hash = "sha256:4be82589bf5c1d7999aedf2a45159d10cb3ca4f19b2271f8792bc8e6da7b22f6"},
+ {file = "importlib_resources-6.0.1-py3-none-any.whl", hash = "sha256:134832a506243891221b88b4ae1213327eea96ceb4e407a00d790bb0626f45cf"},
+ {file = "importlib_resources-6.0.1.tar.gz", hash = "sha256:4359457e42708462b9626a04657c6208ad799ceb41e5c58c57ffa0e6a098a5d4"},
]
[package.dependencies]
zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""}
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
[[package]]
name = "iniconfig"
@@ -978,14 +970,14 @@ files = [
[[package]]
name = "ipykernel"
-version = "6.23.2"
+version = "6.25.1"
description = "IPython Kernel for Jupyter"
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
- {file = "ipykernel-6.23.2-py3-none-any.whl", hash = "sha256:7ccb6e2d32fd958c21453db494c914f3474908a2fdefd99ab548a5375b548d1f"},
- {file = "ipykernel-6.23.2.tar.gz", hash = "sha256:fcfb67c5b504aa1bfcda1c5b3716636239e0f7b9290958f1c558c79b4c0e7ed5"},
+ {file = "ipykernel-6.25.1-py3-none-any.whl", hash = "sha256:c8a2430b357073b37c76c21c52184db42f6b4b0e438e1eb7df3c4440d120497c"},
+ {file = "ipykernel-6.25.1.tar.gz", hash = "sha256:050391364c0977e768e354bdb60cbbfbee7cbb943b1af1618382021136ffd42f"},
]
[package.dependencies]
@@ -1070,22 +1062,22 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"]
[[package]]
name = "jedi"
-version = "0.18.2"
+version = "0.19.0"
description = "An autocompletion tool for Python that can be used for text editors."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
- {file = "jedi-0.18.2-py2.py3-none-any.whl", hash = "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e"},
- {file = "jedi-0.18.2.tar.gz", hash = "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612"},
+ {file = "jedi-0.19.0-py2.py3-none-any.whl", hash = "sha256:cb8ce23fbccff0025e9386b5cf85e892f94c9b822378f8da49970471335ac64e"},
+ {file = "jedi-0.19.0.tar.gz", hash = "sha256:bcf9894f1753969cbac8022a8c2eaee06bfa3724e4192470aaffe7eb6272b0c4"},
]
[package.dependencies]
-parso = ">=0.8.0,<0.9.0"
+parso = ">=0.8.3,<0.9.0"
[package.extras]
docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"]
-qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
+qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"]
testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
[[package]]
@@ -1108,36 +1100,54 @@ i18n = ["Babel (>=2.7)"]
[[package]]
name = "jsonschema"
-version = "4.17.3"
+version = "4.19.0"
description = "An implementation of JSON Schema validation for Python"
category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"},
- {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"},
+ {file = "jsonschema-4.19.0-py3-none-any.whl", hash = "sha256:043dc26a3845ff09d20e4420d6012a9c91c9aa8999fa184e7efcfeccb41e32cb"},
+ {file = "jsonschema-4.19.0.tar.gz", hash = "sha256:6e1e7569ac13be8139b2dd2c21a55d350066ee3f80df06c608b398cdc6f30e8f"},
]
[package.dependencies]
-attrs = ">=17.4.0"
+attrs = ">=22.2.0"
importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""}
+jsonschema-specifications = ">=2023.03.6"
pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""}
-pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2"
+referencing = ">=0.28.4"
+rpds-py = ">=0.7.1"
[package.extras]
format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"]
format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"]
+[[package]]
+name = "jsonschema-specifications"
+version = "2023.7.1"
+description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry"
+category = "dev"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "jsonschema_specifications-2023.7.1-py3-none-any.whl", hash = "sha256:05adf340b659828a004220a9613be00fa3f223f2b82002e273dee62fd50524b1"},
+ {file = "jsonschema_specifications-2023.7.1.tar.gz", hash = "sha256:c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb"},
+]
+
+[package.dependencies]
+importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""}
+referencing = ">=0.28.0"
+
[[package]]
name = "jupyter-client"
-version = "8.2.0"
+version = "8.3.0"
description = "Jupyter protocol implementation and client libraries"
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
- {file = "jupyter_client-8.2.0-py3-none-any.whl", hash = "sha256:b18219aa695d39e2ad570533e0d71fb7881d35a873051054a84ee2a17c4b7389"},
- {file = "jupyter_client-8.2.0.tar.gz", hash = "sha256:9fe233834edd0e6c0aa5f05ca2ab4bdea1842bfd2d8a932878212fc5301ddaf0"},
+ {file = "jupyter_client-8.3.0-py3-none-any.whl", hash = "sha256:7441af0c0672edc5d28035e92ba5e32fadcfa8a4e608a434c228836a89df6158"},
+ {file = "jupyter_client-8.3.0.tar.gz", hash = "sha256:3af69921fe99617be1670399a0b857ad67275eefcfa291e2c81a160b7b650f5f"},
]
[package.dependencies]
@@ -1326,36 +1336,36 @@ files = [
[[package]]
name = "llvmlite"
-version = "0.40.0"
+version = "0.40.1"
description = "lightweight wrapper around basic LLVM functionality"
category = "main"
optional = false
python-versions = ">=3.8"
files = [
- {file = "llvmlite-0.40.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90a46db1ed219d93ef05245ec17cf243074ec2b2687209cb310a803a2c2510dc"},
- {file = "llvmlite-0.40.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b9d742b66023298532d0e7beddd3d9f04334c046df7a02a1ec2ba8b4046a978c"},
- {file = "llvmlite-0.40.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ff38c309dc758b996d556e599e00647e6b8dbd21125c06b2d0584a9984a2288"},
- {file = "llvmlite-0.40.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ecb8cdee35bbbdad9b331f446641977645de1973f6270bf4194307a1753666"},
- {file = "llvmlite-0.40.0-cp310-cp310-win32.whl", hash = "sha256:83dd5148f6ddd4d35585b69ebaa50605fdf8011a5b7259a0463afd4aefc62414"},
- {file = "llvmlite-0.40.0-cp310-cp310-win_amd64.whl", hash = "sha256:f72d6ccbfd9cc7da43098fcef23ffbe173ce2d986215072dbb2e7929412f9ff8"},
- {file = "llvmlite-0.40.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bbf19077144e159406ef222348d5330d5061177fb79d3f7f82abf2cf29b77c0b"},
- {file = "llvmlite-0.40.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a4732d6c981f658f014dd2ab2b682ac631cd12a6695e77c2d460cc68dc767868"},
- {file = "llvmlite-0.40.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2754c4d2b6f027ab45425abd94dee4cbd228b598531b1e9e1fc15f3298265d88"},
- {file = "llvmlite-0.40.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb79b992bdc2e62c5f5f86263d5546b5298d498e7c1a9d64b3a6f0d31f46ba5b"},
- {file = "llvmlite-0.40.0-cp311-cp311-win_amd64.whl", hash = "sha256:be0ff5b68a86e47a7ec6cd5389bb17b4b8f020b981628c9e714dc2cfdbe89c86"},
- {file = "llvmlite-0.40.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f5d4445eccd9c9c5639b35cb6279231f97cbd77a1c49fb41c05081ff96e041db"},
- {file = "llvmlite-0.40.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:060f00611d8e65d6db80cabba17fbefde9ebefbfb6937fe5677f06cd3e7bbe3c"},
- {file = "llvmlite-0.40.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58f5ba5febb2372418a3d37bd76d51bb987276a6fd979c2f2772b60b9061e575"},
- {file = "llvmlite-0.40.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d1622237e6ce543ac185751f782c7e10cabe45abf2de802cd5dca8023805a5c"},
- {file = "llvmlite-0.40.0-cp38-cp38-win32.whl", hash = "sha256:06803a1a38f911576bbe63a4082334d6661c59f2080e4681de1c66ec4924b0ac"},
- {file = "llvmlite-0.40.0-cp38-cp38-win_amd64.whl", hash = "sha256:87c2114567f95c715ae35b03d82caa0df66a978c93a1ff752964949e9ce596d5"},
- {file = "llvmlite-0.40.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a3382d81fcda57f5502f45a9ca62e0c9103fabd5f817c9820c7e61b9375f3d7"},
- {file = "llvmlite-0.40.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:260b0241c17a1ec585020e1df58ed30b9975c3573c619fa1724ceb4cd53cbe42"},
- {file = "llvmlite-0.40.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f980992b6c9dfee20a1608c5a4d875f8a52d76353ca02470550a85be6e5d3680"},
- {file = "llvmlite-0.40.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52eee9e245ef6eb911d6c2a3a1a66378745a40c637284386031b0915754f457e"},
- {file = "llvmlite-0.40.0-cp39-cp39-win32.whl", hash = "sha256:d27c2ec699b820296659dfd36ead1c527eb190c6d5cb3de24bfbee1024bdc20a"},
- {file = "llvmlite-0.40.0-cp39-cp39-win_amd64.whl", hash = "sha256:6cf84141d1793c69285b88acf4216370cb831eab99778546a2a9002fadac932d"},
- {file = "llvmlite-0.40.0.tar.gz", hash = "sha256:c910b8fbfd67b8e9d0b10ebc012b23cd67cbecef1b96f00d391ddd298d71671c"},
+ {file = "llvmlite-0.40.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:84ce9b1c7a59936382ffde7871978cddcda14098e5a76d961e204523e5c372fb"},
+ {file = "llvmlite-0.40.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3673c53cb21c65d2ff3704962b5958e967c6fc0bd0cff772998face199e8d87b"},
+ {file = "llvmlite-0.40.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bba2747cf5b4954e945c287fe310b3fcc484e2a9d1b0c273e99eb17d103bb0e6"},
+ {file = "llvmlite-0.40.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbd5e82cc990e5a3e343a3bf855c26fdfe3bfae55225f00efd01c05bbda79918"},
+ {file = "llvmlite-0.40.1-cp310-cp310-win32.whl", hash = "sha256:09f83ea7a54509c285f905d968184bba00fc31ebf12f2b6b1494d677bb7dde9b"},
+ {file = "llvmlite-0.40.1-cp310-cp310-win_amd64.whl", hash = "sha256:7b37297f3cbd68d14a97223a30620589d98ad1890e5040c9e5fc181063f4ed49"},
+ {file = "llvmlite-0.40.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a66a5bd580951751b4268f4c3bddcef92682814d6bc72f3cd3bb67f335dd7097"},
+ {file = "llvmlite-0.40.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:467b43836b388eaedc5a106d76761e388dbc4674b2f2237bc477c6895b15a634"},
+ {file = "llvmlite-0.40.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c23edd196bd797dc3a7860799054ea3488d2824ecabc03f9135110c2e39fcbc"},
+ {file = "llvmlite-0.40.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a36d9f244b6680cb90bbca66b146dabb2972f4180c64415c96f7c8a2d8b60a36"},
+ {file = "llvmlite-0.40.1-cp311-cp311-win_amd64.whl", hash = "sha256:5b3076dc4e9c107d16dc15ecb7f2faf94f7736cd2d5e9f4dc06287fd672452c1"},
+ {file = "llvmlite-0.40.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4a7525db121f2e699809b539b5308228854ccab6693ecb01b52c44a2f5647e20"},
+ {file = "llvmlite-0.40.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:84747289775d0874e506f907a4513db889471607db19b04de97d144047fec885"},
+ {file = "llvmlite-0.40.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e35766e42acef0fe7d1c43169a8ffc327a47808fae6a067b049fe0e9bbf84dd5"},
+ {file = "llvmlite-0.40.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cda71de10a1f48416309e408ea83dab5bf36058f83e13b86a2961defed265568"},
+ {file = "llvmlite-0.40.1-cp38-cp38-win32.whl", hash = "sha256:96707ebad8b051bbb4fc40c65ef93b7eeee16643bd4d579a14d11578e4b7a647"},
+ {file = "llvmlite-0.40.1-cp38-cp38-win_amd64.whl", hash = "sha256:e44f854dc11559795bcdeaf12303759e56213d42dabbf91a5897aa2d8b033810"},
+ {file = "llvmlite-0.40.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f643d15aacd0b0b0dc8b74b693822ba3f9a53fa63bc6a178c2dba7cc88f42144"},
+ {file = "llvmlite-0.40.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:39a0b4d0088c01a469a5860d2e2d7a9b4e6a93c0f07eb26e71a9a872a8cadf8d"},
+ {file = "llvmlite-0.40.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9329b930d699699846623054121ed105fd0823ed2180906d3b3235d361645490"},
+ {file = "llvmlite-0.40.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2dbbb8424037ca287983b115a29adf37d806baf7e1bf4a67bd2cffb74e085ed"},
+ {file = "llvmlite-0.40.1-cp39-cp39-win32.whl", hash = "sha256:e74e7bec3235a1e1c9ad97d897a620c5007d0ed80c32c84c1d787e7daa17e4ec"},
+ {file = "llvmlite-0.40.1-cp39-cp39-win_amd64.whl", hash = "sha256:ff8f31111bb99d135ff296757dc81ab36c2dee54ed4bd429158a96da9807c316"},
+ {file = "llvmlite-0.40.1.tar.gz", hash = "sha256:5cdb0d45df602099d833d50bd9e81353a5e036242d3c003c5b294fc61d1986b4"},
]
[[package]]
@@ -1470,53 +1480,53 @@ files = [
[[package]]
name = "matplotlib"
-version = "3.7.1"
+version = "3.7.2"
description = "Python plotting package"
category = "main"
optional = true
python-versions = ">=3.8"
files = [
- {file = "matplotlib-3.7.1-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:95cbc13c1fc6844ab8812a525bbc237fa1470863ff3dace7352e910519e194b1"},
- {file = "matplotlib-3.7.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:08308bae9e91aca1ec6fd6dda66237eef9f6294ddb17f0d0b3c863169bf82353"},
- {file = "matplotlib-3.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:544764ba51900da4639c0f983b323d288f94f65f4024dc40ecb1542d74dc0500"},
- {file = "matplotlib-3.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56d94989191de3fcc4e002f93f7f1be5da476385dde410ddafbb70686acf00ea"},
- {file = "matplotlib-3.7.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99bc9e65901bb9a7ce5e7bb24af03675cbd7c70b30ac670aa263240635999a4"},
- {file = "matplotlib-3.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb7d248c34a341cd4c31a06fd34d64306624c8cd8d0def7abb08792a5abfd556"},
- {file = "matplotlib-3.7.1-cp310-cp310-win32.whl", hash = "sha256:ce463ce590f3825b52e9fe5c19a3c6a69fd7675a39d589e8b5fbe772272b3a24"},
- {file = "matplotlib-3.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:3d7bc90727351fb841e4d8ae620d2d86d8ed92b50473cd2b42ce9186104ecbba"},
- {file = "matplotlib-3.7.1-cp311-cp311-macosx_10_12_universal2.whl", hash = "sha256:770a205966d641627fd5cf9d3cb4b6280a716522cd36b8b284a8eb1581310f61"},
- {file = "matplotlib-3.7.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f67bfdb83a8232cb7a92b869f9355d677bce24485c460b19d01970b64b2ed476"},
- {file = "matplotlib-3.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2bf092f9210e105f414a043b92af583c98f50050559616930d884387d0772aba"},
- {file = "matplotlib-3.7.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89768d84187f31717349c6bfadc0e0d8c321e8eb34522acec8a67b1236a66332"},
- {file = "matplotlib-3.7.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83111e6388dec67822e2534e13b243cc644c7494a4bb60584edbff91585a83c6"},
- {file = "matplotlib-3.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a867bf73a7eb808ef2afbca03bcdb785dae09595fbe550e1bab0cd023eba3de0"},
- {file = "matplotlib-3.7.1-cp311-cp311-win32.whl", hash = "sha256:fbdeeb58c0cf0595efe89c05c224e0a502d1aa6a8696e68a73c3efc6bc354304"},
- {file = "matplotlib-3.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:c0bd19c72ae53e6ab979f0ac6a3fafceb02d2ecafa023c5cca47acd934d10be7"},
- {file = "matplotlib-3.7.1-cp38-cp38-macosx_10_12_universal2.whl", hash = "sha256:6eb88d87cb2c49af00d3bbc33a003f89fd9f78d318848da029383bfc08ecfbfb"},
- {file = "matplotlib-3.7.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:cf0e4f727534b7b1457898c4f4ae838af1ef87c359b76dcd5330fa31893a3ac7"},
- {file = "matplotlib-3.7.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:46a561d23b91f30bccfd25429c3c706afe7d73a5cc64ef2dfaf2b2ac47c1a5dc"},
- {file = "matplotlib-3.7.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8704726d33e9aa8a6d5215044b8d00804561971163563e6e6591f9dcf64340cc"},
- {file = "matplotlib-3.7.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4cf327e98ecf08fcbb82685acaf1939d3338548620ab8dfa02828706402c34de"},
- {file = "matplotlib-3.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:617f14ae9d53292ece33f45cba8503494ee199a75b44de7717964f70637a36aa"},
- {file = "matplotlib-3.7.1-cp38-cp38-win32.whl", hash = "sha256:7c9a4b2da6fac77bcc41b1ea95fadb314e92508bf5493ceff058e727e7ecf5b0"},
- {file = "matplotlib-3.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:14645aad967684e92fc349493fa10c08a6da514b3d03a5931a1bac26e6792bd1"},
- {file = "matplotlib-3.7.1-cp39-cp39-macosx_10_12_universal2.whl", hash = "sha256:81a6b377ea444336538638d31fdb39af6be1a043ca5e343fe18d0f17e098770b"},
- {file = "matplotlib-3.7.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:28506a03bd7f3fe59cd3cd4ceb2a8d8a2b1db41afede01f66c42561b9be7b4b7"},
- {file = "matplotlib-3.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8c587963b85ce41e0a8af53b9b2de8dddbf5ece4c34553f7bd9d066148dc719c"},
- {file = "matplotlib-3.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8bf26ade3ff0f27668989d98c8435ce9327d24cffb7f07d24ef609e33d582439"},
- {file = "matplotlib-3.7.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:def58098f96a05f90af7e92fd127d21a287068202aa43b2a93476170ebd99e87"},
- {file = "matplotlib-3.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f883a22a56a84dba3b588696a2b8a1ab0d2c3d41be53264115c71b0a942d8fdb"},
- {file = "matplotlib-3.7.1-cp39-cp39-win32.whl", hash = "sha256:4f99e1b234c30c1e9714610eb0c6d2f11809c9c78c984a613ae539ea2ad2eb4b"},
- {file = "matplotlib-3.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:3ba2af245e36990facf67fde840a760128ddd71210b2ab6406e640188d69d136"},
- {file = "matplotlib-3.7.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3032884084f541163f295db8a6536e0abb0db464008fadca6c98aaf84ccf4717"},
- {file = "matplotlib-3.7.1-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a2cb34336110e0ed8bb4f650e817eed61fa064acbefeb3591f1b33e3a84fd96"},
- {file = "matplotlib-3.7.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b867e2f952ed592237a1828f027d332d8ee219ad722345b79a001f49df0936eb"},
- {file = "matplotlib-3.7.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:57bfb8c8ea253be947ccb2bc2d1bb3862c2bccc662ad1b4626e1f5e004557042"},
- {file = "matplotlib-3.7.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:438196cdf5dc8d39b50a45cb6e3f6274edbcf2254f85fa9b895bf85851c3a613"},
- {file = "matplotlib-3.7.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:21e9cff1a58d42e74d01153360de92b326708fb205250150018a52c70f43c290"},
- {file = "matplotlib-3.7.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75d4725d70b7c03e082bbb8a34639ede17f333d7247f56caceb3801cb6ff703d"},
- {file = "matplotlib-3.7.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:97cc368a7268141afb5690760921765ed34867ffb9655dd325ed207af85c7529"},
- {file = "matplotlib-3.7.1.tar.gz", hash = "sha256:7b73305f25eab4541bd7ee0b96d87e53ae9c9f1823be5659b806cd85786fe882"},
+ {file = "matplotlib-3.7.2-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:2699f7e73a76d4c110f4f25be9d2496d6ab4f17345307738557d345f099e07de"},
+ {file = "matplotlib-3.7.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a8035ba590658bae7562786c9cc6ea1a84aa49d3afab157e414c9e2ea74f496d"},
+ {file = "matplotlib-3.7.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2f8e4a49493add46ad4a8c92f63e19d548b2b6ebbed75c6b4c7f46f57d36cdd1"},
+ {file = "matplotlib-3.7.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71667eb2ccca4c3537d9414b1bc00554cb7f91527c17ee4ec38027201f8f1603"},
+ {file = "matplotlib-3.7.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:152ee0b569a37630d8628534c628456b28686e085d51394da6b71ef84c4da201"},
+ {file = "matplotlib-3.7.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:070f8dddd1f5939e60aacb8fa08f19551f4b0140fab16a3669d5cd6e9cb28fc8"},
+ {file = "matplotlib-3.7.2-cp310-cp310-win32.whl", hash = "sha256:fdbb46fad4fb47443b5b8ac76904b2e7a66556844f33370861b4788db0f8816a"},
+ {file = "matplotlib-3.7.2-cp310-cp310-win_amd64.whl", hash = "sha256:23fb1750934e5f0128f9423db27c474aa32534cec21f7b2153262b066a581fd1"},
+ {file = "matplotlib-3.7.2-cp311-cp311-macosx_10_12_universal2.whl", hash = "sha256:30e1409b857aa8a747c5d4f85f63a79e479835f8dffc52992ac1f3f25837b544"},
+ {file = "matplotlib-3.7.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:50e0a55ec74bf2d7a0ebf50ac580a209582c2dd0f7ab51bc270f1b4a0027454e"},
+ {file = "matplotlib-3.7.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ac60daa1dc83e8821eed155796b0f7888b6b916cf61d620a4ddd8200ac70cd64"},
+ {file = "matplotlib-3.7.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:305e3da477dc8607336ba10bac96986d6308d614706cae2efe7d3ffa60465b24"},
+ {file = "matplotlib-3.7.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c308b255efb9b06b23874236ec0f10f026673ad6515f602027cc8ac7805352d"},
+ {file = "matplotlib-3.7.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60c521e21031632aa0d87ca5ba0c1c05f3daacadb34c093585a0be6780f698e4"},
+ {file = "matplotlib-3.7.2-cp311-cp311-win32.whl", hash = "sha256:26bede320d77e469fdf1bde212de0ec889169b04f7f1179b8930d66f82b30cbc"},
+ {file = "matplotlib-3.7.2-cp311-cp311-win_amd64.whl", hash = "sha256:af4860132c8c05261a5f5f8467f1b269bf1c7c23902d75f2be57c4a7f2394b3e"},
+ {file = "matplotlib-3.7.2-cp38-cp38-macosx_10_12_universal2.whl", hash = "sha256:a1733b8e84e7e40a9853e505fe68cc54339f97273bdfe6f3ed980095f769ddc7"},
+ {file = "matplotlib-3.7.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d9881356dc48e58910c53af82b57183879129fa30492be69058c5b0d9fddf391"},
+ {file = "matplotlib-3.7.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f081c03f413f59390a80b3e351cc2b2ea0205839714dbc364519bcf51f4b56ca"},
+ {file = "matplotlib-3.7.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1cd120fca3407a225168238b790bd5c528f0fafde6172b140a2f3ab7a4ea63e9"},
+ {file = "matplotlib-3.7.2-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a2c1590b90aa7bd741b54c62b78de05d4186271e34e2377e0289d943b3522273"},
+ {file = "matplotlib-3.7.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d2ff3c984b8a569bc1383cd468fc06b70d7b59d5c2854ca39f1436ae8394117"},
+ {file = "matplotlib-3.7.2-cp38-cp38-win32.whl", hash = "sha256:5dea00b62d28654b71ca92463656d80646675628d0828e08a5f3b57e12869e13"},
+ {file = "matplotlib-3.7.2-cp38-cp38-win_amd64.whl", hash = "sha256:0f506a1776ee94f9e131af1ac6efa6e5bc7cb606a3e389b0ccb6e657f60bb676"},
+ {file = "matplotlib-3.7.2-cp39-cp39-macosx_10_12_universal2.whl", hash = "sha256:6515e878f91894c2e4340d81f0911857998ccaf04dbc1bba781e3d89cbf70608"},
+ {file = "matplotlib-3.7.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:71f7a8c6b124e904db550f5b9fe483d28b896d4135e45c4ea381ad3b8a0e3256"},
+ {file = "matplotlib-3.7.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:12f01b92ecd518e0697da4d97d163b2b3aa55eb3eb4e2c98235b3396d7dad55f"},
+ {file = "matplotlib-3.7.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7e28d6396563955f7af437894a36bf2b279462239a41028323e04b85179058b"},
+ {file = "matplotlib-3.7.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbcf59334ff645e6a67cd5f78b4b2cdb76384cdf587fa0d2dc85f634a72e1a3e"},
+ {file = "matplotlib-3.7.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:318c89edde72ff95d8df67d82aca03861240512994a597a435a1011ba18dbc7f"},
+ {file = "matplotlib-3.7.2-cp39-cp39-win32.whl", hash = "sha256:ce55289d5659b5b12b3db4dc9b7075b70cef5631e56530f14b2945e8836f2d20"},
+ {file = "matplotlib-3.7.2-cp39-cp39-win_amd64.whl", hash = "sha256:2ecb5be2b2815431c81dc115667e33da0f5a1bcf6143980d180d09a717c4a12e"},
+ {file = "matplotlib-3.7.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:fdcd28360dbb6203fb5219b1a5658df226ac9bebc2542a9e8f457de959d713d0"},
+ {file = "matplotlib-3.7.2-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c3cca3e842b11b55b52c6fb8bd6a4088693829acbfcdb3e815fa9b7d5c92c1b"},
+ {file = "matplotlib-3.7.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebf577c7a6744e9e1bd3fee45fc74a02710b214f94e2bde344912d85e0c9af7c"},
+ {file = "matplotlib-3.7.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:936bba394682049919dda062d33435b3be211dc3dcaa011e09634f060ec878b2"},
+ {file = "matplotlib-3.7.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bc221ffbc2150458b1cd71cdd9ddd5bb37962b036e41b8be258280b5b01da1dd"},
+ {file = "matplotlib-3.7.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35d74ebdb3f71f112b36c2629cf32323adfbf42679e2751252acd468f5001c07"},
+ {file = "matplotlib-3.7.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:717157e61b3a71d3d26ad4e1770dc85156c9af435659a25ee6407dc866cb258d"},
+ {file = "matplotlib-3.7.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:20f844d6be031948148ba49605c8b96dfe7d3711d1b63592830d650622458c11"},
+ {file = "matplotlib-3.7.2.tar.gz", hash = "sha256:a8cdb91dddb04436bd2f098b8fdf4b81352e68cf4d2c6756fcc414791076569b"},
]
[package.dependencies]
@@ -1528,7 +1538,7 @@ kiwisolver = ">=1.0.1"
numpy = ">=1.20"
packaging = ">=20.0"
pillow = ">=6.2.0"
-pyparsing = ">=2.3.1"
+pyparsing = ">=2.3.1,<3.1"
python-dateutil = ">=2.7"
[[package]]
@@ -1560,14 +1570,14 @@ files = [
[[package]]
name = "mistune"
-version = "2.0.5"
-description = "A sane Markdown parser with useful plugins and renderers"
+version = "3.0.1"
+description = "A sane and fast Markdown parser with useful plugins and renderers"
category = "dev"
optional = false
-python-versions = "*"
+python-versions = ">=3.7"
files = [
- {file = "mistune-2.0.5-py2.py3-none-any.whl", hash = "sha256:bad7f5d431886fcbaf5f758118ecff70d31f75231b34024a1341120340a65ce8"},
- {file = "mistune-2.0.5.tar.gz", hash = "sha256:0246113cb2492db875c6be56974a7c893333bf26cd92891c85f63151cee09d34"},
+ {file = "mistune-3.0.1-py3-none-any.whl", hash = "sha256:b9b3e438efbb57c62b5beb5e134dab664800bdf1284a7ee09e8b12b13eb1aac6"},
+ {file = "mistune-3.0.1.tar.gz", hash = "sha256:e912116c13aa0944f9dc530db38eb88f6a77087ab128f49f84a48f4c05ea163c"},
]
[[package]]
@@ -1595,14 +1605,14 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=
[[package]]
name = "nbconvert"
-version = "7.5.0"
+version = "7.7.4"
description = "Converting Jupyter Notebooks"
category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "nbconvert-7.5.0-py3-none-any.whl", hash = "sha256:852e44392d5650ef217a5ce3a8050747051d4e6ba75f0574cb5435049ee6c0d9"},
- {file = "nbconvert-7.5.0.tar.gz", hash = "sha256:f78fd22fd2410b960d5d9bcecf3e1d6c7bdc5fec2c865964c84aa4e74e6e88da"},
+ {file = "nbconvert-7.7.4-py3-none-any.whl", hash = "sha256:ace26f4386d08eb5c55833596a942048c5502a95e05590cb523826a749a40a37"},
+ {file = "nbconvert-7.7.4.tar.gz", hash = "sha256:1113d039fa3fc3a846ffa5a3b0a019e85aaa94c566a09fa0c400fb7638e46087"},
]
[package.dependencies]
@@ -1614,7 +1624,7 @@ jinja2 = ">=3.0"
jupyter-core = ">=4.7"
jupyterlab-pygments = "*"
markupsafe = ">=2.0"
-mistune = ">=2.0.3,<3"
+mistune = ">=2.0.3,<4"
nbclient = ">=0.5.0"
nbformat = ">=5.7"
packaging = "*"
@@ -1629,19 +1639,19 @@ docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sp
qtpdf = ["nbconvert[qtpng]"]
qtpng = ["pyqtwebengine (>=5.15)"]
serve = ["tornado (>=6.1)"]
-test = ["ipykernel", "ipywidgets (>=7)", "pre-commit", "pytest", "pytest-dependency"]
-webpdf = ["pyppeteer (>=1,<1.1)"]
+test = ["flaky", "ipykernel", "ipywidgets (>=7)", "pre-commit", "pytest", "pytest-dependency"]
+webpdf = ["playwright"]
[[package]]
name = "nbformat"
-version = "5.9.0"
+version = "5.9.2"
description = "The Jupyter Notebook format"
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
- {file = "nbformat-5.9.0-py3-none-any.whl", hash = "sha256:8c8fa16d6d05062c26177754bfbfac22de644888e2ef69d27ad2a334cf2576e5"},
- {file = "nbformat-5.9.0.tar.gz", hash = "sha256:e98ebb6120c3efbafdee2a40af2a140cadee90bb06dd69a2a63d9551fcc7f976"},
+ {file = "nbformat-5.9.2-py3-none-any.whl", hash = "sha256:1c5172d786a41b82bcfd0c23f9e6b6f072e8fb49c39250219e4acfff1efe89e9"},
+ {file = "nbformat-5.9.2.tar.gz", hash = "sha256:5f98b5ba1997dff175e77e0c17d5c10a96eaed2cbd1de3533d1fc35d5e111192"},
]
[package.dependencies]
@@ -1676,48 +1686,48 @@ traitlets = ">=5"
[[package]]
name = "nest-asyncio"
-version = "1.5.6"
+version = "1.5.7"
description = "Patch asyncio to allow nested event loops"
category = "dev"
optional = false
python-versions = ">=3.5"
files = [
- {file = "nest_asyncio-1.5.6-py3-none-any.whl", hash = "sha256:b9a953fb40dceaa587d109609098db21900182b16440652454a146cffb06e8b8"},
- {file = "nest_asyncio-1.5.6.tar.gz", hash = "sha256:d267cc1ff794403f7df692964d1d2a3fa9418ffea2a3f6859a439ff482fef290"},
+ {file = "nest_asyncio-1.5.7-py3-none-any.whl", hash = "sha256:5301c82941b550b3123a1ea772ba9a1c80bad3a182be8c1a5ae6ad3be57a9657"},
+ {file = "nest_asyncio-1.5.7.tar.gz", hash = "sha256:6a80f7b98f24d9083ed24608977c09dd608d83f91cccc24c9d2cba6d10e01c10"},
]
[[package]]
name = "numba"
-version = "0.57.0"
+version = "0.57.1"
description = "compiling Python code using LLVM"
category = "main"
optional = false
python-versions = ">=3.8"
files = [
- {file = "numba-0.57.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2e2c14c411545e80bf0f1a33232fb0bd6aa3368f86e56eeffc7f6d3ac16ea3fd"},
- {file = "numba-0.57.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6b3382c56d805ffcdc7b46eb69a906be733dd35b84be14abba8e5fd27d7916b2"},
- {file = "numba-0.57.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:133cba9b5002bf67f6f73d9b3050d919c1be91326bbdcccfdf3259bcfb1cec0e"},
- {file = "numba-0.57.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d92a17ee849574665c5d94e9c9b862e469e1231d3dbb9e58e58b30b4bb0cbce9"},
- {file = "numba-0.57.0-cp310-cp310-win32.whl", hash = "sha256:abc90c3d303a67ae5194770a6f0d0a83edf076683b8a426349a27b91d98e00d1"},
- {file = "numba-0.57.0-cp310-cp310-win_amd64.whl", hash = "sha256:430f43c96f866ca4fe6008d8aa28bb608911d908ff94f879e0dbad7768ef9869"},
- {file = "numba-0.57.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:069f7d8fddad4c0eb1d7534c2a18098fe50473dc77832b409176002e9011b96f"},
- {file = "numba-0.57.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:79daa130fc9e4ebd1eea0a594d1de86d8a4366989f5fab93c482246b502520db"},
- {file = "numba-0.57.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:274f4db4814ebd5ec81697acfc36df04a865b86610d7714905185b753f3f9baf"},
- {file = "numba-0.57.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0106ee441e3f69cc6f17cb470c4fcccd592e0606567d43245635d72b071ab88e"},
- {file = "numba-0.57.0-cp311-cp311-win_amd64.whl", hash = "sha256:a5d31b4d95000d86ffa9652ab5bcfa0ea30e6c3fc40e610147d4f2f00116703d"},
- {file = "numba-0.57.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3e0b8de39bf17519435937b53276dfb02e2eb8bc27cd211c8eeb01ffed1cab6b"},
- {file = "numba-0.57.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:18d90fa6fcd5b796999392a8ea67f2fbccecf8dabcea726e2e721c79f40566a6"},
- {file = "numba-0.57.0-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d4f62528c7c8c5f97e9689fd788e420b68c67ee0a1a9a7715a57fd584b7aef1e"},
- {file = "numba-0.57.0-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fd12cf0b431676c08057685e229ea5daaa1ec8efba2506c38671734ace49c2d7"},
- {file = "numba-0.57.0-cp38-cp38-win32.whl", hash = "sha256:e5f11b1d435fb4d1d1b68fa68ff456d632dc4bfd40b18825ff80d6081d1afb26"},
- {file = "numba-0.57.0-cp38-cp38-win_amd64.whl", hash = "sha256:5810ed2d6d22eb3c48bedfac2187fc44bb90e05f02d47fd31059e69207ae4106"},
- {file = "numba-0.57.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eddba74493d4003a42cd61ff7feca4928a94a45553d1fddac77a5cc339f6f4f9"},
- {file = "numba-0.57.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:110be5e1213d0a3d5fc691e921a000779500620196d99cee9908fce83d1e48df"},
- {file = "numba-0.57.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f949018ab9c467d38f14fe17db4df0d4a1c664be802189e2d6c5a434d9ffd4f6"},
- {file = "numba-0.57.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9fc0cd4ec93a1e3877985e10ed5837ed2991c83aa4b7ca574caae5c8b448cc4b"},
- {file = "numba-0.57.0-cp39-cp39-win32.whl", hash = "sha256:83d4f21c98eed3001e9896a43a1ce9c825999c03f7eb39ddd1c2d07a76708392"},
- {file = "numba-0.57.0-cp39-cp39-win_amd64.whl", hash = "sha256:9173d00c6753212b68e4fd319cfa96c21b2263949452c97b034e78ce09539dee"},
- {file = "numba-0.57.0.tar.gz", hash = "sha256:2af6d81067a5bdc13960c6d2519dbabbf4d5d597cf75d640c5aeaefd48c6420a"},
+ {file = "numba-0.57.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db8268eb5093cae2288942a8cbd69c9352f6fe6e0bfa0a9a27679436f92e4248"},
+ {file = "numba-0.57.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:643cb09a9ba9e1bd8b060e910aeca455e9442361e80fce97690795ff9840e681"},
+ {file = "numba-0.57.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:53e9fab973d9e82c9f8449f75994a898daaaf821d84f06fbb0b9de2293dd9306"},
+ {file = "numba-0.57.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c0602e4f896e6a6d844517c3ab434bc978e7698a22a733cc8124465898c28fa8"},
+ {file = "numba-0.57.1-cp310-cp310-win32.whl", hash = "sha256:3d6483c27520d16cf5d122868b79cad79e48056ecb721b52d70c126bed65431e"},
+ {file = "numba-0.57.1-cp310-cp310-win_amd64.whl", hash = "sha256:a32ee263649aa3c3587b833d6311305379529570e6c20deb0c6f4fb5bc7020db"},
+ {file = "numba-0.57.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c078f84b5529a7fdb8413bb33d5100f11ec7b44aa705857d9eb4e54a54ff505"},
+ {file = "numba-0.57.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e447c4634d1cc99ab50d4faa68f680f1d88b06a2a05acf134aa6fcc0342adeca"},
+ {file = "numba-0.57.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4838edef2df5f056cb8974670f3d66562e751040c448eb0b67c7e2fec1726649"},
+ {file = "numba-0.57.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9b17fbe4a69dcd9a7cd49916b6463cd9a82af5f84911feeb40793b8bce00dfa7"},
+ {file = "numba-0.57.1-cp311-cp311-win_amd64.whl", hash = "sha256:93df62304ada9b351818ba19b1cfbddaf72cd89348e81474326ca0b23bf0bae1"},
+ {file = "numba-0.57.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8e00ca63c5d0ad2beeb78d77f087b3a88c45ea9b97e7622ab2ec411a868420ee"},
+ {file = "numba-0.57.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ff66d5b022af6c7d81ddbefa87768e78ed4f834ab2da6ca2fd0d60a9e69b94f5"},
+ {file = "numba-0.57.1-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:60ec56386076e9eed106a87c96626d5686fbb16293b9834f0849cf78c9491779"},
+ {file = "numba-0.57.1-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6c057ccedca95df23802b6ccad86bb318be624af45b5a38bb8412882be57a681"},
+ {file = "numba-0.57.1-cp38-cp38-win32.whl", hash = "sha256:5a82bf37444039c732485c072fda21a361790ed990f88db57fd6941cd5e5d307"},
+ {file = "numba-0.57.1-cp38-cp38-win_amd64.whl", hash = "sha256:9bcc36478773ce838f38afd9a4dfafc328d4ffb1915381353d657da7f6473282"},
+ {file = "numba-0.57.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae50c8c90c2ce8057f9618b589223e13faa8cbc037d8f15b4aad95a2c33a0582"},
+ {file = "numba-0.57.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9a1b2b69448e510d672ff9a6b18d2db9355241d93c6a77677baa14bec67dc2a0"},
+ {file = "numba-0.57.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3cf78d74ad9d289fbc1e5b1c9f2680fca7a788311eb620581893ab347ec37a7e"},
+ {file = "numba-0.57.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f47dd214adc5dcd040fe9ad2adbd2192133c9075d2189ce1b3d5f9d72863ef05"},
+ {file = "numba-0.57.1-cp39-cp39-win32.whl", hash = "sha256:a3eac19529956185677acb7f01864919761bfffbb9ae04bbbe5e84bbc06cfc2b"},
+ {file = "numba-0.57.1-cp39-cp39-win_amd64.whl", hash = "sha256:9587ba1bf5f3035575e45562ada17737535c6d612df751e811d702693a72d95e"},
+ {file = "numba-0.57.1.tar.gz", hash = "sha256:33c0500170d213e66d90558ad6aca57d3e03e97bb11da82e6d87ab793648cb17"},
]
[package.dependencies]
@@ -1727,40 +1737,40 @@ numpy = ">=1.21,<1.25"
[[package]]
name = "numpy"
-version = "1.24.3"
+version = "1.24.4"
description = "Fundamental package for array computing in Python"
category = "main"
optional = false
python-versions = ">=3.8"
files = [
- {file = "numpy-1.24.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c1104d3c036fb81ab923f507536daedc718d0ad5a8707c6061cdfd6d184e570"},
- {file = "numpy-1.24.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:202de8f38fc4a45a3eea4b63e2f376e5f2dc64ef0fa692838e31a808520efaf7"},
- {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8535303847b89aa6b0f00aa1dc62867b5a32923e4d1681a35b5eef2d9591a463"},
- {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d926b52ba1367f9acb76b0df6ed21f0b16a1ad87c6720a1121674e5cf63e2b6"},
- {file = "numpy-1.24.3-cp310-cp310-win32.whl", hash = "sha256:f21c442fdd2805e91799fbe044a7b999b8571bb0ab0f7850d0cb9641a687092b"},
- {file = "numpy-1.24.3-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f23af8c16022663a652d3b25dcdc272ac3f83c3af4c02eb8b824e6b3ab9d7"},
- {file = "numpy-1.24.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9a7721ec204d3a237225db3e194c25268faf92e19338a35f3a224469cb6039a3"},
- {file = "numpy-1.24.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6cc757de514c00b24ae8cf5c876af2a7c3df189028d68c0cb4eaa9cd5afc2bf"},
- {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76e3f4e85fc5d4fd311f6e9b794d0c00e7002ec122be271f2019d63376f1d385"},
- {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1d3c026f57ceaad42f8231305d4653d5f05dc6332a730ae5c0bea3513de0950"},
- {file = "numpy-1.24.3-cp311-cp311-win32.whl", hash = "sha256:c91c4afd8abc3908e00a44b2672718905b8611503f7ff87390cc0ac3423fb096"},
- {file = "numpy-1.24.3-cp311-cp311-win_amd64.whl", hash = "sha256:5342cf6aad47943286afa6f1609cad9b4266a05e7f2ec408e2cf7aea7ff69d80"},
- {file = "numpy-1.24.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7776ea65423ca6a15255ba1872d82d207bd1e09f6d0894ee4a64678dd2204078"},
- {file = "numpy-1.24.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ae8d0be48d1b6ed82588934aaaa179875e7dc4f3d84da18d7eae6eb3f06c242c"},
- {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecde0f8adef7dfdec993fd54b0f78183051b6580f606111a6d789cd14c61ea0c"},
- {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4749e053a29364d3452c034827102ee100986903263e89884922ef01a0a6fd2f"},
- {file = "numpy-1.24.3-cp38-cp38-win32.whl", hash = "sha256:d933fabd8f6a319e8530d0de4fcc2e6a61917e0b0c271fded460032db42a0fe4"},
- {file = "numpy-1.24.3-cp38-cp38-win_amd64.whl", hash = "sha256:56e48aec79ae238f6e4395886b5eaed058abb7231fb3361ddd7bfdf4eed54289"},
- {file = "numpy-1.24.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4719d5aefb5189f50887773699eaf94e7d1e02bf36c1a9d353d9f46703758ca4"},
- {file = "numpy-1.24.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ec87a7084caa559c36e0a2309e4ecb1baa03b687201d0a847c8b0ed476a7187"},
- {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea8282b9bcfe2b5e7d491d0bf7f3e2da29700cec05b49e64d6246923329f2b02"},
- {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210461d87fb02a84ef243cac5e814aad2b7f4be953b32cb53327bb49fd77fbb4"},
- {file = "numpy-1.24.3-cp39-cp39-win32.whl", hash = "sha256:784c6da1a07818491b0ffd63c6bbe5a33deaa0e25a20e1b3ea20cf0e43f8046c"},
- {file = "numpy-1.24.3-cp39-cp39-win_amd64.whl", hash = "sha256:d5036197ecae68d7f491fcdb4df90082b0d4960ca6599ba2659957aafced7c17"},
- {file = "numpy-1.24.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:352ee00c7f8387b44d19f4cada524586f07379c0d49270f87233983bc5087ca0"},
- {file = "numpy-1.24.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7d6acc2e7524c9955e5c903160aa4ea083736fde7e91276b0e5d98e6332812"},
- {file = "numpy-1.24.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:35400e6a8d102fd07c71ed7dcadd9eb62ee9a6e84ec159bd48c28235bbb0f8e4"},
- {file = "numpy-1.24.3.tar.gz", hash = "sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155"},
+ {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"},
+ {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"},
+ {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"},
+ {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"},
+ {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"},
+ {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"},
+ {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"},
+ {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"},
+ {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"},
+ {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"},
+ {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"},
+ {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"},
+ {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"},
+ {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"},
+ {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"},
+ {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"},
+ {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"},
+ {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"},
+ {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"},
+ {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"},
+ {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"},
+ {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"},
+ {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"},
+ {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"},
+ {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"},
+ {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"},
+ {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"},
+ {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"},
]
[[package]]
@@ -1937,78 +1947,68 @@ files = [
[[package]]
name = "pillow"
-version = "9.5.0"
+version = "10.0.0"
description = "Python Imaging Library (Fork)"
category = "main"
optional = true
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "Pillow-9.5.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:ace6ca218308447b9077c14ea4ef381ba0b67ee78d64046b3f19cf4e1139ad16"},
- {file = "Pillow-9.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3d403753c9d5adc04d4694d35cf0391f0f3d57c8e0030aac09d7678fa8030aa"},
- {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ba1b81ee69573fe7124881762bb4cd2e4b6ed9dd28c9c60a632902fe8db8b38"},
- {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062"},
- {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f36397bf3f7d7c6a3abdea815ecf6fd14e7fcd4418ab24bae01008d8d8ca15e"},
- {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:252a03f1bdddce077eff2354c3861bf437c892fb1832f75ce813ee94347aa9b5"},
- {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:85ec677246533e27770b0de5cf0f9d6e4ec0c212a1f89dfc941b64b21226009d"},
- {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b416f03d37d27290cb93597335a2f85ed446731200705b22bb927405320de903"},
- {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1781a624c229cb35a2ac31cc4a77e28cafc8900733a864870c49bfeedacd106a"},
- {file = "Pillow-9.5.0-cp310-cp310-win32.whl", hash = "sha256:8507eda3cd0608a1f94f58c64817e83ec12fa93a9436938b191b80d9e4c0fc44"},
- {file = "Pillow-9.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:d3c6b54e304c60c4181da1c9dadf83e4a54fd266a99c70ba646a9baa626819eb"},
- {file = "Pillow-9.5.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32"},
- {file = "Pillow-9.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c"},
- {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3"},
- {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a"},
- {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1"},
- {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99"},
- {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625"},
- {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579"},
- {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296"},
- {file = "Pillow-9.5.0-cp311-cp311-win32.whl", hash = "sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec"},
- {file = "Pillow-9.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4"},
- {file = "Pillow-9.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089"},
- {file = "Pillow-9.5.0-cp312-cp312-win32.whl", hash = "sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb"},
- {file = "Pillow-9.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b"},
- {file = "Pillow-9.5.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:5d4ebf8e1db4441a55c509c4baa7a0587a0210f7cd25fcfe74dbbce7a4bd1906"},
- {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:375f6e5ee9620a271acb6820b3d1e94ffa8e741c0601db4c0c4d3cb0a9c224bf"},
- {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99eb6cafb6ba90e436684e08dad8be1637efb71c4f2180ee6b8f940739406e78"},
- {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dfaaf10b6172697b9bceb9a3bd7b951819d1ca339a5ef294d1f1ac6d7f63270"},
- {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:763782b2e03e45e2c77d7779875f4432e25121ef002a41829d8868700d119392"},
- {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:35f6e77122a0c0762268216315bf239cf52b88865bba522999dc38f1c52b9b47"},
- {file = "Pillow-9.5.0-cp37-cp37m-win32.whl", hash = "sha256:aca1c196f407ec7cf04dcbb15d19a43c507a81f7ffc45b690899d6a76ac9fda7"},
- {file = "Pillow-9.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322724c0032af6692456cd6ed554bb85f8149214d97398bb80613b04e33769f6"},
- {file = "Pillow-9.5.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:a0aa9417994d91301056f3d0038af1199eb7adc86e646a36b9e050b06f526597"},
- {file = "Pillow-9.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8286396b351785801a976b1e85ea88e937712ee2c3ac653710a4a57a8da5d9c"},
- {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c830a02caeb789633863b466b9de10c015bded434deb3ec87c768e53752ad22a"},
- {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fbd359831c1657d69bb81f0db962905ee05e5e9451913b18b831febfe0519082"},
- {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8fc330c3370a81bbf3f88557097d1ea26cd8b019d6433aa59f71195f5ddebbf"},
- {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:7002d0797a3e4193c7cdee3198d7c14f92c0836d6b4a3f3046a64bd1ce8df2bf"},
- {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:229e2c79c00e85989a34b5981a2b67aa079fd08c903f0aaead522a1d68d79e51"},
- {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9adf58f5d64e474bed00d69bcd86ec4bcaa4123bfa70a65ce72e424bfb88ed96"},
- {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:662da1f3f89a302cc22faa9f14a262c2e3951f9dbc9617609a47521c69dd9f8f"},
- {file = "Pillow-9.5.0-cp38-cp38-win32.whl", hash = "sha256:6608ff3bf781eee0cd14d0901a2b9cc3d3834516532e3bd673a0a204dc8615fc"},
- {file = "Pillow-9.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:e49eb4e95ff6fd7c0c402508894b1ef0e01b99a44320ba7d8ecbabefddcc5569"},
- {file = "Pillow-9.5.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:482877592e927fd263028c105b36272398e3e1be3269efda09f6ba21fd83ec66"},
- {file = "Pillow-9.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3ded42b9ad70e5f1754fb7c2e2d6465a9c842e41d178f262e08b8c85ed8a1d8e"},
- {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c446d2245ba29820d405315083d55299a796695d747efceb5717a8b450324115"},
- {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aca1152d93dcc27dc55395604dcfc55bed5f25ef4c98716a928bacba90d33a3"},
- {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:608488bdcbdb4ba7837461442b90ea6f3079397ddc968c31265c1e056964f1ef"},
- {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:60037a8db8750e474af7ffc9faa9b5859e6c6d0a50e55c45576bf28be7419705"},
- {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1"},
- {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a127ae76092974abfbfa38ca2d12cbeddcdeac0fb71f9627cc1135bedaf9d51a"},
- {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:489f8389261e5ed43ac8ff7b453162af39c3e8abd730af8363587ba64bb2e865"},
- {file = "Pillow-9.5.0-cp39-cp39-win32.whl", hash = "sha256:9b1af95c3a967bf1da94f253e56b6286b50af23392a886720f563c547e48e964"},
- {file = "Pillow-9.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:77165c4a5e7d5a284f10a6efaa39a0ae8ba839da344f20b111d62cc932fa4e5d"},
- {file = "Pillow-9.5.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5"},
- {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140"},
- {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba"},
- {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829"},
- {file = "Pillow-9.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd"},
- {file = "Pillow-9.5.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572"},
- {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe"},
- {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1"},
- {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7"},
- {file = "Pillow-9.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799"},
- {file = "Pillow-9.5.0.tar.gz", hash = "sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1"},
+ {file = "Pillow-10.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f62406a884ae75fb2f818694469519fb685cc7eaff05d3451a9ebe55c646891"},
+ {file = "Pillow-10.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d5db32e2a6ccbb3d34d87c87b432959e0db29755727afb37290e10f6e8e62614"},
+ {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edf4392b77bdc81f36e92d3a07a5cd072f90253197f4a52a55a8cec48a12483b"},
+ {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:520f2a520dc040512699f20fa1c363eed506e94248d71f85412b625026f6142c"},
+ {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:8c11160913e3dd06c8ffdb5f233a4f254cb449f4dfc0f8f4549eda9e542c93d1"},
+ {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a74ba0c356aaa3bb8e3eb79606a87669e7ec6444be352870623025d75a14a2bf"},
+ {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d0dae4cfd56969d23d94dc8e89fb6a217be461c69090768227beb8ed28c0a3"},
+ {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22c10cc517668d44b211717fd9775799ccec4124b9a7f7b3635fc5386e584992"},
+ {file = "Pillow-10.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:dffe31a7f47b603318c609f378ebcd57f1554a3a6a8effbc59c3c69f804296de"},
+ {file = "Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485"},
+ {file = "Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f"},
+ {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3"},
+ {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d"},
+ {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd"},
+ {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629"},
+ {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3b08d4cc24f471b2c8ca24ec060abf4bebc6b144cb89cba638c720546b1cf538"},
+ {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737a602fbd82afd892ca746392401b634e278cb65d55c4b7a8f48e9ef8d008d"},
+ {file = "Pillow-10.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f"},
+ {file = "Pillow-10.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:bc2ec7c7b5d66b8ec9ce9f720dbb5fa4bace0f545acd34870eff4a369b44bf37"},
+ {file = "Pillow-10.0.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:d80cf684b541685fccdd84c485b31ce73fc5c9b5d7523bf1394ce134a60c6883"},
+ {file = "Pillow-10.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76de421f9c326da8f43d690110f0e79fe3ad1e54be811545d7d91898b4c8493e"},
+ {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81ff539a12457809666fef6624684c008e00ff6bf455b4b89fd00a140eecd640"},
+ {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce543ed15570eedbb85df19b0a1a7314a9c8141a36ce089c0a894adbfccb4568"},
+ {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:685ac03cc4ed5ebc15ad5c23bc555d68a87777586d970c2c3e216619a5476223"},
+ {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d72e2ecc68a942e8cf9739619b7f408cc7b272b279b56b2c83c6123fcfa5cdff"},
+ {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d50b6aec14bc737742ca96e85d6d0a5f9bfbded018264b3b70ff9d8c33485551"},
+ {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:00e65f5e822decd501e374b0650146063fbb30a7264b4d2744bdd7b913e0cab5"},
+ {file = "Pillow-10.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:f31f9fdbfecb042d046f9d91270a0ba28368a723302786c0009ee9b9f1f60199"},
+ {file = "Pillow-10.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:1ce91b6ec08d866b14413d3f0bbdea7e24dfdc8e59f562bb77bc3fe60b6144ca"},
+ {file = "Pillow-10.0.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:349930d6e9c685c089284b013478d6f76e3a534e36ddfa912cde493f235372f3"},
+ {file = "Pillow-10.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3a684105f7c32488f7153905a4e3015a3b6c7182e106fe3c37fbb5ef3e6994c3"},
+ {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4f69b3700201b80bb82c3a97d5e9254084f6dd5fb5b16fc1a7b974260f89f43"},
+ {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f07ea8d2f827d7d2a49ecf1639ec02d75ffd1b88dcc5b3a61bbb37a8759ad8d"},
+ {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:040586f7d37b34547153fa383f7f9aed68b738992380ac911447bb78f2abe530"},
+ {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:f88a0b92277de8e3ca715a0d79d68dc82807457dae3ab8699c758f07c20b3c51"},
+ {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c7cf14a27b0d6adfaebb3ae4153f1e516df54e47e42dcc073d7b3d76111a8d86"},
+ {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3400aae60685b06bb96f99a21e1ada7bc7a413d5f49bce739828ecd9391bb8f7"},
+ {file = "Pillow-10.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbc02381779d412145331789b40cc7b11fdf449e5d94f6bc0b080db0a56ea3f0"},
+ {file = "Pillow-10.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9211e7ad69d7c9401cfc0e23d49b69ca65ddd898976d660a2fa5904e3d7a9baa"},
+ {file = "Pillow-10.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:faaf07ea35355b01a35cb442dd950d8f1bb5b040a7787791a535de13db15ed90"},
+ {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f72a021fbb792ce98306ffb0c348b3c9cb967dce0f12a49aa4c3d3fdefa967"},
+ {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f7c16705f44e0504a3a2a14197c1f0b32a95731d251777dcb060aa83022cb2d"},
+ {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:76edb0a1fa2b4745fb0c99fb9fb98f8b180a1bbceb8be49b087e0b21867e77d3"},
+ {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:368ab3dfb5f49e312231b6f27b8820c823652b7cd29cfbd34090565a015e99ba"},
+ {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:608bfdee0d57cf297d32bcbb3c728dc1da0907519d1784962c5f0c68bb93e5a3"},
+ {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5c6e3df6bdd396749bafd45314871b3d0af81ff935b2d188385e970052091017"},
+ {file = "Pillow-10.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:7be600823e4c8631b74e4a0d38384c73f680e6105a7d3c6824fcf226c178c7e6"},
+ {file = "Pillow-10.0.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:92be919bbc9f7d09f7ae343c38f5bb21c973d2576c1d45600fce4b74bafa7ac0"},
+ {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8182b523b2289f7c415f589118228d30ac8c355baa2f3194ced084dac2dbba"},
+ {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:38250a349b6b390ee6047a62c086d3817ac69022c127f8a5dc058c31ccef17f3"},
+ {file = "Pillow-10.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:88af2003543cc40c80f6fca01411892ec52b11021b3dc22ec3bc9d5afd1c5334"},
+ {file = "Pillow-10.0.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c189af0545965fa8d3b9613cfdb0cd37f9d71349e0f7750e1fd704648d475ed2"},
+ {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce7b031a6fc11365970e6a5686d7ba8c63e4c1cf1ea143811acbb524295eabed"},
+ {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db24668940f82321e746773a4bc617bfac06ec831e5c88b643f91f122a785684"},
+ {file = "Pillow-10.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:efe8c0681042536e0d06c11f48cebe759707c9e9abf880ee213541c5b46c5bf3"},
+ {file = "Pillow-10.0.0.tar.gz", hash = "sha256:9c82b5b3e043c7af0d95792d0d20ccf68f61a1fec6b3530e718b688422727396"},
]
[package.extras]
@@ -2029,30 +2029,30 @@ files = [
[[package]]
name = "platformdirs"
-version = "3.5.3"
+version = "3.10.0"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "platformdirs-3.5.3-py3-none-any.whl", hash = "sha256:0ade98a4895e87dc51d47151f7d2ec290365a585151d97b4d8d6312ed6132fed"},
- {file = "platformdirs-3.5.3.tar.gz", hash = "sha256:e48fabd87db8f3a7df7150a4a5ea22c546ee8bc39bc2473244730d4b56d2cc4e"},
+ {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"},
+ {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"},
]
[package.extras]
-docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
-test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"]
+docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
[[package]]
name = "pluggy"
-version = "1.0.0"
+version = "1.2.0"
description = "plugin and hook calling mechanisms for python"
category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
- {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
+ {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"},
+ {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"},
]
[package.extras]
@@ -2061,14 +2061,14 @@ testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "prompt-toolkit"
-version = "3.0.38"
+version = "3.0.39"
description = "Library for building powerful interactive command lines in Python"
category = "main"
optional = false
python-versions = ">=3.7.0"
files = [
- {file = "prompt_toolkit-3.0.38-py3-none-any.whl", hash = "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f"},
- {file = "prompt_toolkit-3.0.38.tar.gz", hash = "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b"},
+ {file = "prompt_toolkit-3.0.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"},
+ {file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"},
]
[package.dependencies]
@@ -2178,14 +2178,14 @@ files = [
[[package]]
name = "pygments"
-version = "2.15.1"
+version = "2.16.1"
description = "Pygments is a syntax highlighting package written in Python."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
- {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
- {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
+ {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"},
+ {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"},
]
[package.extras]
@@ -2193,18 +2193,18 @@ plugins = ["importlib-metadata"]
[[package]]
name = "pylint"
-version = "2.17.4"
+version = "2.17.5"
description = "python code static checker"
category = "dev"
optional = false
python-versions = ">=3.7.2"
files = [
- {file = "pylint-2.17.4-py3-none-any.whl", hash = "sha256:7a1145fb08c251bdb5cca11739722ce64a63db479283d10ce718b2460e54123c"},
- {file = "pylint-2.17.4.tar.gz", hash = "sha256:5dcf1d9e19f41f38e4e85d10f511e5b9c35e1aa74251bf95cdd8cb23584e2db1"},
+ {file = "pylint-2.17.5-py3-none-any.whl", hash = "sha256:73995fb8216d3bed149c8d51bba25b2c52a8251a2c8ac846ec668ce38fab5413"},
+ {file = "pylint-2.17.5.tar.gz", hash = "sha256:f7b601cbc06fef7e62a754e2b41294c2aa31f1cb659624b9a85bcba29eaf8252"},
]
[package.dependencies]
-astroid = ">=2.15.4,<=2.17.0-dev0"
+astroid = ">=2.15.6,<=2.17.0-dev0"
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
dill = [
{version = ">=0.2", markers = "python_version < \"3.11\""},
@@ -2258,53 +2258,16 @@ files = [
{file = "pyrepl-0.9.0.tar.gz", hash = "sha256:292570f34b5502e871bbb966d639474f2b57fbfcd3373c2d6a2f3d56e681a775"},
]
-[[package]]
-name = "pyrsistent"
-version = "0.19.3"
-description = "Persistent/Functional/Immutable data structures"
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "pyrsistent-0.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a"},
- {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64"},
- {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf"},
- {file = "pyrsistent-0.19.3-cp310-cp310-win32.whl", hash = "sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a"},
- {file = "pyrsistent-0.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da"},
- {file = "pyrsistent-0.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9"},
- {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393"},
- {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19"},
- {file = "pyrsistent-0.19.3-cp311-cp311-win32.whl", hash = "sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3"},
- {file = "pyrsistent-0.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8"},
- {file = "pyrsistent-0.19.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28"},
- {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf"},
- {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9"},
- {file = "pyrsistent-0.19.3-cp37-cp37m-win32.whl", hash = "sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1"},
- {file = "pyrsistent-0.19.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b"},
- {file = "pyrsistent-0.19.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8"},
- {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a"},
- {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c"},
- {file = "pyrsistent-0.19.3-cp38-cp38-win32.whl", hash = "sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c"},
- {file = "pyrsistent-0.19.3-cp38-cp38-win_amd64.whl", hash = "sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7"},
- {file = "pyrsistent-0.19.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc"},
- {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2"},
- {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3"},
- {file = "pyrsistent-0.19.3-cp39-cp39-win32.whl", hash = "sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2"},
- {file = "pyrsistent-0.19.3-cp39-cp39-win_amd64.whl", hash = "sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98"},
- {file = "pyrsistent-0.19.3-py3-none-any.whl", hash = "sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64"},
- {file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"},
-]
-
[[package]]
name = "pytest"
-version = "7.3.2"
+version = "7.4.0"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "pytest-7.3.2-py3-none-any.whl", hash = "sha256:cdcbd012c9312258922f8cd3f1b62a6580fdced17db6014896053d47cddf9295"},
- {file = "pytest-7.3.2.tar.gz", hash = "sha256:ee990a3cc55ba808b80795a79944756f315c67c12b56abd3ac993a7b8c17030b"},
+ {file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"},
+ {file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"},
]
[package.dependencies]
@@ -2416,144 +2379,176 @@ files = [
[[package]]
name = "pyyaml"
-version = "6.0"
+version = "6.0.1"
description = "YAML parser and emitter for Python"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
- {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-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
- {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
- {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
- {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
- {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
- {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
- {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
- {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"},
+ {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
+ {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
+ {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
+ {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
+ {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
+ {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
+ {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
+ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
+ {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
+ {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
+ {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
+ {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
+ {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
+ {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
+ {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
+ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
]
[[package]]
name = "pyzmq"
-version = "25.1.0"
+version = "25.1.1"
description = "Python bindings for 0MQ"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
- {file = "pyzmq-25.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:1a6169e69034eaa06823da6a93a7739ff38716142b3596c180363dee729d713d"},
- {file = "pyzmq-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:19d0383b1f18411d137d891cab567de9afa609b214de68b86e20173dc624c101"},
- {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1e931d9a92f628858a50f5bdffdfcf839aebe388b82f9d2ccd5d22a38a789dc"},
- {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97d984b1b2f574bc1bb58296d3c0b64b10e95e7026f8716ed6c0b86d4679843f"},
- {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:154bddda2a351161474b36dba03bf1463377ec226a13458725183e508840df89"},
- {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:cb6d161ae94fb35bb518b74bb06b7293299c15ba3bc099dccd6a5b7ae589aee3"},
- {file = "pyzmq-25.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:90146ab578931e0e2826ee39d0c948d0ea72734378f1898939d18bc9c823fcf9"},
- {file = "pyzmq-25.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:831ba20b660b39e39e5ac8603e8193f8fce1ee03a42c84ade89c36a251449d80"},
- {file = "pyzmq-25.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3a522510e3434e12aff80187144c6df556bb06fe6b9d01b2ecfbd2b5bfa5c60c"},
- {file = "pyzmq-25.1.0-cp310-cp310-win32.whl", hash = "sha256:be24a5867b8e3b9dd5c241de359a9a5217698ff616ac2daa47713ba2ebe30ad1"},
- {file = "pyzmq-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:5693dcc4f163481cf79e98cf2d7995c60e43809e325b77a7748d8024b1b7bcba"},
- {file = "pyzmq-25.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:13bbe36da3f8aaf2b7ec12696253c0bf6ffe05f4507985a8844a1081db6ec22d"},
- {file = "pyzmq-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:69511d604368f3dc58d4be1b0bad99b61ee92b44afe1cd9b7bd8c5e34ea8248a"},
- {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a983c8694667fd76d793ada77fd36c8317e76aa66eec75be2653cef2ea72883"},
- {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:332616f95eb400492103ab9d542b69d5f0ff628b23129a4bc0a2fd48da6e4e0b"},
- {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58416db767787aedbfd57116714aad6c9ce57215ffa1c3758a52403f7c68cff5"},
- {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cad9545f5801a125f162d09ec9b724b7ad9b6440151b89645241d0120e119dcc"},
- {file = "pyzmq-25.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d6128d431b8dfa888bf51c22a04d48bcb3d64431caf02b3cb943269f17fd2994"},
- {file = "pyzmq-25.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2b15247c49d8cbea695b321ae5478d47cffd496a2ec5ef47131a9e79ddd7e46c"},
- {file = "pyzmq-25.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:442d3efc77ca4d35bee3547a8e08e8d4bb88dadb54a8377014938ba98d2e074a"},
- {file = "pyzmq-25.1.0-cp311-cp311-win32.whl", hash = "sha256:65346f507a815a731092421d0d7d60ed551a80d9b75e8b684307d435a5597425"},
- {file = "pyzmq-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:8b45d722046fea5a5694cba5d86f21f78f0052b40a4bbbbf60128ac55bfcc7b6"},
- {file = "pyzmq-25.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f45808eda8b1d71308c5416ef3abe958f033fdbb356984fabbfc7887bed76b3f"},
- {file = "pyzmq-25.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b697774ea8273e3c0460cf0bba16cd85ca6c46dfe8b303211816d68c492e132"},
- {file = "pyzmq-25.1.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b324fa769577fc2c8f5efcd429cef5acbc17d63fe15ed16d6dcbac2c5eb00849"},
- {file = "pyzmq-25.1.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:5873d6a60b778848ce23b6c0ac26c39e48969823882f607516b91fb323ce80e5"},
- {file = "pyzmq-25.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f0d9e7ba6a815a12c8575ba7887da4b72483e4cfc57179af10c9b937f3f9308f"},
- {file = "pyzmq-25.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:414b8beec76521358b49170db7b9967d6974bdfc3297f47f7d23edec37329b00"},
- {file = "pyzmq-25.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:01f06f33e12497dca86353c354461f75275a5ad9eaea181ac0dc1662da8074fa"},
- {file = "pyzmq-25.1.0-cp36-cp36m-win32.whl", hash = "sha256:b5a07c4f29bf7cb0164664ef87e4aa25435dcc1f818d29842118b0ac1eb8e2b5"},
- {file = "pyzmq-25.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:968b0c737797c1809ec602e082cb63e9824ff2329275336bb88bd71591e94a90"},
- {file = "pyzmq-25.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:47b915ba666c51391836d7ed9a745926b22c434efa76c119f77bcffa64d2c50c"},
- {file = "pyzmq-25.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5af31493663cf76dd36b00dafbc839e83bbca8a0662931e11816d75f36155897"},
- {file = "pyzmq-25.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5489738a692bc7ee9a0a7765979c8a572520d616d12d949eaffc6e061b82b4d1"},
- {file = "pyzmq-25.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1fc56a0221bdf67cfa94ef2d6ce5513a3d209c3dfd21fed4d4e87eca1822e3a3"},
- {file = "pyzmq-25.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:75217e83faea9edbc29516fc90c817bc40c6b21a5771ecb53e868e45594826b0"},
- {file = "pyzmq-25.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3830be8826639d801de9053cf86350ed6742c4321ba4236e4b5568528d7bfed7"},
- {file = "pyzmq-25.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3575699d7fd7c9b2108bc1c6128641a9a825a58577775ada26c02eb29e09c517"},
- {file = "pyzmq-25.1.0-cp37-cp37m-win32.whl", hash = "sha256:95bd3a998d8c68b76679f6b18f520904af5204f089beebb7b0301d97704634dd"},
- {file = "pyzmq-25.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:dbc466744a2db4b7ca05589f21ae1a35066afada2f803f92369f5877c100ef62"},
- {file = "pyzmq-25.1.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:3bed53f7218490c68f0e82a29c92335daa9606216e51c64f37b48eb78f1281f4"},
- {file = "pyzmq-25.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eb52e826d16c09ef87132c6e360e1879c984f19a4f62d8a935345deac43f3c12"},
- {file = "pyzmq-25.1.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ddbef8b53cd16467fdbfa92a712eae46dd066aa19780681a2ce266e88fbc7165"},
- {file = "pyzmq-25.1.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9301cf1d7fc1ddf668d0abbe3e227fc9ab15bc036a31c247276012abb921b5ff"},
- {file = "pyzmq-25.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e23a8c3b6c06de40bdb9e06288180d630b562db8ac199e8cc535af81f90e64b"},
- {file = "pyzmq-25.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4a82faae00d1eed4809c2f18b37f15ce39a10a1c58fe48b60ad02875d6e13d80"},
- {file = "pyzmq-25.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c8398a1b1951aaa330269c35335ae69744be166e67e0ebd9869bdc09426f3871"},
- {file = "pyzmq-25.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d40682ac60b2a613d36d8d3a0cd14fbdf8e7e0618fbb40aa9fa7b796c9081584"},
- {file = "pyzmq-25.1.0-cp38-cp38-win32.whl", hash = "sha256:33d5c8391a34d56224bccf74f458d82fc6e24b3213fc68165c98b708c7a69325"},
- {file = "pyzmq-25.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:c66b7ff2527e18554030319b1376d81560ca0742c6e0b17ff1ee96624a5f1afd"},
- {file = "pyzmq-25.1.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:af56229ea6527a849ac9fb154a059d7e32e77a8cba27e3e62a1e38d8808cb1a5"},
- {file = "pyzmq-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bdca18b94c404af6ae5533cd1bc310c4931f7ac97c148bbfd2cd4bdd62b96253"},
- {file = "pyzmq-25.1.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0b6b42f7055bbc562f63f3df3b63e3dd1ebe9727ff0f124c3aa7bcea7b3a00f9"},
- {file = "pyzmq-25.1.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4c2fc7aad520a97d64ffc98190fce6b64152bde57a10c704b337082679e74f67"},
- {file = "pyzmq-25.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be86a26415a8b6af02cd8d782e3a9ae3872140a057f1cadf0133de685185c02b"},
- {file = "pyzmq-25.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:851fb2fe14036cfc1960d806628b80276af5424db09fe5c91c726890c8e6d943"},
- {file = "pyzmq-25.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2a21fec5c3cea45421a19ccbe6250c82f97af4175bc09de4d6dd78fb0cb4c200"},
- {file = "pyzmq-25.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bad172aba822444b32eae54c2d5ab18cd7dee9814fd5c7ed026603b8cae2d05f"},
- {file = "pyzmq-25.1.0-cp39-cp39-win32.whl", hash = "sha256:4d67609b37204acad3d566bb7391e0ecc25ef8bae22ff72ebe2ad7ffb7847158"},
- {file = "pyzmq-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:71c7b5896e40720d30cd77a81e62b433b981005bbff0cb2f739e0f8d059b5d99"},
- {file = "pyzmq-25.1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4cb27ef9d3bdc0c195b2dc54fcb8720e18b741624686a81942e14c8b67cc61a6"},
- {file = "pyzmq-25.1.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0c4fc2741e0513b5d5a12fe200d6785bbcc621f6f2278893a9ca7bed7f2efb7d"},
- {file = "pyzmq-25.1.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fc34fdd458ff77a2a00e3c86f899911f6f269d393ca5675842a6e92eea565bae"},
- {file = "pyzmq-25.1.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8751f9c1442624da391bbd92bd4b072def6d7702a9390e4479f45c182392ff78"},
- {file = "pyzmq-25.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:6581e886aec3135964a302a0f5eb68f964869b9efd1dbafdebceaaf2934f8a68"},
- {file = "pyzmq-25.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5482f08d2c3c42b920e8771ae8932fbaa0a67dff925fc476996ddd8155a170f3"},
- {file = "pyzmq-25.1.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7fbcafa3ea16d1de1f213c226005fea21ee16ed56134b75b2dede5a2129e62"},
- {file = "pyzmq-25.1.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:adecf6d02b1beab8d7c04bc36f22bb0e4c65a35eb0b4750b91693631d4081c70"},
- {file = "pyzmq-25.1.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6d39e42a0aa888122d1beb8ec0d4ddfb6c6b45aecb5ba4013c27e2f28657765"},
- {file = "pyzmq-25.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7018289b402ebf2b2c06992813523de61d4ce17bd514c4339d8f27a6f6809492"},
- {file = "pyzmq-25.1.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9e68ae9864d260b18f311b68d29134d8776d82e7f5d75ce898b40a88df9db30f"},
- {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e21cc00e4debe8f54c3ed7b9fcca540f46eee12762a9fa56feb8512fd9057161"},
- {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f666ae327a6899ff560d741681fdcdf4506f990595201ed39b44278c471ad98"},
- {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f5efcc29056dfe95e9c9db0dfbb12b62db9c4ad302f812931b6d21dd04a9119"},
- {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:48e5e59e77c1a83162ab3c163fc01cd2eebc5b34560341a67421b09be0891287"},
- {file = "pyzmq-25.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:108c96ebbd573d929740d66e4c3d1bdf31d5cde003b8dc7811a3c8c5b0fc173b"},
- {file = "pyzmq-25.1.0.tar.gz", hash = "sha256:80c41023465d36280e801564a69cbfce8ae85ff79b080e1913f6e90481fb8957"},
+ {file = "pyzmq-25.1.1-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:381469297409c5adf9a0e884c5eb5186ed33137badcbbb0560b86e910a2f1e76"},
+ {file = "pyzmq-25.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:955215ed0604dac5b01907424dfa28b40f2b2292d6493445dd34d0dfa72586a8"},
+ {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:985bbb1316192b98f32e25e7b9958088431d853ac63aca1d2c236f40afb17c83"},
+ {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:afea96f64efa98df4da6958bae37f1cbea7932c35878b185e5982821bc883369"},
+ {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76705c9325d72a81155bb6ab48d4312e0032bf045fb0754889133200f7a0d849"},
+ {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:77a41c26205d2353a4c94d02be51d6cbdf63c06fbc1295ea57dad7e2d3381b71"},
+ {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:12720a53e61c3b99d87262294e2b375c915fea93c31fc2336898c26d7aed34cd"},
+ {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:57459b68e5cd85b0be8184382cefd91959cafe79ae019e6b1ae6e2ba8a12cda7"},
+ {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:292fe3fc5ad4a75bc8df0dfaee7d0babe8b1f4ceb596437213821f761b4589f9"},
+ {file = "pyzmq-25.1.1-cp310-cp310-win32.whl", hash = "sha256:35b5ab8c28978fbbb86ea54958cd89f5176ce747c1fb3d87356cf698048a7790"},
+ {file = "pyzmq-25.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:11baebdd5fc5b475d484195e49bae2dc64b94a5208f7c89954e9e354fc609d8f"},
+ {file = "pyzmq-25.1.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:d20a0ddb3e989e8807d83225a27e5c2eb2260eaa851532086e9e0fa0d5287d83"},
+ {file = "pyzmq-25.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e1c1be77bc5fb77d923850f82e55a928f8638f64a61f00ff18a67c7404faf008"},
+ {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d89528b4943d27029a2818f847c10c2cecc79fa9590f3cb1860459a5be7933eb"},
+ {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:90f26dc6d5f241ba358bef79be9ce06de58d477ca8485e3291675436d3827cf8"},
+ {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2b92812bd214018e50b6380ea3ac0c8bb01ac07fcc14c5f86a5bb25e74026e9"},
+ {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:2f957ce63d13c28730f7fd6b72333814221c84ca2421298f66e5143f81c9f91f"},
+ {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:047a640f5c9c6ade7b1cc6680a0e28c9dd5a0825135acbd3569cc96ea00b2505"},
+ {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7f7e58effd14b641c5e4dec8c7dab02fb67a13df90329e61c869b9cc607ef752"},
+ {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c2910967e6ab16bf6fbeb1f771c89a7050947221ae12a5b0b60f3bca2ee19bca"},
+ {file = "pyzmq-25.1.1-cp311-cp311-win32.whl", hash = "sha256:76c1c8efb3ca3a1818b837aea423ff8a07bbf7aafe9f2f6582b61a0458b1a329"},
+ {file = "pyzmq-25.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:44e58a0554b21fc662f2712814a746635ed668d0fbc98b7cb9d74cb798d202e6"},
+ {file = "pyzmq-25.1.1-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:e1ffa1c924e8c72778b9ccd386a7067cddf626884fd8277f503c48bb5f51c762"},
+ {file = "pyzmq-25.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1af379b33ef33757224da93e9da62e6471cf4a66d10078cf32bae8127d3d0d4a"},
+ {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cff084c6933680d1f8b2f3b4ff5bbb88538a4aac00d199ac13f49d0698727ecb"},
+ {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2400a94f7dd9cb20cd012951a0cbf8249e3d554c63a9c0cdfd5cbb6c01d2dec"},
+ {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d81f1ddae3858b8299d1da72dd7d19dd36aab654c19671aa8a7e7fb02f6638a"},
+ {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:255ca2b219f9e5a3a9ef3081512e1358bd4760ce77828e1028b818ff5610b87b"},
+ {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a882ac0a351288dd18ecae3326b8a49d10c61a68b01419f3a0b9a306190baf69"},
+ {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:724c292bb26365659fc434e9567b3f1adbdb5e8d640c936ed901f49e03e5d32e"},
+ {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ca1ed0bb2d850aa8471387882247c68f1e62a4af0ce9c8a1dbe0d2bf69e41fb"},
+ {file = "pyzmq-25.1.1-cp312-cp312-win32.whl", hash = "sha256:b3451108ab861040754fa5208bca4a5496c65875710f76789a9ad27c801a0075"},
+ {file = "pyzmq-25.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:eadbefd5e92ef8a345f0525b5cfd01cf4e4cc651a2cffb8f23c0dd184975d787"},
+ {file = "pyzmq-25.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:db0b2af416ba735c6304c47f75d348f498b92952f5e3e8bff449336d2728795d"},
+ {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c133e93b405eb0d36fa430c94185bdd13c36204a8635470cccc200723c13bb"},
+ {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:273bc3959bcbff3f48606b28229b4721716598d76b5aaea2b4a9d0ab454ec062"},
+ {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cbc8df5c6a88ba5ae385d8930da02201165408dde8d8322072e3e5ddd4f68e22"},
+ {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:18d43df3f2302d836f2a56f17e5663e398416e9dd74b205b179065e61f1a6edf"},
+ {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:73461eed88a88c866656e08f89299720a38cb4e9d34ae6bf5df6f71102570f2e"},
+ {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:34c850ce7976d19ebe7b9d4b9bb8c9dfc7aac336c0958e2651b88cbd46682123"},
+ {file = "pyzmq-25.1.1-cp36-cp36m-win32.whl", hash = "sha256:d2045d6d9439a0078f2a34b57c7b18c4a6aef0bee37f22e4ec9f32456c852c71"},
+ {file = "pyzmq-25.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:458dea649f2f02a0b244ae6aef8dc29325a2810aa26b07af8374dc2a9faf57e3"},
+ {file = "pyzmq-25.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7cff25c5b315e63b07a36f0c2bab32c58eafbe57d0dce61b614ef4c76058c115"},
+ {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1579413ae492b05de5a6174574f8c44c2b9b122a42015c5292afa4be2507f28"},
+ {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3d0a409d3b28607cc427aa5c30a6f1e4452cc44e311f843e05edb28ab5e36da0"},
+ {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:21eb4e609a154a57c520e3d5bfa0d97e49b6872ea057b7c85257b11e78068222"},
+ {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:034239843541ef7a1aee0c7b2cb7f6aafffb005ede965ae9cbd49d5ff4ff73cf"},
+ {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f8115e303280ba09f3898194791a153862cbf9eef722ad8f7f741987ee2a97c7"},
+ {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1a5d26fe8f32f137e784f768143728438877d69a586ddeaad898558dc971a5ae"},
+ {file = "pyzmq-25.1.1-cp37-cp37m-win32.whl", hash = "sha256:f32260e556a983bc5c7ed588d04c942c9a8f9c2e99213fec11a031e316874c7e"},
+ {file = "pyzmq-25.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:abf34e43c531bbb510ae7e8f5b2b1f2a8ab93219510e2b287a944432fad135f3"},
+ {file = "pyzmq-25.1.1-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:87e34f31ca8f168c56d6fbf99692cc8d3b445abb5bfd08c229ae992d7547a92a"},
+ {file = "pyzmq-25.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c9c6c9b2c2f80747a98f34ef491c4d7b1a8d4853937bb1492774992a120f475d"},
+ {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5619f3f5a4db5dbb572b095ea3cb5cc035335159d9da950830c9c4db2fbb6995"},
+ {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a34d2395073ef862b4032343cf0c32a712f3ab49d7ec4f42c9661e0294d106f"},
+ {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25f0e6b78220aba09815cd1f3a32b9c7cb3e02cb846d1cfc526b6595f6046618"},
+ {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3669cf8ee3520c2f13b2e0351c41fea919852b220988d2049249db10046a7afb"},
+ {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2d163a18819277e49911f7461567bda923461c50b19d169a062536fffe7cd9d2"},
+ {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:df27ffddff4190667d40de7beba4a950b5ce78fe28a7dcc41d6f8a700a80a3c0"},
+ {file = "pyzmq-25.1.1-cp38-cp38-win32.whl", hash = "sha256:a382372898a07479bd34bda781008e4a954ed8750f17891e794521c3e21c2e1c"},
+ {file = "pyzmq-25.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:52533489f28d62eb1258a965f2aba28a82aa747202c8fa5a1c7a43b5db0e85c1"},
+ {file = "pyzmq-25.1.1-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:03b3f49b57264909aacd0741892f2aecf2f51fb053e7d8ac6767f6c700832f45"},
+ {file = "pyzmq-25.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:330f9e188d0d89080cde66dc7470f57d1926ff2fb5576227f14d5be7ab30b9fa"},
+ {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2ca57a5be0389f2a65e6d3bb2962a971688cbdd30b4c0bd188c99e39c234f414"},
+ {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d457aed310f2670f59cc5b57dcfced452aeeed77f9da2b9763616bd57e4dbaae"},
+ {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c56d748ea50215abef7030c72b60dd723ed5b5c7e65e7bc2504e77843631c1a6"},
+ {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8f03d3f0d01cb5a018debeb412441996a517b11c5c17ab2001aa0597c6d6882c"},
+ {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:820c4a08195a681252f46926de10e29b6bbf3e17b30037bd4250d72dd3ddaab8"},
+ {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17ef5f01d25b67ca8f98120d5fa1d21efe9611604e8eb03a5147360f517dd1e2"},
+ {file = "pyzmq-25.1.1-cp39-cp39-win32.whl", hash = "sha256:04ccbed567171579ec2cebb9c8a3e30801723c575601f9a990ab25bcac6b51e2"},
+ {file = "pyzmq-25.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:e61f091c3ba0c3578411ef505992d356a812fb200643eab27f4f70eed34a29ef"},
+ {file = "pyzmq-25.1.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ade6d25bb29c4555d718ac6d1443a7386595528c33d6b133b258f65f963bb0f6"},
+ {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0c95ddd4f6e9fca4e9e3afaa4f9df8552f0ba5d1004e89ef0a68e1f1f9807c7"},
+ {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48e466162a24daf86f6b5ca72444d2bf39a5e58da5f96370078be67c67adc978"},
+ {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abc719161780932c4e11aaebb203be3d6acc6b38d2f26c0f523b5b59d2fc1996"},
+ {file = "pyzmq-25.1.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1ccf825981640b8c34ae54231b7ed00271822ea1c6d8ba1090ebd4943759abf5"},
+ {file = "pyzmq-25.1.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c2f20ce161ebdb0091a10c9ca0372e023ce24980d0e1f810f519da6f79c60800"},
+ {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:deee9ca4727f53464daf089536e68b13e6104e84a37820a88b0a057b97bba2d2"},
+ {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:aa8d6cdc8b8aa19ceb319aaa2b660cdaccc533ec477eeb1309e2a291eaacc43a"},
+ {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:019e59ef5c5256a2c7378f2fb8560fc2a9ff1d315755204295b2eab96b254d0a"},
+ {file = "pyzmq-25.1.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:b9af3757495c1ee3b5c4e945c1df7be95562277c6e5bccc20a39aec50f826cd0"},
+ {file = "pyzmq-25.1.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:548d6482dc8aadbe7e79d1b5806585c8120bafa1ef841167bc9090522b610fa6"},
+ {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:057e824b2aae50accc0f9a0570998adc021b372478a921506fddd6c02e60308e"},
+ {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2243700cc5548cff20963f0ca92d3e5e436394375ab8a354bbea2b12911b20b0"},
+ {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79986f3b4af059777111409ee517da24a529bdbd46da578b33f25580adcff728"},
+ {file = "pyzmq-25.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:11d58723d44d6ed4dd677c5615b2ffb19d5c426636345567d6af82be4dff8a55"},
+ {file = "pyzmq-25.1.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:49d238cf4b69652257db66d0c623cd3e09b5d2e9576b56bc067a396133a00d4a"},
+ {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fedbdc753827cf014c01dbbee9c3be17e5a208dcd1bf8641ce2cd29580d1f0d4"},
+ {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc16ac425cc927d0a57d242589f87ee093884ea4804c05a13834d07c20db203c"},
+ {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11c1d2aed9079c6b0c9550a7257a836b4a637feb334904610f06d70eb44c56d2"},
+ {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e8a701123029cc240cea61dd2d16ad57cab4691804143ce80ecd9286b464d180"},
+ {file = "pyzmq-25.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:61706a6b6c24bdece85ff177fec393545a3191eeda35b07aaa1458a027ad1304"},
+ {file = "pyzmq-25.1.1.tar.gz", hash = "sha256:259c22485b71abacdfa8bf79720cd7bcf4b9d128b30ea554f01ae71fdbfdaa23"},
]
[package.dependencies]
cffi = {version = "*", markers = "implementation_name == \"pypy\""}
+[[package]]
+name = "referencing"
+version = "0.30.2"
+description = "JSON Referencing + Python"
+category = "dev"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "referencing-0.30.2-py3-none-any.whl", hash = "sha256:449b6669b6121a9e96a7f9e410b245d471e8d48964c67113ce9afe50c8dd7bdf"},
+ {file = "referencing-0.30.2.tar.gz", hash = "sha256:794ad8003c65938edcdbc027f1933215e0d0ccc0291e3ce20a4d87432b59efc0"},
+]
+
+[package.dependencies]
+attrs = ">=22.2.0"
+rpds-py = ">=0.7.0"
+
[[package]]
name = "requests"
version = "2.31.0"
@@ -2596,6 +2591,113 @@ typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9
[package.extras]
jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"]
+[[package]]
+name = "rpds-py"
+version = "0.9.2"
+description = "Python bindings to Rust's persistent data structures (rpds)"
+category = "dev"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "rpds_py-0.9.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:ab6919a09c055c9b092798ce18c6c4adf49d24d4d9e43a92b257e3f2548231e7"},
+ {file = "rpds_py-0.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d55777a80f78dd09410bd84ff8c95ee05519f41113b2df90a69622f5540c4f8b"},
+ {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a216b26e5af0a8e265d4efd65d3bcec5fba6b26909014effe20cd302fd1138fa"},
+ {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29cd8bfb2d716366a035913ced99188a79b623a3512292963d84d3e06e63b496"},
+ {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44659b1f326214950a8204a248ca6199535e73a694be8d3e0e869f820767f12f"},
+ {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:745f5a43fdd7d6d25a53ab1a99979e7f8ea419dfefebcab0a5a1e9095490ee5e"},
+ {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a987578ac5214f18b99d1f2a3851cba5b09f4a689818a106c23dbad0dfeb760f"},
+ {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bf4151acb541b6e895354f6ff9ac06995ad9e4175cbc6d30aaed08856558201f"},
+ {file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:03421628f0dc10a4119d714a17f646e2837126a25ac7a256bdf7c3943400f67f"},
+ {file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:13b602dc3e8dff3063734f02dcf05111e887f301fdda74151a93dbbc249930fe"},
+ {file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fae5cb554b604b3f9e2c608241b5d8d303e410d7dfb6d397c335f983495ce7f6"},
+ {file = "rpds_py-0.9.2-cp310-none-win32.whl", hash = "sha256:47c5f58a8e0c2c920cc7783113df2fc4ff12bf3a411d985012f145e9242a2764"},
+ {file = "rpds_py-0.9.2-cp310-none-win_amd64.whl", hash = "sha256:4ea6b73c22d8182dff91155af018b11aac9ff7eca085750455c5990cb1cfae6e"},
+ {file = "rpds_py-0.9.2-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:e564d2238512c5ef5e9d79338ab77f1cbbda6c2d541ad41b2af445fb200385e3"},
+ {file = "rpds_py-0.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f411330a6376fb50e5b7a3e66894e4a39e60ca2e17dce258d53768fea06a37bd"},
+ {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e7521f5af0233e89939ad626b15278c71b69dc1dfccaa7b97bd4cdf96536bb7"},
+ {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8d3335c03100a073883857e91db9f2e0ef8a1cf42dc0369cbb9151c149dbbc1b"},
+ {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d25b1c1096ef0447355f7293fbe9ad740f7c47ae032c2884113f8e87660d8f6e"},
+ {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a5d3fbd02efd9cf6a8ffc2f17b53a33542f6b154e88dd7b42ef4a4c0700fdad"},
+ {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5934e2833afeaf36bd1eadb57256239785f5af0220ed8d21c2896ec4d3a765f"},
+ {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:095b460e117685867d45548fbd8598a8d9999227e9061ee7f012d9d264e6048d"},
+ {file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:91378d9f4151adc223d584489591dbb79f78814c0734a7c3bfa9c9e09978121c"},
+ {file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:24a81c177379300220e907e9b864107614b144f6c2a15ed5c3450e19cf536fae"},
+ {file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:de0b6eceb46141984671802d412568d22c6bacc9b230174f9e55fc72ef4f57de"},
+ {file = "rpds_py-0.9.2-cp311-none-win32.whl", hash = "sha256:700375326ed641f3d9d32060a91513ad668bcb7e2cffb18415c399acb25de2ab"},
+ {file = "rpds_py-0.9.2-cp311-none-win_amd64.whl", hash = "sha256:0766babfcf941db8607bdaf82569ec38107dbb03c7f0b72604a0b346b6eb3298"},
+ {file = "rpds_py-0.9.2-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:b1440c291db3f98a914e1afd9d6541e8fc60b4c3aab1a9008d03da4651e67386"},
+ {file = "rpds_py-0.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0f2996fbac8e0b77fd67102becb9229986396e051f33dbceada3debaacc7033f"},
+ {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f30d205755566a25f2ae0382944fcae2f350500ae4df4e795efa9e850821d82"},
+ {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:159fba751a1e6b1c69244e23ba6c28f879a8758a3e992ed056d86d74a194a0f3"},
+ {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1f044792e1adcea82468a72310c66a7f08728d72a244730d14880cd1dabe36b"},
+ {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9251eb8aa82e6cf88510530b29eef4fac825a2b709baf5b94a6094894f252387"},
+ {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01899794b654e616c8625b194ddd1e5b51ef5b60ed61baa7a2d9c2ad7b2a4238"},
+ {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0c43f8ae8f6be1d605b0465671124aa8d6a0e40f1fb81dcea28b7e3d87ca1e1"},
+ {file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:207f57c402d1f8712618f737356e4b6f35253b6d20a324d9a47cb9f38ee43a6b"},
+ {file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b52e7c5ae35b00566d244ffefba0f46bb6bec749a50412acf42b1c3f402e2c90"},
+ {file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:978fa96dbb005d599ec4fd9ed301b1cc45f1a8f7982d4793faf20b404b56677d"},
+ {file = "rpds_py-0.9.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6aa8326a4a608e1c28da191edd7c924dff445251b94653988efb059b16577a4d"},
+ {file = "rpds_py-0.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aad51239bee6bff6823bbbdc8ad85136c6125542bbc609e035ab98ca1e32a192"},
+ {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd4dc3602370679c2dfb818d9c97b1137d4dd412230cfecd3c66a1bf388a196"},
+ {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dd9da77c6ec1f258387957b754f0df60766ac23ed698b61941ba9acccd3284d1"},
+ {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:190ca6f55042ea4649ed19c9093a9be9d63cd8a97880106747d7147f88a49d18"},
+ {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:876bf9ed62323bc7dcfc261dbc5572c996ef26fe6406b0ff985cbcf460fc8a4c"},
+ {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa2818759aba55df50592ecbc95ebcdc99917fa7b55cc6796235b04193eb3c55"},
+ {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9ea4d00850ef1e917815e59b078ecb338f6a8efda23369677c54a5825dbebb55"},
+ {file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:5855c85eb8b8a968a74dc7fb014c9166a05e7e7a8377fb91d78512900aadd13d"},
+ {file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:14c408e9d1a80dcb45c05a5149e5961aadb912fff42ca1dd9b68c0044904eb32"},
+ {file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:65a0583c43d9f22cb2130c7b110e695fff834fd5e832a776a107197e59a1898e"},
+ {file = "rpds_py-0.9.2-cp38-none-win32.whl", hash = "sha256:71f2f7715935a61fa3e4ae91d91b67e571aeb5cb5d10331ab681256bda2ad920"},
+ {file = "rpds_py-0.9.2-cp38-none-win_amd64.whl", hash = "sha256:674c704605092e3ebbbd13687b09c9f78c362a4bc710343efe37a91457123044"},
+ {file = "rpds_py-0.9.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:07e2c54bef6838fa44c48dfbc8234e8e2466d851124b551fc4e07a1cfeb37260"},
+ {file = "rpds_py-0.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f7fdf55283ad38c33e35e2855565361f4bf0abd02470b8ab28d499c663bc5d7c"},
+ {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:890ba852c16ace6ed9f90e8670f2c1c178d96510a21b06d2fa12d8783a905193"},
+ {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50025635ba8b629a86d9d5474e650da304cb46bbb4d18690532dd79341467846"},
+ {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:517cbf6e67ae3623c5127206489d69eb2bdb27239a3c3cc559350ef52a3bbf0b"},
+ {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0836d71ca19071090d524739420a61580f3f894618d10b666cf3d9a1688355b1"},
+ {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c439fd54b2b9053717cca3de9583be6584b384d88d045f97d409f0ca867d80f"},
+ {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f68996a3b3dc9335037f82754f9cdbe3a95db42bde571d8c3be26cc6245f2324"},
+ {file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7d68dc8acded354c972116f59b5eb2e5864432948e098c19fe6994926d8e15c3"},
+ {file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f963c6b1218b96db85fc37a9f0851eaf8b9040aa46dec112611697a7023da535"},
+ {file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a46859d7f947061b4010e554ccd1791467d1b1759f2dc2ec9055fa239f1bc26"},
+ {file = "rpds_py-0.9.2-cp39-none-win32.whl", hash = "sha256:e07e5dbf8a83c66783a9fe2d4566968ea8c161199680e8ad38d53e075df5f0d0"},
+ {file = "rpds_py-0.9.2-cp39-none-win_amd64.whl", hash = "sha256:682726178138ea45a0766907957b60f3a1bf3acdf212436be9733f28b6c5af3c"},
+ {file = "rpds_py-0.9.2-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:196cb208825a8b9c8fc360dc0f87993b8b260038615230242bf18ec84447c08d"},
+ {file = "rpds_py-0.9.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:c7671d45530fcb6d5e22fd40c97e1e1e01965fc298cbda523bb640f3d923b387"},
+ {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83b32f0940adec65099f3b1c215ef7f1d025d13ff947975a055989cb7fd019a4"},
+ {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f67da97f5b9eac838b6980fc6da268622e91f8960e083a34533ca710bec8611"},
+ {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03975db5f103997904c37e804e5f340c8fdabbb5883f26ee50a255d664eed58c"},
+ {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:987b06d1cdb28f88a42e4fb8a87f094e43f3c435ed8e486533aea0bf2e53d931"},
+ {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c861a7e4aef15ff91233751619ce3a3d2b9e5877e0fcd76f9ea4f6847183aa16"},
+ {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02938432352359805b6da099c9c95c8a0547fe4b274ce8f1a91677401bb9a45f"},
+ {file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:ef1f08f2a924837e112cba2953e15aacfccbbfcd773b4b9b4723f8f2ddded08e"},
+ {file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:35da5cc5cb37c04c4ee03128ad59b8c3941a1e5cd398d78c37f716f32a9b7f67"},
+ {file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:141acb9d4ccc04e704e5992d35472f78c35af047fa0cfae2923835d153f091be"},
+ {file = "rpds_py-0.9.2-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:79f594919d2c1a0cc17d1988a6adaf9a2f000d2e1048f71f298b056b1018e872"},
+ {file = "rpds_py-0.9.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:a06418fe1155e72e16dddc68bb3780ae44cebb2912fbd8bb6ff9161de56e1798"},
+ {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b2eb034c94b0b96d5eddb290b7b5198460e2d5d0c421751713953a9c4e47d10"},
+ {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b08605d248b974eb02f40bdcd1a35d3924c83a2a5e8f5d0fa5af852c4d960af"},
+ {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a0805911caedfe2736935250be5008b261f10a729a303f676d3d5fea6900c96a"},
+ {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab2299e3f92aa5417d5e16bb45bb4586171c1327568f638e8453c9f8d9e0f020"},
+ {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c8d7594e38cf98d8a7df25b440f684b510cf4627fe038c297a87496d10a174f"},
+ {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b9ec12ad5f0a4625db34db7e0005be2632c1013b253a4a60e8302ad4d462afd"},
+ {file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1fcdee18fea97238ed17ab6478c66b2095e4ae7177e35fb71fbe561a27adf620"},
+ {file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:933a7d5cd4b84f959aedeb84f2030f0a01d63ae6cf256629af3081cf3e3426e8"},
+ {file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:686ba516e02db6d6f8c279d1641f7067ebb5dc58b1d0536c4aaebb7bf01cdc5d"},
+ {file = "rpds_py-0.9.2-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0173c0444bec0a3d7d848eaeca2d8bd32a1b43f3d3fde6617aac3731fa4be05f"},
+ {file = "rpds_py-0.9.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d576c3ef8c7b2d560e301eb33891d1944d965a4d7a2eacb6332eee8a71827db6"},
+ {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed89861ee8c8c47d6beb742a602f912b1bb64f598b1e2f3d758948721d44d468"},
+ {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1054a08e818f8e18910f1bee731583fe8f899b0a0a5044c6e680ceea34f93876"},
+ {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99e7c4bb27ff1aab90dcc3e9d37ee5af0231ed98d99cb6f5250de28889a3d502"},
+ {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c545d9d14d47be716495076b659db179206e3fd997769bc01e2d550eeb685596"},
+ {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9039a11bca3c41be5a58282ed81ae422fa680409022b996032a43badef2a3752"},
+ {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fb39aca7a64ad0c9490adfa719dbeeb87d13be137ca189d2564e596f8ba32c07"},
+ {file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2d8b3b3a2ce0eaa00c5bbbb60b6713e94e7e0becab7b3db6c5c77f979e8ed1f1"},
+ {file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:99b1c16f732b3a9971406fbfe18468592c5a3529585a45a35adbc1389a529a03"},
+ {file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c27ee01a6c3223025f4badd533bea5e87c988cb0ba2811b690395dfe16088cfe"},
+ {file = "rpds_py-0.9.2.tar.gz", hash = "sha256:8d70e8f14900f2657c249ea4def963bed86a29b81f81f5b76b5a9215680de945"},
+]
+
[[package]]
name = "scipy"
version = "1.10.1"
@@ -2858,53 +2960,50 @@ test = ["pytest"]
[[package]]
name = "sqlalchemy"
-version = "1.4.48"
+version = "1.4.49"
description = "Database Abstraction Library"
category = "main"
optional = true
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
files = [
- {file = "SQLAlchemy-1.4.48-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:4bac3aa3c3d8bc7408097e6fe8bf983caa6e9491c5d2e2488cfcfd8106f13b6a"},
- {file = "SQLAlchemy-1.4.48-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:dbcae0e528d755f4522cad5842f0942e54b578d79f21a692c44d91352ea6d64e"},
- {file = "SQLAlchemy-1.4.48-cp27-cp27m-win32.whl", hash = "sha256:cbbe8b8bffb199b225d2fe3804421b7b43a0d49983f81dc654d0431d2f855543"},
- {file = "SQLAlchemy-1.4.48-cp27-cp27m-win_amd64.whl", hash = "sha256:627e04a5d54bd50628fc8734d5fc6df2a1aa5962f219c44aad50b00a6cdcf965"},
- {file = "SQLAlchemy-1.4.48-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9af1db7a287ef86e0f5cd990b38da6bd9328de739d17e8864f1817710da2d217"},
- {file = "SQLAlchemy-1.4.48-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:ce7915eecc9c14a93b73f4e1c9d779ca43e955b43ddf1e21df154184f39748e5"},
- {file = "SQLAlchemy-1.4.48-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5381ddd09a99638f429f4cbe1b71b025bed318f6a7b23e11d65f3eed5e181c33"},
- {file = "SQLAlchemy-1.4.48-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:87609f6d4e81a941a17e61a4c19fee57f795e96f834c4f0a30cee725fc3f81d9"},
- {file = "SQLAlchemy-1.4.48-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb0808ad34167f394fea21bd4587fc62f3bd81bba232a1e7fbdfa17e6cfa7cd7"},
- {file = "SQLAlchemy-1.4.48-cp310-cp310-win32.whl", hash = "sha256:d53cd8bc582da5c1c8c86b6acc4ef42e20985c57d0ebc906445989df566c5603"},
- {file = "SQLAlchemy-1.4.48-cp310-cp310-win_amd64.whl", hash = "sha256:4355e5915844afdc5cf22ec29fba1010166e35dd94a21305f49020022167556b"},
- {file = "SQLAlchemy-1.4.48-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:066c2b0413e8cb980e6d46bf9d35ca83be81c20af688fedaef01450b06e4aa5e"},
- {file = "SQLAlchemy-1.4.48-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c99bf13e07140601d111a7c6f1fc1519914dd4e5228315bbda255e08412f61a4"},
- {file = "SQLAlchemy-1.4.48-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ee26276f12614d47cc07bc85490a70f559cba965fb178b1c45d46ffa8d73fda"},
- {file = "SQLAlchemy-1.4.48-cp311-cp311-win32.whl", hash = "sha256:49c312bcff4728bffc6fb5e5318b8020ed5c8b958a06800f91859fe9633ca20e"},
- {file = "SQLAlchemy-1.4.48-cp311-cp311-win_amd64.whl", hash = "sha256:cef2e2abc06eab187a533ec3e1067a71d7bbec69e582401afdf6d8cad4ba3515"},
- {file = "SQLAlchemy-1.4.48-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:3509159e050bd6d24189ec7af373359f07aed690db91909c131e5068176c5a5d"},
- {file = "SQLAlchemy-1.4.48-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fc2ab4d9f6d9218a5caa4121bdcf1125303482a1cdcfcdbd8567be8518969c0"},
- {file = "SQLAlchemy-1.4.48-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e1ddbbcef9bcedaa370c03771ebec7e39e3944782bef49e69430383c376a250b"},
- {file = "SQLAlchemy-1.4.48-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f82d8efea1ca92b24f51d3aea1a82897ed2409868a0af04247c8c1e4fef5890"},
- {file = "SQLAlchemy-1.4.48-cp36-cp36m-win32.whl", hash = "sha256:e3e98d4907805b07743b583a99ecc58bf8807ecb6985576d82d5e8ae103b5272"},
- {file = "SQLAlchemy-1.4.48-cp36-cp36m-win_amd64.whl", hash = "sha256:25887b4f716e085a1c5162f130b852f84e18d2633942c8ca40dfb8519367c14f"},
- {file = "SQLAlchemy-1.4.48-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:0817c181271b0ce5df1aa20949f0a9e2426830fed5ecdcc8db449618f12c2730"},
- {file = "SQLAlchemy-1.4.48-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe1dd2562313dd9fe1778ed56739ad5d9aae10f9f43d9f4cf81d65b0c85168bb"},
- {file = "SQLAlchemy-1.4.48-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:68413aead943883b341b2b77acd7a7fe2377c34d82e64d1840860247cec7ff7c"},
- {file = "SQLAlchemy-1.4.48-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbde5642104ac6e95f96e8ad6d18d9382aa20672008cf26068fe36f3004491df"},
- {file = "SQLAlchemy-1.4.48-cp37-cp37m-win32.whl", hash = "sha256:11c6b1de720f816c22d6ad3bbfa2f026f89c7b78a5c4ffafb220e0183956a92a"},
- {file = "SQLAlchemy-1.4.48-cp37-cp37m-win_amd64.whl", hash = "sha256:eb5464ee8d4bb6549d368b578e9529d3c43265007193597ddca71c1bae6174e6"},
- {file = "SQLAlchemy-1.4.48-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:92e6133cf337c42bfee03ca08c62ba0f2d9695618c8abc14a564f47503157be9"},
- {file = "SQLAlchemy-1.4.48-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44d29a3fc6d9c45962476b470a81983dd8add6ad26fdbfae6d463b509d5adcda"},
- {file = "SQLAlchemy-1.4.48-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:005e942b451cad5285015481ae4e557ff4154dde327840ba91b9ac379be3b6ce"},
- {file = "SQLAlchemy-1.4.48-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c8cfe951ed074ba5e708ed29c45397a95c4143255b0d022c7c8331a75ae61f3"},
- {file = "SQLAlchemy-1.4.48-cp38-cp38-win32.whl", hash = "sha256:2b9af65cc58726129d8414fc1a1a650dcdd594ba12e9c97909f1f57d48e393d3"},
- {file = "SQLAlchemy-1.4.48-cp38-cp38-win_amd64.whl", hash = "sha256:2b562e9d1e59be7833edf28b0968f156683d57cabd2137d8121806f38a9d58f4"},
- {file = "SQLAlchemy-1.4.48-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:a1fc046756cf2a37d7277c93278566ddf8be135c6a58397b4c940abf837011f4"},
- {file = "SQLAlchemy-1.4.48-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d9b55252d2ca42a09bcd10a697fa041e696def9dfab0b78c0aaea1485551a08"},
- {file = "SQLAlchemy-1.4.48-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6dab89874e72a9ab5462997846d4c760cdb957958be27b03b49cf0de5e5c327c"},
- {file = "SQLAlchemy-1.4.48-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fd8b5ee5a3acc4371f820934b36f8109ce604ee73cc668c724abb054cebcb6e"},
- {file = "SQLAlchemy-1.4.48-cp39-cp39-win32.whl", hash = "sha256:eee09350fd538e29cfe3a496ec6f148504d2da40dbf52adefb0d2f8e4d38ccc4"},
- {file = "SQLAlchemy-1.4.48-cp39-cp39-win_amd64.whl", hash = "sha256:7ad2b0f6520ed5038e795cc2852eb5c1f20fa6831d73301ced4aafbe3a10e1f6"},
- {file = "SQLAlchemy-1.4.48.tar.gz", hash = "sha256:b47bc287096d989a0838ce96f7d8e966914a24da877ed41a7531d44b55cdb8df"},
+ {file = "SQLAlchemy-1.4.49-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2e126cf98b7fd38f1e33c64484406b78e937b1a280e078ef558b95bf5b6895f6"},
+ {file = "SQLAlchemy-1.4.49-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:03db81b89fe7ef3857b4a00b63dedd632d6183d4ea5a31c5d8a92e000a41fc71"},
+ {file = "SQLAlchemy-1.4.49-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:95b9df9afd680b7a3b13b38adf6e3a38995da5e162cc7524ef08e3be4e5ed3e1"},
+ {file = "SQLAlchemy-1.4.49-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a63e43bf3f668c11bb0444ce6e809c1227b8f067ca1068898f3008a273f52b09"},
+ {file = "SQLAlchemy-1.4.49-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f835c050ebaa4e48b18403bed2c0fda986525896efd76c245bdd4db995e51a4c"},
+ {file = "SQLAlchemy-1.4.49-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c21b172dfb22e0db303ff6419451f0cac891d2e911bb9fbf8003d717f1bcf91"},
+ {file = "SQLAlchemy-1.4.49-cp310-cp310-win32.whl", hash = "sha256:5fb1ebdfc8373b5a291485757bd6431de8d7ed42c27439f543c81f6c8febd729"},
+ {file = "SQLAlchemy-1.4.49-cp310-cp310-win_amd64.whl", hash = "sha256:f8a65990c9c490f4651b5c02abccc9f113a7f56fa482031ac8cb88b70bc8ccaa"},
+ {file = "SQLAlchemy-1.4.49-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8923dfdf24d5aa8a3adb59723f54118dd4fe62cf59ed0d0d65d940579c1170a4"},
+ {file = "SQLAlchemy-1.4.49-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9ab2c507a7a439f13ca4499db6d3f50423d1d65dc9b5ed897e70941d9e135b0"},
+ {file = "SQLAlchemy-1.4.49-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5debe7d49b8acf1f3035317e63d9ec8d5e4d904c6e75a2a9246a119f5f2fdf3d"},
+ {file = "SQLAlchemy-1.4.49-cp311-cp311-win32.whl", hash = "sha256:82b08e82da3756765c2e75f327b9bf6b0f043c9c3925fb95fb51e1567fa4ee87"},
+ {file = "SQLAlchemy-1.4.49-cp311-cp311-win_amd64.whl", hash = "sha256:171e04eeb5d1c0d96a544caf982621a1711d078dbc5c96f11d6469169bd003f1"},
+ {file = "SQLAlchemy-1.4.49-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:36e58f8c4fe43984384e3fbe6341ac99b6b4e083de2fe838f0fdb91cebe9e9cb"},
+ {file = "SQLAlchemy-1.4.49-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b31e67ff419013f99ad6f8fc73ee19ea31585e1e9fe773744c0f3ce58c039c30"},
+ {file = "SQLAlchemy-1.4.49-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c14b29d9e1529f99efd550cd04dbb6db6ba5d690abb96d52de2bff4ed518bc95"},
+ {file = "SQLAlchemy-1.4.49-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c40f3470e084d31247aea228aa1c39bbc0904c2b9ccbf5d3cfa2ea2dac06f26d"},
+ {file = "SQLAlchemy-1.4.49-cp36-cp36m-win32.whl", hash = "sha256:706bfa02157b97c136547c406f263e4c6274a7b061b3eb9742915dd774bbc264"},
+ {file = "SQLAlchemy-1.4.49-cp36-cp36m-win_amd64.whl", hash = "sha256:a7f7b5c07ae5c0cfd24c2db86071fb2a3d947da7bd487e359cc91e67ac1c6d2e"},
+ {file = "SQLAlchemy-1.4.49-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:4afbbf5ef41ac18e02c8dc1f86c04b22b7a2125f2a030e25bbb4aff31abb224b"},
+ {file = "SQLAlchemy-1.4.49-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24e300c0c2147484a002b175f4e1361f102e82c345bf263242f0449672a4bccf"},
+ {file = "SQLAlchemy-1.4.49-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:201de072b818f8ad55c80d18d1a788729cccf9be6d9dc3b9d8613b053cd4836d"},
+ {file = "SQLAlchemy-1.4.49-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7653ed6817c710d0c95558232aba799307d14ae084cc9b1f4c389157ec50df5c"},
+ {file = "SQLAlchemy-1.4.49-cp37-cp37m-win32.whl", hash = "sha256:647e0b309cb4512b1f1b78471fdaf72921b6fa6e750b9f891e09c6e2f0e5326f"},
+ {file = "SQLAlchemy-1.4.49-cp37-cp37m-win_amd64.whl", hash = "sha256:ab73ed1a05ff539afc4a7f8cf371764cdf79768ecb7d2ec691e3ff89abbc541e"},
+ {file = "SQLAlchemy-1.4.49-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:37ce517c011560d68f1ffb28af65d7e06f873f191eb3a73af5671e9c3fada08a"},
+ {file = "SQLAlchemy-1.4.49-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1878ce508edea4a879015ab5215546c444233881301e97ca16fe251e89f1c55"},
+ {file = "SQLAlchemy-1.4.49-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0e8e608983e6f85d0852ca61f97e521b62e67969e6e640fe6c6b575d4db68557"},
+ {file = "SQLAlchemy-1.4.49-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ccf956da45290df6e809ea12c54c02ace7f8ff4d765d6d3dfb3655ee876ce58d"},
+ {file = "SQLAlchemy-1.4.49-cp38-cp38-win32.whl", hash = "sha256:f167c8175ab908ce48bd6550679cc6ea20ae169379e73c7720a28f89e53aa532"},
+ {file = "SQLAlchemy-1.4.49-cp38-cp38-win_amd64.whl", hash = "sha256:45806315aae81a0c202752558f0df52b42d11dd7ba0097bf71e253b4215f34f4"},
+ {file = "SQLAlchemy-1.4.49-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:b6d0c4b15d65087738a6e22e0ff461b407533ff65a73b818089efc8eb2b3e1de"},
+ {file = "SQLAlchemy-1.4.49-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a843e34abfd4c797018fd8d00ffffa99fd5184c421f190b6ca99def4087689bd"},
+ {file = "SQLAlchemy-1.4.49-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1c890421651b45a681181301b3497e4d57c0d01dc001e10438a40e9a9c25ee77"},
+ {file = "SQLAlchemy-1.4.49-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d26f280b8f0a8f497bc10573849ad6dc62e671d2468826e5c748d04ed9e670d5"},
+ {file = "SQLAlchemy-1.4.49-cp39-cp39-win32.whl", hash = "sha256:ec2268de67f73b43320383947e74700e95c6770d0c68c4e615e9897e46296294"},
+ {file = "SQLAlchemy-1.4.49-cp39-cp39-win_amd64.whl", hash = "sha256:bbdf16372859b8ed3f4d05f925a984771cd2abd18bd187042f24be4886c2a15f"},
+ {file = "SQLAlchemy-1.4.49.tar.gz", hash = "sha256:06ff25cbae30c396c4b7737464f2a7fc37a67b7da409993b182b024cec80aed9"},
]
[package.dependencies]
@@ -2984,35 +3083,35 @@ files = [
[[package]]
name = "tomlkit"
-version = "0.11.8"
+version = "0.12.1"
description = "Style preserving TOML library"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"},
- {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"},
+ {file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"},
+ {file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"},
]
[[package]]
name = "tornado"
-version = "6.3.2"
+version = "6.3.3"
description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
category = "dev"
optional = false
python-versions = ">= 3.8"
files = [
- {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:c367ab6c0393d71171123ca5515c61ff62fe09024fa6bf299cd1339dc9456829"},
- {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b46a6ab20f5c7c1cb949c72c1994a4585d2eaa0be4853f50a03b5031e964fc7c"},
- {file = "tornado-6.3.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2de14066c4a38b4ecbbcd55c5cc4b5340eb04f1c5e81da7451ef555859c833f"},
- {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05615096845cf50a895026f749195bf0b10b8909f9be672f50b0fe69cba368e4"},
- {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b17b1cf5f8354efa3d37c6e28fdfd9c1c1e5122f2cb56dac121ac61baa47cbe"},
- {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:29e71c847a35f6e10ca3b5c2990a52ce38b233019d8e858b755ea6ce4dcdd19d"},
- {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:834ae7540ad3a83199a8da8f9f2d383e3c3d5130a328889e4cc991acc81e87a0"},
- {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6a0848f1aea0d196a7c4f6772197cbe2abc4266f836b0aac76947872cd29b411"},
- {file = "tornado-6.3.2-cp38-abi3-win32.whl", hash = "sha256:7efcbcc30b7c654eb6a8c9c9da787a851c18f8ccd4a5a3a95b05c7accfa068d2"},
- {file = "tornado-6.3.2-cp38-abi3-win_amd64.whl", hash = "sha256:0c325e66c8123c606eea33084976c832aa4e766b7dff8aedd7587ea44a604cdf"},
- {file = "tornado-6.3.2.tar.gz", hash = "sha256:4b927c4f19b71e627b13f3db2324e4ae660527143f9e1f2e2fb404f3a187e2ba"},
+ {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d"},
+ {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a"},
+ {file = "tornado-6.3.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd19ca6c16882e4d37368e0152f99c099bad93e0950ce55e71daed74045908f"},
+ {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ac51f42808cca9b3613f51ffe2a965c8525cb1b00b7b2d56828b8045354f76a"},
+ {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71a8db65160a3c55d61839b7302a9a400074c9c753040455494e2af74e2501f2"},
+ {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ceb917a50cd35882b57600709dd5421a418c29ddc852da8bcdab1f0db33406b0"},
+ {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:7d01abc57ea0dbb51ddfed477dfe22719d376119844e33c661d873bf9c0e4a16"},
+ {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9dc4444c0defcd3929d5c1eb5706cbe1b116e762ff3e0deca8b715d14bf6ec17"},
+ {file = "tornado-6.3.3-cp38-abi3-win32.whl", hash = "sha256:65ceca9500383fbdf33a98c0087cb975b2ef3bfb874cb35b8de8740cf7f41bd3"},
+ {file = "tornado-6.3.3-cp38-abi3-win_amd64.whl", hash = "sha256:22d3c2fa10b5793da13c807e6fc38ff49a4f6e1e3868b0a6f4164768bb8e20f5"},
+ {file = "tornado-6.3.3.tar.gz", hash = "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe"},
]
[[package]]
@@ -3033,26 +3132,26 @@ test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"]
[[package]]
name = "typing-extensions"
-version = "4.6.3"
+version = "4.7.1"
description = "Backported and Experimental Type Hints for Python 3.7+"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
- {file = "typing_extensions-4.6.3-py3-none-any.whl", hash = "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26"},
- {file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"},
+ {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"},
+ {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"},
]
[[package]]
name = "urllib3"
-version = "2.0.3"
+version = "2.0.4"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "urllib3-2.0.3-py3-none-any.whl", hash = "sha256:48e7fafa40319d358848e1bc6809b208340fafe2096f1725d05d67443d0483d1"},
- {file = "urllib3-2.0.3.tar.gz", hash = "sha256:bee28b5e56addb8226c96f7f13ac28cb4c301dd5ea8a6ca179c0b9835e032825"},
+ {file = "urllib3-2.0.4-py3-none-any.whl", hash = "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"},
+ {file = "urllib3-2.0.4.tar.gz", hash = "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11"},
]
[package.extras]
@@ -3063,24 +3162,24 @@ zstd = ["zstandard (>=0.18.0)"]
[[package]]
name = "virtualenv"
-version = "20.23.0"
+version = "20.24.3"
description = "Virtual Python Environment builder"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "virtualenv-20.23.0-py3-none-any.whl", hash = "sha256:6abec7670e5802a528357fdc75b26b9f57d5d92f29c5462ba0fbe45feacc685e"},
- {file = "virtualenv-20.23.0.tar.gz", hash = "sha256:a85caa554ced0c0afbd0d638e7e2d7b5f92d23478d05d17a76daeac8f279f924"},
+ {file = "virtualenv-20.24.3-py3-none-any.whl", hash = "sha256:95a6e9398b4967fbcb5fef2acec5efaf9aa4972049d9ae41f95e0972a683fd02"},
+ {file = "virtualenv-20.24.3.tar.gz", hash = "sha256:e5c3b4ce817b0b328af041506a2a299418c98747c4b1e68cb7527e74ced23efc"},
]
[package.dependencies]
-distlib = ">=0.3.6,<1"
-filelock = ">=3.11,<4"
-platformdirs = ">=3.2,<4"
+distlib = ">=0.3.7,<1"
+filelock = ">=3.12.2,<4"
+platformdirs = ">=3.9.1,<4"
[package.extras]
-docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"]
-test = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.7.1)", "time-machine (>=2.9)"]
+docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
+test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
[[package]]
name = "wcwidth"
@@ -3204,19 +3303,19 @@ files = [
[[package]]
name = "zipp"
-version = "3.15.0"
+version = "3.16.2"
description = "Backport of pathlib-compatible object wrapper for zip files"
category = "main"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
- {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
+ {file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"},
+ {file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"},
]
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
[extras]
box = ["click", "rich"]
@@ -3225,4 +3324,4 @@ mark = ["banana-hep", "matplotlib", "pandas", "sqlalchemy"]
[metadata]
lock-version = "2.0"
python-versions = "^3.8,<3.12"
-content-hash = "1b953c2ab9f1d4629f923a290a9db0b092ce2ff711b2e6009372cf1d602d5da3"
+content-hash = "223b56c91574c33cd1f4b6b74a6bde4002d72ab471ef8f90dc6d453b4936756e"
diff --git a/pyproject.toml b/pyproject.toml
index 31be6cb0c..ac9192de3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -44,7 +44,7 @@ PyYAML = "^6.0"
lz4 = "^4.0.2"
numba = "^0.57.0"
# ekomark
-banana-hep = { version = "^0.6.9", optional = true }
+banana-hep = { version = "^0.6.10", optional = true }
sqlalchemy = { version = "^1.4.21", optional = true }
pandas = { version = "^1.3.0", optional = true }
matplotlib = { version = "^3.5.1", optional = true }
From a49fca63858f9e7101e8dc1a40a63e54606e9e20 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 12 Jan 2024 16:40:44 +0200
Subject: [PATCH 51/67] Fix evol_pdf
---
src/ekobox/evol_pdf.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/ekobox/evol_pdf.py b/src/ekobox/evol_pdf.py
index 94c8e416c..4310a0eda 100644
--- a/src/ekobox/evol_pdf.py
+++ b/src/ekobox/evol_pdf.py
@@ -60,12 +60,16 @@ def evolve_pdfs(
# apply PDF to eko
evolved_PDF_list = []
+ q2block_per_nf = {}
with EKO.read(eko_path) as eko_output:
for initial_PDF in initial_PDF_list:
evolved_PDF_list.append(
apply.apply_pdf(eko_output, initial_PDF, targetgrid)
)
+ # separate by nf the evolgrid (and order per nf/q)
+ q2block_per_nf = regroup_evolgrid(eko_output.evolgrid) # pylint: disable=E1101
+
# update info file
if targetgrid is None:
targetgrid = operators_card.xgrid
@@ -80,9 +84,6 @@ def evolve_pdfs(
info_update=info_update,
)
- # separate by nf the evolgrid (and order per nf/q)
- q2block_per_nf = regroup_evolgrid(eko_output.evolgrid)
-
# write all replicas
all_member_blocks = []
for evolved_PDF in evolved_PDF_list:
From 7bf06e2ffaa0cdb892004e29cb838d40b9786bbc Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 15 Jul 2024 16:08:38 +0300
Subject: [PATCH 52/67] Fix outdated sc tests
---
tests/eko/scale_variations/test_diff.py | 4 +---
tests/eko/scale_variations/test_expanded.py | 4 +---
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/tests/eko/scale_variations/test_diff.py b/tests/eko/scale_variations/test_diff.py
index c0dd67236..6c169e3bd 100644
--- a/tests/eko/scale_variations/test_diff.py
+++ b/tests/eko/scale_variations/test_diff.py
@@ -27,9 +27,7 @@ def compute_a_s(q2, order):
couplings=CouplingsInfo(
alphas=0.1181,
alphaem=0.007496,
- scale=91.00,
- max_num_flavs=4,
- num_flavs_ref=4,
+ ref=(91.00, 4),
),
order=order,
method=CouplingEvolutionMethod.EXPANDED,
diff --git a/tests/eko/scale_variations/test_expanded.py b/tests/eko/scale_variations/test_expanded.py
index 6af22dd51..be14e45a6 100644
--- a/tests/eko/scale_variations/test_expanded.py
+++ b/tests/eko/scale_variations/test_expanded.py
@@ -18,9 +18,7 @@ def compute_a_s(q2, order):
couplings=CouplingsInfo(
alphas=0.1181,
alphaem=0.007496,
- scale=91.00,
- max_num_flavs=4,
- num_flavs_ref=4,
+ ref=(91.00, 4),
),
order=order,
method=CouplingEvolutionMethod.EXPANDED,
From 618639b606b1a7aa93276dcc1fd9e87c51c51ba1 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 15 Jul 2024 16:12:20 +0300
Subject: [PATCH 53/67] Appease black
---
src/ekomark/data/__init__.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/ekomark/data/__init__.py b/src/ekomark/data/__init__.py
index b6242845b..89fb6377b 100644
--- a/src/ekomark/data/__init__.py
+++ b/src/ekomark/data/__init__.py
@@ -1,4 +1,5 @@
"""EKO database configuration."""
+
from typing import Union
from eko.io.runcards import Legacy, OperatorCard, TheoryCard
From 6b004dba87d494415a71a78535c65fbe32b7c142 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 19 Jul 2024 14:37:54 +0300
Subject: [PATCH 54/67] Make add SV to ModeMixin name
---
src/eko/evolution_operator/__init__.py | 2 +-
src/eko/evolution_operator/__init__.py.patch | 8 ++++----
src/eko/evolution_operator/grid.py | 2 +-
src/eko/scale_variations/__init__.py | 2 +-
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py
index 1c759c5c5..16aa4bb5b 100644
--- a/src/eko/evolution_operator/__init__.py
+++ b/src/eko/evolution_operator/__init__.py
@@ -600,7 +600,7 @@ def quad_ker_qed(
return ker
-class Operator(sv.ModeMixin):
+class Operator(sv.ScaleVariationModeMixin):
"""Internal representation of a single EKO.
The actual matrices are computed upon calling :meth:`compute`.
diff --git a/src/eko/evolution_operator/__init__.py.patch b/src/eko/evolution_operator/__init__.py.patch
index a3bc24ec1..58c3f74fd 100644
--- a/src/eko/evolution_operator/__init__.py.patch
+++ b/src/eko/evolution_operator/__init__.py.patch
@@ -534,10 +534,10 @@ index 1c759c5c..5eb394d0 100644
- return ker
-
-
- class Operator(sv.ModeMixin):
+ class Operator(sv.ScaleVariationModeMixin):
"""Internal representation of a single EKO.
-@@ -780,50 +282,6 @@ class Operator(sv.ModeMixin):
+@@ -780,50 +282,6 @@ class Operator(sv.ScaleVariationModeMixin):
labels.extend(br.singlet_unified_labels)
return labels
@@ -588,7 +588,7 @@ index 1c759c5c..5eb394d0 100644
def initialize_op_members(self):
"""Init all operators with the identity or zeros."""
eye = OpMember(
-@@ -846,10 +304,7 @@ class Operator(sv.ModeMixin):
+@@ -846,10 +304,7 @@ class Operator(sv.ScaleVariationModeMixin):
else:
self.op_members[n] = zero.copy()
@@ -600,7 +600,7 @@ index 1c759c5c..5eb394d0 100644
"""Run the integration for each grid point.
Parameters
-@@ -864,18 +319,56 @@ class Operator(sv.ModeMixin):
+@@ -864,18 +319,56 @@ class Operator(sv.ScaleVariationModeMixin):
"""
column = []
k, logx = log_grid
diff --git a/src/eko/evolution_operator/grid.py b/src/eko/evolution_operator/grid.py
index e64885418..2539c3fc7 100644
--- a/src/eko/evolution_operator/grid.py
+++ b/src/eko/evolution_operator/grid.py
@@ -29,7 +29,7 @@
"""In particular, only the ``operator`` and ``error`` fields are expected."""
-class OperatorGrid(sv.ModeMixin):
+class OperatorGrid(sv.ScaleVariationModeMixin):
"""Collection of evolution operators for several scales.
The operator grid is the driver class of the evolution.
diff --git a/src/eko/scale_variations/__init__.py b/src/eko/scale_variations/__init__.py
index 4af80592b..9c43f1f9c 100644
--- a/src/eko/scale_variations/__init__.py
+++ b/src/eko/scale_variations/__init__.py
@@ -36,7 +36,7 @@ def sv_mode(s):
return Modes.unvaried
-class ModeMixin:
+class ScaleVariationModeMixin:
"""Mixin to cast scale variation mode."""
@property
From 7a6c1cc2c42bd63a42ad2e4bae4d362cd4daafb7 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 19 Jul 2024 15:15:12 +0300
Subject: [PATCH 55/67] Introduce EvoMethods
---
src/eko/evolution_operator/__init__.py | 6 +++++
src/eko/kernels/__init__.py | 32 ++++++++++++++++++++++++++
src/eko/scale_variations/__init__.py | 13 ++++++-----
tests/eko/kernels/test_init.py | 21 +++++++++++++++++
4 files changed, 66 insertions(+), 6 deletions(-)
create mode 100644 tests/eko/kernels/test_init.py
diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py
index 16aa4bb5b..8cd5829bd 100644
--- a/src/eko/evolution_operator/__init__.py
+++ b/src/eko/evolution_operator/__init__.py
@@ -20,6 +20,7 @@
from .. import basis_rotation as br
from .. import interpolation, mellin
from .. import scale_variations as sv
+from ..kernels import ev_method
from ..kernels import non_singlet as ns
from ..kernels import non_singlet_qed as qed_ns
from ..kernels import singlet as s
@@ -780,6 +781,11 @@ def labels(self):
labels.extend(br.singlet_unified_labels)
return labels
+ @property
+ def ev_method(self):
+ """Return the evolution method."""
+ return ev_method(self.config["method"])
+
def quad_ker(self, label, logx, areas):
"""Return partially initialized integrand function.
diff --git a/src/eko/kernels/__init__.py b/src/eko/kernels/__init__.py
index 7640727b5..a10998b23 100644
--- a/src/eko/kernels/__init__.py
+++ b/src/eko/kernels/__init__.py
@@ -1 +1,33 @@
"""The solutions to the |DGLAP| equations."""
+
+import enum
+
+
+class EvoMethods(enum.IntEnum):
+ """Enumerate evolution methods."""
+
+ ITERATE_EXACT = enum.auto()
+ ITERATE_EXPANDED = enum.auto()
+ PERTURBATIVE_EXACT = enum.auto()
+ PERTURBATIVE_EXPANDED = enum.auto()
+ TRUNCATED = enum.auto()
+ ORDERED_TRUNCATED = enum.auto()
+ DECOMPOSE_EXACT = enum.auto()
+ DECOMPOSE_EXPANDED = enum.auto()
+
+
+def ev_method(s: EvoMethods) -> EvoMethods:
+ """Return the evolution methods.
+
+ Parameters
+ ----------
+ s :
+ string representation
+
+ Returns
+ -------
+ i :
+ int representation
+
+ """
+ return EvoMethods[s.value.upper().replace("-", "_")]
diff --git a/src/eko/scale_variations/__init__.py b/src/eko/scale_variations/__init__.py
index 9c43f1f9c..21d56a503 100644
--- a/src/eko/scale_variations/__init__.py
+++ b/src/eko/scale_variations/__init__.py
@@ -6,29 +6,30 @@
import enum
+from ..io.types import ScaleVariationsMethod
from . import expanded, exponentiated
class Modes(enum.IntEnum):
- """Enumerate scale Variation modes."""
+ """Enumerate scale variation modes."""
unvaried = enum.auto()
exponentiated = enum.auto()
expanded = enum.auto()
-def sv_mode(s):
+def sv_mode(s: ScaleVariationsMethod) -> Modes:
"""Return the scale variation mode.
Parameters
----------
- s : str
+ s :
string representation
Returns
-------
- enum.IntEnum
- enum representation
+ i :
+ int representation
"""
if s is not None:
@@ -40,6 +41,6 @@ class ScaleVariationModeMixin:
"""Mixin to cast scale variation mode."""
@property
- def sv_mode(self):
+ def sv_mode(self) -> Modes:
"""Return the scale variation mode."""
return sv_mode(self.config["ModSV"])
diff --git a/tests/eko/kernels/test_init.py b/tests/eko/kernels/test_init.py
new file mode 100644
index 000000000..3717de275
--- /dev/null
+++ b/tests/eko/kernels/test_init.py
@@ -0,0 +1,21 @@
+from eko.io.types import EvolutionMethod
+from eko.kernels import EvoMethods, ev_method
+
+
+def test_ev_method():
+ methods = {
+ "iterate-expanded": EvoMethods.ITERATE_EXPANDED,
+ "decompose-expanded": EvoMethods.DECOMPOSE_EXPANDED,
+ "perturbative-expanded": EvoMethods.PERTURBATIVE_EXPANDED,
+ "truncated": EvoMethods.TRUNCATED,
+ "ordered-truncated": EvoMethods.ORDERED_TRUNCATED,
+ "iterate-exact": EvoMethods.ITERATE_EXACT,
+ "decompose-exact": EvoMethods.DECOMPOSE_EXACT,
+ "perturbative-exact": EvoMethods.PERTURBATIVE_EXACT,
+ }
+ assert len(methods.keys()) == len(EvolutionMethod)
+ assert len(methods.keys()) == len(EvoMethods)
+ for s, i in methods.items():
+ j = ev_method(EvolutionMethod(s))
+ assert j == i
+ assert isinstance(j, int)
From 5636b4a7e2e14f83ca0f5e34a24f71b53042e026 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 19 Jul 2024 15:45:25 +0300
Subject: [PATCH 56/67] Use EvoMethods in kernels
---
src/eko/kernels/non_singlet.py | 27 ++++++------
src/eko/kernels/non_singlet_qed.py | 4 +-
src/eko/kernels/singlet.py | 19 +++++----
src/eko/kernels/singlet_qed.py | 7 ++--
src/eko/kernels/valence_qed.py | 5 ++-
tests/eko/kernels/test_kernels_QEDns.py | 3 +-
tests/eko/kernels/test_kernels_QEDsinglet.py | 12 +++++-
tests/eko/kernels/test_kernels_QEDvalence.py | 16 +++++--
tests/eko/kernels/test_ns.py | 32 ++++++--------
tests/eko/kernels/test_s.py | 44 ++++++++------------
10 files changed, 87 insertions(+), 82 deletions(-)
diff --git a/src/eko/kernels/non_singlet.py b/src/eko/kernels/non_singlet.py
index bd5bd10f0..15b913438 100644
--- a/src/eko/kernels/non_singlet.py
+++ b/src/eko/kernels/non_singlet.py
@@ -4,6 +4,7 @@
import numpy as np
from .. import beta
+from . import EvoMethods
from . import as4_evolution_integrals as as4_ei
from . import evolution_integrals as ei
@@ -355,7 +356,7 @@ def dispatcher(
----------
order : tuple(int,int)
perturbation order
- method : str
+ method : int
method
gamma_ns : numpy.ndarray
non-singlet anomalous dimensions
@@ -378,38 +379,38 @@ def dispatcher(
# use always exact in LO
if order[0] == 1:
return lo_exact(gamma_ns, a1, a0, betalist)
- if method == "ordered-truncated":
+ if method is EvoMethods.ORDERED_TRUNCATED:
return eko_ordered_truncated(
gamma_ns, a1, a0, betalist, order, ev_op_iterations
)
- if method == "truncated":
+ if method is EvoMethods.TRUNCATED:
return eko_truncated(gamma_ns, a1, a0, betalist, order, ev_op_iterations)
# NLO
if order[0] == 2:
if method in [
- "iterate-expanded",
- "decompose-expanded",
- "perturbative-expanded",
+ EvoMethods.ITERATE_EXPANDED,
+ EvoMethods.DECOMPOSE_EXPANDED,
+ EvoMethods.PERTURBATIVE_EXPANDED,
]:
return nlo_expanded(gamma_ns, a1, a0, betalist)
- # if method in ["iterate-exact", "decompose-exact", "perturbative-exact"]:
+ # exact is left
return nlo_exact(gamma_ns, a1, a0, betalist)
# NNLO
if order[0] == 3:
if method in [
- "iterate-expanded",
- "decompose-expanded",
- "perturbative-expanded",
+ EvoMethods.ITERATE_EXPANDED,
+ EvoMethods.DECOMPOSE_EXPANDED,
+ EvoMethods.PERTURBATIVE_EXPANDED,
]:
return nnlo_expanded(gamma_ns, a1, a0, betalist)
return nnlo_exact(gamma_ns, a1, a0, betalist)
# N3LO
if order[0] == 4:
if method in [
- "iterate-expanded",
- "decompose-expanded",
- "perturbative-expanded",
+ EvoMethods.ITERATE_EXPANDED,
+ EvoMethods.DECOMPOSE_EXPANDED,
+ EvoMethods.PERTURBATIVE_EXPANDED,
]:
return n3lo_expanded(gamma_ns, a1, a0, betalist)
return n3lo_exact(gamma_ns, a1, a0, betalist)
diff --git a/src/eko/kernels/non_singlet_qed.py b/src/eko/kernels/non_singlet_qed.py
index 7a2de816a..d81d5076b 100644
--- a/src/eko/kernels/non_singlet_qed.py
+++ b/src/eko/kernels/non_singlet_qed.py
@@ -146,7 +146,7 @@ def as4_exact(gamma_ns, a1, a0, beta):
@nb.njit(cache=True)
def dispatcher(
order,
- method,
+ _method,
gamma_ns,
as_list,
aem_half,
@@ -164,7 +164,7 @@ def dispatcher(
----------
order : tuple(int,int)
perturbation order
- method : str
+ method : int
method
gamma_ns : numpy.ndarray
non-singlet anomalous dimensions
diff --git a/src/eko/kernels/singlet.py b/src/eko/kernels/singlet.py
index 5983c0c67..e637af046 100644
--- a/src/eko/kernels/singlet.py
+++ b/src/eko/kernels/singlet.py
@@ -6,6 +6,7 @@
from ekore import anomalous_dimensions as ad
from .. import beta
+from . import EvoMethods
from . import as4_evolution_integrals as as4_ei
from . import evolution_integrals as ei
@@ -579,7 +580,7 @@ def dispatcher( # pylint: disable=too-many-return-statements
----------
order : tuple(int,int)
perturbative order
- method : str
+ method : int
method
gamma_singlet : numpy.ndarray
singlet anomalous dimensions matrices
@@ -609,9 +610,9 @@ def dispatcher( # pylint: disable=too-many-return-statements
return lo_exact(gamma_singlet, a1, a0, betalist)
# Common method for NLO and NNLO
- if method in ["iterate-exact", "iterate-expanded"]:
+ if method in [EvoMethods.ITERATE_EXACT, EvoMethods.ITERATE_EXPANDED]:
return eko_iterate(gamma_singlet, a1, a0, betalist, order, ev_op_iterations)
- if method == "perturbative-exact":
+ if method is EvoMethods.PERTURBATIVE_EXACT:
return eko_perturbative(
gamma_singlet,
a1,
@@ -622,7 +623,7 @@ def dispatcher( # pylint: disable=too-many-return-statements
ev_op_max_order,
True,
)
- if method == "perturbative-expanded":
+ if method is EvoMethods.PERTURBATIVE_EXPANDED:
return eko_perturbative(
gamma_singlet,
a1,
@@ -633,19 +634,19 @@ def dispatcher( # pylint: disable=too-many-return-statements
ev_op_max_order,
False,
)
- if method in ["truncated", "ordered-truncated"]:
+ if method in [EvoMethods.TRUNCATED, EvoMethods.ORDERED_TRUNCATED]:
return eko_truncated(gamma_singlet, a1, a0, betalist, order, ev_op_iterations)
# These methods are scattered for nlo and nnlo
- if method == "decompose-exact":
+ if method is EvoMethods.DECOMPOSE_EXACT:
if order[0] == 2:
return nlo_decompose_exact(gamma_singlet, a1, a0, betalist)
- elif order[0] == 3:
+ if order[0] == 3:
return nnlo_decompose_exact(gamma_singlet, a1, a0, betalist)
return n3lo_decompose_exact(gamma_singlet, a1, a0, nf)
- if method == "decompose-expanded":
+ if method is EvoMethods.DECOMPOSE_EXPANDED:
if order[0] == 2:
return nlo_decompose_expanded(gamma_singlet, a1, a0, betalist)
- elif order[0] == 3:
+ if order[0] == 3:
return nnlo_decompose_expanded(gamma_singlet, a1, a0, betalist)
return n3lo_decompose_expanded(gamma_singlet, a1, a0, nf)
raise NotImplementedError("Selected method is not implemented")
diff --git a/src/eko/kernels/singlet_qed.py b/src/eko/kernels/singlet_qed.py
index c13dee95c..2f2ba8eee 100644
--- a/src/eko/kernels/singlet_qed.py
+++ b/src/eko/kernels/singlet_qed.py
@@ -6,6 +6,7 @@
from ekore import anomalous_dimensions as ad
from .. import beta
+from . import EvoMethods
@nb.njit(cache=True)
@@ -66,7 +67,7 @@ def dispatcher(
a_half,
nf,
ev_op_iterations,
- ev_op_max_order,
+ _ev_op_max_order,
):
"""Determine used kernel and call it.
@@ -74,7 +75,7 @@ def dispatcher(
----------
order : tuple(int,int)
perturbative order
- method : str
+ method : int
method
gamma_singlet : numpy.ndarray
singlet anomalous dimensions matrices
@@ -96,7 +97,7 @@ def dispatcher(
e_s : numpy.ndarray
singlet EKO
"""
- if method in ["iterate-exact", "iterate-expanded"]:
+ if method in [EvoMethods.ITERATE_EXACT, EvoMethods.ITERATE_EXPANDED]:
return eko_iterate(
gamma_singlet, as_list, a_half, nf, order, ev_op_iterations, 4
)
diff --git a/src/eko/kernels/valence_qed.py b/src/eko/kernels/valence_qed.py
index 0d5b747c3..074dd95ed 100644
--- a/src/eko/kernels/valence_qed.py
+++ b/src/eko/kernels/valence_qed.py
@@ -2,6 +2,7 @@
import numba as nb
+from . import EvoMethods
from .singlet_qed import eko_iterate
@@ -14,7 +15,7 @@ def dispatcher(
a_half,
nf,
ev_op_iterations,
- ev_op_max_order,
+ _ev_op_max_order,
):
"""
Determine used kernel and call it.
@@ -45,7 +46,7 @@ def dispatcher(
e_v : numpy.ndarray
singlet EKO
"""
- if method in ["iterate-exact", "iterate-expanded"]:
+ if method in [EvoMethods.ITERATE_EXACT, EvoMethods.ITERATE_EXPANDED]:
return eko_iterate(
gamma_valence, as_list, a_half, nf, order, ev_op_iterations, 2
)
diff --git a/tests/eko/kernels/test_kernels_QEDns.py b/tests/eko/kernels/test_kernels_QEDns.py
index bb18c3e17..9fce3097b 100644
--- a/tests/eko/kernels/test_kernels_QEDns.py
+++ b/tests/eko/kernels/test_kernels_QEDns.py
@@ -3,6 +3,7 @@
from eko import basis_rotation as br
from eko.couplings import Couplings
+from eko.kernels import EvoMethods
from eko.kernels import non_singlet_qed as ns
from eko.quantities.couplings import CouplingEvolutionMethod, CouplingsInfo
from eko.quantities.heavy_quarks import QuarkMassScheme
@@ -14,7 +15,7 @@
# "perturbative-expanded",
# "truncated",
# "ordered-truncated",
- "iterate-exact",
+ EvoMethods.ITERATE_EXACT,
# "decompose-exact",
# "perturbative-exact",
]
diff --git a/tests/eko/kernels/test_kernels_QEDsinglet.py b/tests/eko/kernels/test_kernels_QEDsinglet.py
index b953c053c..2fee4e17f 100644
--- a/tests/eko/kernels/test_kernels_QEDsinglet.py
+++ b/tests/eko/kernels/test_kernels_QEDsinglet.py
@@ -1,6 +1,7 @@
import numpy as np
import pytest
+from eko.kernels import EvoMethods
from eko.kernels import singlet_qed as s
from ekore.anomalous_dimensions.unpolarized import space_like as ad
@@ -10,7 +11,7 @@
# "perturbative-expanded",
# "truncated",
# "ordered-truncated",
- "iterate-exact",
+ EvoMethods.ITERATE_EXACT,
# "decompose-exact",
# "perturbative-exact",
]
@@ -125,5 +126,12 @@ def test_zero_true_gamma(monkeypatch):
def test_error():
with pytest.raises(NotImplementedError):
s.dispatcher(
- (3, 2), "AAA", np.random.rand(4, 3, 2, 2), [0.2, 0.1], [0.01], 3, 10, 10
+ (3, 2),
+ "iterate-exact",
+ np.random.rand(4, 3, 2, 2),
+ [0.2, 0.1],
+ [0.01],
+ 3,
+ 10,
+ 10,
)
diff --git a/tests/eko/kernels/test_kernels_QEDvalence.py b/tests/eko/kernels/test_kernels_QEDvalence.py
index 29f0f3d7a..4b12a492b 100644
--- a/tests/eko/kernels/test_kernels_QEDvalence.py
+++ b/tests/eko/kernels/test_kernels_QEDvalence.py
@@ -1,6 +1,7 @@
import numpy as np
import pytest
+from eko.kernels import EvoMethods
from eko.kernels import valence_qed as val
from ekore import anomalous_dimensions
@@ -10,13 +11,13 @@
# "perturbative-expanded",
# "truncated",
# "ordered-truncated",
- "iterate-exact",
+ EvoMethods.ITERATE_EXACT,
# "decompose-exact",
# "perturbative-exact",
]
-def test_zero(monkeypatch):
+def test_zero():
"""No evolution results in exp(0)"""
nf = 3
ev_op_iterations = 2
@@ -57,7 +58,7 @@ def test_zero(monkeypatch):
)
-def test_zero_true_gamma(monkeypatch):
+def test_zero_true_gamma():
"""No evolution results in exp(0)"""
nf = 3
ev_op_iterations = 2
@@ -101,5 +102,12 @@ def test_zero_true_gamma(monkeypatch):
def test_error():
with pytest.raises(NotImplementedError):
val.dispatcher(
- (3, 2), "AAA", np.random.rand(4, 3, 2, 2), [0.2, 0.1], [0.01], 3, 10, 10
+ (3, 2),
+ "iterate-exact",
+ np.random.rand(4, 3, 2, 2),
+ [0.2, 0.1],
+ [0.01],
+ 3,
+ 10,
+ 10,
)
diff --git a/tests/eko/kernels/test_ns.py b/tests/eko/kernels/test_ns.py
index f78282142..70e7faf8d 100644
--- a/tests/eko/kernels/test_ns.py
+++ b/tests/eko/kernels/test_ns.py
@@ -5,19 +5,9 @@
import ekore.anomalous_dimensions.unpolarized.space_like as ad
from eko import beta
+from eko.kernels import EvoMethods
from eko.kernels import non_singlet as ns
-methods = [
- "iterate-expanded",
- "decompose-expanded",
- "perturbative-expanded",
- "truncated",
- "ordered-truncated",
- "iterate-exact",
- "decompose-exact",
- "perturbative-exact",
-]
-
def test_zero():
"""No evolution results in exp(0)"""
@@ -25,7 +15,7 @@ def test_zero():
ev_op_iterations = 2
gamma_ns = np.array([1 + 0.0j, 1 + 0j, 1 + 0j, 1 + 0j])
for order in [1, 2, 3, 4]:
- for method in methods:
+ for method in EvoMethods:
np.testing.assert_allclose(
ns.dispatcher(
(order, 0), method, gamma_ns, 1.0, 1.0, nf, ev_op_iterations
@@ -54,7 +44,7 @@ def test_ode_lo():
a0 = 0.3
for a1 in [0.1, 0.2]:
r = a1 * gamma_ns / (beta.beta_qcd((2, 0), nf) * a1**2)
- for method in methods:
+ for method in EvoMethods:
rhs = r * ns.dispatcher(
(1, 0), method, gamma_ns, a1, a0, nf, ev_op_iterations
)
@@ -91,7 +81,7 @@ def test_ode_nlo():
r = (a1 * gamma_ns[0] + a1**2 * gamma_ns[1]) / (
beta.beta_qcd((2, 0), nf) * a1**2 + beta.beta_qcd((3, 0), nf) * a1**3
)
- for method in ["iterate-exact"]:
+ for method in [EvoMethods.ITERATE_EXACT]:
rhs = r * ns.dispatcher(
(2, 0), method, gamma_ns, a1, a0, nf, ev_op_iterations
)
@@ -130,7 +120,7 @@ def test_ode_nnlo():
+ beta.beta_qcd((3, 0), nf) * a1**2
+ beta.beta_qcd((4, 0), nf) * a1**3
)
- for method in ["iterate-exact"]:
+ for method in [EvoMethods.ITERATE_EXACT]:
rhs = r * ns.dispatcher(
(3, 0), method, gamma_ns, a1, a0, nf, ev_op_iterations
)
@@ -172,7 +162,7 @@ def test_ode_n3lo():
+ beta.beta_qcd((4, 0), nf) * a1**3
+ beta.beta_qcd((5, 0), nf) * a1**4
)
- for method in ["iterate-exact"]:
+ for method in [EvoMethods.ITERATE_EXACT]:
rhs = r * ns.dispatcher(
(4, 0), method, gamma_ns, a1, a0, nf, ev_op_iterations
)
@@ -202,7 +192,9 @@ def test_ode_n3lo():
def test_error(monkeypatch):
monkeypatch.setattr("eko.beta.beta_qcd", lambda *_args: 1.0)
with pytest.raises(NotImplementedError, match="order is not implemented"):
- ns.dispatcher((5, 0), "iterate-exact", np.random.rand(3) + 0j, 0.2, 0.1, 3, 10)
+ ns.dispatcher(
+ (5, 0), EvoMethods.ITERATE_EXACT, np.random.rand(3) + 0j, 0.2, 0.1, 3, 10
+ )
with pytest.raises(NotImplementedError):
ad.gamma_ns((2, 0), 10202, 1, (0, 0, 0, 0, 0, 0, 0), 3)
@@ -216,7 +208,7 @@ def test_gamma_usage():
gamma_ns = np.full(4, np.nan)
for order in range(1, 5):
gamma_ns[order - 1] = np.random.rand()
- for method in methods:
+ for method in EvoMethods:
r = ns.dispatcher(
(order, 0), method, gamma_ns, a1, a0, nf, ev_op_iterations
)
@@ -225,8 +217,8 @@ def test_gamma_usage():
for order in range(1, 5):
gamma_ns = np.random.rand(order)
gamma_ns[order - 1] = np.nan
- for method in methods:
- if method == "ordered-truncated":
+ for method in EvoMethods:
+ if method is EvoMethods.ORDERED_TRUNCATED:
# we are actually dividing by a np.nan,
# since the sum of U vec is nan
warnings.simplefilter("ignore", RuntimeWarning)
diff --git a/tests/eko/kernels/test_s.py b/tests/eko/kernels/test_s.py
index 5380ba319..ff4fdfc0d 100644
--- a/tests/eko/kernels/test_s.py
+++ b/tests/eko/kernels/test_s.py
@@ -3,20 +3,10 @@
import numpy as np
import pytest
+from eko.kernels import EvoMethods
from eko.kernels import singlet as s
from ekore import anomalous_dimensions as ad
-methods = [
- "iterate-expanded",
- "decompose-expanded",
- "perturbative-expanded",
- "truncated",
- "ordered-truncated",
- "iterate-exact",
- "decompose-exact",
- "perturbative-exact",
-]
-
def test_zero_lo(monkeypatch):
"""No evolution results in exp(0)"""
@@ -35,7 +25,7 @@ def test_zero_lo(monkeypatch):
np.array([[0, 0], [0, 1]]),
),
)
- for method in methods:
+ for method in EvoMethods:
np.testing.assert_allclose(
s.dispatcher(
(1, 0), method, gamma_s, 1, 1, nf, ev_op_iterations, ev_op_max_order
@@ -75,8 +65,8 @@ def test_zero_nlo_decompose(monkeypatch):
),
)
for method in [
- "decompose-expanded",
- "decompose-exact",
+ EvoMethods.DECOMPOSE_EXPANDED,
+ EvoMethods.DECOMPOSE_EXACT,
]:
np.testing.assert_allclose(
s.dispatcher(
@@ -117,8 +107,8 @@ def test_zero_nnlo_decompose(monkeypatch):
),
)
for method in [
- "decompose-expanded",
- "decompose-exact",
+ EvoMethods.DECOMPOSE_EXPANDED,
+ EvoMethods.DECOMPOSE_EXACT,
]:
np.testing.assert_allclose(
s.dispatcher(
@@ -159,8 +149,8 @@ def test_zero_n3lo_decompose(monkeypatch):
),
)
for method in [
- "decompose-expanded",
- "decompose-exact",
+ EvoMethods.DECOMPOSE_EXPANDED,
+ EvoMethods.DECOMPOSE_EXACT,
]:
np.testing.assert_allclose(
s.dispatcher(
@@ -200,7 +190,7 @@ def test_similarity():
]:
ref = s.dispatcher(
order,
- "decompose-exact",
+ EvoMethods.DECOMPOSE_EXACT,
gamma_s,
a1,
a0,
@@ -208,7 +198,7 @@ def test_similarity():
ev_op_iterations,
ev_op_max_order,
)
- for method in methods:
+ for method in EvoMethods:
np.testing.assert_allclose(
s.dispatcher(
order,
@@ -227,7 +217,9 @@ def test_similarity():
def test_error():
with pytest.raises(NotImplementedError):
- s.dispatcher((4, 0), "AAA", np.random.rand(3, 2, 2), 0.2, 0.1, 3, 10, 10)
+ s.dispatcher(
+ (4, 0), "iterate-exact", np.random.rand(3, 2, 2), 0.2, 0.1, 3, 10, 10
+ )
def mk_almost_diag_matrix(n, max_ang=np.pi / 8.0):
@@ -247,7 +239,7 @@ def test_gamma_usage():
gamma_s = np.full((4, 2, 2), np.nan)
for order in range(1, 5):
gamma_s[order - 1] = mk_almost_diag_matrix(1)
- for method in methods:
+ for method in EvoMethods:
r = s.dispatcher(
(order, 0),
method,
@@ -263,8 +255,8 @@ def test_gamma_usage():
for order in range(1, 5):
gamma_s = mk_almost_diag_matrix(4)
gamma_s[order - 1] = np.full((2, 2), np.nan)
- for method in methods:
- if "iterate" in method:
+ for method in EvoMethods:
+ if method in [EvoMethods.ITERATE_EXACT, EvoMethods.ITERATE_EXPANDED]:
# we are actually dividing by the determinant of
# matrix full of np.nan
warnings.simplefilter("ignore", RuntimeWarning)
@@ -287,8 +279,8 @@ def test_singlet_back():
nf = 4
a1 = 3.0
a0 = 4.0
- s10 = s.dispatcher(order, "iterate-exact", gamma_s, a1, a0, nf, 15, 1)
+ s10 = s.dispatcher(order, EvoMethods.ITERATE_EXACT, gamma_s, a1, a0, nf, 15, 1)
np.testing.assert_allclose(
np.linalg.inv(s10),
- s.dispatcher(order, "iterate-exact", gamma_s, a0, a1, nf, 15, 1),
+ s.dispatcher(order, EvoMethods.ITERATE_EXACT, gamma_s, a0, a1, nf, 15, 1),
)
From db2ef3ed63894e806b78e4c0ff41281179a3ac64 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 19 Jul 2024 16:03:51 +0300
Subject: [PATCH 57/67] Use EvoMethods in ev_op
---
src/eko/evolution_operator/__init__.py | 5 ++-
tests/eko/evolution_operator/test_init.py | 43 ++++++++++++++-------
tests/eko/scale_variations/test_diff.py | 4 +-
tests/eko/scale_variations/test_expanded.py | 4 +-
4 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py
index 8cd5829bd..ec56b6db6 100644
--- a/src/eko/evolution_operator/__init__.py
+++ b/src/eko/evolution_operator/__init__.py
@@ -20,6 +20,7 @@
from .. import basis_rotation as br
from .. import interpolation, mellin
from .. import scale_variations as sv
+from ..io.types import EvolutionMethod
from ..kernels import ev_method
from ..kernels import non_singlet as ns
from ..kernels import non_singlet_qed as qed_ns
@@ -784,7 +785,7 @@ def labels(self):
@property
def ev_method(self):
"""Return the evolution method."""
- return ev_method(self.config["method"])
+ return ev_method(EvolutionMethod(self.config["method"]))
def quad_ker(self, label, logx, areas):
"""Return partially initialized integrand function.
@@ -809,7 +810,7 @@ def quad_ker(self, label, logx, areas):
order=self.order,
mode0=label[0],
mode1=label[1],
- method=self.config["method"],
+ method=self.ev_method,
is_log=self.int_disp.log,
logx=logx,
areas=areas,
diff --git a/tests/eko/evolution_operator/test_init.py b/tests/eko/evolution_operator/test_init.py
index 597f645f8..23395f66b 100644
--- a/tests/eko/evolution_operator/test_init.py
+++ b/tests/eko/evolution_operator/test_init.py
@@ -11,6 +11,7 @@
from eko.evolution_operator import Operator, quad_ker
from eko.interpolation import InterpolatorDispatcher
from eko.io.runcards import OperatorCard, ScaleVariationsMethod, TheoryCard
+from eko.kernels import EvoMethods
from eko.kernels import non_singlet as ns
from eko.kernels import non_singlet_qed as qed_ns
from eko.kernels import singlet as s
@@ -25,7 +26,7 @@ def test_quad_ker_errors():
order=(1, 0),
mode0=mode0,
mode1=0,
- method="",
+ method="iterate-exact",
is_log=True,
logx=np.log(0.1),
areas=[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
@@ -60,15 +61,29 @@ def test_quad_ker(monkeypatch):
monkeypatch.setattr(qed_ns, "dispatcher", lambda *args: 1.0)
monkeypatch.setattr(s, "dispatcher", lambda *args: np.identity(2))
params = [
- ((1, 0), br.non_singlet_pids_map["ns+"], 0, "", 0.0, 0.0),
- ((1, 0), br.non_singlet_pids_map["ns+"], 0, "", 0.123, 1.0),
- ((3, 1), br.non_singlet_pids_map["ns+u"], 0, "", 0.0, 0.0),
- ((1, 0), 100, 100, "", 0.123, 1.0),
- ((1, 0), 100, 21, "", 0.0, 0.0),
- ((1, 1), 100, 100, "iterate-exact", 0.123, 1.0),
- ((1, 1), 100, 21, "iterate-exact", 0.123, 0.0),
- ((1, 1), 10200, 10200, "iterate-exact", 0.123, 1.0),
- ((1, 1), 10200, 10204, "iterate-exact", 0.123, 0.0),
+ ((1, 0), br.non_singlet_pids_map["ns+"], 0, EvoMethods.ITERATE_EXACT, 0.0, 0.0),
+ (
+ (1, 0),
+ br.non_singlet_pids_map["ns+"],
+ 0,
+ EvoMethods.ITERATE_EXACT,
+ 0.123,
+ 1.0,
+ ),
+ (
+ (3, 1),
+ br.non_singlet_pids_map["ns+u"],
+ 0,
+ EvoMethods.ITERATE_EXACT,
+ 0.0,
+ 0.0,
+ ),
+ ((1, 0), 100, 100, EvoMethods.ITERATE_EXACT, 0.123, 1.0),
+ ((1, 0), 100, 21, EvoMethods.ITERATE_EXACT, 0.0, 0.0),
+ ((1, 1), 100, 100, EvoMethods.ITERATE_EXACT, 0.123, 1.0),
+ ((1, 1), 100, 21, EvoMethods.ITERATE_EXACT, 0.123, 0.0),
+ ((1, 1), 10200, 10200, EvoMethods.ITERATE_EXACT, 0.123, 1.0),
+ ((1, 1), 10200, 10204, EvoMethods.ITERATE_EXACT, 0.123, 0.0),
]
for order, mode0, mode1, method, logx, res in params:
for is_log in [True, False]:
@@ -107,7 +122,7 @@ def test_quad_ker(monkeypatch):
order=(1, 0),
mode0=label[0],
mode1=label[1],
- method="",
+ method=EvoMethods.ITERATE_EXACT,
is_log=True,
logx=0.123,
areas=np.zeros(3),
@@ -143,7 +158,7 @@ def test_quad_ker(monkeypatch):
order=(1, 1),
mode0=label[0],
mode1=label[1],
- method="iterate-exact",
+ method=EvoMethods.ITERATE_EXACT,
is_log=True,
logx=0.123,
areas=np.zeros(3),
@@ -171,7 +186,7 @@ def test_quad_ker(monkeypatch):
order=(1, 0),
mode0=br.non_singlet_pids_map["ns+"],
mode1=0,
- method="",
+ method=EvoMethods.ITERATE_EXACT,
is_log=True,
logx=0.0,
areas=np.zeros(3),
@@ -436,7 +451,7 @@ def quad_ker_pegasus(
order = (2, 0)
mode0 = br.non_singlet_pids_map["ns+"]
mode1 = 0
- method = ""
+ method = EvoMethods.ITERATE_EXACT
logxs = np.log(int_disp.xgrid.raw)
a1 = 1
a0 = 2
diff --git a/tests/eko/scale_variations/test_diff.py b/tests/eko/scale_variations/test_diff.py
index c0dd67236..8ade8bcac 100644
--- a/tests/eko/scale_variations/test_diff.py
+++ b/tests/eko/scale_variations/test_diff.py
@@ -11,7 +11,7 @@
from eko import basis_rotation as br
from eko.beta import beta_qcd_as2, beta_qcd_as3
from eko.couplings import CouplingEvolutionMethod, Couplings, CouplingsInfo
-from eko.kernels import non_singlet, singlet
+from eko.kernels import EvoMethods, non_singlet, singlet
from eko.quantities.heavy_quarks import QuarkMassScheme
from eko.scale_variations import expanded, exponentiated
from ekore.anomalous_dimensions.unpolarized.space_like import gamma_ns, gamma_singlet
@@ -19,7 +19,7 @@
NF = 4
Q02 = 1.65**2
Q12 = 100**2
-EV_METHOD = "truncated"
+EV_METHOD = EvoMethods.TRUNCATED
def compute_a_s(q2, order):
diff --git a/tests/eko/scale_variations/test_expanded.py b/tests/eko/scale_variations/test_expanded.py
index 6af22dd51..bfacc1c96 100644
--- a/tests/eko/scale_variations/test_expanded.py
+++ b/tests/eko/scale_variations/test_expanded.py
@@ -2,7 +2,7 @@
from eko import basis_rotation as br
from eko.couplings import CouplingEvolutionMethod, Couplings, CouplingsInfo
-from eko.kernels import non_singlet, singlet
+from eko.kernels import EvoMethods, non_singlet, singlet
from eko.quantities.heavy_quarks import QuarkMassScheme
from eko.scale_variations import Modes, expanded
from ekore.anomalous_dimensions.unpolarized.space_like import gamma_ns, gamma_singlet
@@ -10,7 +10,7 @@
NF = 4
Q02 = 1.65**2
Q12 = 100**2
-EV_METHOD = "truncated"
+EV_METHOD = EvoMethods.TRUNCATED
def compute_a_s(q2, order):
From 1b1e4ce4b651033fc1c23c89cb79f42a03019c66 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 19 Jul 2024 16:41:12 +0300
Subject: [PATCH 58/67] Introduce BackwardsMethods
---
.../operator_matrix_element.py | 50 ++++++++++++++++---
src/eko/kernels/__init__.py | 6 ++-
tests/eko/evolution_operator/test_ome.py | 19 +++----
3 files changed, 57 insertions(+), 18 deletions(-)
diff --git a/src/eko/evolution_operator/operator_matrix_element.py b/src/eko/evolution_operator/operator_matrix_element.py
index 202fd18d9..b4b6731b4 100644
--- a/src/eko/evolution_operator/operator_matrix_element.py
+++ b/src/eko/evolution_operator/operator_matrix_element.py
@@ -1,6 +1,7 @@
"""The |OME| for the non-trivial matching conditions in the |VFNS| evolution."""
import copy
+import enum
import functools
import logging
@@ -20,6 +21,33 @@
logger = logging.getLogger(__name__)
+class BackwardsMethods(enum.IntEnum):
+ """Enumerate backward methods."""
+
+ FORWARD = enum.auto()
+ EXACT = enum.auto()
+ EXPANDED = enum.auto()
+
+
+def bw_method(s: InversionMethod) -> BackwardsMethods:
+ """Return the backward method.
+
+ Parameters
+ ----------
+ s :
+ string representation
+
+ Returns
+ -------
+ i :
+ int representation
+
+ """
+ if s is not None:
+ return BackwardsMethods[s.value.upper()]
+ return BackwardsMethods.FORWARD
+
+
@nb.njit(cache=True)
def build_ome(A, matching_order, a_s, backward_method):
r"""Construct the matching expansion in :math:`a_s` with the appropriate method.
@@ -32,7 +60,7 @@ def build_ome(A, matching_order, a_s, backward_method):
perturbation matching order
a_s : float
strong coupling, needed only for the exact inverse
- backward_method : InversionMethod or None
+ backward_method : BackwardsMethods
empty or method for inverting the matching condition (exact or expanded)
Returns
@@ -51,7 +79,7 @@ def build_ome(A, matching_order, a_s, backward_method):
ome = np.eye(len(A[0]), dtype=np.complex_)
A = A[:, :, :]
A = np.ascontiguousarray(A)
- if backward_method is InversionMethod.EXPANDED:
+ if backward_method is BackwardsMethods.EXPANDED:
# expended inverse
if matching_order[0] >= 1:
ome -= a_s * A[0]
@@ -68,7 +96,7 @@ def build_ome(A, matching_order, a_s, backward_method):
if matching_order[0] >= 3:
ome += a_s**3 * A[2]
# need inverse exact ? so add the missing pieces
- if backward_method is InversionMethod.EXACT:
+ if backward_method is BackwardsMethods.EXACT:
ome = np.linalg.inv(ome)
return ome
@@ -216,7 +244,9 @@ class OperatorMatrixElement(Operator):
def __init__(self, config, managers, nf, q2, is_backward, L, is_msbar):
super().__init__(config, managers, Segment(q2, q2, nf))
- self.backward_method = config["backward_inversion"] if is_backward else None
+ self.backward_method = bw_method(
+ config["backward_inversion"] if is_backward else None
+ )
if is_backward:
self.is_intrinsic = True
else:
@@ -241,7 +271,10 @@ def labels(self):
logger.warning("%s: skipping non-singlet sector", self.log_label)
else:
labels.append((200, 200))
- if self.is_intrinsic or self.backward_method is not None:
+ if (
+ self.is_intrinsic
+ or self.backward_method is not BackwardsMethods.FORWARD
+ ):
# intrinsic labels, which are not zero at NLO
labels.append((br.matching_hminus_pid, br.matching_hminus_pid))
# These contributions are always 0 for the moment
@@ -257,7 +290,10 @@ def labels(self):
(br.matching_hplus_pid, 100),
]
)
- if self.is_intrinsic or self.backward_method is not None:
+ if (
+ self.is_intrinsic
+ or self.backward_method is not BackwardsMethods.FORWARD
+ ):
labels.extend(
[
(21, br.matching_hplus_pid),
@@ -329,7 +365,7 @@ def compute(self):
self.log_label,
self.order[0],
self.order[1],
- self.backward_method,
+ BackwardsMethods(self.backward_method).name,
)
self.integrate()
diff --git a/src/eko/kernels/__init__.py b/src/eko/kernels/__init__.py
index a10998b23..594fbf1fa 100644
--- a/src/eko/kernels/__init__.py
+++ b/src/eko/kernels/__init__.py
@@ -2,6 +2,8 @@
import enum
+from ..io.types import EvolutionMethod
+
class EvoMethods(enum.IntEnum):
"""Enumerate evolution methods."""
@@ -16,8 +18,8 @@ class EvoMethods(enum.IntEnum):
DECOMPOSE_EXPANDED = enum.auto()
-def ev_method(s: EvoMethods) -> EvoMethods:
- """Return the evolution methods.
+def ev_method(s: EvolutionMethod) -> EvoMethods:
+ """Return the evolution method.
Parameters
----------
diff --git a/tests/eko/evolution_operator/test_ome.py b/tests/eko/evolution_operator/test_ome.py
index b844290c9..584635967 100644
--- a/tests/eko/evolution_operator/test_ome.py
+++ b/tests/eko/evolution_operator/test_ome.py
@@ -8,6 +8,7 @@
from eko import interpolation, mellin
from eko import scale_variations as sv
from eko.evolution_operator.operator_matrix_element import (
+ BackwardsMethods,
OperatorMatrixElement,
build_ome,
quad_ker,
@@ -33,7 +34,7 @@ def test_build_ome_as():
aS = A_singlet((o, 0), N, nf, L, is_msbar)
for a in [aNS, aS]:
- for method in [None, InversionMethod.EXPANDED, InversionMethod.EXACT]:
+ for method in BackwardsMethods:
dim = len(a[0])
if o != 1:
assert len(a) == o
@@ -53,7 +54,7 @@ def test_build_ome_nlo():
aNSi = A_non_singlet((1, 0), N, nf, L)
aSi = A_singlet((1, 0), N, nf, L, is_msbar)
for a in [aNSi, aSi]:
- for method in [None, InversionMethod.EXPANDED, InversionMethod.EXACT]:
+ for method in BackwardsMethods:
dim = len(a[0])
# hh
assert a[0, -1, -1] != 0.0
@@ -86,7 +87,7 @@ def test_quad_ker_errors():
is_log=True,
logx=0.123,
areas=[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
- backward_method=None,
+ backward_method=BackwardsMethods.FORWARD,
a_s=0.0,
nf=3,
L=0.0,
@@ -119,7 +120,7 @@ def test_quad_ker(monkeypatch):
is_log=is_log,
logx=0.123,
areas=np.zeros(3),
- backward_method=None,
+ backward_method=BackwardsMethods.FORWARD,
a_s=0.0,
nf=3,
L=0.0,
@@ -138,7 +139,7 @@ def test_quad_ker(monkeypatch):
is_log=is_log,
logx=0.123,
areas=np.zeros(3),
- backward_method=None,
+ backward_method=BackwardsMethods.FORWARD,
a_s=0.0,
nf=3,
L=0.0,
@@ -157,7 +158,7 @@ def test_quad_ker(monkeypatch):
is_log=is_log,
logx=0.0,
areas=np.zeros(3),
- backward_method=None,
+ backward_method=BackwardsMethods.FORWARD,
a_s=0.0,
nf=3,
L=0.0,
@@ -191,7 +192,7 @@ def test_quad_ker(monkeypatch):
is_log=True,
logx=0.123,
areas=np.zeros(3),
- backward_method=InversionMethod.EXPANDED,
+ backward_method=BackwardsMethods.EXPANDED,
a_s=0.0,
nf=3,
L=0.0,
@@ -228,7 +229,7 @@ def test_quad_ker(monkeypatch):
is_log=True,
logx=0.123,
areas=np.zeros(3),
- backward_method=InversionMethod.EXACT,
+ backward_method=BackwardsMethods.EXACT,
a_s=0.0,
nf=3,
L=0.0,
@@ -252,7 +253,7 @@ def test_quad_ker(monkeypatch):
is_log=True,
logx=0.0,
areas=np.array([0.01, 0.1, 1.0]),
- backward_method=None,
+ backward_method=BackwardsMethods.FORWARD,
a_s=0.0,
nf=3,
L=0.0,
From c88627f71da3df6780692cbcc1bd04c37d0776ae Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 22 Jul 2024 13:23:45 +0300
Subject: [PATCH 59/67] Rename matching method
---
.../operator_matrix_element.py | 34 ++++++++-----------
src/ekomark/data/operators.py | 2 +-
tests/eko/evolution_operator/test_ome.py | 20 +++++------
3 files changed, 25 insertions(+), 31 deletions(-)
diff --git a/src/eko/evolution_operator/operator_matrix_element.py b/src/eko/evolution_operator/operator_matrix_element.py
index b4b6731b4..cf6cbcb97 100644
--- a/src/eko/evolution_operator/operator_matrix_element.py
+++ b/src/eko/evolution_operator/operator_matrix_element.py
@@ -21,16 +21,16 @@
logger = logging.getLogger(__name__)
-class BackwardsMethods(enum.IntEnum):
+class MatchingMethods(enum.IntEnum):
"""Enumerate backward methods."""
FORWARD = enum.auto()
- EXACT = enum.auto()
- EXPANDED = enum.auto()
+ BACKWARD_EXACT = enum.auto()
+ BACKWARD_EXPANDED = enum.auto()
-def bw_method(s: InversionMethod) -> BackwardsMethods:
- """Return the backward method.
+def matching_method(s: InversionMethod) -> MatchingMethods:
+ """Return the matching method.
Parameters
----------
@@ -44,8 +44,8 @@ def bw_method(s: InversionMethod) -> BackwardsMethods:
"""
if s is not None:
- return BackwardsMethods[s.value.upper()]
- return BackwardsMethods.FORWARD
+ return MatchingMethods[s.value.upper()]
+ return MatchingMethods.FORWARD
@nb.njit(cache=True)
@@ -60,7 +60,7 @@ def build_ome(A, matching_order, a_s, backward_method):
perturbation matching order
a_s : float
strong coupling, needed only for the exact inverse
- backward_method : BackwardsMethods
+ backward_method : MatchingMethods
empty or method for inverting the matching condition (exact or expanded)
Returns
@@ -79,7 +79,7 @@ def build_ome(A, matching_order, a_s, backward_method):
ome = np.eye(len(A[0]), dtype=np.complex_)
A = A[:, :, :]
A = np.ascontiguousarray(A)
- if backward_method is BackwardsMethods.EXPANDED:
+ if backward_method is MatchingMethods.BACKWARD_EXPANDED:
# expended inverse
if matching_order[0] >= 1:
ome -= a_s * A[0]
@@ -96,7 +96,7 @@ def build_ome(A, matching_order, a_s, backward_method):
if matching_order[0] >= 3:
ome += a_s**3 * A[2]
# need inverse exact ? so add the missing pieces
- if backward_method is BackwardsMethods.EXACT:
+ if backward_method is MatchingMethods.BACKWARD_EXACT:
ome = np.linalg.inv(ome)
return ome
@@ -244,7 +244,7 @@ class OperatorMatrixElement(Operator):
def __init__(self, config, managers, nf, q2, is_backward, L, is_msbar):
super().__init__(config, managers, Segment(q2, q2, nf))
- self.backward_method = bw_method(
+ self.backward_method = matching_method(
config["backward_inversion"] if is_backward else None
)
if is_backward:
@@ -271,10 +271,7 @@ def labels(self):
logger.warning("%s: skipping non-singlet sector", self.log_label)
else:
labels.append((200, 200))
- if (
- self.is_intrinsic
- or self.backward_method is not BackwardsMethods.FORWARD
- ):
+ if self.is_intrinsic or self.backward_method is not MatchingMethods.FORWARD:
# intrinsic labels, which are not zero at NLO
labels.append((br.matching_hminus_pid, br.matching_hminus_pid))
# These contributions are always 0 for the moment
@@ -290,10 +287,7 @@ def labels(self):
(br.matching_hplus_pid, 100),
]
)
- if (
- self.is_intrinsic
- or self.backward_method is not BackwardsMethods.FORWARD
- ):
+ if self.is_intrinsic or self.backward_method is not MatchingMethods.FORWARD:
labels.extend(
[
(21, br.matching_hplus_pid),
@@ -365,7 +359,7 @@ def compute(self):
self.log_label,
self.order[0],
self.order[1],
- BackwardsMethods(self.backward_method).name,
+ MatchingMethods(self.backward_method).name,
)
self.integrate()
diff --git a/src/ekomark/data/operators.py b/src/ekomark/data/operators.py
index ad928574d..03ad4d349 100644
--- a/src/ekomark/data/operators.py
+++ b/src/ekomark/data/operators.py
@@ -15,7 +15,7 @@
ev_op_max_order=10,
ev_op_iterations=10,
backward_inversion="expanded",
- n_integration_cores=0,
+ n_integration_cores=1,
debug_skip_non_singlet=False,
debug_skip_singlet=False,
mugrid=[10],
diff --git a/tests/eko/evolution_operator/test_ome.py b/tests/eko/evolution_operator/test_ome.py
index 584635967..553e5823c 100644
--- a/tests/eko/evolution_operator/test_ome.py
+++ b/tests/eko/evolution_operator/test_ome.py
@@ -8,7 +8,7 @@
from eko import interpolation, mellin
from eko import scale_variations as sv
from eko.evolution_operator.operator_matrix_element import (
- BackwardsMethods,
+ MatchingMethods,
OperatorMatrixElement,
build_ome,
quad_ker,
@@ -34,7 +34,7 @@ def test_build_ome_as():
aS = A_singlet((o, 0), N, nf, L, is_msbar)
for a in [aNS, aS]:
- for method in BackwardsMethods:
+ for method in MatchingMethods:
dim = len(a[0])
if o != 1:
assert len(a) == o
@@ -54,7 +54,7 @@ def test_build_ome_nlo():
aNSi = A_non_singlet((1, 0), N, nf, L)
aSi = A_singlet((1, 0), N, nf, L, is_msbar)
for a in [aNSi, aSi]:
- for method in BackwardsMethods:
+ for method in MatchingMethods:
dim = len(a[0])
# hh
assert a[0, -1, -1] != 0.0
@@ -87,7 +87,7 @@ def test_quad_ker_errors():
is_log=True,
logx=0.123,
areas=[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
- backward_method=BackwardsMethods.FORWARD,
+ backward_method=MatchingMethods.FORWARD,
a_s=0.0,
nf=3,
L=0.0,
@@ -120,7 +120,7 @@ def test_quad_ker(monkeypatch):
is_log=is_log,
logx=0.123,
areas=np.zeros(3),
- backward_method=BackwardsMethods.FORWARD,
+ backward_method=MatchingMethods.FORWARD,
a_s=0.0,
nf=3,
L=0.0,
@@ -139,7 +139,7 @@ def test_quad_ker(monkeypatch):
is_log=is_log,
logx=0.123,
areas=np.zeros(3),
- backward_method=BackwardsMethods.FORWARD,
+ backward_method=MatchingMethods.FORWARD,
a_s=0.0,
nf=3,
L=0.0,
@@ -158,7 +158,7 @@ def test_quad_ker(monkeypatch):
is_log=is_log,
logx=0.0,
areas=np.zeros(3),
- backward_method=BackwardsMethods.FORWARD,
+ backward_method=MatchingMethods.FORWARD,
a_s=0.0,
nf=3,
L=0.0,
@@ -192,7 +192,7 @@ def test_quad_ker(monkeypatch):
is_log=True,
logx=0.123,
areas=np.zeros(3),
- backward_method=BackwardsMethods.EXPANDED,
+ backward_method=MatchingMethods.BACKWARD_EXPANDED,
a_s=0.0,
nf=3,
L=0.0,
@@ -229,7 +229,7 @@ def test_quad_ker(monkeypatch):
is_log=True,
logx=0.123,
areas=np.zeros(3),
- backward_method=BackwardsMethods.EXACT,
+ backward_method=MatchingMethods.BACKWARD_EXACT,
a_s=0.0,
nf=3,
L=0.0,
@@ -253,7 +253,7 @@ def test_quad_ker(monkeypatch):
is_log=True,
logx=0.0,
areas=np.array([0.01, 0.1, 1.0]),
- backward_method=BackwardsMethods.FORWARD,
+ backward_method=MatchingMethods.FORWARD,
a_s=0.0,
nf=3,
L=0.0,
From d4a3f71889822f0311f342ec2d3ca97c049acf8f Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 22 Jul 2024 13:29:41 +0300
Subject: [PATCH 60/67] Fix MatchingMethods doc string
---
src/eko/evolution_operator/operator_matrix_element.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/eko/evolution_operator/operator_matrix_element.py b/src/eko/evolution_operator/operator_matrix_element.py
index cf6cbcb97..87c76183a 100644
--- a/src/eko/evolution_operator/operator_matrix_element.py
+++ b/src/eko/evolution_operator/operator_matrix_element.py
@@ -22,7 +22,7 @@
class MatchingMethods(enum.IntEnum):
- """Enumerate backward methods."""
+ """Enumerate matching methods."""
FORWARD = enum.auto()
BACKWARD_EXACT = enum.auto()
From 7f079bc6001ac3f38d0d55ebd0a3cd271da7e976 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Mon, 22 Jul 2024 15:12:05 +0300
Subject: [PATCH 61/67] Fix matching renaming
---
src/eko/evolution_operator/operator_matrix_element.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/eko/evolution_operator/operator_matrix_element.py b/src/eko/evolution_operator/operator_matrix_element.py
index 87c76183a..25e5df2dd 100644
--- a/src/eko/evolution_operator/operator_matrix_element.py
+++ b/src/eko/evolution_operator/operator_matrix_element.py
@@ -44,7 +44,7 @@ def matching_method(s: InversionMethod) -> MatchingMethods:
"""
if s is not None:
- return MatchingMethods[s.value.upper()]
+ return MatchingMethods["BACKWARD_" + s.value.upper()]
return MatchingMethods.FORWARD
From e40acaec28c4212d5a3ffb809ece959d415c2016 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Wed, 24 Jul 2024 15:10:40 +0300
Subject: [PATCH 62/67] Allow only iterate-exact for QED
---
src/eko/kernels/singlet_qed.py | 2 +-
src/eko/kernels/valence_qed.py | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/eko/kernels/singlet_qed.py b/src/eko/kernels/singlet_qed.py
index 2f2ba8eee..d63a2f1ac 100644
--- a/src/eko/kernels/singlet_qed.py
+++ b/src/eko/kernels/singlet_qed.py
@@ -97,7 +97,7 @@ def dispatcher(
e_s : numpy.ndarray
singlet EKO
"""
- if method in [EvoMethods.ITERATE_EXACT, EvoMethods.ITERATE_EXPANDED]:
+ if method is EvoMethods.ITERATE_EXACT:
return eko_iterate(
gamma_singlet, as_list, a_half, nf, order, ev_op_iterations, 4
)
diff --git a/src/eko/kernels/valence_qed.py b/src/eko/kernels/valence_qed.py
index 074dd95ed..186c70219 100644
--- a/src/eko/kernels/valence_qed.py
+++ b/src/eko/kernels/valence_qed.py
@@ -24,7 +24,7 @@ def dispatcher(
----------
order : tuple(int,int)
perturbative order
- method : str
+ method : int
method
gamma_singlet : numpy.ndarray
singlet anomalous dimensions matrices
@@ -46,7 +46,7 @@ def dispatcher(
e_v : numpy.ndarray
singlet EKO
"""
- if method in [EvoMethods.ITERATE_EXACT, EvoMethods.ITERATE_EXPANDED]:
+ if method is EvoMethods.ITERATE_EXACT:
return eko_iterate(
gamma_valence, as_list, a_half, nf, order, ev_op_iterations, 2
)
From c92c3a24a0cd2cc440048f1028af9b98ab63b49a Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Mon, 29 Jul 2024 18:11:07 +0000
Subject: [PATCH 63/67] [pre-commit.ci] pre-commit autoupdate
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
updates:
- [github.com/asottile/pyupgrade: v3.16.0 → v3.17.0](https://github.com/asottile/pyupgrade/compare/v3.16.0...v3.17.0)
- [github.com/pre-commit/pre-commit: v3.7.1 → v3.8.0](https://github.com/pre-commit/pre-commit/compare/v3.7.1...v3.8.0)
---
.pre-commit-config.yaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 67e901972..d579fb856 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -32,7 +32,7 @@ repos:
- id: isort
args: ["--profile", "black"]
- repo: https://github.com/asottile/pyupgrade
- rev: v3.16.0
+ rev: v3.17.0
hooks:
- id: pyupgrade
- repo: https://github.com/pycqa/pydocstyle
@@ -53,6 +53,6 @@ repos:
files: ^crates/.*\.rs$
args: []
- repo: https://github.com/pre-commit/pre-commit
- rev: v3.7.1
+ rev: v3.8.0
hooks:
- id: validate_manifest
From 48476f9f2a3ab8121ff694db7c413fbb3bdddf1c Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Thu, 8 Aug 2024 14:49:28 +0300
Subject: [PATCH 64/67] Fix Rust ev_op patch
---
src/eko/evolution_operator/__init__.py.patch | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/eko/evolution_operator/__init__.py.patch b/src/eko/evolution_operator/__init__.py.patch
index 58c3f74fd..d8258ee14 100644
--- a/src/eko/evolution_operator/__init__.py.patch
+++ b/src/eko/evolution_operator/__init__.py.patch
@@ -1,5 +1,5 @@
diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py
-index 1c759c5c..5eb394d0 100644
+index ec56b6db..374d0d0b 100644
--- a/src/eko/evolution_operator/__init__.py
+++ b/src/eko/evolution_operator/__init__.py
@@ -3,15 +3,15 @@ r"""Contains the central operator classes.
@@ -20,7 +20,7 @@ index 1c759c5c..5eb394d0 100644
import ekore.anomalous_dimensions.polarized.space_like as ad_ps
import ekore.anomalous_dimensions.unpolarized.space_like as ad_us
-@@ -27,92 +27,10 @@ from ..kernels import singlet_qed as qed_s
+@@ -29,92 +29,10 @@ from ..kernels import singlet_qed as qed_s
from ..kernels import valence_qed as qed_v
from ..matchings import Segment, lepton_number
from ..member import OpMember
@@ -114,7 +114,7 @@ index 1c759c5c..5eb394d0 100644
spec = [
("is_singlet", nb.boolean),
("is_QEDsinglet", nb.boolean),
-@@ -184,422 +102,6 @@ class QuadKerBase:
+@@ -186,422 +104,6 @@ class QuadKerBase:
return self.path.prefactor * pj * self.path.jac
@@ -537,9 +537,9 @@ index 1c759c5c..5eb394d0 100644
class Operator(sv.ScaleVariationModeMixin):
"""Internal representation of a single EKO.
-@@ -780,50 +282,6 @@ class Operator(sv.ScaleVariationModeMixin):
- labels.extend(br.singlet_unified_labels)
- return labels
+@@ -787,50 +289,6 @@ class Operator(sv.ScaleVariationModeMixin):
+ """Return the evolution method."""
+ return ev_method(EvolutionMethod(self.config["method"]))
- def quad_ker(self, label, logx, areas):
- """Return partially initialized integrand function.
@@ -564,7 +564,7 @@ index 1c759c5c..5eb394d0 100644
- order=self.order,
- mode0=label[0],
- mode1=label[1],
-- method=self.config["method"],
+- method=self.ev_method,
- is_log=self.int_disp.log,
- logx=logx,
- areas=areas,
@@ -588,7 +588,7 @@ index 1c759c5c..5eb394d0 100644
def initialize_op_members(self):
"""Init all operators with the identity or zeros."""
eye = OpMember(
-@@ -846,10 +304,7 @@ class Operator(sv.ScaleVariationModeMixin):
+@@ -853,10 +311,7 @@ class Operator(sv.ScaleVariationModeMixin):
else:
self.op_members[n] = zero.copy()
@@ -600,7 +600,7 @@ index 1c759c5c..5eb394d0 100644
"""Run the integration for each grid point.
Parameters
-@@ -864,18 +319,56 @@ class Operator(sv.ScaleVariationModeMixin):
+@@ -871,18 +326,56 @@ class Operator(sv.ScaleVariationModeMixin):
"""
column = []
k, logx = log_grid
From b651ebe9699dc2ffcacd561e05bb52026e4d1944 Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Thu, 8 Aug 2024 15:02:47 +0300
Subject: [PATCH 65/67] Fix Rust ev_op patch
---
src/eko/evolution_operator/__init__.py.patch | 26 ++++++++++----------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/src/eko/evolution_operator/__init__.py.patch b/src/eko/evolution_operator/__init__.py.patch
index 58c3f74fd..995d77b6b 100644
--- a/src/eko/evolution_operator/__init__.py.patch
+++ b/src/eko/evolution_operator/__init__.py.patch
@@ -1,8 +1,8 @@
diff --git a/src/eko/evolution_operator/__init__.py b/src/eko/evolution_operator/__init__.py
-index 1c759c5c..5eb394d0 100644
+index fe07ade9..0f58c9e5 100644
--- a/src/eko/evolution_operator/__init__.py
+++ b/src/eko/evolution_operator/__init__.py
-@@ -3,15 +3,15 @@ r"""Contains the central operator classes.
+@@ -3,16 +3,16 @@ r"""Contains the central operator classes.
See :doc:`Operator overview `.
"""
@@ -11,6 +11,7 @@ index 1c759c5c..5eb394d0 100644
import os
import time
from multiprocessing import Pool
+ from typing import Dict, Tuple
+import ekors
import numba as nb
@@ -20,7 +21,7 @@ index 1c759c5c..5eb394d0 100644
import ekore.anomalous_dimensions.polarized.space_like as ad_ps
import ekore.anomalous_dimensions.unpolarized.space_like as ad_us
-@@ -27,92 +27,10 @@ from ..kernels import singlet_qed as qed_s
+@@ -30,92 +30,10 @@ from ..kernels import singlet_qed as qed_s
from ..kernels import valence_qed as qed_v
from ..matchings import Segment, lepton_number
from ..member import OpMember
@@ -114,7 +115,7 @@ index 1c759c5c..5eb394d0 100644
spec = [
("is_singlet", nb.boolean),
("is_QEDsinglet", nb.boolean),
-@@ -184,422 +102,6 @@ class QuadKerBase:
+@@ -187,421 +105,6 @@ class QuadKerBase:
return self.path.prefactor * pj * self.path.jac
@@ -533,13 +534,12 @@ index 1c759c5c..5eb394d0 100644
- )
- return ker
-
--
- class Operator(sv.ScaleVariationModeMixin):
- """Internal representation of a single EKO.
-@@ -780,50 +282,6 @@ class Operator(sv.ScaleVariationModeMixin):
- labels.extend(br.singlet_unified_labels)
- return labels
+ OpMembers = Dict[OperatorLabel, OpMember]
+ """Map of all operators."""
+@@ -792,50 +295,6 @@ class Operator(sv.ScaleVariationModeMixin):
+ """Return the evolution method."""
+ return ev_method(EvolutionMethod(self.config["method"]))
- def quad_ker(self, label, logx, areas):
- """Return partially initialized integrand function.
@@ -564,7 +564,7 @@ index 1c759c5c..5eb394d0 100644
- order=self.order,
- mode0=label[0],
- mode1=label[1],
-- method=self.config["method"],
+- method=self.ev_method,
- is_log=self.int_disp.log,
- logx=logx,
- areas=areas,
@@ -588,7 +588,7 @@ index 1c759c5c..5eb394d0 100644
def initialize_op_members(self):
"""Init all operators with the identity or zeros."""
eye = OpMember(
-@@ -846,10 +304,7 @@ class Operator(sv.ScaleVariationModeMixin):
+@@ -858,10 +317,7 @@ class Operator(sv.ScaleVariationModeMixin):
else:
self.op_members[n] = zero.copy()
@@ -600,7 +600,7 @@ index 1c759c5c..5eb394d0 100644
"""Run the integration for each grid point.
Parameters
-@@ -864,18 +319,56 @@ class Operator(sv.ScaleVariationModeMixin):
+@@ -876,18 +332,56 @@ class Operator(sv.ScaleVariationModeMixin):
"""
column = []
k, logx = log_grid
From 873853904bce8f3d5856d4c300f279c7f524a0df Mon Sep 17 00:00:00 2001
From: Felix Hekhorn
Date: Fri, 9 Aug 2024 11:01:11 +0300
Subject: [PATCH 66/67] Merge master
---
.github/workflows/crates.yml | 28 +
.github/workflows/maturin.yml | 123 +
.github/workflows/pypi.yml | 2 +-
.github/workflows/unittests-rust.yml | 21 +
.github/workflows/unittests.yml | 6 +-
.pre-commit-config.yaml | 36 +-
.readthedocs.yaml | 12 +-
crates/Cargo.lock => Cargo.lock | 52 +-
Cargo.toml | 22 +
README.md | 1 +
benchmarks/DSSV_bench.py | 1 +
benchmarks/NNPDF_bench.py | 1 +
benchmarks/apfel_bench.py | 2 +-
benchmarks/asv.conf.json | 2 +-
benchmarks/eko/benchmark_alphaem.py | 12 +-
benchmarks/eko/benchmark_evol_to_unity.py | 8 +-
benchmarks/eko/benchmark_inverse_matching.py | 9 +-
benchmarks/eko/benchmark_msbar_evolution.py | 8 +-
benchmarks/eko/benchmark_strong_coupling.py | 74 +-
benchmarks/ekobox/benchmark_evol_pdf.py | 10 +-
...k_ad.py => benchmark_pegasus_ad_us_as2.py} | 40 +-
benchmarks/ekore/benchmark_pegasus_mellin.py | 41 +
.../ekore/benchmark_pegasus_ome_ps_as2.py | 199 +
benchmarks/lha_paper_bench.py | 23 +-
crates/Cargo.toml | 3 -
crates/README.md | 18 +
crates/bump-versions.py | 40 +
crates/doc-header.html | 65 +
crates/eko/Cargo.toml | 19 +-
crates/eko/doc-header.html | 1 +
crates/eko/pyproject.toml | 4 +-
crates/eko/src/bib.rs | 1 +
crates/eko/src/lib.rs | 31 +-
crates/eko/src/mellin.rs | 20 +-
crates/ekore/Cargo.toml | 17 +-
crates/ekore/doc-header.html | 1 +
crates/ekore/refs.bib | 19 +
.../unpolarized/spacelike.rs | 33 +-
.../unpolarized/spacelike/as2.rs | 338 ++
.../unpolarized/spacelike/as3.rs | 455 +++
crates/ekore/src/bib.rs | 30 +-
crates/ekore/src/constants.rs | 26 +-
crates/ekore/src/harmonics.rs | 6 +-
crates/ekore/src/harmonics/cache.rs | 82 +-
crates/ekore/src/harmonics/g_functions.rs | 50 +
crates/ekore/src/harmonics/polygamma.rs | 15 +-
crates/ekore/src/harmonics/w1.rs | 3 +-
crates/ekore/src/harmonics/w2.rs | 13 +
crates/ekore/src/harmonics/w3.rs | 13 +
crates/ekore/src/harmonics/w4.rs | 13 +
crates/ekore/src/util.rs | 20 +
crates/make_bib.py | 23 +-
crates/parse-abbrev.py | 20 +
crates/release.json | 1 +
doc/source/code/genpdf.rst | 56 +-
doc/source/conf.py | 10 +-
doc/source/overview/tutorials/alpha_s.ipynb | 17 +-
doc/source/overview/tutorials/dglap.ipynb | 15 +-
doc/source/overview/tutorials/output.ipynb | 8 +-
doc/source/overview/tutorials/pdf.ipynb | 134 +-
doc/source/refs.bib | 63 +-
doc/source/theory/Matching.rst | 6 +-
doc/source/theory/N3LO_ad.rst | 5 +-
extras/lh_bench_23/.gitignore | 1 +
extras/lh_bench_23/cfg.py | 16 +-
extras/lh_bench_23/parse_to_latex.py | 179 +
extras/lh_bench_23/plot_bench.py | 49 -
extras/lh_bench_23/plot_bench_evol.py | 16 +-
extras/lh_bench_23/plot_bench_msht.py | 57 +-
extras/lh_bench_23/plot_trn_exa.py | 64 +
extras/lh_bench_23/run-n3lo.py | 2 +-
extras/lh_bench_23/run-nnlo.py | 3 +-
extras/lh_bench_23/run-trn_exa.py | 72 +
.../{run_fhmv.sh => run_fhmruvv.sh} | 8 +-
extras/lh_bench_23/tables/EKO.zip | Bin 0 -> 742394 bytes
extras/lh_bench_23/tables/MSHT.zip | Bin 0 -> 99712 bytes
extras/lh_bench_23/tables/table14-part1.csv | 12 +
extras/lh_bench_23/tables/table15-part1.csv | 12 +
.../tables/table_FFNS-1_iterate-exact.csv | 12 +
.../tables/table_FFNS-1_truncated.csv | 12 +
.../tables/table_FFNS-2_iterate-exact.csv | 12 +
.../tables/table_FFNS-2_truncated.csv | 12 +
.../tables/table_FFNS-3_iterate-exact.csv | 12 +
.../tables/table_FFNS-3_truncated.csv | 12 +
extras/lh_bench_23/utils.py | 84 +-
extras/n3lo_bench/plot_msht.py | 2 +-
extras/n3lo_bench/splitting_function_utils.py | 4 +-
flake.lock | 130 +-
flake.nix | 62 +-
poetry.lock | 3254 +++++++++--------
pyproject.toml | 24 +-
pyproject.toml.patch | 16 +-
rustify.sh | 8 +-
src/eko/__init__.py | 1 +
src/eko/couplings.py | 16 +-
src/eko/evolution_operator/__init__.py | 69 +-
src/eko/evolution_operator/__init__.py.patch | 70 +-
src/eko/evolution_operator/flavors.py | 1 +
src/eko/evolution_operator/grid.py | 49 +-
.../evolution_operator/matching_condition.py | 50 +-
.../operator_matrix_element.py | 74 +-
src/eko/evolution_operator/physical.py | 24 +-
src/eko/evolution_operator/quad_ker.py | 4 +-
src/eko/gamma.py | 1 +
src/eko/interpolation.py | 1 +
src/eko/io/bases.py | 117 -
src/eko/io/dictlike.py | 1 +
src/eko/io/exceptions.py | 1 +
src/eko/io/inventory.py | 5 +-
src/eko/io/items.py | 1 +
src/eko/io/legacy.py | 49 +-
src/eko/io/manipulate.py | 234 +-
src/eko/io/metadata.py | 9 +-
src/eko/io/paths.py | 1 +
src/eko/io/raw.py | 1 +
src/eko/io/runcards.py | 56 +-
src/eko/io/struct.py | 21 +-
src/eko/io/types.py | 9 +-
src/eko/kernels/__init__.py | 34 +
src/eko/kernels/as4_evolution_integrals.py | 4 +-
src/eko/kernels/non_singlet.py | 32 +-
src/eko/kernels/non_singlet_qed.py | 8 +-
src/eko/kernels/singlet.py | 26 +-
src/eko/kernels/singlet_qed.py | 8 +-
src/eko/kernels/utils.py | 26 -
src/eko/kernels/valence_qed.py | 8 +-
src/eko/matchings.py | 1 +
src/eko/mellin.py | 7 +-
src/eko/member.py | 1 +
src/eko/msbar_masses.py | 7 +-
src/eko/quantities/couplings.py | 15 +-
src/eko/quantities/heavy_quarks.py | 19 +-
src/eko/runner/__init__.py | 5 +-
src/eko/runner/commons.py | 3 +-
src/eko/runner/legacy.py | 11 +-
src/eko/runner/managed.py | 3 +-
src/eko/runner/operators.py | 5 +-
src/eko/runner/parts.py | 55 +-
src/eko/runner/recipes.py | 1 +
src/eko/scale_variations/__init__.py | 19 +-
src/eko/scale_variations/expanded.py | 8 +-
src/eko/scale_variations/exponentiated.py | 1 +
src/ekobox/apply.py | 65 +-
src/ekobox/cards.py | 10 +-
src/ekobox/cli/__init__.py | 1 +
src/ekobox/cli/base.py | 1 +
src/ekobox/cli/convert.py | 1 +
src/ekobox/cli/inspect.py | 3 +-
src/ekobox/cli/library.py | 1 +
src/ekobox/cli/log.py | 1 +
src/ekobox/cli/run.py | 15 +-
src/ekobox/cli/runcards.py | 7 +-
src/ekobox/evol_pdf.py | 36 +-
src/ekobox/genpdf/__init__.py | 13 +-
src/ekobox/genpdf/export.py | 1 +
src/ekobox/genpdf/flavors.py | 1 +
src/ekobox/genpdf/load.py | 1 +
src/ekobox/info_file.py | 77 +-
src/ekobox/mock.py | 1 +
src/ekobox/utils.py | 16 +-
src/ekomark/__init__.py | 1 +
src/ekomark/benchmark/external/LHA_utils.py | 1 +
src/ekomark/benchmark/external/apfel_utils.py | 1 +
.../benchmark/external/lhapdf_utils.py | 1 +
.../benchmark/external/pegasus_utils.py | 1 +
src/ekomark/benchmark/runner.py | 14 +-
src/ekomark/data/__init__.py | 29 +
src/ekomark/data/operators.py | 3 +-
src/ekomark/navigator/__init__.py | 1 +
src/ekomark/navigator/glob.py | 1 +
src/ekomark/navigator/navigator.py | 1 +
src/ekomark/plots.py | 50 +-
.../polarized/space_like/__init__.py | 1 +
.../polarized/space_like/as2.py | 16 +-
.../polarized/space_like/as3.py | 10 +-
.../unpolarized/space_like/__init__.py | 2 +
.../unpolarized/space_like/as2.py | 2 +-
.../unpolarized/space_like/as3.py | 1 +
.../unpolarized/space_like/as4/__init__.py | 1 +
.../space_like/as4/fhmruvv/__init__.py | 1 +
.../unpolarized/space_like/as4/fhmruvv/ggg.py | 1 +
.../unpolarized/space_like/as4/fhmruvv/ggq.py | 132 +-
.../space_like/as4/fhmruvv/gnsm.py | 1 +
.../space_like/as4/fhmruvv/gnsp.py | 1 +
.../space_like/as4/fhmruvv/gnsv.py | 1 +
.../unpolarized/space_like/as4/fhmruvv/gps.py | 1 +
.../unpolarized/space_like/as4/fhmruvv/gqg.py | 1 +
.../unpolarized/space_like/as4/ggq.py | 89 +-
.../unpolarized/space_like/as4/gnsm.py | 1 +
.../unpolarized/space_like/as4/gnsp.py | 1 +
.../unpolarized/space_like/as4/gnsv.py | 1 +
.../unpolarized/time_like/__init__.py | 2 +
.../unpolarized/time_like/as3.py | 2 +-
src/ekore/harmonics/__init__.py | 1 +
src/ekore/harmonics/cache.py | 1 +
src/ekore/harmonics/g_functions.py | 1 +
src/ekore/harmonics/log_functions.py | 1 +
src/ekore/harmonics/w3.py | 3 +-
src/ekore/harmonics/w4.py | 3 +-
src/ekore/harmonics/w5.py | 3 +-
.../polarized/space_like/as1.py | 1 +
.../polarized/space_like/as2.py | 36 +-
.../unpolarized/space_like/__init__.py | 4 +-
.../unpolarized/space_like/as1.py | 12 +-
.../unpolarized/space_like/as2.py | 37 +-
.../unpolarized/space_like/as3/__init__.py | 16 +-
.../unpolarized/space_like/as3/aHg.py | 5 +-
.../unpolarized/space_like/as3/aHg_param.py | 1178 ++----
.../unpolarized/space_like/as3/aHq.py | 3 +-
.../unpolarized/space_like/as3/agg.py | 99 +-
.../unpolarized/space_like/as3/agq.py | 3 +-
.../unpolarized/space_like/as3/aqg.py | 3 +-
.../unpolarized/space_like/as3/aqqNS.py | 5 +-
.../unpolarized/space_like/as3/aqqPS.py | 3 +-
tests/eko/evolution_operator/test_grid.py | 2 +-
tests/eko/evolution_operator/test_init.py | 53 +-
.../eko/evolution_operator/test_init.py.patch | 601 ---
.../test_matching_condition.py | 91 +-
tests/eko/evolution_operator/test_ome.py | 20 +-
tests/eko/evolution_operator/test_physical.py | 36 +-
tests/eko/io/test_bases.py | 83 -
tests/eko/io/test_manipulate.py | 274 +-
tests/eko/io/test_metadata.py | 6 +-
tests/eko/io/test_runcards.py | 90 -
tests/eko/kernels/test_init.py | 21 +
tests/eko/kernels/test_kernels_QEDns.py | 7 +-
tests/eko/kernels/test_kernels_QEDsinglet.py | 12 +-
tests/eko/kernels/test_kernels_QEDvalence.py | 16 +-
tests/eko/kernels/test_ns.py | 37 +-
tests/eko/kernels/test_s.py | 44 +-
tests/eko/kernels/test_utils.py | 12 -
tests/eko/quantities/test_couplings.py | 4 +-
tests/eko/runner/__init__.py | 10 +-
tests/eko/runner/conftest.py | 3 +-
tests/eko/runner/test_legacy.py | 2 +-
tests/eko/runner/test_operators.py | 6 +-
tests/eko/scale_variations/test_diff.py | 182 +
tests/eko/scale_variations/test_expanded.py | 206 +-
tests/eko/test_beta.py | 1 +
tests/eko/test_couplings.py | 39 +-
tests/eko/test_gamma.py | 1 +
tests/eko/test_matchings.py | 1 +
tests/eko/test_msbar_masses.py | 4 +-
tests/eko/test_quantities.py | 3 -
tests/ekobox/test_apply.py | 11 +-
tests/ekobox/test_cards.py | 8 +-
tests/ekobox/test_evol_pdf.py | 18 +-
tests/ekobox/test_info_file.py | 26 +-
tests/ekobox/test_utils.py | 7 +-
tests/ekomark/data/__init__.py | 0
tests/ekomark/data/test_init.py | 96 +
.../polarized/space_like/test_ad_as2.py | 8 +-
.../unpolarized/space_like/test_as4.py | 4 +-
.../unpolarized/space_like/test_as4_fhmv.py | 4 +-
.../polarized/space_like/test_nnlo.py | 20 +-
.../unpolarized/space_like/test_as3.py | 29 +-
256 files changed, 6317 insertions(+), 5568 deletions(-)
create mode 100644 .github/workflows/crates.yml
create mode 100644 .github/workflows/maturin.yml
create mode 100644 .github/workflows/unittests-rust.yml
rename crates/Cargo.lock => Cargo.lock (75%)
create mode 100644 Cargo.toml
rename benchmarks/ekore/{benchmark_ad.py => benchmark_pegasus_ad_us_as2.py} (87%)
create mode 100644 benchmarks/ekore/benchmark_pegasus_mellin.py
create mode 100644 benchmarks/ekore/benchmark_pegasus_ome_ps_as2.py
delete mode 100644 crates/Cargo.toml
create mode 100644 crates/README.md
create mode 100644 crates/bump-versions.py
create mode 100644 crates/doc-header.html
create mode 120000 crates/eko/doc-header.html
create mode 120000 crates/eko/src/bib.rs
create mode 120000 crates/ekore/doc-header.html
create mode 100644 crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as2.rs
create mode 100644 crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as3.rs
create mode 100644 crates/ekore/src/harmonics/g_functions.rs
create mode 100644 crates/ekore/src/harmonics/w2.rs
create mode 100644 crates/ekore/src/harmonics/w3.rs
create mode 100644 crates/ekore/src/harmonics/w4.rs
create mode 100644 crates/parse-abbrev.py
create mode 100644 crates/release.json
create mode 100644 extras/lh_bench_23/parse_to_latex.py
delete mode 100644 extras/lh_bench_23/plot_bench.py
create mode 100644 extras/lh_bench_23/plot_trn_exa.py
create mode 100644 extras/lh_bench_23/run-trn_exa.py
rename extras/lh_bench_23/{run_fhmv.sh => run_fhmruvv.sh} (76%)
create mode 100644 extras/lh_bench_23/tables/EKO.zip
create mode 100644 extras/lh_bench_23/tables/MSHT.zip
create mode 100644 extras/lh_bench_23/tables/table14-part1.csv
create mode 100644 extras/lh_bench_23/tables/table15-part1.csv
create mode 100644 extras/lh_bench_23/tables/table_FFNS-1_iterate-exact.csv
create mode 100644 extras/lh_bench_23/tables/table_FFNS-1_truncated.csv
create mode 100644 extras/lh_bench_23/tables/table_FFNS-2_iterate-exact.csv
create mode 100644 extras/lh_bench_23/tables/table_FFNS-2_truncated.csv
create mode 100644 extras/lh_bench_23/tables/table_FFNS-3_iterate-exact.csv
create mode 100644 extras/lh_bench_23/tables/table_FFNS-3_truncated.csv
delete mode 100644 src/eko/io/bases.py
delete mode 100644 src/eko/kernels/utils.py
delete mode 100644 tests/eko/evolution_operator/test_init.py.patch
delete mode 100644 tests/eko/io/test_bases.py
create mode 100644 tests/eko/kernels/test_init.py
delete mode 100644 tests/eko/kernels/test_utils.py
create mode 100644 tests/eko/scale_variations/test_diff.py
create mode 100644 tests/ekomark/data/__init__.py
create mode 100644 tests/ekomark/data/test_init.py
diff --git a/.github/workflows/crates.yml b/.github/workflows/crates.yml
new file mode 100644
index 000000000..935ce2aba
--- /dev/null
+++ b/.github/workflows/crates.yml
@@ -0,0 +1,28 @@
+name: Deploy Crates
+
+on:
+ push:
+ tags:
+ - "*"
+ workflow_dispatch:
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ - name: Install and configure Poetry
+ uses: snok/install-poetry@v1
+ - name: Install task runner
+ run: pip install poethepoet
+ - name: Bump versions
+ run: |
+ poetry install --only version
+ poe bump-version
+ - name: Publish crates
+ run: |
+ jq '.[]' crates/release.json | xargs -I _ cargo publish -p _ --allow-dirty
+ env:
+ CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
diff --git a/.github/workflows/maturin.yml b/.github/workflows/maturin.yml
new file mode 100644
index 000000000..4680d0316
--- /dev/null
+++ b/.github/workflows/maturin.yml
@@ -0,0 +1,123 @@
+name: Deploy Maturin wheels
+
+on:
+ push:
+ tags:
+ - "*"
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+jobs:
+ linux:
+ runs-on: ${{ matrix.platform.runner }}
+ strategy:
+ matrix:
+ platform:
+ - runner: ubuntu-latest
+ target: x86_64
+ - runner: ubuntu-latest
+ target: x86
+ - runner: ubuntu-latest
+ target: aarch64
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.10"
+ - name: Build wheels
+ uses: PyO3/maturin-action@v1
+ with:
+ target: ${{ matrix.platform.target }}
+ args: --release --out dist --find-interpreter -m crates/eko/Cargo.toml
+ sccache: "true"
+ manylinux: auto
+ - name: Upload wheels
+ uses: actions/upload-artifact@v4
+ with:
+ name: wheels-linux-${{ matrix.platform.target }}
+ path: dist
+
+ windows:
+ runs-on: ${{ matrix.platform.runner }}
+ strategy:
+ matrix:
+ platform:
+ - runner: windows-latest
+ target: x64
+ - runner: windows-latest
+ target: x86
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.10"
+ architecture: ${{ matrix.platform.target }}
+ - name: Build wheels
+ uses: PyO3/maturin-action@v1
+ with:
+ target: ${{ matrix.platform.target }}
+ args: --release --out dist --find-interpreter -m crates/eko/Cargo.toml
+ sccache: "true"
+ - name: Upload wheels
+ uses: actions/upload-artifact@v4
+ with:
+ name: wheels-windows-${{ matrix.platform.target }}
+ path: dist
+
+ macos:
+ runs-on: ${{ matrix.platform.runner }}
+ strategy:
+ matrix:
+ platform:
+ - runner: macos-latest
+ target: x86_64
+ - runner: macos-14
+ target: aarch64
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.10"
+ - name: Build wheels
+ uses: PyO3/maturin-action@v1
+ with:
+ target: ${{ matrix.platform.target }}
+ args: --release --out dist --find-interpreter -m crates/eko/Cargo.toml
+ sccache: "true"
+ - name: Upload wheels
+ uses: actions/upload-artifact@v4
+ with:
+ name: wheels-macos-${{ matrix.platform.target }}
+ path: dist
+
+ sdist:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Build sdist
+ uses: PyO3/maturin-action@v1
+ with:
+ command: sdist
+ args: --out dist -m crates/eko/Cargo.toml
+ - name: Upload sdist
+ uses: actions/upload-artifact@v4
+ with:
+ name: wheels-sdist
+ path: dist
+
+ release:
+ name: Release
+ runs-on: ubuntu-latest
+ if: "startsWith(github.ref, 'refs/tags/')"
+ needs: [linux, windows, macos, sdist]
+ steps:
+ - uses: actions/download-artifact@v4
+ - name: Publish to PyPI
+ uses: PyO3/maturin-action@v1
+ env:
+ MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
+ with:
+ command: upload
+ args: --non-interactive --skip-existing wheels-*/*
diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml
index 46040a1ae..45f89248b 100644
--- a/.github/workflows/pypi.yml
+++ b/.github/workflows/pypi.yml
@@ -7,7 +7,7 @@ on:
jobs:
publish:
- uses: N3PDF/workflows/.github/workflows/python-poetry-pypi.yml@v2
+ uses: NNPDF/workflows/.github/workflows/python-poetry-pypi.yml@v2
secrets:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
with:
diff --git a/.github/workflows/unittests-rust.yml b/.github/workflows/unittests-rust.yml
new file mode 100644
index 000000000..2b05cb4d6
--- /dev/null
+++ b/.github/workflows/unittests-rust.yml
@@ -0,0 +1,21 @@
+name: Rust unit tests
+
+on: push
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ - name: Install task runner
+ run: pip install poethepoet
+ - name: Run fmt
+ run: |
+ poe fmtcheck
+ - name: Run clippy
+ run: |
+ poe clippy
+ - name: Run Rust unit tests
+ run: |
+ poe rtest
diff --git a/.github/workflows/unittests.yml b/.github/workflows/unittests.yml
index ef3f7fa3f..a21b8531e 100644
--- a/.github/workflows/unittests.yml
+++ b/.github/workflows/unittests.yml
@@ -1,4 +1,4 @@
-name: tests
+name: Python unit tests
on: push
@@ -6,10 +6,10 @@ jobs:
test:
strategy:
matrix:
- python-version: ["3.8", "3.9", "3.10", "3.11"]
+ python-version: ["3.9", "3.10", "3.11", "3.12"]
fail-fast: false
- uses: N3PDF/workflows/.github/workflows/python-poetry-tests.yml@v2
+ uses: NNPDF/workflows/.github/workflows/python-poetry-tests.yml@v2
with:
python-version: ${{ matrix.python-version }}
poetry-extras: "-E mark -E box"
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index bee3e7adc..dfd0862f5 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -2,10 +2,10 @@
# See https://pre-commit.com/hooks.html for more hooks
ci:
autofix_prs: false
- skip: [fmt-eko, fmt-ekore]
+ skip: [fmt] # will be run by a separate CI
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.5.0
+ rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
@@ -19,11 +19,11 @@ repos:
- id: pycln
args: [--config=pyproject.toml]
- repo: https://github.com/psf/black-pre-commit-mirror
- rev: 23.12.1
+ rev: 24.4.2
hooks:
- id: black
- repo: https://github.com/asottile/blacken-docs
- rev: 1.16.0
+ rev: 1.18.0
hooks:
- id: blacken-docs
- repo: https://github.com/pycqa/isort
@@ -32,7 +32,7 @@ repos:
- id: isort
args: ["--profile", "black"]
- repo: https://github.com/asottile/pyupgrade
- rev: v3.15.0
+ rev: v3.17.0
hooks:
- id: pyupgrade
- repo: https://github.com/pycqa/pydocstyle
@@ -43,25 +43,23 @@ repos:
args: ["--add-ignore=D107,D105"]
additional_dependencies:
- toml
- - repo: local
+ - repo: https://github.com/pre-commit/mirrors-mypy
+ rev: v1.4.1
hooks:
- - id: fmt-eko
- name: fmt-eko
- description: Format eko files with cargo fmt.
- entry: cargo fmt --manifest-path crates/eko/Cargo.toml --
- language: system
- files: ^crates/eko/.*\.rs$
- args: []
+ - id: mypy
+ additional_dependencies: [types-PyYAML]
+ pass_filenames: false
+ args: ["--ignore-missing-imports", "src/"]
- repo: local
hooks:
- - id: fmt-ekore
- name: fmt-ekore
- description: Format ekore files with cargo fmt.
- entry: cargo fmt --manifest-path crates/ekore/Cargo.toml --
+ - id: fmt
+ name: fmt
+ description: Format Rust files with cargo fmt.
+ entry: cargo fmt --
language: system
- files: ^crates/ekore/.*\.rs$
+ files: ^crates/.*\.rs$
args: []
- repo: https://github.com/pre-commit/pre-commit
- rev: v3.6.0
+ rev: v3.8.0
hooks:
- id: validate_manifest
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index 7b5c39c8d..e734d32c8 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -1,3 +1,7 @@
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+# for poetry see https://docs.readthedocs.io/en/stable/build-customization.html#install-dependencies-with-poetry
+
+# Required
version: 2
build:
@@ -9,17 +13,13 @@ build:
jobs:
post_create_environment:
- pip install poetry
- - poetry config virtualenvs.create false
post_install:
- - poetry install --with docs
+ - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install --with docs
+# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: doc/source/conf.py
-# Optionally build your docs in additional formats such as PDF
-# formats:
-# - pdf
-
python:
install:
- method: pip
diff --git a/crates/Cargo.lock b/Cargo.lock
similarity index 75%
rename from crates/Cargo.lock
rename to Cargo.lock
index b6d5d084d..80fa02400 100644
--- a/crates/Cargo.lock
+++ b/Cargo.lock
@@ -33,20 +33,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "eko"
-version = "0.1.0"
+version = "0.0.1"
dependencies = [
"ekore",
- "katexit",
"num",
]
[[package]]
name = "ekore"
-version = "0.1.0"
+version = "0.0.1"
dependencies = [
"float-cmp",
"hashbrown",
- "katexit",
"num",
]
@@ -69,17 +67,6 @@ dependencies = [
"allocator-api2",
]
-[[package]]
-name = "katexit"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb1304c448ce2c207c2298a34bc476ce7ae47f63c23fa2b498583b26be9bc88c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
[[package]]
name = "num"
version = "0.4.1"
@@ -162,41 +149,6 @@ version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
-[[package]]
-name = "proc-macro2"
-version = "1.0.66"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
-
[[package]]
name = "version_check"
version = "0.9.4"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 000000000..f26518890
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,22 @@
+[workspace]
+members = ["crates/*"]
+resolver = "2"
+
+[workspace.package]
+authors = [
+ "A. Barontini ",
+ "A. Candido ",
+ "F. Hekhorn ",
+ "N. Laurenti ",
+ "G. Magni ",
+ "T. Sharma ",
+]
+description = "Evolution Kernel Operators"
+readme = "README.md"
+categories = ["science"]
+edition = "2021"
+keywords = ["physics"]
+license = "GPL-3.0-or-later"
+repository = "https://github.com/NNPDF/eko"
+rust-version = "1.60.0"
+version = "0.0.1"
diff --git a/README.md b/README.md
index 8344d4cb1..aef72ca2f 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
+
diff --git a/benchmarks/DSSV_bench.py b/benchmarks/DSSV_bench.py
index 3df7af356..4654f67d7 100644
--- a/benchmarks/DSSV_bench.py
+++ b/benchmarks/DSSV_bench.py
@@ -3,6 +3,7 @@
Note that the PDF set is private, but can be obtained from the
authors upon request.
"""
+
from banana import register
from eko import interpolation
diff --git a/benchmarks/NNPDF_bench.py b/benchmarks/NNPDF_bench.py
index 0e939f9ea..444b452cd 100644
--- a/benchmarks/NNPDF_bench.py
+++ b/benchmarks/NNPDF_bench.py
@@ -1,6 +1,7 @@
"""
Benchmark NNPDF pdf family
"""
+
from banana import register
from eko import interpolation
diff --git a/benchmarks/apfel_bench.py b/benchmarks/apfel_bench.py
index ae3189119..d40c65894 100644
--- a/benchmarks/apfel_bench.py
+++ b/benchmarks/apfel_bench.py
@@ -1,6 +1,7 @@
"""
Benchmark EKO to Apfel
"""
+
import numpy as np
from banana import register
from banana.data import cartesian_product
@@ -20,7 +21,6 @@ def tolist(input_dict):
class ApfelBenchmark(Runner):
-
"""
Globally set the external program to Apfel
"""
diff --git a/benchmarks/asv.conf.json b/benchmarks/asv.conf.json
index 628c6b460..eea67e10c 100644
--- a/benchmarks/asv.conf.json
+++ b/benchmarks/asv.conf.json
@@ -35,7 +35,7 @@
// The Pythons you'd like to test against. If not provided, defaults
// to the current version of Python used to run `asv`.
- "pythons": ["3.8", "3.9", "3.10"],
+ "pythons": ["3.9", "3.10"],
// The matrix of dependencies to test. Each key is the name of a
// package (in PyPI) and the values are version numbers. An empty
diff --git a/benchmarks/eko/benchmark_alphaem.py b/benchmarks/eko/benchmark_alphaem.py
index 16e56ac4a..9cc05536c 100644
--- a/benchmarks/eko/benchmark_alphaem.py
+++ b/benchmarks/eko/benchmark_alphaem.py
@@ -35,9 +35,7 @@ def test_alphaQED_high(self):
dict(
alphas=0.118,
alphaem=7.7553e-03,
- scale=91.2,
- num_flavs_ref=5,
- max_num_flavs=5,
+ ref=(91.2, 5),
em_running=True,
)
)
@@ -75,9 +73,7 @@ def test_alphaQED_low(self):
dict(
alphas=0.118,
alphaem=7.7553e-03,
- scale=91.2,
- num_flavs_ref=5,
- max_num_flavs=5,
+ ref=(91.2, 5),
em_running=True,
)
)
@@ -124,9 +120,7 @@ def test_validphys(self):
dict(
alphas=0.118,
alphaem=7.7553e-03,
- scale=91.2,
- num_flavs_ref=5,
- max_num_flavs=5,
+ ref=(91.2, 5),
em_running=True,
)
)
diff --git a/benchmarks/eko/benchmark_evol_to_unity.py b/benchmarks/eko/benchmark_evol_to_unity.py
index 41bc4b4d0..c466d00d8 100644
--- a/benchmarks/eko/benchmark_evol_to_unity.py
+++ b/benchmarks/eko/benchmark_evol_to_unity.py
@@ -19,16 +19,12 @@ def update_cards(theory: TheoryCard, operator: OperatorCard):
theory.couplings = CouplingsInfo(
alphas=0.35,
alphaem=0.007496,
- scale=float(np.sqrt(2)),
- max_num_flavs=6,
- num_flavs_ref=None,
+ ref=(float(np.sqrt(2)), 4),
)
- theory.heavy.num_flavs_init = 4
- theory.heavy.intrinsic_flavors = [4, 5]
theory.heavy.masses.c.value = 1.0
theory.heavy.masses.b.value = 4.75
theory.heavy.masses.t.value = 173.0
- operator.mu0 = float(np.sqrt(2))
+ operator.init = (float(np.sqrt(2)), 4)
operator.mugrid = [(10, 5)]
operator.xgrid = XGrid(np.linspace(1e-1, 1, 30))
operator.configs.interpolation_polynomial_degree = 1
diff --git a/benchmarks/eko/benchmark_inverse_matching.py b/benchmarks/eko/benchmark_inverse_matching.py
index d9c16b0b2..d63b776f0 100644
--- a/benchmarks/eko/benchmark_inverse_matching.py
+++ b/benchmarks/eko/benchmark_inverse_matching.py
@@ -20,14 +20,9 @@
couplings=dict(
alphas=0.118,
alphaem=0.007496252,
- scale=91.2,
- num_flavs_ref=5,
- max_num_flavs=6,
+ ref=(91.2, 5),
),
heavy=dict(
- num_flavs_init=4,
- num_flavs_max_pdf=6,
- intrinsic_flavors=[],
masses=[ReferenceRunning([mq, np.nan]) for mq in (MC, 4.92, 172.5)],
masses_scheme="POLE",
matching_ratios=[1.0, 1.0, np.inf],
@@ -40,7 +35,7 @@
# operator settings
op_raw = dict(
- mu0=1.65,
+ init=(1.65, 4),
xgrid=[0.0001, 0.001, 0.01, 0.1, 1],
mugrid=[(MC, 3), (MC, 4)],
configs=dict(
diff --git a/benchmarks/eko/benchmark_msbar_evolution.py b/benchmarks/eko/benchmark_msbar_evolution.py
index 6286e15ad..49dc0e952 100644
--- a/benchmarks/eko/benchmark_msbar_evolution.py
+++ b/benchmarks/eko/benchmark_msbar_evolution.py
@@ -1,4 +1,5 @@
"""This module benchmarks MSbar mass evolution against APFEL."""
+
import numpy as np
import pytest
@@ -20,9 +21,8 @@
def update_theory(theory: TheoryCard):
theory.order = (3, 0)
- theory.couplings.scale = 91
+ theory.couplings.ref = (91, 5)
theory.couplings.alphaem = 0.007496
- theory.couplings.num_flavs_ref = 5
theory.heavy.masses_scheme = QuarkMassScheme.MSBAR
theory.heavy.masses.c = QuarkMassRef([1.5, 18])
theory.heavy.masses.b = QuarkMassRef([4.1, 20])
@@ -149,7 +149,7 @@ def benchmark_APFEL_msbar_evolution(
apfel.SetTheory("QCD")
apfel.SetPerturbativeOrder(order - 1)
apfel.SetAlphaEvolution(method)
- apfel.SetAlphaQCDRef(coupl.alphas, coupl.scale)
+ apfel.SetAlphaQCDRef(coupl.alphas, coupl.ref[0])
apfel.SetVFNS()
apfel.SetMSbarMasses(
qmasses.c.value, qmasses.b.value, qmasses.t.value
@@ -217,7 +217,7 @@ def benchmark_APFEL_msbar_solution(
apfel.SetTheory("QCD")
apfel.SetPerturbativeOrder(order - 1)
apfel.SetAlphaEvolution("exact")
- apfel.SetAlphaQCDRef(coupl.alphas, coupl.scale)
+ apfel.SetAlphaQCDRef(coupl.alphas, coupl.ref[0])
apfel.SetVFNS()
apfel.SetMSbarMasses(qmasses.c.value, qmasses.b.value, qmasses.t.value)
apfel.SetMassScaleReference(
diff --git a/benchmarks/eko/benchmark_strong_coupling.py b/benchmarks/eko/benchmark_strong_coupling.py
index d13a264bd..d60bd28b0 100644
--- a/benchmarks/eko/benchmark_strong_coupling.py
+++ b/benchmarks/eko/benchmark_strong_coupling.py
@@ -8,7 +8,7 @@
from eko.couplings import Couplings
from eko.io.runcards import TheoryCard
from eko.quantities.couplings import CouplingEvolutionMethod, CouplingsInfo
-from eko.quantities.heavy_quarks import QuarkMassScheme
+from eko.quantities.heavy_quarks import FlavorsNumber, QuarkMassScheme
# try to load LHAPDF - if not available, we'll use the cached values
try:
@@ -35,16 +35,11 @@
use_PEGASUS = False
-def ref_couplings(
- ref_values,
- ref_scale: float,
-) -> CouplingsInfo:
+def ref_couplings(ref_values, ref_scale: float, ref_nf: FlavorsNumber) -> CouplingsInfo:
return CouplingsInfo(
alphas=ref_values[0],
alphaem=ref_values[1],
- scale=ref_scale,
- max_num_flavs=6,
- num_flavs_ref=None,
+ ref=(ref_scale, ref_nf),
)
@@ -54,11 +49,11 @@ def test_a_s(self):
"""Tests the value of alpha_s (for now only at LO)
for a given set of parameters
"""
- # TODO @JCM: we need a source for this!
+ # source: JCM
known_val = 0.0091807954
ref_mu2 = 90
ask_q2 = 125
- ref = ref_couplings([0.1181, 0.007496], np.sqrt(ref_mu2))
+ ref = ref_couplings([0.1181, 0.007496], np.sqrt(ref_mu2), 5)
as_FFNS_LO = Couplings(
couplings=ref,
order=(1, 0),
@@ -80,7 +75,7 @@ def benchmark_LHA_paper(self):
# LO - FFNS
# note that the LO-FFNS value reported in :cite:`Giele:2002hx`
# was corrected in :cite:`Dittmar:2005ed`
- coupling_ref = ref_couplings([0.35, 0.007496], np.sqrt(2))
+ coupling_ref = ref_couplings([0.35, 0.007496], np.sqrt(2), 4)
as_FFNS_LO = Couplings(
couplings=coupling_ref,
order=(1, 0),
@@ -141,7 +136,7 @@ def benchmark_APFEL_ffns(self):
threshold_holder = matchings.Atlas.ffns(nf, 0.0)
for order in [1, 2, 3]:
as_FFNS = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf),
order=(order, 0),
method=CouplingEvolutionMethod.EXPANDED,
masses=threshold_holder.walls[1:-1],
@@ -212,8 +207,7 @@ def benchmark_pegasus_ffns(self):
}
# collect my values
threshold_holder = matchings.Atlas.ffns(nf, 0.0)
- couplings = ref_couplings(coupling_ref, scale_ref)
- couplings.max_num_flavs = 4
+ couplings = ref_couplings(coupling_ref, scale_ref, nf)
for order in [1, 2, 3, 4]:
as_FFNS = Couplings(
couplings=couplings,
@@ -259,6 +253,7 @@ def benchmark_APFEL_vfns(self):
Q2s = [1, 2**2, 3**2, 90**2, 100**2]
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 91.0
+ nf_ref = 5
threshold_list = np.power([2, 4, 175], 2)
apfel_vals_dict = {
1: np.array(
@@ -292,7 +287,7 @@ def benchmark_APFEL_vfns(self):
# collect my values
for order in [1, 2, 3]:
as_VFNS = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf_ref),
order=(order, 0),
method=CouplingEvolutionMethod.EXPANDED,
masses=threshold_list,
@@ -339,8 +334,9 @@ def benchmark_APFEL_vfns_fact_to_ren(self):
]
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 91.0
+ nf_refs = (5, 6)
fact_to_ren_lin_list = [0.567, 2.34]
- threshold_list = np.power([2, 2 * 4, 2 * 92], 2)
+ masses_list = np.power([2, 2 * 4, 2 * 92], 2)
apfel_vals_dict_list = [
{
1: np.array(
@@ -431,16 +427,16 @@ def benchmark_APFEL_vfns_fact_to_ren(self):
),
},
]
- for fact_to_ren_lin, apfel_vals_dict in zip(
- fact_to_ren_lin_list, apfel_vals_dict_list
+ for fact_to_ren_lin, apfel_vals_dict, nf_ref in zip(
+ fact_to_ren_lin_list, apfel_vals_dict_list, nf_refs
):
# collect my values
for order in [1, 2, 3]:
as_VFNS = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf_ref),
order=(order, 0),
method=CouplingEvolutionMethod.EXACT,
- masses=threshold_list.tolist(),
+ masses=masses_list.tolist(),
hqm_scheme=QuarkMassScheme.POLE,
thresholds_ratios=np.array([1.0, 1.0, 1.0]) / fact_to_ren_lin**2,
)
@@ -457,7 +453,7 @@ def benchmark_APFEL_vfns_fact_to_ren(self):
apfel.SetAlphaEvolution("exact")
apfel.SetAlphaQCDRef(coupling_ref[0], scale_ref)
apfel.SetVFNS()
- apfel.SetPoleMasses(*np.sqrt(threshold_list))
+ apfel.SetPoleMasses(*np.sqrt(masses_list))
apfel.SetRenFacRatio(1.0 / fact_to_ren_lin)
apfel.InitializeAPFEL()
# collect a_s
@@ -468,12 +464,18 @@ def benchmark_APFEL_vfns_fact_to_ren(self):
)
np.testing.assert_allclose(apfel_vals, np.array(apfel_vals_cur))
# check myself to APFEL
- np.testing.assert_allclose(apfel_vals, np.array(my_vals), rtol=2.5e-5)
+ np.testing.assert_allclose(
+ apfel_vals,
+ np.array(my_vals),
+ rtol=2.5e-5,
+ err_msg=f"{order=},{fact_to_ren_lin=}",
+ )
def benchmark_APFEL_vfns_threshold(self):
Q2s = np.power([30, 96, 150], 2)
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 91.0
+ nf_ref = 4
threshold_list = np.power([30, 95, 240], 2)
thresholds_ratios = [2.34**2, 1.0**2, 0.5**2]
apfel_vals_dict = {
@@ -487,7 +489,7 @@ def benchmark_APFEL_vfns_threshold(self):
# collect my values
for order in [2, 3]:
as_VFNS = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf_ref),
order=(order, 0),
method=CouplingEvolutionMethod.EXPANDED,
masses=threshold_list.tolist(),
@@ -496,7 +498,6 @@ def benchmark_APFEL_vfns_threshold(self):
)
my_vals = []
for Q2 in Q2s:
- print(Q2)
my_vals.append(as_VFNS.a(Q2)[0])
# get APFEL numbers - if available else use cache
apfel_vals = apfel_vals_dict[order]
@@ -516,7 +517,6 @@ def benchmark_APFEL_vfns_threshold(self):
apfel_vals_cur = []
for Q2 in Q2s:
apfel_vals_cur.append(apfel.AlphaQCD(np.sqrt(Q2)) / (4.0 * np.pi))
- print(apfel_vals_cur)
np.testing.assert_allclose(apfel_vals, np.array(apfel_vals_cur))
# check myself to APFEL
np.testing.assert_allclose(apfel_vals, np.array(my_vals))
@@ -525,6 +525,7 @@ def benchmark_APFEL_vfns_msbar(self):
Q2s = np.power([3, 96, 150], 2)
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 91.0
+ nf_ref = 5
Q2m = np.power([2.0, 4.0, 175], 2)
m2s = np.power((1.4, 4.0, 175), 2)
apfel_vals_dict = {
@@ -538,7 +539,7 @@ def benchmark_APFEL_vfns_msbar(self):
# collect my values
for order in [2, 3]:
as_VFNS = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf_ref),
order=(order, 0),
method=CouplingEvolutionMethod.EXPANDED,
masses=m2s.tolist(),
@@ -586,7 +587,7 @@ def benchmark_lhapdf_ffns_lo(self):
# collect my values
threshold_holder = matchings.Atlas.ffns(nf, 0.0)
as_FFNS_LO = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf),
order=(1, 0),
method=CouplingEvolutionMethod.EXACT,
masses=threshold_holder.walls[1:-1],
@@ -629,8 +630,9 @@ def benchmark_apfel_exact(self):
Q2s = [1e1, 1e2, 1e3, 1e4]
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 90
+ nf = 3
# collect my values
- threshold_holder = matchings.Atlas.ffns(3, 0.0)
+ threshold_holder = matchings.Atlas.ffns(nf, 0.0)
# LHAPDF cache
apfel_vals_dict = {
1: np.array(
@@ -660,7 +662,7 @@ def benchmark_apfel_exact(self):
}
for order in range(1, 3 + 1):
sc = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf),
order=(order, 0),
method=CouplingEvolutionMethod.EXACT,
masses=threshold_holder.walls[1:-1],
@@ -696,8 +698,9 @@ def benchmark_lhapdf_exact(self):
Q2s = [1e1, 1e2, 1e3, 1e4]
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 90
+ nf = 3
# collect my values
- threshold_holder = matchings.Atlas.ffns(3, 0.0)
+ threshold_holder = matchings.Atlas.ffns(nf, 0.0)
# LHAPDF cache
lhapdf_vals_dict = {
1: np.array(
@@ -735,7 +738,7 @@ def benchmark_lhapdf_exact(self):
}
for order in range(1, 4 + 1):
sc = Couplings(
- couplings=ref_couplings(coupling_ref, scale_ref),
+ couplings=ref_couplings(coupling_ref, scale_ref, nf),
order=(order, 0),
method=CouplingEvolutionMethod.EXACT,
masses=threshold_holder.walls[1:-1],
@@ -766,6 +769,7 @@ def benchmark_lhapdf_zmvfns_lo(self):
Q2s = [1, 1e1, 1e2, 1e3, 1e4]
coupling_ref = np.array([0.118, 0.007496])
scale_ref = 900
+ nf_ref = 5
m2c = 2.0
m2b = 25.0
m2t = 1500.0
@@ -785,7 +789,7 @@ def benchmark_lhapdf_zmvfns_lo(self):
# collect my values
as_VFNS_LO = Couplings(
- couplings=ref_couplings(coupling_ref, np.sqrt(scale_ref)),
+ couplings=ref_couplings(coupling_ref, np.sqrt(scale_ref), nf_ref),
order=(1, 0),
method=CouplingEvolutionMethod.EXACT,
masses=threshold_list,
@@ -836,10 +840,8 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self, theory_card: TheoryCard):
theory = theory_card
theory.order = (3, 0)
theory.couplings.alphas = 0.35
- theory.couplings.scale = float(np.sqrt(2))
theory.couplings.alphaem = 0.007496
- theory.couplings.num_flavs_ref = 4
- theory.heavy.num_flavs_init = 3
+ theory.couplings.ref = (float(np.sqrt(2)), 4)
theory.xif = np.sqrt(1.0 / 2.0)
theory.heavy.masses.c.value = np.sqrt(2.0)
theory.heavy.masses.b.value = 4.5
@@ -881,7 +883,7 @@ def benchmark_APFEL_fact_to_ren_lha_settings(self, theory_card: TheoryCard):
apfel.SetTheory("QCD")
apfel.SetPerturbativeOrder(theory.order[0] - 1)
apfel.SetAlphaEvolution("exact")
- apfel.SetAlphaQCDRef(theory.couplings.alphas, theory.couplings.scale)
+ apfel.SetAlphaQCDRef(theory.couplings.alphas, theory.couplings.ref[0])
apfel.SetVFNS()
apfel.SetPoleMasses(qmasses.c.value, qmasses.b.value, qmasses.t.value)
apfel.SetMassMatchingScales(
diff --git a/benchmarks/ekobox/benchmark_evol_pdf.py b/benchmarks/ekobox/benchmark_evol_pdf.py
index 3a9dc0f4a..a0ddcaac4 100644
--- a/benchmarks/ekobox/benchmark_evol_pdf.py
+++ b/benchmarks/ekobox/benchmark_evol_pdf.py
@@ -21,15 +21,13 @@ def benchmark_evolve_single_member(
theory = theory_card
theory.order = (1, 0)
theory.couplings.alphas = 0.118000
- theory.couplings.scale = 91.1876
+ theory.couplings.ref = (91.1876, 5)
theory.couplings.alphaem = 0.007496
- theory.couplings.max_num_flavs = 3
- theory.heavy.num_flavs_max_pdf = 3
theory.heavy.masses.c.value = 1.3
theory.heavy.masses.b.value = 4.75
theory.heavy.masses.t.value = 172
op = operator_card
- op.mu0 = 5.0
+ op.init = (5.0, 4)
op.mugrid = mugrid
# lhapdf import (maybe i have to dump with a x*), do plots)
with lhapdf_path(test_pdf):
@@ -49,7 +47,7 @@ def benchmark_evolve_single_member(
ev_pdf = lhapdf.mkPDF("EvPDF", 0)
assert info["XMin"] == op.xgrid.raw[0]
assert info["SetDesc"] == "MyEvolvedPDF"
- assert info["MZ"] == theory.couplings.scale
+ assert info["MZ"] == theory.couplings.ref[0]
assert info["Debug"] == "Debug"
xgrid = op.xgrid.raw
for idx, mu2 in enumerate(op.mu2grid):
@@ -76,7 +74,7 @@ def benchmark_evolve_more_members(
theory = theory_card
theory.order = (1, 0)
op = operator_card
- op.mu0 = 1.0
+ op.init = (1.0, 3)
op.mugrid = [(10.0, 5), (100.0, 5)]
op.xgrid = XGrid([1e-7, 0.01, 0.1, 0.2, 0.3])
with lhapdf_path(test_pdf):
diff --git a/benchmarks/ekore/benchmark_ad.py b/benchmarks/ekore/benchmark_pegasus_ad_us_as2.py
similarity index 87%
rename from benchmarks/ekore/benchmark_ad.py
rename to benchmarks/ekore/benchmark_pegasus_ad_us_as2.py
index c3c8de01e..ebc53e3ae 100644
--- a/benchmarks/ekore/benchmark_ad.py
+++ b/benchmarks/ekore/benchmark_pegasus_ad_us_as2.py
@@ -1,4 +1,8 @@
-"""Benchmark the NLO anomalous dimensions against PEGASUS"""
+"""Benchmark the unpolarized NLO anomalous dimensions against PEGASUS.
+
+Recall that we obtained our representation not from PEGASUS, but derived it
+ourselves (see comment there)."""
+
import numpy as np
import pytest
@@ -7,39 +11,6 @@
from eko.constants import CA, CF, TR, zeta2, zeta3
-@pytest.mark.isolated
-def benchmark_melling_g3_pegasus():
- for N in [1, 2, 3, 4, 1 + 1j, 1 - 1j, 2 + 1j, 3 + 1j]:
- check_melling_g3_pegasus(N)
-
-
-def check_melling_g3_pegasus(N):
- S1 = h.S1(N)
- N1 = N + 1.0
- N2 = N + 2.0
- N3 = N + 3.0
- N4 = N + 4.0
- N5 = N + 5.0
- N6 = N + 6.0
- S11 = S1 + 1.0 / N1
- S12 = S11 + 1.0 / N2
- S13 = S12 + 1.0 / N3
- S14 = S13 + 1.0 / N4
- S15 = S14 + 1.0 / N5
- S16 = S15 + 1.0 / N6
-
- SPMOM = (
- 1.0000 * (zeta2 - S1 / N) / N
- - 0.9992 * (zeta2 - S11 / N1) / N1
- + 0.9851 * (zeta2 - S12 / N2) / N2
- - 0.9005 * (zeta2 - S13 / N3) / N3
- + 0.6621 * (zeta2 - S14 / N4) / N4
- - 0.3174 * (zeta2 - S15 / N5) / N5
- + 0.0699 * (zeta2 - S16 / N6) / N6
- )
- np.testing.assert_allclose(h.g_functions.mellin_g3(N, S1), SPMOM)
-
-
@pytest.mark.isolated
def benchmark_gamma_ns_1_pegasus():
# remember that singlet has pole at N=1
@@ -53,7 +24,6 @@ def check_gamma_1_pegasus(N, NF):
ZETA2 = zeta2
ZETA3 = zeta3
- # N = np.random.rand(1) + np.random.rand(1) * 1j
S1 = h.S1(N)
S2 = h.S2(N)
diff --git a/benchmarks/ekore/benchmark_pegasus_mellin.py b/benchmarks/ekore/benchmark_pegasus_mellin.py
new file mode 100644
index 000000000..addefe421
--- /dev/null
+++ b/benchmarks/ekore/benchmark_pegasus_mellin.py
@@ -0,0 +1,41 @@
+"""Benchmark the Mellin transforms against PEGASUS."""
+
+import numpy as np
+import pytest
+
+import ekore.anomalous_dimensions.unpolarized.space_like.as2 as ad_as2
+import ekore.harmonics as h
+from eko.constants import CA, CF, TR, zeta2, zeta3
+
+
+@pytest.mark.isolated
+def benchmark_melling_g3_pegasus():
+ for N in [1, 2, 3, 4, 1 + 1j, 1 - 1j, 2 + 1j, 3 + 1j]:
+ check_melling_g3_pegasus(N)
+
+
+def check_melling_g3_pegasus(N):
+ S1 = h.S1(N)
+ N1 = N + 1.0
+ N2 = N + 2.0
+ N3 = N + 3.0
+ N4 = N + 4.0
+ N5 = N + 5.0
+ N6 = N + 6.0
+ S11 = S1 + 1.0 / N1
+ S12 = S11 + 1.0 / N2
+ S13 = S12 + 1.0 / N3
+ S14 = S13 + 1.0 / N4
+ S15 = S14 + 1.0 / N5
+ S16 = S15 + 1.0 / N6
+
+ SPMOM = (
+ 1.0000 * (zeta2 - S1 / N) / N
+ - 0.9992 * (zeta2 - S11 / N1) / N1
+ + 0.9851 * (zeta2 - S12 / N2) / N2
+ - 0.9005 * (zeta2 - S13 / N3) / N3
+ + 0.6621 * (zeta2 - S14 / N4) / N4
+ - 0.3174 * (zeta2 - S15 / N5) / N5
+ + 0.0699 * (zeta2 - S16 / N6) / N6
+ )
+ np.testing.assert_allclose(h.g_functions.mellin_g3(N, S1), SPMOM)
diff --git a/benchmarks/ekore/benchmark_pegasus_ome_ps_as2.py b/benchmarks/ekore/benchmark_pegasus_ome_ps_as2.py
new file mode 100644
index 000000000..66b471c57
--- /dev/null
+++ b/benchmarks/ekore/benchmark_pegasus_ome_ps_as2.py
@@ -0,0 +1,199 @@
+"""Benchmark the polarized NNLO OME against PEGASUS"""
+
+import numpy as np
+import pytest
+
+import ekore.harmonics as h
+import ekore.operator_matrix_elements.polarized.space_like.as2 as ome_as2
+from eko.constants import CA, CF, TR, zeta2, zeta3
+
+
+@pytest.mark.isolated
+def benchmark_pegasus_ome_ps_as2():
+ # remember that singlet has pole at N=1
+ for N in [2, 3, 4, +1j, -1j, +1j, +1j]:
+ for NF in [3, 4, 5]:
+ check_pegasus_ome_ps_as2_s(N, NF)
+
+
+def check_pegasus_ome_ps_as2_s(N, NF):
+ # Test against pegasus implementation by Ignacio Borsa
+ ZETA2 = zeta2
+ ZETA3 = zeta3
+
+ S1 = h.S1(N)
+ S2 = h.S2(N)
+ S3 = h.S3(N)
+ #
+ NM = N - 1.0
+ N1 = N + 1.0
+ N2 = N + 2.0
+ NI = 1.0 / N
+ NMI = 1.0 / NM
+ N1I = 1.0 / N1
+ N2I = 1.0 / N2
+ #
+ S1M = S1 - NI
+ S2M = S2 - NI * NI
+ S3M = S3 - NI**3
+ S11 = S1 + N1I
+ S21 = S2 + N1I * N1I
+ S31 = S3 + N1I**3
+ S22 = S21 + N2I * N2I
+ ACG3 = h.g_functions.mellin_g3(N1, S11)
+ #
+ # CALL BET(N1,V1)
+ # CALL BET1(N1,V2)
+ # CALL BET2(N1,V3)
+ # CALL BET3(N1,V4)
+ V1 = (
+ h.polygamma.cern_polygamma((N1 + 1.0) / 2.0, 0)
+ - h.polygamma.cern_polygamma(N1 / 2.0, 0)
+ ) / 2.0
+ V2 = (
+ h.polygamma.cern_polygamma((N1 + 1.0) / 2.0, 1)
+ - h.polygamma.cern_polygamma(N1 / 2.0, 1)
+ ) / 4.0
+ V3 = (
+ h.polygamma.cern_polygamma((N1 + 1.0) / 2.0, 2)
+ - h.polygamma.cern_polygamma(N1 / 2.0, 2)
+ ) / 8.0
+ #
+ #
+ # ..The moments of the OME's DA_Hq^{PS,(2)} and DA_Hg^{S,(2)} given in
+ # Eqs. (138) and (111) of BBDKS. Note that for the former, an
+ # additional finite renormalization is needed to go from the Larin
+ # to the the M scheme
+ #
+ #
+ # ... Anomalous dimension terms
+ #
+ G0QG_HAT = -8 * TR * NM / N / N1
+ #
+ G0GQ = -4 * CF * N2 / N / N1
+ #
+ G0QQ = -CF * (2 * (2.0 + 3.0 * N + 3.0 * N**2) / N / N1 - 8.0 * S1)
+ #
+ # ... Polinomials in N
+ POL1 = (
+ 12 * N**8 + 52 * N**7 + 60 * N**6 - 25 * N**4 - 2 * N**3 + 3 * N**2 + 8 * N + 4
+ )
+ #
+ POL2 = (
+ 2.0 * N**8
+ + 10.0 * N**7
+ + 22.0 * N**6
+ + 36.0 * N**5
+ + 29.0 * N**4
+ + 4.0 * N**3
+ + 33.0 * N**2
+ + 12.0 * N
+ + 4
+ )
+ #
+ POLR3 = 15 * N**6 + 45 * N**5 + 374 * N**4 + 601 * N**3 + 161 * N**2 - 24 * N + 36
+ #
+ POLR8 = (
+ -15 * N**8
+ - 60 * N**7
+ - 82 * N**6
+ - 44 * N**5
+ - 15 * N**4
+ - 4 * N**2
+ - 12 * N
+ - 8
+ )
+ #
+ # ... Finite renormalization term from Larin to M scheme
+ #
+ ZQQPS = -CF * TR * 8 * N2 * (N**2 - N - 1.0) / N**3 / N1**3
+ #
+ A2HQ = (
+ -4
+ * CF
+ * TR
+ * N2
+ / N**2
+ / N1**2
+ * (NM * (2 * S2 + ZETA2) - (4 * N**3 - 4 * N**2 - 3 * N - 1) / N**2 / N1**2)
+ + ZETA2 / 8 * G0QG_HAT * G0GQ
+ )
+ #
+ #
+ A2HG = (
+ CF
+ * TR
+ * (
+ 4.0
+ / 3
+ * NM
+ / N
+ / N1
+ * (-4.0 * S3 + S1**3 + 3.0 * S1 * S2 + 6.0 * S1 * ZETA2)
+ - 4
+ * (N**4 + 17.0 * N**3 + 43.0 * N**2 + 33.0 * N + 2)
+ * S2
+ / N**2
+ / N1**2
+ / N2
+ - 4 * (3.0 * N**2 + 3.0 * N - 2) * S1**2 / N**2 / N1 / N2
+ - 2 * NM * (3.0 * N**2 + 3.0 * N + 2) * ZETA2 / N**2 / N1**2
+ - 4 * (N**3 - 2.0 * N**2 - 22.0 * N - 36) * S1 / N**2 / N1 / N2
+ - 2 * POL1 / N**4 / N1**4 / N2
+ )
+ + CA
+ * TR
+ * (
+ 4 * (N**2 + 4.0 * N + 5) * S1**2 / N / N1**2 / N2
+ + 4 * (7.0 * N**3 + 24.0 * N**2 + 15.0 * N - 16) * S2 / N**2 / N1**2 / N2
+ + 8 * NM * N2 * ZETA2 / N**2 / N1**2
+ + 4 * (N**4 + 4.0 * N**3 - N**2 - 10.0 * N + 2) * S1 / N / N1**3 / N2
+ - 4 * POL2 / N**4 / N1**4 / N2
+ - 16 * NM / N / N1**2 * V2
+ + 4
+ * NM
+ / 3.0
+ / N
+ / N1
+ * (
+ 12.0 * ACG3
+ + 3.0 * V3
+ - 8.0 * S3
+ - S1**3
+ - 9.0 * S1 * S2
+ - 12.0 * S1 * V2
+ - 12.0 * V1 * ZETA2
+ - 3.0 * ZETA3
+ )
+ )
+ # ... added simplified Gamma0_gg+2*beta0
+ + 1 / 8 * G0QG_HAT * (8 * CA * (-2.0 / N / N1 + S1) - G0QQ)
+ )
+ #
+ # ..The moments of the OME's DA_{gq,H}^{S,(2)} and DA_{gg,H}^{S,(2)}
+ # given in Eqs. (175) and (188) of Bierenblaum et al.
+ #
+ A2GQ = (
+ CF
+ * TR
+ * N2
+ * (
+ 8 * (22.0 + 41.0 * N + 28.0 * N**2) / 27.0 / N / N1**3
+ - 8 * (2.0 + 5.0 * N) * S1 / 9.0 / N / N1**2
+ + 4 * (S1**2 + S2) / 3.0 / N / N1
+ )
+ )
+ #
+ A2GG = (
+ CA
+ * TR
+ * (2 * POLR3 / 27.0 / N**3 / N1**3 - 4 * (47.0 + 56.0 * N) * S1 / 27.0 / N1)
+ + CF * TR * POLR8 / N**4 / N1**4
+ )
+
+ cache = h.cache.reset()
+ omeS2 = ome_as2.A_singlet(N, cache, 0.0, NF)
+ np.testing.assert_allclose(omeS2[0, 0], A2GG, err_msg=f"gg,{N=}")
+ np.testing.assert_allclose(omeS2[0, 1], A2GQ, err_msg=f"gq,{N=}")
+ np.testing.assert_allclose(omeS2[2, 1], A2HQ + NF * ZQQPS, err_msg=f"hq,{N=}")
+ np.testing.assert_allclose(omeS2[2, 0], A2HG, err_msg=f"hg,{N=}")
diff --git a/benchmarks/lha_paper_bench.py b/benchmarks/lha_paper_bench.py
index 9254307dc..bdc48ce59 100644
--- a/benchmarks/lha_paper_bench.py
+++ b/benchmarks/lha_paper_bench.py
@@ -1,6 +1,7 @@
"""
Benchmark to :cite:`Giele:2002hx` (LO + NLO) and :cite:`Dittmar:2005ed` (NNLO).
"""
+
import os
import numpy as np
@@ -12,19 +13,15 @@
register(__file__)
+_sqrt2 = float(np.sqrt(2.0))
+
base_theory = {
"ModEv": "EXA",
- "Q0": np.sqrt(
- 2.0
- ), # Eq. (30) :cite:`Giele:2002hx`, Eq. (4.53) :cite:`Dittmar:2005ed`
- "mc": np.sqrt(
- 2.0
- ), # Eq. (34) :cite:`Giele:2002hx`, Eq. (4.56) :cite:`Dittmar:2005ed`
+ "Q0": _sqrt2, # Eq. (30) :cite:`Giele:2002hx`, Eq. (4.53) :cite:`Dittmar:2005ed`
+ "mc": _sqrt2, # Eq. (34) :cite:`Giele:2002hx`, Eq. (4.56) :cite:`Dittmar:2005ed`
"mb": 4.5,
"mt": 175,
- "Qref": np.sqrt(
- 2.0
- ), # Eq. (32) :cite:`Giele:2002hx`,Eq. (4.53) :cite:`Dittmar:2005ed`
+ "Qref": _sqrt2, # Eq. (32) :cite:`Giele:2002hx`,Eq. (4.53) :cite:`Dittmar:2005ed`
"alphas": 0.35, # Eq. (4.55) :cite:`Dittmar:2005ed`
"alphaqed": 0.007496,
"QED": 0,
@@ -78,11 +75,11 @@ def sv_theories(self, pto):
"""
low = self.theory.copy()
low["PTO"] = pto
- low["XIF"] = np.sqrt(1.0 / 2.0)
+ low["XIF"] = 1.0 / _sqrt2
low["ModSV"] = "exponentiated"
high = self.theory.copy()
high["PTO"] = pto
- high["XIF"] = np.sqrt(2.0)
+ high["XIF"] = _sqrt2
high["ModSV"] = "exponentiated"
return [high, low]
@@ -301,7 +298,7 @@ def benchmark_sv(self, pto):
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)
+ low["XIR"] = _sqrt2
+ high["XIR"] = 1.0 / _sqrt2
self.run_lha([low, high])
diff --git a/crates/Cargo.toml b/crates/Cargo.toml
deleted file mode 100644
index 8a69f7202..000000000
--- a/crates/Cargo.toml
+++ /dev/null
@@ -1,3 +0,0 @@
-[workspace]
-
-members = ["eko", "ekore"]
diff --git a/crates/README.md b/crates/README.md
new file mode 100644
index 000000000..baa27a087
--- /dev/null
+++ b/crates/README.md
@@ -0,0 +1,18 @@
+# Welcome to the rusty side of EKO!
+
+Here, we develop the Rust components of the EKO library
+
+## Crates
+
+- `ekore` contains the underlying collinear anomalous dimensions and the operator matrix elements
+- `eko` is the glue between the Python side and the `ekore` crate
+
+## Files
+
+- `release.json` defines the releasing order of crates
+ - only listed crates will be released
+ - dependent crates should follow those they are depending on
+- `katex-header.html` is an HTML snippet to be included in every docs page to inject
+ KaTeX support
+- `bump-versions.py` increases the Rust versions in all crates consistently
+- `make_bib.py` generates the Rust function stubs which serve as fake bibliography system
diff --git a/crates/bump-versions.py b/crates/bump-versions.py
new file mode 100644
index 000000000..6b7220f7e
--- /dev/null
+++ b/crates/bump-versions.py
@@ -0,0 +1,40 @@
+import json
+import sys
+from pathlib import Path
+
+import tomlkit
+
+HERE = Path(__file__).parent
+CRATES = json.loads((HERE / "release.json").read_text())
+
+
+def workspace(manifest, version):
+ manifest["workspace"]["package"]["version"] = version
+ return manifest
+
+
+def crate(manifest, version):
+ internals = set(manifest["dependencies"].keys()).intersection(CRATES)
+ for dep in internals:
+ manifest["dependencies"][dep]["version"] = version
+ return manifest
+
+
+def update(path, version, edit):
+ path = HERE / Path(path) / "Cargo.toml"
+ manifest = tomlkit.parse(path.read_text())
+ manifest = edit(manifest, version)
+ path.write_text(tomlkit.dumps(manifest))
+
+
+def main(version):
+ update("..", version, workspace)
+ for name in CRATES:
+ update(name, version, crate)
+
+
+if __name__ == "__main__":
+ if len(sys.argv) < 2:
+ raise ValueError(f"Pass a version (e.g. v0.0.0) to {sys.argv[0]}")
+ # `git describe` starts with a `v` which we need to remove again
+ main(sys.argv[1][1:])
diff --git a/crates/doc-header.html b/crates/doc-header.html
new file mode 100644
index 000000000..3b2f9651b
--- /dev/null
+++ b/crates/doc-header.html
@@ -0,0 +1,65 @@
+
+
+
+
diff --git a/crates/eko/Cargo.toml b/crates/eko/Cargo.toml
index 50aee6504..0fffdea1a 100644
--- a/crates/eko/Cargo.toml
+++ b/crates/eko/Cargo.toml
@@ -1,7 +1,19 @@
[package]
name = "eko"
-version = "0.1.0"
-edition = "2021"
+
+authors.workspace = true
+description.workspace = true
+readme.workspace = true
+categories.workspace = true
+edition.workspace = true
+keywords.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
+version.workspace = true
+
+[package.metadata.docs.rs]
+rustdoc-args = ["--html-in-header", "doc-header.html"]
[lib]
name = "ekors"
@@ -9,5 +21,4 @@ crate-type = ["cdylib"]
[dependencies]
num = "0.4.1"
-katexit = "0.1.4"
-ekore = { version = "0.1.0", path = "../ekore" }
+ekore = { path = "../ekore", version = "0.0.1" }
diff --git a/crates/eko/doc-header.html b/crates/eko/doc-header.html
new file mode 120000
index 000000000..22282661d
--- /dev/null
+++ b/crates/eko/doc-header.html
@@ -0,0 +1 @@
+../doc-header.html
\ No newline at end of file
diff --git a/crates/eko/pyproject.toml b/crates/eko/pyproject.toml
index 2fff64504..7b2921e04 100644
--- a/crates/eko/pyproject.toml
+++ b/crates/eko/pyproject.toml
@@ -3,8 +3,8 @@ requires = ["maturin>=1.1,<2.0"]
build-backend = "maturin"
[project]
-name = "ekors"
-requires-python = ">=3.8"
+name = "eko-rs"
+requires-python = ">=3.9"
classifiers = [
"Programming Language :: Rust",
"Programming Language :: Python :: Implementation :: CPython",
diff --git a/crates/eko/src/bib.rs b/crates/eko/src/bib.rs
new file mode 120000
index 000000000..1e713280e
--- /dev/null
+++ b/crates/eko/src/bib.rs
@@ -0,0 +1 @@
+../../ekore/src/bib.rs
\ No newline at end of file
diff --git a/crates/eko/src/lib.rs b/crates/eko/src/lib.rs
index e6b3e44cc..67bf8956a 100644
--- a/crates/eko/src/lib.rs
+++ b/crates/eko/src/lib.rs
@@ -1,12 +1,15 @@
//! Interface to the eko Python package.
-use ekore;
use ekore::harmonics::cache::Cache;
use std::ffi::c_void;
-mod mellin;
+pub mod bib;
+pub mod mellin;
/// QCD intergration kernel inside quad.
+///
+/// # Safety
+/// This is the connection from Python, so we don't know what is on the other side.
#[no_mangle]
pub unsafe extern "C" fn rust_quad_ker_qcd(u: f64, rargs: *mut c_void) -> f64 {
let args = *(rargs as *mut QuadQCDargs);
@@ -23,11 +26,11 @@ pub unsafe extern "C" fn rust_quad_ker_qcd(u: f64, rargs: *mut c_void) -> f64 {
&mut c,
args.nf,
);
- for k in 0..args.order_qcd {
- for l in 0..2 {
- for m in 0..2 {
- re.push(res[k][l][m].re);
- im.push(res[k][l][m].im);
+ for gamma_s in res.iter().take(args.order_qcd) {
+ for col in gamma_s.iter().take(2) {
+ for el in col.iter().take(2) {
+ re.push(el.re);
+ im.push(el.im);
}
}
}
@@ -38,9 +41,9 @@ pub unsafe extern "C" fn rust_quad_ker_qcd(u: f64, rargs: *mut c_void) -> f64 {
&mut c,
args.nf,
);
- for j in 0..args.order_qcd {
- re.push(res[j].re);
- im.push(res[j].im);
+ for el in res.iter().take(args.order_qcd) {
+ re.push(el.re);
+ im.push(el.im);
}
}
// pass on
@@ -127,7 +130,10 @@ pub struct QuadQCDargs {
pub is_threshold: bool,
}
-/// empty placeholder function for python callback
+/// Empty placeholder function for python callback.
+///
+/// # Safety
+/// This is the connection back to Python, so we don't know what is on the other side.
pub unsafe extern "C" fn my_py(
_re_gamma: *const f64,
_im_gamma: *const f64,
@@ -161,6 +167,9 @@ pub unsafe extern "C" fn my_py(
///
/// This is required to make the arguments part of the API, otherwise it won't be added to the compiled
/// package (since it does not appear in the signature of `quad_ker_qcd`).
+///
+/// # Safety
+/// This is the connection from and back to Python, so we don't know what is on the other side.
#[no_mangle]
pub unsafe extern "C" fn empty_qcd_args() -> QuadQCDargs {
QuadQCDargs {
diff --git a/crates/eko/src/mellin.rs b/crates/eko/src/mellin.rs
index 5afc96f5f..1322bbe08 100644
--- a/crates/eko/src/mellin.rs
+++ b/crates/eko/src/mellin.rs
@@ -6,14 +6,16 @@
use num::complex::Complex;
use std::f64::consts::PI;
-#[cfg_attr(doc, katexit::katexit)]
/// Talbot inversion path.
///
/// Implements the algorithm presented in [\[Abate\]](crate::bib::Abate).
-/// $p_{\text{Talbot}}(t) = o + r \cdot ( \theta \cot(\theta) + i\theta)$ with $\theta = \pi(2t-1)$
-/// The default values for the parameters $r,o$ are given by $r = 1/2, o = 0$ for
-/// the non-singlet integrals and by $r = \frac{2}{5} \frac{16}{1 - \ln(x)}, o = 1$
-/// for the singlet sector. Note that the non-singlet kernels evolve poles only up to
+///
+/// $$p_{\text{Talbot}}(t) = o + r \cdot ( \theta \cot(\theta) + i\theta) ~ \text{with}~ \theta = \pi(2t-1)$$
+///
+/// The default values for the parameters $r,o$ are given by
+/// $r = \frac{2}{5} \frac{16}{0.1 - \ln(x)}$ and $o = 0$ for
+/// the non-singlet integrals and $o = 1$ for the singlet sector.
+/// Note that the non-singlet kernels evolve poles only up to
/// $N=0$ whereas the singlet kernels have poles up to $N=1$.
pub struct TalbotPath {
/// integration variable
@@ -27,16 +29,20 @@ pub struct TalbotPath {
}
impl TalbotPath {
- /// Auxilary angle.
+ /// Auxiliary angle.
fn theta(&self) -> f64 {
PI * (2.0 * self.t - 1.0)
}
/// Constructor from parameters.
pub fn new(t: f64, logx: f64, is_singlet: bool) -> Self {
+ // The prescription suggested by Abate for r is 0.4 * M / ( - logx)
+ // with M the number of accurate digits; Maria Ubiali suggested in her thesis M = 16.
+ // However, this seems to yield unstable results for the OME in the large x region
+ // so we add an additional regularization, which makes the path less "edgy" there.
Self {
t,
- r: 0.4 * 16.0 / (1.0 - logx),
+ r: 0.4 * 16.0 / (0.1 - logx),
o: if is_singlet { 1. } else { 0. },
}
}
diff --git a/crates/ekore/Cargo.toml b/crates/ekore/Cargo.toml
index ef8499dba..419bc126a 100644
--- a/crates/ekore/Cargo.toml
+++ b/crates/ekore/Cargo.toml
@@ -1,14 +1,23 @@
[package]
name = "ekore"
-version = "0.1.0"
-edition = "2021"
description = "EKO expressions"
-license = "GPL-3.0-or-later"
+
+authors.workspace = true
+readme.workspace = true
+categories.workspace = true
+edition.workspace = true
+keywords.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
+version.workspace = true
+
+[package.metadata.docs.rs]
+rustdoc-args = ["--html-in-header", "doc-header.html"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
num = "0.4.1"
float-cmp = "0.9.0"
-katexit = "0.1.4"
hashbrown = "0.14"
diff --git a/crates/ekore/doc-header.html b/crates/ekore/doc-header.html
new file mode 120000
index 000000000..22282661d
--- /dev/null
+++ b/crates/ekore/doc-header.html
@@ -0,0 +1 @@
+../doc-header.html
\ No newline at end of file
diff --git a/crates/ekore/refs.bib b/crates/ekore/refs.bib
index 3c63b69e7..e8ef02c2b 100644
--- a/crates/ekore/refs.bib
+++ b/crates/ekore/refs.bib
@@ -50,3 +50,22 @@ @article{Abate
journal = {International Journal for Numerical Methods in Engineering},
doi = {10.1002/nme.995}
}
+@phdthesis{MuselliPhD,
+ author = "Muselli, Claudio",
+ title = "{Resummations of Transverse Momentum Distributions}",
+ doi = "10.13130/muselli-claudio_phd2017-12-01",
+ school = "Università degli studi di Milano, Dipartimento di Fisica",
+ year = "2017"
+}
+@article{Vogt2004ns,
+ author = "Vogt, A.",
+ archivePrefix = "arXiv",
+ doi = "10.1016/j.cpc.2005.03.103",
+ eprint = "hep-ph/0408244",
+ journal = "Comput. Phys. Commun.",
+ pages = "65--92",
+ reportNumber = "NIKHEF-04-011",
+ title = "{Efficient evolution of unpolarized and polarized parton distributions with QCD-PEGASUS}",
+ volume = "170",
+ year = "2005"
+}
diff --git a/crates/ekore/src/anomalous_dimensions/unpolarized/spacelike.rs b/crates/ekore/src/anomalous_dimensions/unpolarized/spacelike.rs
index c2d0fb0d7..dec73bf04 100644
--- a/crates/ekore/src/anomalous_dimensions/unpolarized/spacelike.rs
+++ b/crates/ekore/src/anomalous_dimensions/unpolarized/spacelike.rs
@@ -1,14 +1,37 @@
//! The unpolarized, space-like anomalous dimensions at various couplings power.
+use crate::constants::{PID_NSM, PID_NSP, PID_NSV};
use crate::harmonics::cache::Cache;
use num::complex::Complex;
use num::Zero;
pub mod as1;
+pub mod as2;
+pub mod as3;
/// Compute the tower of the non-singlet anomalous dimensions.
-pub fn gamma_ns_qcd(order_qcd: usize, _mode: u16, c: &mut Cache, nf: u8) -> Vec> {
+pub fn gamma_ns_qcd(order_qcd: usize, mode: u16, c: &mut Cache, nf: u8) -> Vec> {
let mut gamma_ns = vec![Complex::::zero(); order_qcd];
gamma_ns[0] = as1::gamma_ns(c, nf);
+ // NLO and beyond
+ if order_qcd >= 2 {
+ let gamma_ns_1 = match mode {
+ PID_NSP => as2::gamma_nsp(c, nf),
+ // To fill the full valence vector in NNLO we need to add gamma_ns^1 explicitly here
+ PID_NSM | PID_NSV => as2::gamma_nsm(c, nf),
+ _ => panic!("Unkown non-singlet sector element"),
+ };
+ gamma_ns[1] = gamma_ns_1
+ }
+ // NNLO and beyond
+ if order_qcd >= 3 {
+ let gamma_ns_2 = match mode {
+ PID_NSP => as3::gamma_nsp(c, nf),
+ PID_NSM => as3::gamma_nsm(c, nf),
+ PID_NSV => as3::gamma_nsv(c, nf),
+ _ => panic!("Unkown non-singlet sector element"),
+ };
+ gamma_ns[2] = gamma_ns_2
+ }
gamma_ns
}
@@ -22,5 +45,13 @@ pub fn gamma_singlet_qcd(order_qcd: usize, c: &mut Cache, nf: u8) -> Vec<[[Compl
order_qcd
];
gamma_S[0] = as1::gamma_singlet(c, nf);
+ // NLO and beyond
+ if order_qcd >= 2 {
+ gamma_S[1] = as2::gamma_singlet(c, nf);
+ }
+ // NNLO and beyond
+ if order_qcd >= 3 {
+ gamma_S[2] = as3::gamma_singlet(c, nf);
+ }
gamma_S
}
diff --git a/crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as2.rs b/crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as2.rs
new file mode 100644
index 000000000..b2b16459c
--- /dev/null
+++ b/crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as2.rs
@@ -0,0 +1,338 @@
+//! NLO QCD
+
+use ::num::complex::Complex;
+use std::f64::consts::LN_2;
+
+use crate::constants::{CA, CF, TR, ZETA2, ZETA3};
+use crate::harmonics::cache::{Cache, K};
+
+/// Compute the valence-like non-singlet anomalous dimension.
+///
+/// Implements Eq. (3.6) of [\[Moch:2004pa\]][crate::bib::Moch2004pa].
+pub fn gamma_nsm(c: &mut Cache, nf: u8) -> Complex {
+ let N = c.n;
+ let S1 = c.get(K::S1);
+ let S2 = c.get(K::S2);
+ let Sp1m = c.get(K::S1mh);
+ let Sp2m = c.get(K::S2mh);
+ let Sp3m = c.get(K::S3mh);
+ let g3n = c.get(K::G3);
+ #[rustfmt::skip]
+ let gqq1m_cfca = 16.0 * g3n
+ - (144.0 + N * (1.0 + N) * (156.0 + N * (340.0 + N * (655.0 + 51.0 * N * (2.0 + N)))))
+ / (18.0 * N.powu(3) * (1. + N).powu(3))
+ + (-14.666666666666666 + 8.0 / N - 8.0 / (1.0 + N)) * S2
+ - (4.0 * Sp2m) / (N + N.powu(2))
+ + S1 * (29.77777777777778 + 16.0 / N.powu(2) - 16.0 * S2 + 8.0 * Sp2m)
+ + 2.0 * Sp3m
+ + 10.0 * ZETA3
+ + ZETA2 * (16.0 * S1 - 16.0 * Sp1m - (16.0 * (1. + N * LN_2)) / N);
+ #[rustfmt::skip]
+ let gqq1m_cfcf = -32. * g3n
+ + (24. - N * (-32. + 3. * N * (-8. + N * (3. + N) * (3. + N.powu(2)))))
+ / (2. * N.powu(3) * (1. + N).powu(3))
+ + (12. - 8. / N + 8. / (1. + N)) * S2
+ + S1 * (-24. / N.powu(2) - 8. / (1. + N).powu(2) + 16. * S2 - 16. * Sp2m)
+ + (8. * Sp2m) / (N + N.powu(2))
+ - 4. * Sp3m
+ - 20. * ZETA3
+ + ZETA2 * (-32. * S1 + 32. * Sp1m + 32. * (1. / N + LN_2));
+ #[rustfmt::skip]
+ let gqq1m_cfnf = (-12. + N * (20. + N * (47. + 3. * N * (2. + N))))
+ / (9. * N.powu(2) * (1. + N).powu(2))
+ - (40. * S1) / 9.
+ + (8. * S2) / 3.;
+
+ CF * (CA * gqq1m_cfca + CF * gqq1m_cfcf + 2.0 * TR * (nf as f64) * gqq1m_cfnf)
+}
+
+/// Compute the singlet-like non-singlet anomalous dimension.
+///
+/// Implements Eq. (3.5) of [\[Moch:2004pa\]][crate::bib::Moch2004pa].
+pub fn gamma_nsp(c: &mut Cache, nf: u8) -> Complex {
+ let N = c.n;
+ let S1 = c.get(K::S1);
+ let S2 = c.get(K::S2);
+ let Sp1p = c.get(K::S1h);
+ let Sp2p = c.get(K::S2h);
+ let Sp3p = c.get(K::S3h);
+ let g3n = c.get(K::G3);
+ #[rustfmt::skip]
+ let gqq1p_cfca = -16. * g3n
+ + (132. - N * (340. + N * (655. + 51. * N * (2. + N))))
+ / (18. * N.powu(2) * (1. + N).powu(2))
+ + (-14.666666666666666 + 8. / N - 8. / (1. + N)) * S2
+ - (4. * Sp2p) / (N + N.powu(2))
+ + S1 * (29.77777777777778 - 16. / N.powu(2) - 16. * S2 + 8. * Sp2p)
+ + 2. * Sp3p
+ + 10. * ZETA3
+ + ZETA2 * (16. * S1 - 16. * Sp1p + 16. * (1. / N - LN_2));
+ #[rustfmt::skip]
+ let gqq1p_cfcf = 32. * g3n
+ - (8. + N * (32. + N * (40. + 3. * N * (3. + N) * (3. + N.powu(2)))))
+ / (2. * N.powu(3) * (1. + N).powu(3))
+ + (12. - 8. / N + 8. / (1. + N)) * S2
+ + S1 * (40. / N.powu(2) - 8. / (1. + N).powu(2) + 16. * S2 - 16. * Sp2p)
+ + (8. * Sp2p) / (N + N.powu(2))
+ - 4. * Sp3p
+ - 20. * ZETA3
+ + ZETA2 * (-32. * S1 + 32. * Sp1p + 32. * (-(1. / N) + LN_2));
+ #[rustfmt::skip]
+ let gqq1p_cfnf = (-12. + N * (20. + N * (47. + 3. * N * (2. + N))))
+ / (9. * N.powu(2) * (1. + N).powu(2))
+ - (40. * S1) / 9.
+ + (8. * S2) / 3.;
+
+ CF * (CA * gqq1p_cfca + CF * gqq1p_cfcf + 2.0 * TR * (nf as f64) * gqq1p_cfnf)
+}
+
+/// Compute the pure-singlet quark-quark anomalous dimension.
+///
+/// Implements Eq. (3.6) of [\[Vogt:2004mw\]][crate::bib::Vogt2004mw].
+pub fn gamma_ps(c: &mut Cache, nf: u8) -> Complex {
+ let N = c.n;
+ let gqqps1_nfcf = (-4. * (2. + N * (5. + N)) * (4. + N * (4. + N * (7. + 5. * N))))
+ / ((-1. + N) * N.powu(3) * (1. + N).powu(3) * (2. + N).powu(2));
+ 2.0 * TR * (nf as f64) * CF * gqqps1_nfcf
+}
+
+/// Compute the quark-gluon singlet anomalous dimension.
+///
+/// Implements Eq. (3.7) of [\[Vogt:2004mw\]][crate::bib::Vogt2004mw].
+pub fn gamma_qg(c: &mut Cache, nf: u8) -> Complex {
+ let N = c.n;
+ let S1 = c.get(K::S1);
+ let S2 = c.get(K::S2);
+ let Sp2p = c.get(K::S2h);
+ #[rustfmt::skip]
+ let gqg1_nfca = (-4.
+ * (16.
+ + N * (64.
+ + N * (104.
+ + N * (128. + N * (85. + N * (36. + N * (25. + N * (15. + N * (6. + N))))))))))
+ / ((-1. + N) * N.powu(3) * (1. + N).powu(3) * (2. + N).powu(3))
+ - (16. * (3. + 2. * N) * S1) / (2. + 3. * N + N.powu(2)).powu(2)
+ + (4. * (2. + N + N.powu(2)) * S1.powu(2)) / (N * (2. + 3. * N + N.powu(2)))
+ - (4. * (2. + N + N.powu(2)) * S2) / (N * (2. + 3. * N + N.powu(2)))
+ + (4. * (2. + N + N.powu(2)) * Sp2p) / (N * (2. + 3. * N + N.powu(2)));
+ #[rustfmt::skip]
+ let gqg1_nfcf = (-2. * (4. + N * (8. + N * (1. + N) * (25. + N * (26. + 5. * N * (2. + N))))))
+ / (N.powu(3) * (1. + N).powu(3) * (2. + N))
+ + (8. * S1) / N.powu(2)
+ - (4. * (2. + N + N.powu(2)) * S1.powu(2)) / (N * (2. + 3. * N + N.powu(2)))
+ + (4. * (2. + N + N.powu(2)) * S2) / (N * (2. + 3. * N + N.powu(2)));
+ 2.0 * TR * (nf as f64) * (CA * gqg1_nfca + CF * gqg1_nfcf)
+}
+
+/// Compute the gluon-quark singlet anomalous dimension.
+///
+/// Implements Eq. (3.8) of [\[Vogt:2004mw\]][crate::bib::Vogt2004mw].
+pub fn gamma_gq(c: &mut Cache, nf: u8) -> Complex {
+ let N = c.n;
+ let S1 = c.get(K::S1);
+ let S2 = c.get(K::S2);
+ let Sp2p = c.get(K::S2h);
+ #[rustfmt::skip]
+ let ggq1_cfcf = (-8.
+ + 2. * N * (-12. + N * (-1. + N * (28. + N * (43. + 6. * N * (5. + 2. * N))))))
+ / ((-1. + N) * N.powu(3) * (1. + N).powu(3))
+ - (4. * (10. + N * (17. + N * (8. + 5. * N))) * S1) / ((-1. + N) * N * (1. + N).powu(2))
+ + (4. * (2. + N + N.powu(2)) * S1.powu(2)) / (N * (-1. + N.powu(2)))
+ + (4. * (2. + N + N.powu(2)) * S2) / (N * (-1. + N.powu(2)));
+ #[rustfmt::skip]
+ let ggq1_cfca = (-4.
+ * (144.
+ + N * (432.
+ + N * (-152.
+ + N * (-1304.
+ + N * (-1031.
+ + N * (695. + N * (1678. + N * (1400. + N * (621. + 109. * N))))))))))
+ / (9. * N.powu(3) * (1. + N).powu(3) * (-2. + N + N.powu(2)).powu(2))
+ + (4. * (-12. + N * (-22. + 41. * N + 17. * N.powu(3))) * S1)
+ / (3. * (-1. + N).powu(2) * N.powu(2) * (1. + N))
+ + ((8. + 4. * N + 4. * N.powu(2)) * S1.powu(2)) / (N - N.powu(3))
+ + ((8. + 4. * N + 4. * N.powu(2)) * S2) / (N - N.powu(3))
+ + (4. * (2. + N + N.powu(2)) * Sp2p) / (N * (-1. + N.powu(2)));
+ #[rustfmt::skip]
+ let ggq1_cfnf = (8. * (16. + N * (27. + N * (13. + 8. * N))))
+ / (9. * (-1. + N) * N * (1. + N).powu(2))
+ - (8. * (2. + N + N.powu(2)) * S1) / (3. * N * (-1. + N.powu(2)));
+ CF * (CA * ggq1_cfca + CF * ggq1_cfcf + 2.0 * TR * (nf as f64) * ggq1_cfnf)
+}
+
+/// Compute the gluon-gluon singlet anomalous dimension.
+///
+/// Implements Eq. (3.9) of [\[Vogt:2004mw\]][crate::bib::Vogt2004mw].
+pub fn gamma_gg(c: &mut Cache, nf: u8) -> Complex {
+ let N = c.n;
+ let S1 = c.get(K::S1);
+ let Sp1p = c.get(K::S1h);
+ let Sp2p = c.get(K::S2h);
+ let Sp3p = c.get(K::S3h);
+ let g3n = c.get(K::G3);
+ #[rustfmt::skip]
+ let ggg1_caca = 16. * g3n
+ - (2.
+ * (576.
+ + N * (1488.
+ + N * (560.
+ + N * (-1248.
+ + N * (-1384.
+ + N * (1663.
+ + N * (4514.
+ + N * (4744.
+ + N * (3030.
+ + N * (1225. + 48. * N * (7. + N))))))))))))
+ / (9. * (-1. + N).powu(2) * N.powu(3) * (1. + N).powu(3) * (2. + N).powu(3))
+ + S1 * (29.77777777777778 + 16. / (-1. + N).powu(2) + 16. / (1. + N).powu(2)
+ - 16. / (2. + N).powu(2)
+ - 8. * Sp2p)
+ + (16. * (1. + N + N.powu(2)) * Sp2p) / (N * (1. + N) * (-2. + N + N.powu(2)))
+ - 2. * Sp3p
+ - 10. * ZETA3
+ + ZETA2 * (-16. * S1 + 16. * Sp1p + 16. * (-(1. / N) + LN_2));
+ #[rustfmt::skip]
+ let ggg1_canf = (8. * (6. + N * (1. + N) * (28. + N * (1. + N) * (13. + 3. * N * (1. + N)))))
+ / (9. * N.powu(2) * (1. + N).powu(2) * (-2. + N + N.powu(2)))
+ - (40. * S1) / 9.;
+ #[rustfmt::skip]
+ let ggg1_cfnf = (2.
+ * (-8.
+ + N * (-8.
+ + N * (-10. + N * (-22. + N * (-3. + N * (6. + N * (8. + N * (4. + N)))))))))
+ / (N.powu(3) * (1. + N).powu(3) * (-2. + N + N.powu(2)));
+
+ CA * CA * ggg1_caca + 2.0 * TR * (nf as f64) * (CA * ggg1_canf + CF * ggg1_cfnf)
+}
+
+/// Compute the singlet anomalous dimension matrix.
+pub fn gamma_singlet(c: &mut Cache, nf: u8) -> [[Complex; 2]; 2] {
+ let gamma_qq = gamma_nsp(c, nf) + gamma_ps(c, nf);
+ [
+ [gamma_qq, gamma_qg(c, nf)],
+ [gamma_gq(c, nf), gamma_gg(c, nf)],
+ ]
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::cmplx;
+ use crate::{anomalous_dimensions::unpolarized::spacelike::as2::*, harmonics::cache::Cache};
+ use float_cmp::assert_approx_eq;
+ use num::complex::Complex;
+ use num::traits::Pow;
+ use std::f64::consts::PI;
+
+ const NF: u8 = 5;
+
+ #[test]
+ fn physical_constraints() {
+ // number conservation
+ let mut c = Cache::new(cmplx![1., 0.]);
+ assert_approx_eq!(f64, gamma_nsm(&mut c, NF).re, 0.0, epsilon = 2e-6);
+
+ // momentum conservation
+ let mut c = Cache::new(cmplx![2., 0.]);
+ let gS1 = gamma_singlet(&mut c, NF);
+
+ // gluon momentum conservation
+ assert_approx_eq!(f64, (gS1[0][1] + gS1[1][1]).re, 0.0, epsilon = 4e-5);
+ // quark momentum conservation
+ assert_approx_eq!(f64, (gS1[0][0] + gS1[1][0]).re, 0.0, epsilon = 2e-6);
+ }
+
+ #[test]
+ fn N2() {
+ // reference values are obtained from MMa
+ let mut c = Cache::new(cmplx![2., 0.]);
+
+ // ns+
+ assert_approx_eq!(
+ f64,
+ gamma_nsp(&mut c, NF).re,
+ (-112.0 * CF + 376.0 * CA - 64.0 * (NF as f64)) * CF / 27.0,
+ epsilon = 2e-6
+ );
+
+ // ns-
+ let check = ((34.0 / 27.0 * (-47.0 + 6. * PI.pow(2)) - 16.0 * ZETA3) * CF
+ + (373.0 / 9.0 - 34.0 * PI.pow(2) / 9.0 + 8.0 * ZETA3) * CA
+ - 64.0 * (NF as f64) / 27.0)
+ * CF;
+ assert_approx_eq!(f64, gamma_nsm(&mut c, NF).re, check, epsilon = 2e-6);
+
+ // singlet sector
+ let gS1 = gamma_singlet(&mut c, NF);
+ // ps
+ assert_approx_eq!(
+ f64,
+ gamma_ps(&mut c, NF).re,
+ -40.0 * CF * (NF as f64) / 27.0
+ );
+ // qg
+ assert_approx_eq!(
+ f64,
+ gS1[0][1].re,
+ (-74.0 * CF - 35.0 * CA) * (NF as f64) / 27.0
+ );
+ // gq
+ assert_approx_eq!(
+ f64,
+ gS1[1][0].re,
+ (112.0 * CF - 376.0 * CA + 104.0 * (NF as f64)) * CF / 27.0,
+ epsilon = 1e-13
+ );
+ }
+
+ #[test]
+ fn N3() {
+ let mut c = Cache::new(cmplx![3., 0.]);
+ // ns+
+ let check = ((-34487.0 / 432.0 + 86.0 * PI.pow(2) / 9.0 - 16.0 * ZETA3) * CF
+ + (459.0 / 8.0 - 43.0 * PI.pow(2) / 9.0 + 8.0 * ZETA3) * CA
+ - 415.0 * (NF as f64) / 108.0)
+ * CF;
+ assert_approx_eq!(f64, gamma_nsp(&mut c, NF).re, check, epsilon = 2e-6);
+
+ // singlet sector
+ let gS1 = gamma_singlet(&mut c, NF);
+ // ps
+ assert_approx_eq!(
+ f64,
+ gamma_ps(&mut c, NF).re,
+ -1391.0 * CF * (NF as f64) / 5400.0
+ );
+ // gq
+ assert_approx_eq!(
+ f64,
+ gS1[1][0].re,
+ (973.0 / 432.0 * CF
+ + (2801.0 / 5400.0 - 7.0 * PI.pow(2) / 9.0) * CA
+ + 61.0 / 54.0 * (NF as f64))
+ * CF
+ );
+ // gg
+ assert_approx_eq!(
+ f64,
+ gS1[1][1].re,
+ (-79909.0 / 3375.0 + 194.0 * PI.pow(2) / 45.0 - 8.0 * ZETA3) * CA.pow(2)
+ - 967.0 / 270.0 * CA * (NF as f64)
+ + 541.0 / 216.0 * CF * (NF as f64),
+ epsilon = 3e-5
+ );
+ }
+
+ #[test]
+ fn N4() {
+ let mut c = Cache::new(cmplx![4., 0.]);
+ // singlet sector
+ let gS1 = gamma_singlet(&mut c, NF);
+ // qg
+ assert_approx_eq!(
+ f64,
+ gS1[0][1].re,
+ (-56317.0 / 18000.0 * CF + 16387.0 / 9000.0 * CA) * (NF as f64),
+ epsilon = 1e-14
+ )
+ }
+}
diff --git a/crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as3.rs b/crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as3.rs
new file mode 100644
index 000000000..14354f736
--- /dev/null
+++ b/crates/ekore/src/anomalous_dimensions/unpolarized/spacelike/as3.rs
@@ -0,0 +1,455 @@
+//! NNLO QCD
+
+use ::num::complex::Complex;
+use num::traits::Pow;
+
+use crate::cmplx;
+use crate::constants::{ZETA2, ZETA3};
+use crate::harmonics::cache::{Cache, K};
+
+/// Compute the valence-like non-singlet anomalous dimension.
+///
+/// Implements Eq. (3.8) of [\[Moch:2004pa\]][crate::bib::Moch2004pa].
+pub fn gamma_nsm(c: &mut Cache, nf: u8) -> Complex {
+ let N = c.n;
+ let S1 = c.get(K::S1);
+ let S2 = c.get(K::S2);
+ let S3 = c.get(K::S3);
+ let E1 = S1 / N.powu(2) + (S2 - ZETA2) / N;
+ let E2 = 2.0 * (-S1 / N.powu(3) + (ZETA2 - S2) / N.powu(2) - (S3 - ZETA3) / N);
+
+ #[rustfmt::skip]
+ let pm2 =
+ -1174.898 * (S1 - 1.0 / N)
+ + 1295.470
+ - 714.1 * S1 / N
+ - 433.2 / (N + 3.0)
+ + 297.0 / (N + 2.0)
+ - 3505.0 / (N + 1.0)
+ + 1860.2 / N
+ - 1465.2 / N.powu(2)
+ + 399.2 * 2.0 / N.powu(3)
+ - 320.0 / 9.0 * 6.0 / N.powu(4)
+ + 116.0 / 81.0 * 24.0 / N.powu(5)
+ + 684.0 * E1
+ + 251.2 * E2;
+
+ #[rustfmt::skip]
+ let pm2_nf =
+ 183.187 * (S1 - 1.0 / N)
+ - 173.933
+ + 5120./ 81.0 * S1 / N
+ + 34.76 / (N + 3.0)
+ + 77.89 / (N + 2.0)
+ + 406.5 / (N + 1.0)
+ - 216.62 / N
+ + 172.69 / N.powu(2)
+ - 3216.0 / 81.0 * 2.0 / N.powu(3)
+ + 256.0 / 81.0 * 6.0 / N.powu(4)
+ - 65.43 * E1
+ + 1.136 * 6.0 / (N + 1.0).powu(4);
+
+ #[rustfmt::skip]
+ let pf2_nfnf =
+ -(
+ 17.0 / 72.0
+ - 2.0 / 27.0 * S1
+ - 10.0 / 27.0 * S2
+ + 2.0 / 9.0 * S3
+ - (12.0 * N.powu(4) + 2.0 * N.powu(3) - 12.0 * N.powu(2) - 2.0 * N + 3.0)
+ / (27.0 * N.powu(3) * (N + 1.0).powu(3))
+ )* 32.0 / 3.0;
+
+ let result = pm2 + (nf as f64) * pm2_nf + (nf as f64).pow(2) * pf2_nfnf;
+ -1. * result
+}
+
+/// Compute the singlet-like non-singlet anomalous dimension.
+///
+/// Implements Eq. (3.7) of [\[Moch:2004pa\]][crate::bib::Moch2004pa].
+pub fn gamma_nsp(c: &mut Cache, nf: u8) -> Complex {
+ let N = c.n;
+ let S1 = c.get(K::S1);
+ let S2 = c.get(K::S2);
+ let S3 = c.get(K::S3);
+ let E1 = S1 / N.powu(2) + (S2 - ZETA2) / N;
+ let E2 = 2.0 * (-S1 / N.powu(3) + (ZETA2 - S2) / N.powu(2) - (S3 - ZETA3) / N);
+
+ #[rustfmt::skip]
+ let pp2 =
+ -1174.898 * (S1 - 1.0 / N)
+ + 1295.384
+ - 714.1 * S1 / N
+ - 522.1 / (N + 3.0)
+ + 243.6 / (N + 2.0)
+ - 3135.0 / (N + 1.0)
+ + 1641.1 / N
+ - 1258.0 / N.powu(2)
+ + 294.9 * 2.0 / N.powu(3)
+ - 800. / 27.0 * 6.0 / N.powu(4)
+ + 128. / 81.0 * 24.0 / N.powu(5)
+ + 563.9 * E1
+ + 256.8 * E2;
+
+ #[rustfmt::skip]
+ let pp2_nf =
+ 183.187 * (S1 - 1.0 / N)
+ - 173.924
+ + 5120. / 81.0 * S1 / N
+ + 44.79 / (N + 3.0)
+ + 72.94 / (N + 2.0)
+ + 381.1 / (N + 1.0)
+ - 197.0 / N
+ + 152.6 / N.powu(2)
+ - 2608.0 / 81.0 * 2.0 / N.powu(3)
+ + 192.0 / 81.0 * 6.0 / N.powu(4)
+ - 56.66 * E1
+ + 1.497 * 6.0 / (N + 1.0).powu(4);
+
+ #[rustfmt::skip]
+ let pf2_nfnf =
+ -(
+ 17.0 / 72.0
+ - 2.0 / 27.0 * S1
+ - 10.0 / 27.0 * S2
+ + 2.0 / 9.0 * S3
+ - (12.0 * N.powu(4) + 2.0 * N.powu(3) - 12.0 * N.powu(2) - 2.0 * N + 3.0)
+ / (27.0 * N.powu(3) * (N + 1.0).powu(3))
+ )* 32.0/ 3.0;
+
+ let result = pp2 + (nf as f64) * pp2_nf + (nf as f64).pow(2) * pf2_nfnf;
+ -1. * result
+}
+
+/// Compute the valence non-singlet anomalous dimension.
+///
+/// Implements Eq. (3.9) of [\[Moch:2004pa\]][crate::bib::Moch2004pa].
+pub fn gamma_nsv(c: &mut Cache, nf: u8) -> Complex {
+ let N = c.n;
+ let S1 = c.get(K::S1);
+ let S2 = c.get(K::S2);
+ let S3 = c.get(K::S3);
+ let E1 = S1 / N.powu(2) + (S2 - ZETA2) / N;
+ let E2 = 2.0 * (-S1 / N.powu(3) + (ZETA2 - S2) / N.powu(2) - (S3 - ZETA3) / N);
+ let B11 = -(S1 + 1.0 / (N + 1.0)) / (N + 1.0);
+ let B12 = -(S1 + 1.0 / (N + 1.0) + 1.0 / (N + 2.0)) / (N + 2.0);
+
+ let B1M = if N.im.abs() < 1.0e-5 && (N - 1.0).re.abs() < 1.0e-5 {
+ cmplx![-ZETA2, 0.]
+ } else {
+ -(S1 - 1.0 / N) / (N - 1.0)
+ };
+
+ #[rustfmt::skip]
+ let ps2 = -(
+ -163.9 * (B1M + S1 / N)
+ - 7.208 * (B11 - B12)
+ + 4.82 * (1.0 / (N + 3.0) - 1.0 / (N + 4.0))
+ - 43.12 * (1.0 / (N + 2.0) - 1.0 / (N + 3.0))
+ + 44.51 * (1.0 / (N + 1.0) - 1.0 / (N + 2.0))
+ + 151.49 * (1.0 / N - 1.0 / (N + 1.0))
+ - 178.04 / N.powu(2)
+ + 6.892 * 2.0 / N.powu(3)
+ - 40.0 / 27.0 * (-2.0 * 6.0 / N.powu(4) - 24.0 / N.powu(5))
+ - 173.1 * E1
+ + 46.18 * E2
+ );
+
+ gamma_nsm(c, nf) + (nf as f64) * ps2
+}
+
+/// Compute the pure-singlet quark-quark anomalous dimension.
+///
+/// Implements Eq. (3.10) of [\[Vogt:2004mw\]][crate::bib::Vogt2004mw].
+pub fn gamma_ps(c: &mut Cache, nf: u8) -> Complex {
+ let N = c.n;
+ let S1 = c.get(K::S1);
+ let S2 = c.get(K::S2);
+ let S3 = c.get(K::S3);
+
+ let E1 = S1 / N.powu(2) + (S2 - ZETA2) / N;
+ let E11 = (S1 + 1.0 / (N + 1.0)) / (N + 1.0).powu(2)
+ + (S2 + 1.0 / (N + 1.0).powu(2) - ZETA2) / (N + 1.0);
+ let B21 = ((S1 + 1.0 / (N + 1.0)).powu(2) + S2 + 1.0 / (N + 1.0).powu(2)) / (N + 1.0);
+ let B3 = -(S1.powu(3) + 3.0 * S1 * S2 + 2.0 * S3) / N;
+
+ #[rustfmt::skip]
+ let B31 = -(
+ (S1 + 1.0 / (N + 1.0)).powu(3)
+ + 3.0 * (S1 + 1.0 / (N + 1.0)) * (S2 + 1.0 / (N + 1.0).powu(2))
+ + 2.0 * (S3 + 1.0 / (N + 1.0).powu(3))
+ ) / (N + 1.0);
+
+ #[rustfmt::skip]
+ let ps1 =
+ -3584.0 / 27.0 * (-1.0 / (N - 1.0).powu(2) + 1.0 / N.powu(2))
+ - 506.0 * (1.0 / (N - 1.0) - 1.0 / N)
+ + 160.0 / 27.0 * (24.0 / N.powu(5) - 24.0 / (N + 1.0).powu(5))
+ - 400.0 / 9.0 * (-6.0 / N.powu(4) + 6.0 / (N + 1.0).powu(4))
+ + 131.4 * (2.0 / N.powu(3) - 2.0 / (N + 1.0).powu(3))
+ - 661.6 * (-1.0 / N.powu(2) + 1.0 / (N + 1.0).powu(2))
+ - 5.926 * (B3 - B31)
+ - 9.751 * ((S1.powu(2) + S2) / N - B21)
+ - 72.11 * (-S1 / N + (S1 + 1.0 / (N + 1.0)) / (N + 1.0))
+ + 177.4 * (1.0 / N - 1.0 / (N + 1.0))
+ + 392.9 * (1.0 / (N + 1.0) - 1.0 / (N + 2.0))
+ - 101.4 * (1.0 / (N + 2.0) - 1.0 / (N + 3.0))
+ - 57.04 * (E1 - E11);
+
+ #[rustfmt::skip]
+ let ps2 =
+ 256.0 / 81.0 * (1.0 / (N - 1.0) - 1.0 / N)
+ + 32.0 / 27.0 * (-6.0 / N.powu(4) + 6.0 / (N + 1.0).powu(4))
+ + 17.89 * (2.0 / N.powu(3) - 2.0 / (N + 1.0).powu(3))
+ + 61.75 * (-1.0 / N.powu(2) + 1.0 / (N + 1.0).powu(2))
+ + 1.778 * ((S1.powu(2) + S2) / N - B21)
+ + 5.944 * (-S1 / N + (S1 + 1.0 / (N + 1.0)) / (N + 1.0))
+ + 100.1 * (1.0 / N - 1.0 / (N + 1.0))
+ - 125.2 * (1.0 / (N + 1.0) - 1.0 / (N + 2.0))
+ + 49.26 * (1.0 / (N + 2.0) - 1.0 / (N + 3.0))
+ - 12.59 * (1.0 / (N + 3.0) - 1.0 / (N + 4.0))
+ - 1.889 * (E1 - E11);
+
+ let result = (nf as f64) * ps1 + (nf as f64).pow(2) * ps2;
+ -1.0 * result
+}
+
+/// Compute the quark-gluon singlet anomalous dimension.
+///
+/// Implements Eq. (3.11) of [\[Vogt:2004mw\]][crate::bib::Vogt2004mw].
+pub fn gamma_qg(c: &mut Cache, nf: u8) -> Complex {
+ let N = c.n;
+ let S1 = c.get(K::S1);
+ let S2 = c.get(K::S2);
+ let S3 = c.get(K::S3);
+ let S4 = c.get(K::S4);
+
+ let E1 = S1 / N.powu(2) + (S2 - ZETA2) / N;
+ let E2 = 2.0 * (-S1 / N.powu(3) + (ZETA2 - S2) / N.powu(2) - (S3 - ZETA3) / N);
+ let B3 = -(S1.powu(3) + 3.0 * S1 * S2 + 2.0 * S3) / N;
+ let B4 = (S1.powu(4) + 6.0 * S1.powu(2) * S2 + 8.0 * S1 * S3 + 3.0 * S2.powu(2) + 6.0 * S4) / N;
+
+ #[rustfmt::skip]
+ let qg1 =
+ 896.0 / 3.0 / (N - 1.0).powu(2)
+ - 1268.3 / (N - 1.0)
+ + 536.0 / 27.0 * 24.0 / N.powu(5)
+ + 44.0 / 3.0 * 6.0 / N.powu(4)
+ + 881.5 * 2.0 / N.powu(3)
+ - 424.9 / N.powu(2)
+ + 100.0 / 27.0 * B4
+ - 70.0 / 9.0 * B3
+ - 120.5 * (S1.powu(2) + S2) / N
+ - 104.42 * S1 / N
+ + 2522.0 / N
+ - 3316.0 / (N + 1.0)
+ + 2126.0 / (N + 2.0)
+ + 1823.0 * E1
+ - 25.22 * E2
+ + 252.5 * 6.0 / (N + 1.0).powu(4);
+
+ #[rustfmt::skip]
+ let qg2 =
+ 1112.0 / 243.0 / (N - 1.0)
+ - 16.0 / 9.0 * 24.0 / N.powu(5)
+ + 376.0 / 27.0 * 6.0 / N.powu(4)
+ - 90.8 * 2.0 / N.powu(3)
+ + 254.0 / N.powu(2)
+ + 20.0 / 27.0 * B3
+ + 200.0 / 27.0 * (S1.powu(2) + S2) / N
+ + 5.496 * S1 / N
+ - 252.0 / N
+ + 158.0 / (N + 1.0)
+ + 145.4 / (N + 2.0)
+ - 139.28 / (N + 3.0)
+ - 53.09 * E1
+ - 80.616 * E2
+ - 98.07 * 2.0 / (N + 1.0).powu(3)
+ - 11.70 * 6.0 / (N + 1.0).powu(4);
+
+ let result = (nf as f64) * qg1 + (nf as f64).pow(2) * qg2;
+ -1.0 * result
+}
+
+/// Compute the gluon-quark singlet anomalous dimension.
+///
+/// Implements Eq. (3.12) of [\[Vogt:2004mw\]][crate::bib::Vogt2004mw].
+pub fn gamma_gq(c: &mut Cache, nf: u8) -> Complex {
+ let N = c.n;
+ let S1 = c.get(K::S1);
+ let S2 = c.get(K::S2);
+ let S3 = c.get(K::S3);
+ let S4 = c.get(K::S4);
+
+ let E1 = S1 / N.powu(2) + (S2 - ZETA2) / N;
+ let E2 = 2.0 * (-S1 / N.powu(3) + (ZETA2 - S2) / N.powu(2) - (S3 - ZETA3) / N);
+ let B21 = ((S1 + 1.0 / (N + 1.0)).powu(2) + S2 + 1.0 / (N + 1.0).powu(2)) / (N + 1.0);
+ let B3 = -(S1.powu(3) + 3.0 * S1 * S2 + 2.0 * S3) / N;
+ let B4 = (S1.powu(4) + 6.0 * S1.powu(2) * S2 + 8.0 * S1 * S3 + 3.0 * S2.powu(2) + 6.0 * S4) / N;
+
+ #[rustfmt::skip]
+ let gq0 =
+ -1189.3 * 1.0 / (N - 1.0).powu(2)
+ + 6163.1 / (N - 1.0)
+ - 4288.0 / 81.0 * 24.0 / N.powu(5)
+ - 1568.0 / 9.0 * 6.0 / N.powu(4)
+ - 1794.0 * 2.0 / N.powu(3)
+ - 4033.0 * 1.0 / N.powu(2)
+ + 400.0 / 81.0 * B4
+ + 2200.0 / 27.0 * B3
+ + 606.3 * (S1.powu(2) + S2) / N
+ - 2193.0 * S1 / N
+ - 4307.0 / N
+ + 489.3 / (N + 1.0)
+ + 1452.0 / (N + 2.0)
+ + 146.0 / (N + 3.0)
+ - 447.3 * E2
+ - 972.9 * 2.0 / (N + 1.0).powu(3);
+
+ #[rustfmt::skip]
+ let gq1 =
+ -71.082 / (N - 1.0).powu(2)
+ - 46.41 / (N - 1.0)
+ + 128.0 / 27.0 * 24.0 / N.powu(5)
+ - 704. / 81.0 * 6.0 / N.powu(4)
+ + 20.39 * 2.0 / N.powu(3)
+ - 174.8 * 1.0 / N.powu(2)
+ - 400.0 / 81.0 * B3
+ - 68.069 * (S1.powu(2) + S2) / N
+ + 296.7 * S1 / N
+ - 183.8 / N
+ + 33.35 / (N + 1.0)
+ - 277.9 / (N + 2.0)
+ + 108.6 * 2.0 / (N + 1.0).powu(3)
+ - 49.68 * E1;
+
+ #[rustfmt::skip]
+ let gq2 = (
+ 64.0 * (-1.0 / (N - 1.0) + 1.0 / N + 2.0 / (N + 1.0))
+ + 320.0
+ * (
+ -(S1 - 1.0 / N) / (N - 1.0)
+ + S1 / N
+ - 0.8 * (S1 + 1.0 / (N + 1.0)) / (N + 1.0)
+ )
+ + 96.0
+ * (
+ ((S1 - 1.0 / N).powu(2) + S2 - 1.0 / N.powu(2)) / (N - 1.0)
+ - (S1.powu(2) + S2) / N
+ + 0.5 * B21
+ )
+ ) / 27.0;
+
+ let result = gq0 + (nf as f64) * gq1 + (nf as f64).pow(2) * gq2;
+ -1.0 * result
+}
+
+/// Compute the gluon-quark singlet anomalous dimension.
+///
+/// Implements Eq. (3.13) of [\[Vogt:2004mw\]][crate::bib::Vogt2004mw].
+pub fn gamma_gg(c: &mut Cache, nf: u8) -> Complex {
+ let N = c.n;
+ let S1 = c.get(K::S1);
+ let S2 = c.get(K::S2);
+ let S3 = c.get(K::S3);
+
+ let E1 = S1 / N.powu(2) + (S2 - ZETA2) / N;
+ let E11 = (S1 + 1.0 / (N + 1.0)) / (N + 1.0).powu(2)
+ + (S2 + 1.0 / (N + 1.0).powu(2) - ZETA2) / (N + 1.0);
+ let E2 = 2.0 * (-S1 / N.powu(3) + (ZETA2 - S2) / N.powu(2) - (S3 - ZETA3) / N);
+
+ #[rustfmt::skip]
+ let gg0 =
+ -2675.8 / (N - 1.0).powu(2)
+ + 14214.0 / (N - 1.0)
+ - 144.0 * 24.0 / N.powu(5)
+ - 72.0 * 6.0 / N.powu(4)
+ - 7471.0 * 2.0 / N.powu(3)
+ - 274.4 / N.powu(2)
+ - 20852.0 / N
+ + 3968.0 / (N + 1.0)
+ - 3363.0 / (N + 2.0)
+ + 4848.0 / (N + 3.0)
+ + 7305.0 * E1
+ + 8757.0 * E2
+ - 3589.0 * S1 / N
+ + 4425.894
+ - 2643.521 * (S1 - 1.0 / N);
+
+ #[rustfmt::skip]
+ let gg1 =
+ -157.27 / (N - 1.0).powu(2)
+ + 182.96 / (N - 1.0)
+ + 512.0 / 27.0 * 24.0 / N.powu(5)
+ - 832.0 / 9.0 * 6.0 / N.powu(4)
+ + 491.3 * 2.0 / N.powu(3)
+ - 1541.0 / N.powu(2)
+ - 350.2 / N
+ + 755.7 / (N + 1.0)
+ - 713.8 / (N + 2.0)
+ + 559.3 / (N + 3.0)
+ + 26.15 * E1
+ - 808.7 * E2
+ + 320.0 * S1 / N
+ - 528.723
+ + 412.172 * (S1 - 1.0 / N);
+
+ #[rustfmt::skip]
+ let gg2 =
+ -680.0 / 243.0 / (N - 1.0)
+ + 32.0 / 27.0 * 6.0 / N.powu(4)
+ + 9.680 * 2.0 / N.powu(3)
+ + 3.422 / N.powu(2)
+ - 13.878 / N
+ + 153.4 / (N + 1.0)
+ - 187.7 / (N + 2.0)
+ + 52.75 / (N + 3.0)
+ - 115.6 * E1
+ + 85.25 * E11
+ - 63.23 * E2
+ + 6.4630
+ + 16.0 / 9.0 * (S1 - 1.0 / N);
+
+ let result = gg0 + (nf as f64) * gg1 + (nf as f64).pow(2) * gg2;
+ -1.0 * result
+}
+
+/// Compute the singlet anomalous dimension matrix.
+pub fn gamma_singlet(c: &mut Cache, nf: u8) -> [[Complex; 2]; 2] {
+ let gamma_qq = gamma_nsp(c, nf) + gamma_ps(c, nf);
+ [
+ [gamma_qq, gamma_qg(c, nf)],
+ [gamma_gq(c, nf), gamma_gg(c, nf)],
+ ]
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::cmplx;
+ use crate::{anomalous_dimensions::unpolarized::spacelike::as3::*, harmonics::cache::Cache};
+ use float_cmp::assert_approx_eq;
+ use num::complex::Complex;
+
+ const NF: u8 = 5;
+
+ #[test]
+ fn physical_constraints() {
+ // number conservation
+ let mut c = Cache::new(cmplx![1., 0.]);
+ assert_approx_eq!(f64, gamma_nsv(&mut c, NF).re, -0.000960586, epsilon = 3e-7);
+ assert_approx_eq!(f64, gamma_nsm(&mut c, NF).re, 0.000594225, epsilon = 6e-7);
+
+ let mut c = Cache::new(cmplx![2., 0.]);
+ let gS2 = gamma_singlet(&mut c, NF);
+ // gluon momentum conservation
+ assert_approx_eq!(f64, (gS2[0][1] + gS2[1][1]).re, -0.00388726, epsilon = 2e-6);
+ // quark momentum conservation
+ assert_approx_eq!(f64, (gS2[0][0] + gS2[1][0]).re, 0.00169375, epsilon = 2e-6);
+ }
+
+ #[test]
+ fn N2() {
+ let mut c = Cache::new(cmplx![2., 0.]);
+ assert_approx_eq!(f64, gamma_nsv(&mut c, NF).re, 188.325593, epsilon = 3e-7);
+ }
+}
diff --git a/crates/ekore/src/bib.rs b/crates/ekore/src/bib.rs
index c62f16d02..75da707bb 100644
--- a/crates/ekore/src/bib.rs
+++ b/crates/ekore/src/bib.rs
@@ -1,5 +1,6 @@
-//! List of References (autogenerated on 2023-11-29T18:07:41.518255).
+//! List of References (autogenerated on 2024-05-30T12:57:15.459698).
+#[allow(non_snake_case)]
/// The Three loop splitting functions in QCD: The Nonsinglet case
///
/// Moch, S. and Vermaseren, J. A. M. and Vogt, A.
@@ -11,6 +12,7 @@
/// DOI: [10.1016/j.nuclphysb.2004.03.030](https:dx.doi.org/10.1016/j.nuclphysb.2004.03.030)
pub fn Moch2004pa() {}
+#[allow(non_snake_case)]
/// The Three-loop splitting functions in QCD: The Singlet case
///
/// Vogt, A. and Moch, S. and Vermaseren, J. A. M.
@@ -22,6 +24,7 @@ pub fn Moch2004pa() {}
/// DOI: [10.1016/j.nuclphysb.2004.04.024](https:dx.doi.org/10.1016/j.nuclphysb.2004.04.024)
pub fn Vogt2004mw() {}
+#[allow(non_snake_case)]
/// Programs for computing the logarithm of the gamma function, and the digamma function, for complex argument
///
/// K.S. Kölbig
@@ -33,6 +36,7 @@ pub fn Vogt2004mw() {}
/// DOI: [https://doi.org/10.1016/0010-4655(72)90012-4](https://doi.org/10.1016/0010-4655(72)90012-4)
pub fn KOLBIG1972221() {}
+#[allow(non_snake_case)]
/// Multi‐precision Laplace transform inversion
///
/// Abate, J. and Valkó, P.
@@ -43,3 +47,27 @@ pub fn KOLBIG1972221() {}
///
/// DOI: [10.1002/nme.995](https:dx.doi.org/10.1002/nme.995)
pub fn Abate() {}
+
+#[allow(non_snake_case)]
+/// Resummations of Transverse Momentum Distributions
+///
+/// Muselli, Claudio
+///
+/// Published as PhD thesis at Università degli studi di Milano, Dipartimento di Fisica (2017)
+///
+///
+///
+/// DOI: [10.13130/muselli-claudio_phd2017-12-01](https:dx.doi.org/10.13130/muselli-claudio_phd2017-12-01)
+pub fn MuselliPhD() {}
+
+#[allow(non_snake_case)]
+/// Efficient evolution of unpolarized and polarized parton distributions with QCD-PEGASUS
+///
+/// Vogt, A.
+///
+/// Published in: Comput. Phys. Commun. 170 (2005), 65--92
+///
+/// e-Print: [hep-ph/0408244](https://arxiv.org/abs/hep-ph/0408244)
+///
+/// DOI: [10.1016/j.cpc.2005.03.103](https:dx.doi.org/10.1016/j.cpc.2005.03.103)
+pub fn Vogt2004ns() {}
diff --git a/crates/ekore/src/constants.rs b/crates/ekore/src/constants.rs
index 3cdd13a15..c824bdf5a 100644
--- a/crates/ekore/src/constants.rs
+++ b/crates/ekore/src/constants.rs
@@ -1,25 +1,43 @@
//! Global constants.
-#[cfg_attr(doc, katexit::katexit)]
/// The number of colors.
///
/// Defaults to $N_C = 3$.
pub const NC: u8 = 3;
-#[cfg_attr(doc, katexit::katexit)]
/// The normalization of fundamental generators.
///
/// Defaults to $T_R = 1/2$.
pub const TR: f64 = 1.0 / 2.0;
-#[cfg_attr(doc, katexit::katexit)]
/// Second Casimir constant in the adjoint representation.
///
/// Defaults to $C_A = N_C = 3$.
pub const CA: f64 = NC as f64;
-#[cfg_attr(doc, katexit::katexit)]
/// Second Casimir constant in the fundamental representation.
///
/// Defaults to $C_F = \frac{N_C^2-1}{2N_C} = 4/3$.
pub const CF: f64 = ((NC * NC - 1) as f64) / ((2 * NC) as f64);
+
+/// Riemann zeta function at z = 2.
+///
+/// $\zeta(2) = \pi^2 / 6$.
+pub const ZETA2: f64 = 1.6449340668482264;
+
+/// Riemann zeta function at z = 3.
+pub const ZETA3: f64 = 1.2020569031595942;
+
+/// Riemann zeta function at z = 4.
+///
+/// $\zeta(4) = \pi^4 / 90$.
+pub const ZETA4: f64 = 1.082323233711138;
+
+/// singlet-like non-singlet PID
+pub const PID_NSP: u16 = 10101;
+
+/// valence-like non-singlet PID
+pub const PID_NSM: u16 = 10201;
+
+/// non-singlet all-valence PID
+pub const PID_NSV: u16 = 10200;
diff --git a/crates/ekore/src/harmonics.rs b/crates/ekore/src/harmonics.rs
index b829060fc..a8a3b3241 100644
--- a/crates/ekore/src/harmonics.rs
+++ b/crates/ekore/src/harmonics.rs
@@ -1,5 +1,9 @@
//! Tools to compute harmonic sums and related special functions.
pub mod cache;
+pub mod g_functions;
pub mod polygamma;
-mod w1;
+pub mod w1;
+pub mod w2;
+pub mod w3;
+pub mod w4;
diff --git a/crates/ekore/src/harmonics/cache.rs b/crates/ekore/src/harmonics/cache.rs
index 6ad72171d..1342f5175 100644
--- a/crates/ekore/src/harmonics/cache.rs
+++ b/crates/ekore/src/harmonics/cache.rs
@@ -1,16 +1,35 @@
//! Cache harmonic sums for given Mellin N.
use hashbrown::HashMap;
-use num::complex::Complex;
+use num::{complex::Complex, Zero};
-use crate::harmonics::w1;
+use crate::harmonics::{g_functions, w1, w2, w3, w4};
-#[cfg_attr(doc, katexit::katexit)]
/// List of available elements.
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum K {
/// $S_1(N)$
S1,
+ /// $S_2(N)$
+ S2,
+ /// $S_3(N)$
+ S3,
+ /// $S_4(N)$
+ S4,
+ /// $S_1(N/2)$
+ S1h,
+ /// $S_2(N/2)$
+ S2h,
+ /// $S_3(N/2)$
+ S3h,
+ /// $S_1((N-1)/2)$
+ S1mh,
+ /// $S_2((N-1)/2)$
+ S2mh,
+ /// $S_3((N-1)/2)$
+ S3mh,
+ /// $g_3(N)$
+ G3,
}
/// Hold all cached values.
@@ -34,15 +53,68 @@ impl Cache {
pub fn get(&mut self, k: K) -> Complex {
let val = self.m.get(&k);
// already there?
- if val.is_some() {
- return *val.unwrap();
+ if let Some(value) = val {
+ return *value;
}
// compute new
let val = match k {
K::S1 => w1::S1(self.n),
+ K::S2 => w2::S2(self.n),
+ K::S3 => w3::S3(self.n),
+ K::S4 => w4::S4(self.n),
+ K::S1h => w1::S1(self.n / 2.),
+ K::S2h => w2::S2(self.n / 2.),
+ K::S3h => w3::S3(self.n / 2.),
+ K::S1mh => w1::S1((self.n - 1.) / 2.),
+ K::S2mh => w2::S2((self.n - 1.) / 2.),
+ K::S3mh => w3::S3((self.n - 1.) / 2.),
+ K::G3 => g_functions::g3(self.n, self.get(K::S1)),
};
// insert
self.m.insert(k, val);
val
}
}
+
+/// Recursive computation of harmonic sums.
+///
+/// Compute the harmonic sum $S_{w}(N+k)$ stating from the value $S_{w}(N)$ via the recurrence relations.
+pub fn recursive_harmonic_sum(
+ base_value: Complex,
+ n: Complex,
+ iterations: usize,
+ weight: u32,
+) -> Complex {
+ let mut fact = Complex::zero();
+ for i in 1..iterations + 1 {
+ fact += (1.0 / (n + (i as f64))).powu(weight);
+ }
+ base_value + fact
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::harmonics::cache::recursive_harmonic_sum;
+ use crate::harmonics::{w1, w2, w3, w4};
+ use crate::{assert_approx_eq_cmplx, cmplx};
+ use num::complex::Complex;
+
+ #[test]
+ fn test_recursive_harmonic_sum() {
+ const SX: [fn(Complex) -> Complex; 4] = [w1::S1, w2::S2, w3::S3, w4::S4];
+ const NS: [Complex; 2] = [cmplx![1.0, 0.0], cmplx![2.34, 3.45]];
+ const ITERS: [usize; 2] = [1, 2];
+ for sit in SX.iter().enumerate() {
+ for nit in NS.iter().enumerate() {
+ let n = *nit.1;
+ for iit in ITERS.iter().enumerate() {
+ let iterations = *iit.1;
+ let s_base = sit.1(n);
+ let s_test = sit.1(n + (iterations as f64));
+ let s_ref = recursive_harmonic_sum(s_base, n, iterations, 1 + (sit.0 as u32));
+ assert_approx_eq_cmplx!(f64, s_test, s_ref);
+ }
+ }
+ }
+ }
+}
diff --git a/crates/ekore/src/harmonics/g_functions.rs b/crates/ekore/src/harmonics/g_functions.rs
new file mode 100644
index 000000000..cfde9e9ea
--- /dev/null
+++ b/crates/ekore/src/harmonics/g_functions.rs
@@ -0,0 +1,50 @@
+//! Auxilary functions for harmonics sums of weight = 3,4.
+
+use crate::constants::ZETA2;
+use crate::harmonics::cache::recursive_harmonic_sum as s;
+use num::{complex::Complex, Zero};
+
+/// Compute the Mellin transform of $\text{Li}_2(x)/(1+x)$.
+///
+/// This function appears in the analytic continuation of the harmonic sum
+/// $S_{-2,1}(N)$ which in turn appears in the NLO anomalous dimension.
+///
+/// We use the name from [\[MuselliPhD\]](crate::bib::MuselliPhD), but not his implementation - rather we use the
+/// Pegasus [\[Vogt:2004ns\]](crate::bib::Vogt2004ns) implementation.
+pub fn g3(N: Complex, S1: Complex) -> Complex {
+ const CS: [f64; 7] = [
+ 1.0000e0, -0.9992e0, 0.9851e0, -0.9005e0, 0.6621e0, -0.3174e0, 0.0699e0,
+ ];
+ let mut g3 = Complex::zero();
+ for cit in CS.iter().enumerate() {
+ let Nj = N + (cit.0 as f64);
+ g3 += (*cit.1) * (ZETA2 - s(S1, N, cit.0, 1) / Nj) / Nj;
+ }
+ g3
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::harmonics::g_functions::g3;
+ use crate::harmonics::w1;
+ use crate::{assert_approx_eq_cmplx, cmplx};
+ use num::complex::Complex;
+
+ #[test]
+ fn test_mellin_g3() {
+ const NS: [Complex; 3] = [cmplx![1.0, 0.0], cmplx![2.0, 0.0], cmplx![1.0, 1.0]];
+ // NIntegrate[x^({1, 2, 1 + I} - 1) PolyLog[2, x]/(1 + x), {x, 0, 1}]
+ const REFVALS: [Complex; 3] = [
+ cmplx![0.3888958462, 0.],
+ cmplx![0.2560382207, 0.],
+ cmplx![0.3049381491, -0.1589060625],
+ ];
+ for it in NS.iter().enumerate() {
+ let n = *it.1;
+ let s1 = w1::S1(n);
+ let refval = REFVALS[it.0];
+ let g3 = g3(n, s1);
+ assert_approx_eq_cmplx![f64, g3, refval, epsilon = 1e-6];
+ }
+ }
+}
diff --git a/crates/ekore/src/harmonics/polygamma.rs b/crates/ekore/src/harmonics/polygamma.rs
index efbdae147..7415db88e 100644
--- a/crates/ekore/src/harmonics/polygamma.rs
+++ b/crates/ekore/src/harmonics/polygamma.rs
@@ -3,10 +3,11 @@
use num::{complex::Complex, Zero};
use std::f64::consts::PI;
-#[cfg_attr(doc, katexit::katexit)]
+#[allow(clippy::excessive_precision, clippy::assign_op_pattern)]
/// Compute the polygamma functions $\psi_k(z)$.
///
-/// Reimplementation of ``WPSIPG`` (C317) in [CERNlib](http://cernlib.web.cern.ch/cernlib/) given by [[KOLBIG1972221]][crate::bib::KOLBIG1972221].
+/// Reimplementation of ``WPSIPG`` (C317) in [CERNlib](http://cernlib.web.cern.ch/cernlib/)
+/// given by [\[KOLBIG1972221\]](crate::bib::KOLBIG1972221).
///
/// TODO: introduce back errors
pub fn cern_polygamma(Z: Complex, K: usize) -> Complex {
@@ -83,9 +84,7 @@ pub fn cern_polygamma(Z: Complex, K: usize) -> Complex {
}
let mut R = 1. / V.powu(2);
let mut P = R * C[K][6 - 1];
- for i in (1..=5).rev()
- // (int i = 5; i>1-1; i--)
- {
+ for i in (1..=5).rev() {
P = R * (C[K][i - 1] + P);
}
H = (SGN[K] as f64)
@@ -121,9 +120,8 @@ pub fn cern_polygamma(Z: Complex, K: usize) -> Complex {
#[cfg(test)]
mod tests {
- use crate::cmplx;
use crate::harmonics::polygamma::cern_polygamma;
- use float_cmp::assert_approx_eq;
+ use crate::{assert_approx_eq_cmplx, cmplx};
use num::complex::Complex;
#[test]
@@ -202,8 +200,7 @@ mod tests {
for zit in ZS.iter().enumerate() {
let fref = FORTRAN_REF[kit.0][zit.0];
let me = cern_polygamma(*zit.1, *kit.1);
- assert_approx_eq!(f64, me.re, fref.re, ulps = 32);
- assert_approx_eq!(f64, me.im, fref.im, ulps = 32);
+ assert_approx_eq_cmplx!(f64, me, fref, ulps = 32);
}
}
}
diff --git a/crates/ekore/src/harmonics/w1.rs b/crates/ekore/src/harmonics/w1.rs
index 2b861cb30..a1aa893d9 100644
--- a/crates/ekore/src/harmonics/w1.rs
+++ b/crates/ekore/src/harmonics/w1.rs
@@ -1,3 +1,4 @@
+//! Harmonic sums of weight 1.
use num::complex::Complex;
use crate::harmonics::polygamma::cern_polygamma;
@@ -7,5 +8,5 @@ use crate::harmonics::polygamma::cern_polygamma;
/// $$S_1(N) = \sum\limits_{j=1}^N \frac 1 j = \psi_0(N+1)+\gamma_E$$
/// with $\psi_0(N)$ the digamma function and $\gamma_E$ the Euler-Mascheroni constant.
pub fn S1(N: Complex) -> Complex {
- cern_polygamma(N + 1.0, 0) + 0.5772156649015328606065120
+ cern_polygamma(N + 1.0, 0) + 0.577_215_664_901_532_9
}
diff --git a/crates/ekore/src/harmonics/w2.rs b/crates/ekore/src/harmonics/w2.rs
new file mode 100644
index 000000000..d55a32679
--- /dev/null
+++ b/crates/ekore/src/harmonics/w2.rs
@@ -0,0 +1,13 @@
+//! Harmonic sums of weight 2.
+use num::complex::Complex;
+
+use crate::constants::ZETA2;
+use crate::harmonics::polygamma::cern_polygamma;
+
+/// Compute the harmonic sum $S_2(N)$.
+///
+/// $$S_2(N) = \sum\limits_{j=1}^N \frac 1 {j^2} = -\psi_1(N+1)+\zeta(2)$$
+/// with $\psi_1(N)$ the trigamma function and $\zeta$ the Riemann zeta function.
+pub fn S2(N: Complex) -> Complex {
+ -cern_polygamma(N + 1.0, 1) + ZETA2
+}
diff --git a/crates/ekore/src/harmonics/w3.rs b/crates/ekore/src/harmonics/w3.rs
new file mode 100644
index 000000000..7850c678d
--- /dev/null
+++ b/crates/ekore/src/harmonics/w3.rs
@@ -0,0 +1,13 @@
+//! Harmonic sums of weight 3.
+use num::complex::Complex;
+
+use crate::constants::ZETA3;
+use crate::harmonics::polygamma::cern_polygamma;
+
+/// Compute the harmonic sum $S_3(N)$.
+///
+/// $$S_3(N) = \sum\limits_{j=1}^N \frac 1 {j^3} = \frac 1 2 \psi_2(N+1)+\zeta(3)$$
+/// with $\psi_2(N)$ the 2nd polygamma function and $\zeta$ the Riemann zeta function.
+pub fn S3(N: Complex) -> Complex {
+ 0.5 * cern_polygamma(N + 1.0, 2) + ZETA3
+}
diff --git a/crates/ekore/src/harmonics/w4.rs b/crates/ekore/src/harmonics/w4.rs
new file mode 100644
index 000000000..66835ac5f
--- /dev/null
+++ b/crates/ekore/src/harmonics/w4.rs
@@ -0,0 +1,13 @@
+//! Harmonic sums of weight 4.
+use num::complex::Complex;
+
+use crate::constants::ZETA4;
+use crate::harmonics::polygamma::cern_polygamma;
+
+/// Compute the harmonic sum $S_4(N)$.
+///
+/// $$S_4(N) = \sum\limits_{j=1}^N \frac 1 {j^4} = - \frac 1 6 \psi_3(N+1)+\zeta(4)$$
+/// with $\psi_3(N)$ the 3rd polygamma function and $\zeta$ the Riemann zeta function.
+pub fn S4(N: Complex) -> Complex {
+ ZETA4 - 1.0 / 6.0 * cern_polygamma(N + 1.0, 3)
+}
diff --git a/crates/ekore/src/util.rs b/crates/ekore/src/util.rs
index 5c4e34f4d..55b1ab2bd 100644
--- a/crates/ekore/src/util.rs
+++ b/crates/ekore/src/util.rs
@@ -7,3 +7,23 @@ macro_rules! cmplx {
Complex::new($re, $im)
};
}
+
+/// Shorthand complex number contructor.
+#[macro_export]
+macro_rules! assert_approx_eq_cmplx {
+ ($size:ty, $ref:expr, $target:expr) => {
+ use float_cmp::assert_approx_eq;
+ assert_approx_eq!($size, $ref.re, $target.re);
+ assert_approx_eq!($size, $ref.im, $target.im);
+ };
+ ($size:ty, $ref:expr, $target:expr, ulps=$ulps:expr) => {
+ use float_cmp::assert_approx_eq;
+ assert_approx_eq!($size, $ref.re, $target.re, ulps = $ulps);
+ assert_approx_eq!($size, $ref.im, $target.im, ulps = $ulps);
+ };
+ ($size:ty, $ref:expr, $target:expr, epsilon=$epsilon:expr) => {
+ use float_cmp::assert_approx_eq;
+ assert_approx_eq!($size, $ref.re, $target.re, epsilon = $epsilon);
+ assert_approx_eq!($size, $ref.im, $target.im, epsilon = $epsilon);
+ };
+}
diff --git a/crates/make_bib.py b/crates/make_bib.py
index 1b15d663d..e758c41ad 100644
--- a/crates/make_bib.py
+++ b/crates/make_bib.py
@@ -1,4 +1,5 @@
"""Parse bibtex file to rust crate."""
+
import datetime
import pathlib
import re
@@ -9,7 +10,8 @@
BIBFILE = pathlib.Path(__file__).parent / "ekore" / "refs.bib"
# A single entry
-ENTRY = """/// {title}
+ENTRY = """#[allow(non_snake_case)]
+/// {title}
///
/// {author}
///
@@ -20,6 +22,7 @@
/// {doi}"""
# Combine publication information
PUB = """Published in: {journal} {volume} ({year}), {pages}"""
+PHD = """Published as PhD thesis at {school} ({year})"""
def clean_nl(t: str) -> str:
@@ -38,12 +41,18 @@ def clean_nl(t: str) -> str:
for el in bib_database.entries:
title = re.sub(r"^\{(.+)\}$", r"\1", clean_nl(el.fields_dict["title"].value))
author = el.fields_dict["author"].value
- publication = PUB.format(
- journal=el.fields_dict["journal"].value,
- volume=el.fields_dict["volume"].value,
- year=el.fields_dict["year"].value,
- pages=el.fields_dict["pages"].value,
- )
+ if el.entry_type == "phdthesis":
+ publication = PHD.format(
+ school=el.fields_dict["school"].value,
+ year=el.fields_dict["year"].value,
+ )
+ else:
+ publication = PUB.format(
+ journal=el.fields_dict["journal"].value,
+ volume=el.fields_dict["volume"].value,
+ year=el.fields_dict["year"].value,
+ pages=el.fields_dict["pages"].value,
+ )
eprint = ""
if (
"eprint" in el.fields_dict
diff --git a/crates/parse-abbrev.py b/crates/parse-abbrev.py
new file mode 100644
index 000000000..b928ed03c
--- /dev/null
+++ b/crates/parse-abbrev.py
@@ -0,0 +1,20 @@
+"""Parse abbreviations from sphinx to Rust."""
+
+import pathlib
+import re
+
+SRC = (
+ pathlib.Path(__file__).parents[1]
+ / "doc"
+ / "source"
+ / "shared"
+ / "abbreviations.rst"
+)
+
+cnt = SRC.read_text("utf-8")
+for el in cnt.split(".."):
+ test = re.match(r"\s*(.+)\s+replace::\n\s+:abbr:`(.+?)\((.+)\)`", el.strip())
+ if test is None:
+ continue
+ # Print to terminal - the user can dump to the relevant file
+ print(f'"{test[2].strip()}": "{test[3].strip()}",')
diff --git a/crates/release.json b/crates/release.json
new file mode 100644
index 000000000..c2b9f6f54
--- /dev/null
+++ b/crates/release.json
@@ -0,0 +1 @@
+["ekore", "eko"]
diff --git a/doc/source/code/genpdf.rst b/doc/source/code/genpdf.rst
index f9d52bd47..ab3f94673 100644
--- a/doc/source/code/genpdf.rst
+++ b/doc/source/code/genpdf.rst
@@ -3,40 +3,46 @@ 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|
+
+To use it, you have to install the additional `ekobox` dependencies via
+the pip extra `box`:
+
+.. code-block:: bash
+
+ $ pip install eko[box]
+
+The ``genpdf generate [NAME]`` command generates a custom |PDF|
and saves it as ``[NAME]`` in the current directory.
-Notice that the argument ``[NAME]`` is the only mandatory one.
+Afterwards, it can be conveniently installed using the ``genpdf install [NAME]`` command
+(which simply copies the generated folder into the LHAPDF folder).
+Note 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]``):
+A custom |PDF| can be generated in three different ways which
+are accessible trough the option ``-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.
+ |PDF| and thus copied to generate the new custom PDF.
+ 2. If ``[PARENT]`` is "toylh" or "toy", the **toy** |PDF| :cite:`Giele:2002hx,Dittmar:2005ed` 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.
+ 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
+Through the use of the argument
+``[LABEL]`` (``genpdf generate [NAME] [LABEL] [OPTIONS]``) it is 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.
+evolution basis components on which to filter the new |PDF|.
+In this way the specified set is kept in the new |PDF|, while the rest
+is discarded, i.e. set to zero.
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.
+file of course). Using the flag ``-m`` when a 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
@@ -49,7 +55,7 @@ Examples
$ genpdf generate gonly 21
-This will generate the custom PDF using the debug x(1-x) PDF as parent
+This will generate a custom PDF using the debug x(1-x) PDF as parent
and then it will keep only the gluon.
.. code-block:: bash
@@ -62,7 +68,7 @@ This will install the previous PDF in the lhapdf folder.
$ genpdf generate Sonly S -p toy -i
-This will generate the custom PDF using the toy PDF as parent and then
+This will generate a 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.
@@ -70,6 +76,14 @@ automatically installed in the lhapdf folder.
$ genpdf generate Vonly V -p CT10 -m
-This will generate the custom PDF using the CT10 PDF set as parent
+This will generate a 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.
+
+.. code-block:: bash
+
+ $ genpdf generate NN40qqbar -p NNPDF40_nnlo_as_01180 -- -5 -4 -3 -2 -1 1 2 3 4 5
+
+This will generate a custom PDF with no gluon contributions, but all quarks
+taken are from NNPDF4.0. Note that (as customary with CLIs) you have to add the explicit
+separator ``--`` before specifying anti-quark flavors.
diff --git a/doc/source/conf.py b/doc/source/conf.py
index c271bd870..1f03599ac 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -27,7 +27,7 @@
# -- Project information -----------------------------------------------------
project = "EKO"
-copyright = "2019-2023, the NNPDF team" # pylint: disable=redefined-builtin
+copyright = "2019-2024, the NNPDF team" # pylint: disable=redefined-builtin
author = "NNPDF team"
# The short X.Y version
@@ -112,10 +112,10 @@
)
extlinks = {
- "yadism": ("https://n3pdf.github.io/yadism/%s", "yadism"),
- "banana": ("https://n3pdf.github.io/banana/%s", "banana"),
- "pineappl": ("https://n3pdf.github.io/pineappl/%s", "pineappl"),
- "pineko": ("https://github.com/N3PDF/pineko/%s", "pineko"),
+ "yadism": ("https://n3pdf.github.io/yadism/%s", "yadism%s"),
+ "banana": ("https://n3pdf.github.io/banana/%s", "banana%s"),
+ "pineappl": ("https://n3pdf.github.io/pineappl/%s", "pineappl%s"),
+ "pineko": ("https://github.com/N3PDF/pineko/%s", "pineko%s"),
}
# -- Options for HTML output -------------------------------------------------
diff --git a/doc/source/overview/tutorials/alpha_s.ipynb b/doc/source/overview/tutorials/alpha_s.ipynb
index a9d75c0ca..f9cc5a240 100644
--- a/doc/source/overview/tutorials/alpha_s.ipynb
+++ b/doc/source/overview/tutorials/alpha_s.ipynb
@@ -39,12 +39,10 @@
"from eko.quantities.heavy_quarks import MatchingScales, QuarkMassScheme\n",
"\n",
"# set the (alpha_s, alpha_em) reference values\n",
- "couplings_ref = CouplingsInfo(\n",
- " alphas=0.118, alphaem=0.007496252, scale=91.0, num_flavs_ref=None, max_num_flavs=5\n",
- ")\n",
+ "couplings_ref = CouplingsInfo(alphas=0.118, alphaem=0.007496252, ref=(91.0, 5))\n",
"\n",
"# set heavy quark masses and their threshold ratios\n",
- "heavy_quark_masses = np.power([1.51, 4.92, 172.0],2)\n",
+ "heavy_quark_masses = np.power([1.51, 4.92, 172.0], 2)\n",
"thresholds_ratios = np.array([1.0, 1.0, 1.0])\n",
"\n",
"# set (QCD,QED) perturbative order\n",
@@ -88,9 +86,9 @@
}
],
"source": [
- "target_scale = 10.0 ** 2\n",
+ "target_scale = 10.0**2\n",
"a_s = sc.a_s(target_scale)\n",
- "print(\"The value of alpha_s at Q^2=100 GeV^2 is: \", 4. * np.pi * a_s)"
+ "print(\"The value of alpha_s at Q^2=100 GeV^2 is: \", 4.0 * np.pi * a_s)"
]
},
{
@@ -105,13 +103,10 @@
}
],
"metadata": {
- "interpreter": {
- "hash": "0a84ba3ac8703c04e87bc503a7d00188dfd591ad56130da93c406115a1e4a408"
- },
"kernelspec": {
- "display_name": "eko-KkPVjVhh-py3.10",
+ "display_name": "Python 3 (ipykernel)",
"language": "python",
- "name": "eko-kkpvjvhh-py3.10"
+ "name": "python3"
},
"language_info": {
"codemirror_mode": {
diff --git a/doc/source/overview/tutorials/dglap.ipynb b/doc/source/overview/tutorials/dglap.ipynb
index 0e271a00c..98cb4a6e1 100644
--- a/doc/source/overview/tutorials/dglap.ipynb
+++ b/doc/source/overview/tutorials/dglap.ipynb
@@ -68,7 +68,7 @@
"th_card = example.theory()\n",
"op_card = example.operator()\n",
"# here we replace the grid with a very minimal one, to speed up the example\n",
- "op_card.xgrid = [1e-3, 1e-2, 1e-1, 5e-1, 1.]"
+ "op_card.xgrid = [1e-3, 1e-2, 1e-1, 5e-1, 1.0]"
]
},
{
@@ -91,14 +91,9 @@
"{'order': [1, 0],\n",
" 'couplings': {'alphas': 0.118,\n",
" 'alphaem': 0.007496252,\n",
- " 'scale': 91.2,\n",
- " 'max_num_flavs': 6,\n",
- " 'num_flavs_ref': 5,\n",
+ " 'ref': [91.2, 5],\n",
" 'em_running': False},\n",
- " 'heavy': {'num_flavs_init': 4,\n",
- " 'num_flavs_max_pdf': 6,\n",
- " 'intrinsic_flavors': [4],\n",
- " 'masses': [[2.0, nan], [4.5, nan], [173.07, nan]],\n",
+ " 'heavy': {'masses': [[2.0, nan], [4.5, nan], [173.07, nan]],\n",
" 'masses_scheme': 'pole',\n",
" 'matching_ratios': [1.0, 1.0, 1.0]},\n",
" 'xif': 1.0,\n",
@@ -123,7 +118,7 @@
{
"data": {
"text/plain": [
- "{'mu0': 1.65,\n",
+ "{'init': [1.65, 4],\n",
" 'mugrid': [[100.0, 5]],\n",
" 'xgrid': [0.001, 0.01, 0.1, 0.5, 1.0],\n",
" 'configs': {'evolution_method': 'iterate-exact',\n",
@@ -174,7 +169,7 @@
"id": "880aadcf-8f87-4918-a0bc-09581d0d3579",
"metadata": {},
"source": [
- "The actual result is a complicate EKO object, we will discuss it in a separate tutorial.\n",
+ "The actual result is a complicate EKO object, which we will discuss it in a separate tutorial.\n",
"\n",
"You have just run your first DGLAP calculation!"
]
diff --git a/doc/source/overview/tutorials/output.ipynb b/doc/source/overview/tutorials/output.ipynb
index 47345ac35..1cfe9f071 100644
--- a/doc/source/overview/tutorials/output.ipynb
+++ b/doc/source/overview/tutorials/output.ipynb
@@ -34,7 +34,7 @@
"id": "2f8f0666-c6ab-40f6-86f5-15773f205b51",
"metadata": {},
"source": [
- "We can access the operator, by using the `open` method (similar to python's `open`):"
+ "We can access the operator, by using the `read` method:"
]
},
{
@@ -76,8 +76,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "TheoryCard(order=(1, 0), couplings=CouplingsInfo(alphas=0.118, alphaem=0.007496252, scale=91.2, max_num_flavs=6, num_flavs_ref=5, em_running=False), heavy=HeavyInfo(num_flavs_init=4, num_flavs_max_pdf=6, intrinsic_flavors=[4, 5, 6], masses=[[2.0, nan], [4.5, nan], [173.07, nan]], masses_scheme=, matching_ratios=[1.0, 1.0, 1.0]), xif=1.0, n3lo_ad_variation=(0, 0, 0, 0))\n",
- "OperatorCard(mu0=1.65, mugrid=[(100.0, 5)], xgrid=, configs=Configs(evolution_method=, ev_op_max_order=(10, 0), ev_op_iterations=10, scvar_method=None, inversion_method=None, interpolation_polynomial_degree=4, interpolation_is_log=True, polarized=False, time_like=False, n_integration_cores=0), debug=Debug(skip_singlet=False, skip_non_singlet=False), eko_version='0.0.0')\n"
+ "TheoryCard(order=(1, 0), couplings=CouplingsInfo(alphas=0.118, alphaem=0.007496252, ref=(91.2, 5), em_running=False), heavy=HeavyInfo(masses=[[2.0, nan], [4.5, nan], [173.07, nan]], masses_scheme=, matching_ratios=[1.0, 1.0, 1.0]), xif=1.0, n3lo_ad_variation=(0, 0, 0, 0))\n",
+ "OperatorCard(init=(1.65, 4), mugrid=[(100.0, 5)], xgrid=, configs=Configs(evolution_method=, ev_op_max_order=(10, 0), ev_op_iterations=10, scvar_method=None, inversion_method=None, interpolation_polynomial_degree=4, interpolation_is_log=True, polarized=False, time_like=False, n_integration_cores=0), debug=Debug(skip_singlet=False, skip_non_singlet=False), eko_version='0.0.0')\n"
]
}
],
@@ -143,7 +143,7 @@
],
"source": [
"with eko.EKO.read(\"./myeko.tar\") as evolution_operator:\n",
- " with evolution_operator.operator((10000.,5)) as op:\n",
+ " with evolution_operator.operator((10000.0, 5)) as op:\n",
" print(f\"operator: {op.operator.shape}\")\n",
" print(f\"error: {op.error.shape}\")"
]
diff --git a/doc/source/overview/tutorials/pdf.ipynb b/doc/source/overview/tutorials/pdf.ipynb
index 4607ef891..bfc6ad3ad 100644
--- a/doc/source/overview/tutorials/pdf.ipynb
+++ b/doc/source/overview/tutorials/pdf.ipynb
@@ -13,9 +13,9 @@
"id": "3e0dcd0f",
"metadata": {},
"source": [
- "## Method 1: Using apply_pdf\n",
+ "## Method 1: Using `apply_pdf`\n",
"\n",
- "In this first part we will compute the eko and subsequently apply the initial PDF \"manually\" calling a dedicated function. "
+ "In this first part, we compute the eko and subsequently apply the initial PDF \"manually\" calling a dedicated function. "
]
},
{
@@ -52,6 +52,7 @@
"import pathlib\n",
"import eko\n",
"from banana import toy\n",
+ "\n",
"pdf = toy.mkPDF(\"\", 0)"
]
},
@@ -71,6 +72,7 @@
"outputs": [],
"source": [
"from ekobox.apply import apply_pdf\n",
+ "\n",
"with eko.EKO.read(\"./myeko.tar\") as evolution_operator:\n",
" evolved_pdfs = apply_pdf(evolution_operator, pdf)"
]
@@ -92,7 +94,7 @@
{
"data": {
"text/plain": [
- "dict_keys([10000.0])"
+ "dict_keys([(10000.0, 5)])"
]
},
"execution_count": 3,
@@ -134,7 +136,7 @@
}
],
"source": [
- "evolved_pdfs[10000.0][\"pdfs\"][21]"
+ "evolved_pdfs[(10000.0, 5)][\"pdfs\"][21]"
]
},
{
@@ -150,7 +152,7 @@
"id": "e925d2c9",
"metadata": {},
"source": [
- "## Method 2: Using evolve_pdfs\n",
+ "## Method 2: Using `evolve_pdfs`\n",
"\n",
"In this second part we illustrate how to get (and install) directly a LHAPDF set evolved with eko. "
]
@@ -171,6 +173,7 @@
"outputs": [],
"source": [
"from banana import toy\n",
+ "\n",
"pdf = toy.mkPDF(\"\", 0)"
]
},
@@ -195,10 +198,10 @@
"th_card = example.theory()\n",
"op_card = example.operator()\n",
"# here we replace the grid with a very minimal one, to speed up the example\n",
- "op_card.xgrid = eko.interpolation.XGrid([1e-3, 1e-2, 1e-1, 5e-1, 1.])\n",
- "op_card.mugrid = [(10.,5), (100.,5)]\n",
+ "op_card.xgrid = eko.interpolation.XGrid([1e-3, 1e-2, 1e-1, 5e-1, 1.0])\n",
+ "op_card.mugrid = [(10.0, 5), (100.0, 5)]\n",
"# set QCD LO evolution\n",
- "th_card.orders = (1,0)"
+ "th_card.orders = (1, 0)"
]
},
{
@@ -236,16 +239,10 @@
],
"source": [
"from ekobox.evol_pdf import evolve_pdfs\n",
+ "\n",
"path = pathlib.Path(\"./myeko2.tar\")\n",
"path.unlink(missing_ok=True)\n",
- "evolve_pdfs(\n",
- " [pdf],\n",
- " th_card,\n",
- " op_card,\n",
- " install=True,\n",
- " name=\"Evolved_PDF\",\n",
- " store_path=path\n",
- ")"
+ "evolve_pdfs([pdf], th_card, op_card, install=True, name=\"Evolved_PDF\", store_path=path)"
]
},
{
@@ -273,6 +270,7 @@
],
"source": [
"import lhapdf\n",
+ "\n",
"evolved_pdf = lhapdf.mkPDF(\"Evolved_PDF\", 0)"
]
},
@@ -300,12 +298,12 @@
}
],
"source": [
- "pid = 21 # gluon pid\n",
- "Q2 = 89.10 # Q^2 in Gev^2\n",
- "x = 0.01 # momentum fraction \n",
+ "pid = 21 # gluon pid\n",
+ "Q2 = 89.10 # Q^2 in Gev^2\n",
+ "x = 0.01 # momentum fraction\n",
"\n",
"# check that the particle is present\n",
- "print(\"has gluon?\",evolved_pdf.hasFlavor(pid))\n",
+ "print(\"has gluon?\", evolved_pdf.hasFlavor(pid))\n",
"# now do the lookup\n",
"xg = evolved_pdf.xfxQ2(pid, x, Q2)\n",
"print(f\"xg(x={x}, Q2={Q2}) = {xg}\")"
@@ -352,28 +350,28 @@
"import lhapdf\n",
"from ekobox.cards import example\n",
"from eko.interpolation import make_grid\n",
- "from eko.quantities.heavy_quarks import QuarkMassRef,HeavyQuarks\n",
+ "from eko.quantities.heavy_quarks import QuarkMassRef, HeavyQuarks\n",
"\n",
"# get the PDF object\n",
"ct14llo = lhapdf.mkPDF(\"CT14llo\")\n",
"\n",
"# setup the operator card\n",
"op_card = example.operator()\n",
- "op_card.xgrid = eko.interpolation.XGrid(make_grid(30, 30)) # x grid\n",
- "op_card.mugrid = [(float(q),5) for q in np.geomspace(5., 100, 5)] # Q2 grid\n",
- "op_card.mu0 = 1.295000 # starting point for the evolution \n",
+ "op_card.xgrid = eko.interpolation.XGrid(make_grid(30, 30)) # x grid\n",
+ "op_card.mugrid = [(float(q), 5) for q in np.geomspace(5.0, 100, 5)] # Q2 grid\n",
+ "op_card.init = (1.295000, 3) # starting point for the evolution\n",
"\n",
"# setup the theory card - this can be mostly inferred from the PDF's .info file\n",
- "\n",
"th_card = example.theory()\n",
- "th_card.orders = (1,0) # QCD LO\n",
- "th_card.heavy.masses = HeavyQuarks([QuarkMassRef([1.3,nan]), QuarkMassRef([4.75,nan]), QuarkMassRef([172.,nan])]) # quark mass\n",
- "th_card.couplings.alphas = 0.130000 # reference value of alpha_s\n",
- "th_card.couplings.scale = 91.1876 # the reference scale at which alpha_s is provided\n",
- "th_card.couplings.num_flavs_ref = 5 # the number of flavors active at the alpha_s reference scale\n",
- "th_card.couplings.max_num_flavs = 5 # the maximum number of flavors active in the alpha_s evolution\n",
- "th_card.couplings.num_flavs_init = 3 # the number of flavors active at the reference scale\n",
- "th_card.num_flavs_max_pdf = 5 # the maximum number of flavors active in the pdf evolution."
+ "th_card.orders = (1, 0) # QCD LO\n",
+ "th_card.heavy.masses = HeavyQuarks(\n",
+ " [QuarkMassRef([1.3, nan]), QuarkMassRef([4.75, nan]), QuarkMassRef([172.0, nan])]\n",
+ ") # quark mass\n",
+ "th_card.couplings.alphas = 0.130000 # reference value of alpha_s\n",
+ "th_card.couplings.ref = (\n",
+ " 91.1876,\n",
+ " 5,\n",
+ ") # the reference scale together with the number of flavors at which alpha_s is provided"
]
},
{
@@ -407,15 +405,11 @@
],
"source": [
"from ekobox.evol_pdf import evolve_pdfs\n",
+ "\n",
"path = pathlib.Path(\"./myeko_ct14llo.tar\")\n",
"path.unlink(missing_ok=True)\n",
"evolve_pdfs(\n",
- " [ct14llo],\n",
- " th_card,\n",
- " op_card,\n",
- " install=True,\n",
- " name=\"my_ct14llo\",\n",
- " store_path=path\n",
+ " [ct14llo], th_card, op_card, install=True, name=\"my_ct14llo\", store_path=path\n",
")"
]
},
@@ -439,33 +433,33 @@
"output_type": "stream",
"text": [
"LHAPDF 6.4.0 loading /home/felix/local/share/LHAPDF/my_ct14llo/my_ct14llo_0000.dat\n",
+ "my_ct14llo PDF set, member #0, version 1\n",
" x Q2 ct14llo my_ct14llo relative_diff\n",
- "0 0.000010 25.000000 7.635785e+01 7.630461e+01 0.000697\n",
- "1 0.000173 25.000000 3.194273e+01 3.192092e+01 0.000683\n",
- "2 0.003000 25.000000 1.081843e+01 1.081086e+01 0.000701\n",
- "3 0.051962 25.000000 1.958956e+00 1.958632e+00 0.000166\n",
- "4 0.900000 25.000000 1.922415e-05 1.955026e-05 -0.016963\n",
- "5 0.000010 111.803399 1.333957e+02 1.332985e+02 0.000729\n",
- "6 0.000173 111.803399 4.777286e+01 4.773664e+01 0.000758\n",
- "7 0.003000 111.803399 1.341028e+01 1.339967e+01 0.000791\n",
- "8 0.051962 111.803399 1.978216e+00 1.978130e+00 0.000044\n",
- "9 0.900000 111.803399 6.644805e-06 6.753652e-06 -0.016381\n",
- "10 0.000010 500.000000 1.967032e+02 1.965456e+02 0.000801\n",
- "11 0.000173 500.000000 6.291393e+01 6.286095e+01 0.000842\n",
- "12 0.003000 500.000000 1.542347e+01 1.540996e+01 0.000876\n",
- "13 0.051962 500.000000 1.947465e+00 1.947391e+00 0.000038\n",
- "14 0.900000 500.000000 2.929060e-06 2.977306e-06 -0.016471\n",
- "15 0.000010 2236.067977 2.633266e+02 2.631109e+02 0.000819\n",
- "16 0.000173 2236.067977 7.708540e+01 7.701938e+01 0.000856\n",
- "17 0.003000 2236.067977 1.700410e+01 1.698928e+01 0.000872\n",
- "18 0.051962 2236.067977 1.893923e+00 1.893971e+00 -0.000025\n",
- "19 0.900000 2236.067977 1.544450e-06 1.570997e-06 -0.017189\n",
- "20 0.000010 10000.000000 3.314097e+02 3.311351e+02 0.000829\n",
- "21 0.000173 10000.000000 9.023010e+01 9.015279e+01 0.000857\n",
- "22 0.003000 10000.000000 1.825934e+01 1.824402e+01 0.000839\n",
- "23 0.051962 10000.000000 1.830992e+00 1.831183e+00 -0.000104\n",
- "24 0.900000 10000.000000 9.288458e-07 9.447927e-07 -0.017169\n",
- "my_ct14llo PDF set, member #0, version 1\n"
+ "0 0.000010 25.000000 7.635785e+01 7.630719e+01 0.000663\n",
+ "1 0.000173 25.000000 3.194273e+01 3.192239e+01 0.000637\n",
+ "2 0.003000 25.000000 1.081843e+01 1.081160e+01 0.000632\n",
+ "3 0.051962 25.000000 1.958956e+00 1.958820e+00 0.000069\n",
+ "4 0.900000 25.000000 1.922415e-05 1.955440e-05 -0.017179\n",
+ "5 0.000010 111.803399 1.333957e+02 1.333028e+02 0.000697\n",
+ "6 0.000173 111.803399 4.777286e+01 4.773855e+01 0.000718\n",
+ "7 0.003000 111.803399 1.341028e+01 1.340044e+01 0.000734\n",
+ "8 0.051962 111.803399 1.978216e+00 1.978292e+00 -0.000038\n",
+ "9 0.900000 111.803399 6.644805e-06 6.756354e-06 -0.016787\n",
+ "10 0.000010 500.000000 1.967032e+02 1.965517e+02 0.000770\n",
+ "11 0.000173 500.000000 6.291393e+01 6.286327e+01 0.000805\n",
+ "12 0.003000 500.000000 1.542347e+01 1.541073e+01 0.000826\n",
+ "13 0.051962 500.000000 1.947465e+00 1.947532e+00 -0.000034\n",
+ "14 0.900000 500.000000 2.929060e-06 2.979511e-06 -0.017224\n",
+ "15 0.000010 2236.067977 2.633266e+02 2.631189e+02 0.000789\n",
+ "16 0.000173 2236.067977 7.708540e+01 7.702204e+01 0.000822\n",
+ "17 0.003000 2236.067977 1.700410e+01 1.699004e+01 0.000827\n",
+ "18 0.051962 2236.067977 1.893923e+00 1.894094e+00 -0.000090\n",
+ "19 0.900000 2236.067977 1.544450e-06 1.572860e-06 -0.018395\n",
+ "20 0.000010 10000.000000 3.314097e+02 3.311450e+02 0.000799\n",
+ "21 0.000173 10000.000000 9.023010e+01 9.015576e+01 0.000824\n",
+ "22 0.003000 10000.000000 1.825934e+01 1.824477e+01 0.000798\n",
+ "23 0.051962 10000.000000 1.830992e+00 1.831291e+00 -0.000163\n",
+ "24 0.900000 10000.000000 9.288458e-07 9.463689e-07 -0.018866\n"
]
}
],
@@ -475,15 +469,15 @@
"# load evolved pdf\n",
"my_ct14llo = lhapdf.mkPDF(\"my_ct14llo\", 0)\n",
"\n",
- "pid = 21 # gluon pid\n",
+ "pid = 21 # gluon pid\n",
"\n",
"# collect data\n",
- "log = {\"x\": [], \"Q2\" : [], \"ct14llo\": [], \"my_ct14llo\": [], \"relative_diff\": []} \n",
- "for q in np.geomspace(5., 100, 5):\n",
- " q2 = q**2.\n",
+ "log = {\"x\": [], \"Q2\": [], \"ct14llo\": [], \"my_ct14llo\": [], \"relative_diff\": []}\n",
+ "for q in np.geomspace(5.0, 100, 5):\n",
+ " q2 = q**2.0\n",
" for x in np.geomspace(1e-5, 0.9, 5):\n",
" value = ct14llo.xfxQ2(pid, x, q2)\n",
- " my_value = my_ct14llo.xfxQ2(pid, x, q2)\n",
+ " my_value = my_ct14llo.xfxQ2(pid, x, q2)\n",
" log[\"x\"].append(x)\n",
" log[\"Q2\"].append(q2)\n",
" log[\"ct14llo\"].append(value)\n",
diff --git a/doc/source/refs.bib b/doc/source/refs.bib
index 16a662451..769f2e326 100644
--- a/doc/source/refs.bib
+++ b/doc/source/refs.bib
@@ -823,14 +823,18 @@ @article{Kawamura:2012cr
@article{Falcioni:2023luc,
author = "Falcioni, G. and Herzog, F. and Moch, S. and Vogt, A.",
- title = "{Four-loop splitting functions in QCD -- The quark-quark case}",
+ title = "{Four-loop splitting functions in QCD \textendash{} The quark-quark case}",
eprint = "2302.07593",
archivePrefix = "arXiv",
primaryClass = "hep-ph",
reportNumber = "DESY 23--022, LTH 1333",
- month = "2",
+ doi = "10.1016/j.physletb.2023.137944",
+ journal = "Phys. Lett. B",
+ volume = "842",
+ pages = "137944",
year = "2023"
}
+
@article{Gluck:1995yr,
author = "Gluck, M. and Reya, E. and Stratmann, M. and Vogelsang, W.",
title = "{Next-to-leading order radiative parton model analysis of polarized deep inelastic lepton - nucleon scattering}",
@@ -991,24 +995,30 @@ @article{Dokshitzer:2005bf
@article{Falcioni:2023vqq,
author = "Falcioni, G. and Herzog, F. and Moch, S. and Vogt, A.",
- title = "{Four-loop splitting functions in QCD -- The gluon-to-quark case}",
+ title = "{Four-loop splitting functions in QCD \textendash{} The gluon-to-quark case}",
eprint = "2307.04158",
archivePrefix = "arXiv",
primaryClass = "hep-ph",
reportNumber = "DESY 23-096, LTH 1345",
- month = "7",
+ doi = "10.1016/j.physletb.2023.138215",
+ journal = "Phys. Lett. B",
+ volume = "846",
+ pages = "138215",
year = "2023"
}
@article{Gehrmann:2023cqm,
author = "Gehrmann, Thomas and von Manteuffel, Andreas and Sotnikov, Vasily and Yang, Tong-Zhi",
- title = "{Complete $N_f^2$ contributions to four-loop pure-singlet splitting functions}",
+ title = "{Complete $ {N}_f^2 $ contributions to four-loop pure-singlet splitting functions}",
eprint = "2308.07958",
archivePrefix = "arXiv",
primaryClass = "hep-ph",
reportNumber = "MSUHEP-23-024, ZU-TH 43/23",
- month = "8",
- year = "2023"
+ doi = "10.1007/JHEP01(2024)029",
+ journal = "JHEP",
+ volume = "01",
+ pages = "029",
+ year = "2024"
}
@article{Falcioni:2023tzp,
@@ -1018,8 +1028,11 @@ @article{Falcioni:2023tzp
archivePrefix = "arXiv",
primaryClass = "hep-ph",
reportNumber = "ZU-TH 62/23, DESY 23-146, Nikhef 2023-015, LTH 1353",
- month = "10",
- year = "2023"
+ doi = "10.1016/j.physletb.2023.138351",
+ journal = "Phys. Lett. B",
+ volume = "848",
+ pages = "138351",
+ year = "2024"
}
@article{Moch:2023tdj,
@@ -1029,6 +1042,34 @@ @article{Moch:2023tdj
archivePrefix = "arXiv",
primaryClass = "hep-ph",
reportNumber = "DESY-23-150, Nikhef 23-016, LTH 1354",
- month = "10",
- year = "2023"
+ doi = "10.1016/j.physletb.2024.138468",
+ journal = "Phys. Lett. B",
+ volume = "849",
+ pages = "138468",
+ year = "2024"
+}
+
+@article{Ablinger:2024xtt,
+ author = {Ablinger, J. and Behring, A. and Bl\"umlein, J. and De Freitas, A. and von Manteuffel, A. and Schneider, C. and Sch\"onwald, K.},
+ title = "{The non-first-order-factorizable contributions to the three-loop single-mass operator matrix elements $A_{Qg}^{(3)}$ and $\Delta A_{Qg}^{(3)}$}",
+ eprint = "2403.00513",
+ archivePrefix = "arXiv",
+ primaryClass = "hep-ph",
+ reportNumber = "DO--TH 23/15. DESY 24--027, RISC Report series 24--02, ZU-TH 13/24,
+ CERN-TH-2024-30, DO-TH 23/15, RISC Report series 24--02, ZU-TH 13/24,
+ CERN-TH-2024-30, DESY-24-027",
+ month = "3",
+ year = "2024",
+ journal = ""
+}
+
+@article{Falcioni:2024xyt,
+ author = "Falcioni, G. and Herzog, F. and Moch, S. and Pelloni, A. and Vogt, A.",
+ title = "{Four-loop splitting functions in QCD -- The quark-to-gluon case}",
+ eprint = "2404.09701",
+ archivePrefix = "arXiv",
+ primaryClass = "hep-ph",
+ reportNumber = "ZU-TH 20/24, DESY-24-053, LTH 1367",
+ month = "4",
+ year = "2024"
}
diff --git a/doc/source/theory/Matching.rst b/doc/source/theory/Matching.rst
index 5089c0a95..fa84cab16 100644
--- a/doc/source/theory/Matching.rst
+++ b/doc/source/theory/Matching.rst
@@ -88,11 +88,11 @@ During the matching we use :math:`a_s^{(n_f+1)}`: in fact the :math:`a_s` decoup
:math:`\ln(\mu_{h}^2/m_{h}^2)`, which are cancelled by the OME's :math:`A_{kl,H}`.
|N3LO| matrix elements have been presented in :cite:`Bierenbaum:2009mv` and following publications
-:cite:`Ablinger:2010ty,Ablinger:2014vwa,Ablinger:2014uka,Behring:2014eya,Blumlein:2017wxd,Ablinger_2014,Ablinger_2015,Ablinger:2022wbb`.
+:cite:`Ablinger:2010ty,Ablinger:2014vwa,Ablinger:2014uka,Behring:2014eya,Blumlein:2017wxd,Ablinger_2014,Ablinger_2015,Ablinger:2022wbb,Ablinger:2024xtt`.
Parts proportional to :math:`\ln(\mu_{h}^2/m_{h}^2)` are also included up to |N3LO|.
-The contribution of :math:`A_{Hg}^{(3)}` is not yet fully known analytically and has been parameterized using the first 5 known
-moments :cite:`Bierenbaum:2009mv` and the |LL| small-x contribution :cite:`Kawamura:2012cr`
+All the contributions are now known analytically. Due to the lengthy and complex expressions
+some parts of :math:`A_{Hg}^{S,(3)},A_{Hq}^{S,(3)},A_{gg}^{S,(3)},A_{qq}^{NS,(3)}` have been parameterized.
We remark that contributions of the heavy quark initiated diagrams at |NNLO| and |N3LO| 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.
diff --git a/doc/source/theory/N3LO_ad.rst b/doc/source/theory/N3LO_ad.rst
index 34030f7e7..1fb13a15e 100644
--- a/doc/source/theory/N3LO_ad.rst
+++ b/doc/source/theory/N3LO_ad.rst
@@ -264,7 +264,8 @@ The other parts are approximated using some known limits:
& \gamma_{qg}(2) + \gamma_{gg}(2) = 0 \\
& \gamma_{qq}(2) + \gamma_{gq}(2) = 0 \\
- For :math:`\gamma_{qq,ps}, \gamma_{qg}` other 5 additional moments are available :cite:`Falcioni:2023luc,Falcioni:2023vqq`.
+ For :math:`\gamma_{qq,ps}, \gamma_{qg},\gamma_{gq}` other 5 additional moments are available from
+ :cite:`Falcioni:2023luc,Falcioni:2023vqq,Falcioni:2024xyt` respectively.
making the parametrization of this splitting function much more accurate.
The difference between the known moments and the known limits is parametrized
@@ -337,7 +338,7 @@ final reduced sets of candidates.
* - :math:`f_4(N)`
- :math:`\frac{1}{N^4},\ \frac{1}{N^3},\ \frac{1}{N^2},\ \frac{1}{(N+1)},\ \frac{1}{(N+2)},\ \mathcal{M}[\ln^2(1-x)],\ \mathcal{M}[\ln(1-x)]`
- Following :cite:`Moch:2023tdj` we have assumed no violation of the scaling with :math:`\gamma_{gg}`
+ Following :cite:`Moch:2023tdj,Falcioni:2024xyt` we have assumed no violation of the scaling with :math:`\gamma_{gg}`
also for the |NLL| small-x term, to help the convergence. We expect that any possible deviation can be parametrized as a shift in the |NNLL| terms
which are free to vary independently.
diff --git a/extras/lh_bench_23/.gitignore b/extras/lh_bench_23/.gitignore
index 2942ad98d..79e096ab2 100644
--- a/extras/lh_bench_23/.gitignore
+++ b/extras/lh_bench_23/.gitignore
@@ -1,3 +1,4 @@
*.tar
*.csv
*.dat
+*.tex
diff --git a/extras/lh_bench_23/cfg.py b/extras/lh_bench_23/cfg.py
index ef7c747ef..c3700687d 100644
--- a/extras/lh_bench_23/cfg.py
+++ b/extras/lh_bench_23/cfg.py
@@ -62,10 +62,12 @@ def vfns_theory(xif=1.0):
]
-def ffns_theory(xif=1.0):
+def ffns_theory(xif=1.0, pto=2):
"""Generate a VFNS theory card."""
tt = copy.deepcopy(_t_ffns)
tt["xif"] = xif
+ tt["order"] = (pto + 1, 0)
+ tt["matching_order"] = (pto, 0)
return runcards.TheoryCard.from_dict(tt)
@@ -107,9 +109,15 @@ def n3lo_theory(ad_variation, is_ffns, use_fhmruvv=False, xif=1.0):
)
vfns_operator = runcards.OperatorCard.from_dict(_o_vfns)
-_o_ffns = copy.deepcopy(_o_vfns)
-_o_ffns["mugrid"] = [(100.0, 4)]
-ffns_operator = runcards.OperatorCard.from_dict(_o_ffns)
+
+def ffns_operator(ev_method="iterate-exact"):
+ """Generate a FFNS theory card."""
+ op = copy.deepcopy(_o_vfns)
+ op["mugrid"] = [(100.0, 4)]
+ op["configs"]["evolution_method"] = ev_method
+ if ev_method == "truncated":
+ op["configs"]["ev_op_iterations"] = 1
+ return runcards.OperatorCard.from_dict(op)
# flavor rotations
diff --git a/extras/lh_bench_23/parse_to_latex.py b/extras/lh_bench_23/parse_to_latex.py
new file mode 100644
index 000000000..7f59ddc2b
--- /dev/null
+++ b/extras/lh_bench_23/parse_to_latex.py
@@ -0,0 +1,179 @@
+from cfg import here, table_dir, xgrid
+from utils import compute_n3lo_avg_err, load_n3lo_tables
+
+n3lo_table_dir = table_dir
+
+latex_tab = here / "latex_tab"
+latex_tab.mkdir(exist_ok=True)
+
+SVS = ["central", "up", "down"]
+
+MIDRULE1 = r"""
+\hline \hline
+\multicolumn{9}{||c||}{} \\[-3mm]
+\multicolumn{9}{||c||}{"""
+
+MIDRULE2 = r"""} \\
+\multicolumn{9}{||c||}{} \\[-0.3cm]
+\hline \hline
+ & & & & & & & \\[-0.3cm]
+"""
+
+BOTTOMRULE = r"""
+\hline \hline
+\end{tabular}
+\end{center}
+\end{table}
+"""
+
+VFNS_LABELS = r"""
+ \multicolumn{1}{c|} {$xu_v$} &
+ \multicolumn{1}{c|} {$xd_v$} &
+ \multicolumn{1}{c|} {$xL_-$} &
+ \multicolumn{1}{c|} {$xL_+$} &
+ \multicolumn{1}{c|} {$xs_+$} &
+ \multicolumn{1}{c|} {$xc_+$} &
+ \multicolumn{1}{c|} {$xb_+$} &
+ \multicolumn{1}{c||}{$xg$} \\[0.5mm]
+ """
+
+FFNS_LABELS = r"""
+ \multicolumn{1}{c|} {$xu_v$} &
+ \multicolumn{1}{c|} {$xd_v$} &
+ \multicolumn{1}{c|} {$xL_-$} &
+ \multicolumn{1}{c|} {$xL_+$} &
+ \multicolumn{1}{c|} {$xs_v$} &
+ \multicolumn{1}{c|} {$xs_+$} &
+ \multicolumn{1}{c|} {$xc_+$} &
+ \multicolumn{1}{c||}{$xg$}
+ """
+
+
+def insert_headrule(scheme, approx, caption):
+ """Insert the middle rule."""
+ label = r"\label{tab:" + f"n3lo_{scheme.lower()}_{approx.lower()}" + "}"
+ scheme_label = (
+ r", $\, N_{\rm f} = 3\ldots 5\,$,"
+ if scheme == "VFNS"
+ else r"$\, N_{\rm f} = 4$,"
+ )
+ HEADRULE = (
+ r"""
+ \begin{table}[htp]
+ \caption{"""
+ + caption
+ + r"""}
+ """
+ + label
+ + r"""
+ \begin{center}
+ \vspace{5mm}
+ \begin{tabular}{||c||r|r|r|r|r|r|r|r||}
+ \hline \hline
+ \multicolumn{9}{||c||}{} \\[-3mm]
+ \multicolumn{9}{||c||}{"""
+ # + r"""aN$^3$LO, """
+ + approx
+ + scheme_label
+ + r"""$\,\mu_{\rm f}^2 = 10^4 \mbox{ GeV}^2$} \\
+ \multicolumn{9}{||c||}{} \\[-0.3cm]
+ \hline \hline
+ \multicolumn{9}{||c||}{} \\[-3mm]
+ \multicolumn{1}{||c||}{$x$} &
+ """
+ )
+ HEADRULE += VFNS_LABELS if scheme == "VFNS" else FFNS_LABELS
+ HEADRULE += r"""\\[0.5mm]"""
+ return HEADRULE
+
+
+def insert_midrule(sv):
+ """Insert the middle rule."""
+ # TODO: is this mapping correct or the other way round ??
+ # xif2 = 2 -> up
+ # xif2 = 1/2 -> down
+ label = {
+ "central": r"$\mu_{\rm r}^2 = \ \mu_{\rm f}^2$",
+ "down": r"$\mu_{\rm r}^2 = 0.5 \ \mu_{\rm f}^2$",
+ "up": r"$\mu_{\rm r}^2 = 2 \ \mu_{\rm f}^2$",
+ }
+ return MIDRULE1 + label[sv] + MIDRULE2
+
+
+def format_float(values):
+ """Clean float format."""
+ values = values.replace("0000", "0")
+ values = values.replace("e-0", "$^{-")
+ values = values.replace("e-10", "$^{-10")
+ values = values.replace("e+0", "$^{+")
+ values = values.replace("&", "}$ &")
+ values = values.replace(r"\\", r"}$ \\")
+ return values
+
+
+def dump_table(scheme: str, approx: str, caption: str):
+ """Write a nice latex table."""
+ final_tab = insert_headrule(scheme, approx.replace("EKO", "NNPDF"), caption)
+ # loop on scales
+ for sv in SVS:
+ # load tables
+ dfs = load_n3lo_tables(n3lo_table_dir, scheme, sv=sv, approx=approx)
+
+ central, err = compute_n3lo_avg_err(dfs)
+
+ central.insert(0, "x", xgrid)
+ values = central.to_latex(float_format="{:.4e}".format, index=False)
+ values = "".join(e for e in values.split("\n")[4:-3])
+ final_tab += insert_midrule(sv) + format_float(values)
+
+ final_tab += BOTTOMRULE
+
+ # write
+ with open(
+ latex_tab / f"table-{scheme}-{approx.replace('EKO', 'NNPDF')}.tex",
+ "w",
+ encoding="utf-8",
+ ) as f:
+ f.writelines(final_tab)
+
+
+if __name__ == "__main__":
+ approx = "FHMRUVV"
+ scheme = "FFNS"
+ caption = r"""
+ Results for the FFNS aN$^3$LO evolution
+ for the initial conditions and the input parton distributions
+ given in Sec.~\ref{sec:toy_pdf},
+ with the FHMRUVV splitting functions approximation and the NNPDF code.
+ """
+ dump_table(scheme, approx, caption)
+
+ approx = "FHMRUVV"
+ scheme = "VFNS"
+ caption = r"""
+ Results for the VFNS aN$^3$LO evolution
+ for the initial conditions and the input parton distributions
+ given in Sec.~\ref{sec:toy_pdf},
+ with the FHMRUVV splitting functions approximation and the NNPDF code.
+ """
+ dump_table(scheme, approx, caption)
+
+ approx = "EKO"
+ scheme = "FFNS"
+ caption = r"""
+ Results for the FFNS aN$^3$LO evolution
+ for the initial conditions and the input parton distributions
+ given in Sec.~\ref{sec:toy_pdf},
+ with the NNPDF splitting functions approximation.
+ """
+ dump_table(scheme, approx, caption)
+
+ approx = "EKO"
+ scheme = "VFNS"
+ caption = r"""
+ Results for the VFNS aN$^3$LO evolution
+ for the initial conditions and the input parton distributions
+ given in Sec.~\ref{sec:toy_pdf},
+ with the NNPDF splitting functions approximation.
+ """
+ dump_table(scheme, approx, caption)
diff --git a/extras/lh_bench_23/plot_bench.py b/extras/lh_bench_23/plot_bench.py
deleted file mode 100644
index 6887e7ac3..000000000
--- a/extras/lh_bench_23/plot_bench.py
+++ /dev/null
@@ -1,49 +0,0 @@
-from cfg import here, table_dir, xgrid
-from utils import (
- compute_n3lo_avg_err,
- compute_n3lo_nnlo_diff,
- load_n3lo_tables,
- load_nnlo_table,
- plot_diff_to_nnlo,
- plot_pdfs,
-)
-
-USE_LINX = True
-REL_DIFF = True
-SCHEME = "VFNS"
-SV = "central"
-
-plot_dir = here / "plots"
-n3lo_table_dir = table_dir # / SCHEME
-
-
-# load tables
-eko_dfs = load_n3lo_tables(n3lo_table_dir, SCHEME, approx="EKO")
-fhmv_dfs = load_n3lo_tables(n3lo_table_dir, SCHEME, approx="FHMV")
-nnlo_central = load_nnlo_table(table_dir, SCHEME, SV)
-
-# compute avg and std
-eko_res = compute_n3lo_avg_err(eko_dfs)
-fhmv_res = compute_n3lo_avg_err(fhmv_dfs)
-# eko_4mom_res = = compute_n3lo_avg_err(eko_dfs_4mom)
-
-n3lo_dfs = [
- (eko_res, "aN3LO EKO"),
- (fhmv_res, "aN3LO FHMV"),
- # (eko_4mom_res, "aN3LO EKO 4 mom"),
-]
-
-# PDFs plots
-plot_pdfs(xgrid, n3lo_dfs, nnlo_central, SCHEME, USE_LINX, plot_dir)
-
-# relative diff plots
-eko_diff = compute_n3lo_nnlo_diff(eko_res, nnlo_central, REL_DIFF)
-fhmv_diff = compute_n3lo_nnlo_diff(fhmv_res, nnlo_central, REL_DIFF)
-n3lo_dfs = [
- (eko_diff, "aN3LO EKO"),
- (fhmv_diff, "aN3LO FHMV"),
- # (eko_4mom_res, "aN3LO EKO 4 mom"),
-]
-
-# relative, absolute diff plots
-plot_diff_to_nnlo(xgrid, n3lo_dfs, SCHEME, USE_LINX, plot_dir, REL_DIFF)
diff --git a/extras/lh_bench_23/plot_bench_evol.py b/extras/lh_bench_23/plot_bench_evol.py
index 92972af14..af25f5c65 100644
--- a/extras/lh_bench_23/plot_bench_evol.py
+++ b/extras/lh_bench_23/plot_bench_evol.py
@@ -18,17 +18,21 @@
# load tables
-eko_dfs = load_n3lo_tables(n3lo_table_dir, SCHEME, approx="EKO", rotate_to_evol=True)
-fhmv_dfs = load_n3lo_tables(n3lo_table_dir, SCHEME, approx="FHMV", rotate_to_evol=True)
+eko_dfs = load_n3lo_tables(
+ n3lo_table_dir, SCHEME, sv="central", approx="EKO", rotate_to_evol=True
+)
+fhmruvv_dfs = load_n3lo_tables(
+ n3lo_table_dir, SCHEME, sv="central", approx="FHMRUVV", rotate_to_evol=True
+)
nnlo_central = load_nnlo_table(table_dir, SCHEME, SV, rotate_to_evol=True)
# compute avg and std
eko_res = compute_n3lo_avg_err(eko_dfs)
-fhmv_res = compute_n3lo_avg_err(fhmv_dfs)
+fhmruvv_res = compute_n3lo_avg_err(fhmruvv_dfs)
n3lo_dfs = [
(eko_res, "aN3LO EKO"),
- (fhmv_res, "aN3LO FHMV"),
+ (fhmruvv_res, "aN3LO FHMRUVV"),
]
# absolute plots
@@ -36,10 +40,10 @@
# relative, absolute diff plots
eko_diff = compute_n3lo_nnlo_diff(eko_res, nnlo_central, REL_DIFF)
-fhmv_diff = compute_n3lo_nnlo_diff(fhmv_res, nnlo_central, REL_DIFF)
+fhmruvv_diff = compute_n3lo_nnlo_diff(fhmruvv_res, nnlo_central, REL_DIFF)
n3lo_dfs = [
(eko_diff, "aN3LO EKO"),
- (fhmv_diff, "aN3LO FHMV"),
+ (fhmruvv_diff, "aN3LO FHMRUVV"),
]
plot_diff_to_nnlo(xgrid, n3lo_dfs, SCHEME, USE_LINX, plot_dir, REL_DIFF)
diff --git a/extras/lh_bench_23/plot_bench_msht.py b/extras/lh_bench_23/plot_bench_msht.py
index 0314082ee..f99c4c613 100644
--- a/extras/lh_bench_23/plot_bench_msht.py
+++ b/extras/lh_bench_23/plot_bench_msht.py
@@ -15,48 +15,51 @@
SV = "central"
plot_dir = here / "plots_msht"
-n3lo_table_dir = table_dir # / SCHEME
+n3lo_table_dir = table_dir
msht_table_dir = table_dir
# load tables
-eko_dfs = load_n3lo_tables(n3lo_table_dir, SCHEME, approx="EKO")
-fhmv_eko_dfs = load_n3lo_tables(n3lo_table_dir, SCHEME, approx="FHMV")
-msht_dfs = load_msht(msht_table_dir, SCHEME, approx="MSHT")
-fhmv_msht_dfs = load_msht(msht_table_dir, SCHEME, approx="FHMV")
+eko_dfs = load_n3lo_tables(n3lo_table_dir, SCHEME, SV, approx="EKO")
+
+fhmruvv_eko_dfs = load_n3lo_tables(n3lo_table_dir, SCHEME, SV, approx="FHMRUVV")
+fhmruvv_msht_dfs = load_msht(msht_table_dir, SCHEME, approx="FHMRUVV")
+
+msht_post_dfs = load_msht(msht_table_dir, SCHEME, approx="MSHTposterior")
+msht_prior_dfs = load_msht(msht_table_dir, SCHEME, approx="MSHTprior")
nnlo_central = load_nnlo_table(table_dir, SCHEME, SV)
# compute avg and std
eko_res = compute_n3lo_avg_err(eko_dfs)
-fhmv_eko_res = compute_n3lo_avg_err(fhmv_eko_dfs)
-msht_res = compute_n3lo_avg_err(msht_dfs)
-fhmv_msht_res = compute_n3lo_avg_err(fhmv_msht_dfs)
-# eko_4mom_res = = compute_n3lo_avg_err(eko_dfs_4mom)
+fhmruvv_eko_res = compute_n3lo_avg_err(fhmruvv_eko_dfs)
+fhmruvv_msht_res = compute_n3lo_avg_err(fhmruvv_msht_dfs)
+msht_post_res = compute_n3lo_avg_err(msht_post_dfs)
+msht_prior_res = compute_n3lo_avg_err(msht_prior_dfs)
-n3lo_dfs = [
- (eko_res, "EKO"),
- (fhmv_eko_res, "FHMV EKO"),
- (msht_res, "MSHT"),
- (fhmv_msht_res, "FHMV MSHT")
- # (eko_4mom_res, "aN3LO EKO 4 mom"),
-]
+# compute average of FHMRUVV
+fhmruvv_res = []
+for a, b in zip(fhmruvv_msht_res, fhmruvv_eko_res):
+ fhmruvv_res.append((a + b) / 2)
# PDFs plots
+n3lo_dfs = [
+ (fhmruvv_res, "FHMRUVV"),
+ (msht_prior_res, "MSHT (prior)"),
+ (msht_post_res, "MSHT (posterior)"),
+ (eko_res, "NNPDF"),
+]
plot_pdfs(xgrid, n3lo_dfs, nnlo_central, SCHEME, USE_LINX, plot_dir)
-# relative diff plots
+# relative, absolute diff plots
eko_diff = compute_n3lo_nnlo_diff(eko_res, nnlo_central, REL_DIFF)
-fhmv_eko_diff = compute_n3lo_nnlo_diff(fhmv_eko_res, nnlo_central, REL_DIFF)
-msht_diff = compute_n3lo_nnlo_diff(msht_res, nnlo_central, REL_DIFF)
-fhmv_msht_diff = compute_n3lo_nnlo_diff(fhmv_msht_res, nnlo_central, REL_DIFF)
+fhmruvv_diff = compute_n3lo_nnlo_diff(fhmruvv_res, nnlo_central, REL_DIFF)
+msht_prior_diff = compute_n3lo_nnlo_diff(msht_prior_res, nnlo_central, REL_DIFF)
+msht_post_diff = compute_n3lo_nnlo_diff(msht_post_res, nnlo_central, REL_DIFF)
n3lo_dfs = [
- (eko_diff, "EKO"),
- (fhmv_eko_diff, "FHMV EKO"),
- (msht_diff, "MSHT"),
- (fhmv_msht_diff, "FHMV MSHT")
- # (eko_4mom_res, "aN3LO EKO 4 mom"),
+ (fhmruvv_diff, "FHMRUVV"),
+ (msht_prior_diff, "MSHT (prior)"),
+ (msht_post_diff, "MSHT (posterior)"),
+ (eko_diff, "NNPDF"),
]
-
-# relative, absolute diff plots
plot_diff_to_nnlo(xgrid, n3lo_dfs, SCHEME, USE_LINX, plot_dir, REL_DIFF)
diff --git a/extras/lh_bench_23/plot_trn_exa.py b/extras/lh_bench_23/plot_trn_exa.py
new file mode 100644
index 000000000..7558cedab
--- /dev/null
+++ b/extras/lh_bench_23/plot_trn_exa.py
@@ -0,0 +1,64 @@
+import matplotlib.pyplot as plt
+import numpy as np
+import pandas as pd
+from cfg import table_dir, xgrid
+from utils import HERE, lha_labels
+
+from eko.io.types import EvolutionMethod
+
+plt.style.use(HERE / "plotstyle.mplstyle")
+plot_dir = HERE / "plots_trn_exa"
+
+PTOS = {1: "NLO", 2: "NNLO", 3: "N$^3$LO"}
+
+COLUMNS_TO_KEEP = ["L_m", "L_p", "g"]
+
+
+def load_table(method):
+ """Load tables."""
+ dfs = {}
+ for pto in PTOS:
+ with open(table_dir / f"table_FFNS-{pto}_{method}.csv", encoding="utf-8") as f:
+ dfs[pto] = pd.read_csv(f, index_col=0)
+ return dfs
+
+
+def plot_diff(xgrid, dfs_trn, dfs_exa):
+ cut_smallx = 0
+ cut_largex = -1
+ xgrid = xgrid[cut_smallx:cut_largex]
+
+ plot_dir.mkdir(exist_ok=True)
+
+ # loop on PDFs
+ for column in COLUMNS_TO_KEEP:
+ _, ax = plt.subplots(1, 1, figsize=(1 * 5, 1 * 3.5))
+ j = np.where(dfs_trn[1].columns == column)[0][0]
+
+ # loop on ptos
+ for pto, pto_label in PTOS.items():
+ diff = (dfs_trn[pto] - dfs_exa[pto]) / dfs_trn[pto] * 100
+
+ ax.plot(xgrid, diff.values[cut_smallx:cut_largex, j], label=pto_label)
+ ax.hlines(
+ 0,
+ xgrid.min() - xgrid.min() / 3,
+ 1,
+ linestyles="dotted",
+ color="black",
+ linewidth=0.5,
+ )
+ ax.set_xscale("log")
+ ax.set_xlabel("$x$")
+ ax.set_ylabel(f'${lha_labels("FFNS")[j]}$')
+ ax.set_xlim(xgrid.min() - xgrid.min() / 3, 1)
+
+ plt.legend()
+ plt.tight_layout()
+ plt.savefig(f"{plot_dir}/diff_trn_exa_{column}.pdf")
+
+
+if __name__ == "__main__":
+ dfs_trn = load_table(EvolutionMethod.TRUNCATED.value)
+ dfs_exa = load_table(EvolutionMethod.ITERATE_EXACT.value)
+ plot_diff(xgrid, dfs_trn, dfs_exa)
diff --git a/extras/lh_bench_23/run-n3lo.py b/extras/lh_bench_23/run-n3lo.py
index 4ee00d520..8098f28dc 100644
--- a/extras/lh_bench_23/run-n3lo.py
+++ b/extras/lh_bench_23/run-n3lo.py
@@ -76,7 +76,7 @@
use_fhmruvv=args.use_fhmruvv,
xif=xif,
)
- o = ffns_operator
+ o = ffns_operator()
tab = 14
lab = ffns_labels
rot = ffns_rotate_to_LHA
diff --git a/extras/lh_bench_23/run-nnlo.py b/extras/lh_bench_23/run-nnlo.py
index 85ab2f984..9f5c681cc 100644
--- a/extras/lh_bench_23/run-nnlo.py
+++ b/extras/lh_bench_23/run-nnlo.py
@@ -3,7 +3,6 @@
import pathlib
import sys
-import numpy as np
import pandas as pd
import yaml
from banana import toy
@@ -63,7 +62,7 @@
if args.scheme == "FFNS":
scheme = "FFNS"
t = ffns_theory(xif)
- o = ffns_operator
+ o = ffns_operator()
tab = 14
lab = ffns_labels
rot = ffns_rotate_to_LHA
diff --git a/extras/lh_bench_23/run-trn_exa.py b/extras/lh_bench_23/run-trn_exa.py
new file mode 100644
index 000000000..97d1a1cf5
--- /dev/null
+++ b/extras/lh_bench_23/run-trn_exa.py
@@ -0,0 +1,72 @@
+import logging
+import pathlib
+import sys
+
+import pandas as pd
+from banana import toy
+from cfg import (
+ ffns_labels,
+ ffns_operator,
+ ffns_rotate_to_LHA,
+ ffns_theory,
+ n3lo_theory,
+ table_dir,
+ xgrid,
+)
+
+import eko
+from eko.io.types import EvolutionMethod
+from eko.runner.managed import solve
+from ekobox import apply
+
+stdout_log = logging.StreamHandler(sys.stdout)
+logger = logging.getLogger("eko")
+logger.handlers = []
+logger.setLevel(logging.INFO)
+logger.addHandler(stdout_log)
+
+
+def compute(op_card, th_card):
+ rot = ffns_rotate_to_LHA
+ lab = ffns_labels
+
+ method = op_card.configs.evolution_method.value
+ pto = th_card.order[0] - 1
+ path = pathlib.Path(f"ekos/FFNS-{pto}_{method}.tar")
+ path.unlink(missing_ok=True)
+
+ solve(th_card, op_card, path)
+
+ # apply PDF
+ out = {}
+ with eko.EKO.read(path) as eko_:
+ pdf = apply.apply_pdf_flavor(eko_, toy.mkPDF("ToyLH", 0), xgrid, rot, lab)
+ for lab, f in list(pdf.values())[0]["pdfs"].items():
+ out[lab] = xgrid * f
+
+ # display result
+ pd.set_option("display.float_format", "{:.4e}".format)
+ me = pd.DataFrame(out)
+ print("EKO")
+ print(me)
+ # dump to file
+ table_dir.mkdir(exist_ok=True)
+ me.to_csv(f"{table_dir}/table_FFNS-{pto}_{method}.csv")
+
+
+if __name__ == "__main__":
+ # loop on ev methods
+ for ev_method in [EvolutionMethod.TRUNCATED, EvolutionMethod.ITERATE_EXACT]:
+ op_card = ffns_operator(ev_method=ev_method.value)
+ # loop on pto
+ for pto in [1, 2, 3]:
+ if pto == 3:
+ th_card = n3lo_theory(
+ ad_variation=(0, 0, 0, 0, 0, 0, 0),
+ is_ffns=True,
+ use_fhmruvv=True,
+ xif=1.0,
+ )
+ else:
+ th_card = ffns_theory(xif=1.0, pto=pto)
+ compute(op_card, th_card)
diff --git a/extras/lh_bench_23/run_fhmv.sh b/extras/lh_bench_23/run_fhmruvv.sh
similarity index 76%
rename from extras/lh_bench_23/run_fhmv.sh
rename to extras/lh_bench_23/run_fhmruvv.sh
index 45807ea4d..a9c572ea8 100755
--- a/extras/lh_bench_23/run_fhmv.sh
+++ b/extras/lh_bench_23/run_fhmruvv.sh
@@ -1,12 +1,12 @@
#!/bin/bash
-SCHEME="FFNS"
-SV="central"
+SCHEME="VFNS"
+SV="up"
AD_VAR=(0 0 0 0 0 0 0)
# run the central
-python run-n3lo.py $SCHEME $SV "${AD_VAR[@]}" "--use_fhmv"
+python run-n3lo.py $SCHEME $SV "${AD_VAR[@]}" "--use_fhmruvv"
# loop on gammas
for I in {0..6}
@@ -15,7 +15,7 @@ for I in {0..6}
for VAR in {1..2}
do
AD_VAR[$I]=$VAR
- python run-n3lo.py $SCHEME $SV "${AD_VAR[@]}" "--use_fhmv"
+ python run-n3lo.py $SCHEME $SV "${AD_VAR[@]}" "--use_fhmruvv"
AD_VAR[$I]=0
done
done
diff --git a/extras/lh_bench_23/tables/EKO.zip b/extras/lh_bench_23/tables/EKO.zip
new file mode 100644
index 0000000000000000000000000000000000000000..66a797e7af18ff15c7a337b8d79e08d3594a6acf
GIT binary patch
literal 742394
zcmd431yo(xmZ*(eaDuyQa3{Ds1c%`6?(Q1ggS&fx;O_43?(XtK-M(Gb{i^y_-M`;>
z1!J?%8RIZnYp%JzX=@`R4h-@U;Qb3)YFPP~7yt1C1ON{}P+XcuK^_JGTqMWD;GdVh
z(+2=RkZV8yfM0%7<`)SN01*F0LiU>!*f$B9nv%Ty(sIf))S7R?{);S`WnY8;CQDZf
zS=UfYN9#;dLh%evF-XP>C=v~r6dn`M8Xw;GE)+coC>$T3SB6BS7aDIzNUkFY9#wK=
zbXuH>tWR{Bl5BuRd{}%)TuNU{PlwfE_(J^E`PKzMMjRXh{e%-s@oh}+O^sBUwbmvXjH-8$wItAZjeV`gW6iRh7MF?&9h
zC}e*0Y+P(gACuIrd3A#ne=QcW|8}z%DYZvcY8j>iF6%jxK)?GFqlsl)y-e>gu;22M
z&DZ#Hen!;q+Kt?{Wp;(1MK~eeo-)2>=vECuRl~T}oEDlPu;9_x514fvLEn~!6ea_cixdSl8Xfu!4>JI+S&>Jb_OdAs1U&tWQv(qQOJneP*eAhET`-Qdx
zCcA=96Wj-3s#-B`w%gF_hz6)YAz}jtV@8bC3(4FAK`T+^9PoW9_dk-mTD@D}+k*Z6
zQaZgYGTLvA@7<26HGh9q|B@M2V!oLnGS3iz+&W&H7cgsp9|&&}GOhaF`%u6kJ_NO~
zGQIur_W}H4Xm2k7jD&x+viJ8W|6yfP3=-0sLL!o16ciOTg@mN!{;}5tg^dkF-mdri
ze>1mVr~6x(?>3G1e@^%R5dVuY|5N&3n)d(x?t9k*>2G%5`+LOS>g8?8exs9yH(j*6
zUGMil)X8tc7rT;(H%e!AWm;BW;&4K(%=`Vu30+NE%=6b&j81>CX#q5~=;->zaI{f9^Ef#5^
zn-3`=Y63ydQmEBw0A2RRoPlR@1?%h+0OQOiE8$gai04ILJYvoAj}^6Uc;iL5qE4f@
z*u14REtT+Qc3JAIp6_=KU@KUPE+>roWKr!2k5HQWklA}YrY3mx<%3b6vYR6pyvyk_
zo;G1g;9!-37DY9MxdT_ko2}PWsq~2Z$*x1_GIoooGKE6%ctj=1!2Fg6x%AEYPT3d+
zvIN!87X<*6`N)eybbf#0GN`M2B$7((A>!ou+KR~4C-M)OG?Q!zIZ@tv
zg%JF39Agu^P)4Ja2-c1Maa*eP2?aCc_@ah(Sf{zAaRjBFDa@VG&uH8}geP3kP_t$E
z)y*j*IWBCQe|nz)gaxdK30WCybfq@5~M)O+q`Bm+nAtRLHa
z#Pr-lXO%+|VDjMaiun9h8OQs{^c`T8t?*}DHiC47yxG#nVIsau0$ICb%;a0YGM@Y}
z&5tm6*xOBEs14=BsuaFZ%aTNq+l2ao1P(5?Rq$~dNpSrs%yvVUWD>u2G8@S9Ek69D!>(yqh;O`~h(T$N+3-{c|}l5(X&3%ZE{uE%0a~
z4#^LQNdq-nE)TpAxf|N1DKYnRatOVZNmhY*yvYqfW2(Bl@C%kaF0INwg*r#|tXVR#
z+AQ9RUy!Q9NZ<@S`E!rp-u=S_Of9fK5CFit75~ce-`e;49{nBH_4}s&|9Ee{Gn?>V
zG5l9vRlRZQowo1y|F%JY)x~e+{VRt5C#(J``Twy#-dXiqzbpq10KoNIpY~sTy`8p>
znf|-i|DXz_{mzkL74C#iL99sbj6zkBZAi3tSb#KQ@Np#^T)#qA01Nl(`}hB|PD
z2E4qz-91_*jLmot;+0kOXbJjUUS4iSFTvASTb}!O%XdjvJuhAzxwthR&$sEhD%~v|
zje}1$InroUIwHsszA=h6uB$BO^Vx-}g&__J(<^o9eJkiqyV)&Pl2j^I4iadNsij_y
zVVBimYD|mYj-j6?k~s7zD57+2q8Jp&(YQGJ!E2~7vN|FqyM2O*vKFhF2ny=DQ7K3i
ztkz&`xKpaZyE50{Iyph@+_D16em7rT*z1Zj$do;vrm>mjOi=a{`D>Rh86rjOeCZ@J
z-z`nE6DvOf9oZl!3(*K?slXb^@DVUpTQ*}f-SD@YL>f#cj142dIq*zX3u^iC?SYjk)?*uocPp
zOfka-2)+Hh9X8njLHsR5fJSO51O;BlnjLfiEl$ENDoIhBGNOtnv`0TzCuI7gu%HV+
zZ|75kq_0M~KaoX|_C;AVO^G4D3La<1DMq%_RR63Av{WXN_<40g2s(y&p@398m|Z;d
z@k1Vj;-XYn_L+U+#~JU)UMtf6@mUvX02&eDZpb0ao#CHsk=+@{<7>4fdynz{b(0)r
zVHqBBz^L75cpSa@59=4mPK(m>P5
z{H6y!pB@Hn<{|#ChJ4J?3{JGpC3o?sXz9#_-7Ob4w**>AReNVXsJz}1YR=Gxj=^-9
zJC2?$q~^+;BU@=I!*`=-i`P_HnIDWiPMhMV^iEVN!Q8JKI<4e&t?C10RG%{=GlgD<
z`xwZNl=fDK585%hwDvBLi;YuA<}{ARN1-o2dgXOe6Yr-$5^0PsFC4jk%uiZL-=tC|
zW-}^h;(N7>xMuo{yQCeg9z`>s{=tgvd;iU*F{BM4zeO1QBV&OjZ~Jf}&NfJxqDS1ZYsc(=t}rlHicNdL*HG4bN@sCPu3bo6!&qMeAZ5>
zy^x)5+b+)^-aW%d$9u(Q!N`$Yfm((_ZCXn2=Abil2ByqzBRsN)(e6+k5)AD@*6S3ZHgecjjaKu@bO
zPtWJmhtyG;)|c+x(?i^s*TB}+^ZQG}*(Gzfq&U*v?%fF7;K9?e=nDo}MY=;~*qX+rpin
z#qyA684?~>(P{z&NwjLgqadm21)>p#Hdb*t(o=IXjp*3WmT
z`q)HDKS$jX>Y9A9O>CP88CZyt{alciNlMxm
zPK6@h#l|8N+-EFB7cQa!b}}wSxtTodwcv@D1FmsL3~KRW&}Leb9~qx)Kp_4kmd|%P
zYcI7-yk$=;Vd7@CSd^OtDBUnpnP?cF%>0Fn*6^!l6M6!vv;=#SUGQUDGLdm4!UMHU
ztU^turC;iNg9W}Mv|p1e+WJ7_5U5NB+0^4#LdRpIaTEEHr@I;5kdn<2-=HiL-JO}<
zwI`9#M^sbLVgHXHQ0uvqo6woTta1dp<$TOWNmWNN?wK_FV0MB`$*KZwxg%6o`kgBY
zZXq73GVTi9UBxl3L7wwsb*gS
z9tlGb979$}(DYf-F%@)pw1k%*xq$nrfjXUbx$L3~c~=dhL$IvfKhXE0d+G5KS=CSQ
zf#&1YJ(q+(R|lhPxQXx+{4}EbRI{#evv)Adg2@Q$%|=~(I+qf$hB~y*T+1Zd$ODnB
zMF@V@+oR@%ne(lVd`ROw&KErk%NAuTG>}rF56~yk$g2PTs>AqIY<8vbJm^(x$h`_(B6hzIUDn
zIb*u*%-sA2%Asvp%l8GF%X_s2p4r
zr!3MO=F~X(O{Y%lOWcZN~tlzCY%8xcr`nTxQNgK|9sSN<`
z=KfihqU}Sb>X8I}UrTB=i>mjP=>&7iy+N;MF`>j)I5p@g$!A&}D
zKjq0(JS<046nUJqlLhuALV_H%E^iI>x1XdgPPa&iE3*;H!o&&`i~?Ubf3AACCWkeK
z6y|A~J38kJam9tJQy@9+L*{}d40F5mex~B_d9BH|aidVP5bn8YgYfOWb)4-@n^w|B(?ppueRb}seZ)gxJa*)A
z#{+w{2FEyD+|-|prZ={g5&S*sVP4
zI!f1N9_F~Fwc7AAvjETx@B}bJPBut$>WOKg^$y16yvF{-$Pm3*%@W5Kg4|)hCc*rx
zR8cPEy^o(6P3sgSCD1W=zVGerA_HxFFt6GC8EerRV{j7fit^18q72i(nJo#WHb5dD
zh+&;9`_8O!^fOtQ3$HoaS(wXu{neNYS4kKq1PZpfYs1
zHJJ11#pcpTAh`-?tb_C)mrvlSDuJ=VYWWwDdbykJ5#4tOOp%+Fyo;Z1$+$@Kxl#tf
zn&G)OppZ|6AxogVg+pi&S=AEoL|E6cZ3ErZTgm4H=Ca3FT&f(+Sy#T|)0rC*Nh_xK
zc8GY7dzq#?JLS>`oGIX#UXYiUgesVyGV7AN6VI@gRIU4@(|BY+2NWPDp*W&YlvE{7
zBun}WXz;gkoE#|_FLLR%;N)PG(A+m>T`RnhwfKeO6l>3<=Q9kgkc|Nrnx34(JGNVC
z(0&v?KWm=xcgPd7q#v!hC}U!7Lez%4M|vJtt30K4)QdoiK(w^!QtZKZ<5pfyTea+E
zKWJ0gsjhrE9=V0*7*!s11L2}rb;|gl4~okSyw7}Fpxa4!1lFZzX`y8c_gVp$4Z7zy
z??z>Y#}R7i9&~`~<>qg<-%WmGUVC(go@JoL@6dg@tX<5#+O*z?Ksg2kHg$Axw{v5d
zRB<$2e|>X#{|iQ?3j@{q-Z1(OkN*;pSmz%4Ha4W6PccHhdvotNQ8<&nN
zo*p9#j;6|a$$tLdo}bvQ_pwQvN+$At`-PBwKtTAb=8+ps_1U2oqO
zKylj_Nwq2rT72L{Kun_`SK3civ{|GJJU)dq$ztAqLmoV7v?`DS8vwY&1zPKtVvhhN7-n4tOKVAwN**K;OafBWN=N
z+}+MKF^|&(1_^6TiXm4&W(!r0ByV6pO>pBa&iLo+GuuLnrnE`+&1tv$IR})%Jt(@_
z6uWD~lxNSd;@t1R8ywjQ@eG%?sZH*Bbl%`|6Q_gq9~QcyCEGp>A94Xgs3u!k?kKJN
zc=87QNa544v$O}SJO{Fo&oxTM2;7WysG(>xI;0LPNQD9IbOBl`Lq!NxkYEQU8Aj3_
ziY+wJGD}-=7?flzLM6OJX(mX_mKwH#Vt~3GPtnr3%y@YiL