-
Notifications
You must be signed in to change notification settings - Fork 9
read metadata and cards from tar without extracting multi-dim arrays #563
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -69,15 +69,27 @@ def load(cls, path: os.PathLike): | |
| # patch if necessary | ||
| if data_version == 1: | ||
| if version.major == 0 and version.minor == 13: | ||
| raw = v1.update_metadata(paths, raw) | ||
| raw = v1.update_metadata(raw) | ||
| elif version.major == 0 and version.minor == 14: | ||
| raw = v2.update_metadata(paths, raw) | ||
| raw = v2.update_metadata(raw) | ||
|
|
||
| # now we are ready | ||
| content = cls.from_dict(raw) | ||
| content._path = path | ||
| return content | ||
|
|
||
| @classmethod | ||
| def from_raw(cls, raw: dict) -> "Metadata": | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
yeah, seems that the |
||
| """Build metadata from raw yaml, applying legacy patches.""" | ||
| version = parse(raw["version"]) | ||
| data_version = int(raw["data_version"]) | ||
| if data_version == 1: | ||
| if version.major == 0 and version.minor == 13: | ||
| raw = v1.update_metadata(raw) | ||
| elif version.major == 0 and version.minor == 14: | ||
| raw = v2.update_metadata(raw) | ||
| return cls.from_dict(raw) | ||
|
|
||
| def update(self): | ||
| """Update the disk copy of metadata.""" | ||
| if self._path is None: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,12 +4,15 @@ | |
| squared value, for consistency. Squares are consistently taken inside. | ||
| """ | ||
|
|
||
| import pathlib | ||
| import tarfile | ||
| from dataclasses import dataclass | ||
| from math import nan | ||
| from typing import List, Optional, Union | ||
|
|
||
| import numpy as np | ||
| import numpy.typing as npt | ||
| import yaml | ||
|
|
||
| from .. import basis_rotation as br | ||
| from .. import interpolation, msbar_masses | ||
|
|
@@ -19,7 +22,10 @@ | |
| from ..quantities import heavy_quarks as hq | ||
| from ..quantities.couplings import CouplingsInfo | ||
| from ..quantities.heavy_quarks import HeavyInfo, QuarkMassScheme | ||
| from . import v1, v2 | ||
| from .dictlike import DictLike | ||
| from .metadata import Metadata | ||
| from .paths import METADATAFILE, OPERATORFILE, THEORYFILE | ||
| from .types import ( | ||
| EvolutionMethod, | ||
| InversionMethod, | ||
|
|
@@ -78,6 +84,15 @@ def __post_init__(self): | |
| if self.matching_order is None: | ||
| self.matching_order = (self.order[0] - 1, 0) | ||
|
|
||
| @classmethod | ||
| def from_raw(cls, raw: dict, data_version: int) -> "TheoryCard": | ||
| """Build a theory card from a raw dictionary.""" | ||
| if data_version == 1: | ||
| raw = v1.update_theory(raw) | ||
| if data_version == 2: | ||
| raw = v2.update_theory(raw) | ||
| return cls.from_dict(raw) | ||
|
|
||
|
|
||
| @dataclass | ||
| class Debug(DictLike): | ||
|
|
@@ -170,6 +185,15 @@ def pids(self): | |
| """Internal flavor basis, used for computation.""" | ||
| return np.array(br.flavor_basis_pids) | ||
|
|
||
| @classmethod | ||
| def from_raw(cls, raw: dict, data_version: int, theory_raw) -> "OperatorCard": | ||
| """Build an operator card from a raw dictionary.""" | ||
| if data_version == 1: | ||
| raw = v1.update_operator(raw, theory_raw) | ||
| if data_version == 2: | ||
| raw = v2.update_operator(raw, theory_raw) | ||
| return cls.from_dict(raw) | ||
|
|
||
|
|
||
| Card = Union[TheoryCard, OperatorCard] | ||
|
|
||
|
|
@@ -343,3 +367,37 @@ def masses(theory: TheoryCard, evmeth: EvolutionMethod) -> List[SquaredScale]: | |
| return [mq.value**2 for mq in theory.heavy.masses] | ||
|
|
||
| raise ValueError(f"Unknown mass scheme '{theory.heavy.masses_scheme}'") | ||
|
|
||
|
|
||
| def _read_yaml_members(tar, filenames): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the last commit you removed types, e.g. |
||
| """Extract and parse several yaml files in a single pass.""" | ||
| wanted = set(filenames) | ||
| found = {} | ||
| for member in tar.getmembers(): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this "costless". If it is, then this is fine. Otherwise, this function could take a list of filenames so that one can extract all of the files we need in one go. |
||
| name = pathlib.Path(member.name).name | ||
| if name in wanted: | ||
| extracted = tar.extractfile(member) | ||
| if extracted is not None: | ||
| found[name] = yaml.safe_load(extracted.read()) | ||
| missing = wanted - found.keys() | ||
| if missing: | ||
| raise KeyError(f"{missing} not found in {tar.name}") | ||
| return found | ||
|
|
||
|
|
||
| def read_eko_cards(eko_path): | ||
| """Read metadata, theory and operator cards from an EKO archive. | ||
|
|
||
| The (large) operators are never extracted, only the small yaml files. | ||
| """ | ||
| with tarfile.open(eko_path) as tar: | ||
| raw_files = _read_yaml_members(tar, [METADATAFILE, THEORYFILE, OPERATORFILE]) | ||
|
|
||
| raw_meta = raw_files[METADATAFILE] | ||
| raw_theory = raw_files[THEORYFILE] | ||
| raw_operator = raw_files[OPERATORFILE] | ||
| metadata = Metadata.from_raw(raw_meta) | ||
| data_version = metadata.data_version | ||
| operator = OperatorCard.from_raw(raw_operator, data_version, raw_theory) | ||
| theory = TheoryCard.from_raw(raw_theory, data_version) | ||
| return metadata, theory, operator | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -68,6 +68,11 @@ def operator_card(): | |
| return card | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def legacy_eko_filenames(): | ||
| return ["v1-0.13.tar", "v1-0.14.tar", "v3.tar"] | ||
|
Comment on lines
+72
to
+73
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
|
|
||
| class EKOFactory: | ||
| def __init__(self, theory: TheoryCard, operator: OperatorCard, path: os.PathLike): | ||
| self.path = path | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to reuse the new function of course