1"""High-level controller for initializing and switching Hyperiso sessions."""
3from __future__
import annotations
8from importlib
import resources
9from pathlib
import Path
10from typing
import Any, Mapping, Optional, Union
12from pyhyperiso.phyperiso.pyhyperiso.core
import APIPath
as _CppAPIPath
13from pyhyperiso.phyperiso.pyhyperiso.core
import HyperisoMaster
as _CppHyperisoMaster
17PathLike = Union[str, os.PathLike[str]]
21 """Filesystem path keys accepted by ``HyperisoMaster.pre_init_set_paths``.
23 ``LHA_PATH`` is exposed for read-only diagnostics through ``APIAdapter`` but
24 is intentionally rejected by ``pre_init_set_paths`` because the active LHA
25 file is provided through ``init(...)`` or ``switch_lha(...)``.
28 LHA_PATH = _CppAPIPath.LHA_PATH
29 ASSETS_ROOT = _CppAPIPath.ASSETS_ROOT
31 DEFAULT_PARAM_VALUES = _CppAPIPath.DEFAULT_PARAM_VALUES
32 DEFAULT_OBS_VALUES = _CppAPIPath.DEFAULT_OBS_VALUES
33 DEFAULT_PARAM_CORR = _CppAPIPath.DEFAULT_PARAM_CORR
34 DEFAULT_OBS_CORR = _CppAPIPath.DEFAULT_OBS_CORR
35 DEFAULT_NUISANCES = _CppAPIPath.DEFAULT_NUISANCES
37 USER_SM_PARAMS = _CppAPIPath.USER_SM_PARAMS
38 USER_FLAVOR_PARAMS = _CppAPIPath.USER_FLAVOR_PARAMS
39 USER_DECAY_PARAMS = _CppAPIPath.USER_DECAY_PARAMS
40 USER_OBS_VALUES = _CppAPIPath.USER_OBS_VALUES
41 USER_PARAM_CORR = _CppAPIPath.USER_PARAM_CORR
42 USER_OBS_CORR = _CppAPIPath.USER_OBS_CORR
43 USER_NUISANCES = _CppAPIPath.USER_NUISANCES
45 PARAM_MAPPING_DIR = _CppAPIPath.PARAM_MAPPING_DIR
46 TEMPLATE_DIR = _CppAPIPath.TEMPLATE_DIR
47 SPECTRUM_DIR = _CppAPIPath.SPECTRUM_DIR
48 MARTY_TEMP_DIR = _CppAPIPath.MARTY_TEMP_DIR
52 """High-level Python wrapper around the C++ ``HyperisoMaster``.
54 The wrapper configures package-friendly defaults before initialization:
55 read-only assets are looked up under ``pyhyperiso/assets`` when available,
56 and writable caches are placed under the user cache directory unless the
57 caller provides explicit directories.
63 configure_default_paths: bool =
True,
64 assets_root: Optional[PathLike] =
None,
65 cache_root: Optional[PathLike] =
None,
67 """Create an uninitialized Hyperiso controller.
70 configure_default_paths: When ``True``, configure packaged assets
71 and cache directories before any call to ``init``.
72 assets_root: Optional replacement for the packaged read-only
74 cache_root: Optional root used to create ``MartyTemp`` and
75 ``Spectrum`` writable cache directories.
78 self.
config: Optional[HyperisoConfig] =
None
80 if configure_default_paths:
85 """Return ``pyhyperiso/assets`` when it is available as a filesystem path."""
87 assets = resources.files(
"pyhyperiso").joinpath(
"assets")
92 return Path(str(assets)).resolve()
97 """Return the historical source-tree ``Assets`` directory when present."""
99 Path(__file__).resolve().parent /
".." /
".." /
".." /
".." /
".." /
"Assets"
101 return assets
if assets.is_dir()
else None
105 """Return a writable cache root without adding a hard platformdirs dependency."""
106 env_root = os.environ.get(
"HYPERISO_CACHE_ROOT")
108 return Path(env_root).expanduser().resolve()
110 xdg_cache = os.environ.get(
"XDG_CACHE_HOME")
112 return (Path(xdg_cache).expanduser() /
"pyhyperiso").resolve()
114 home = os.environ.get(
"HOME")
116 return (Path(home).expanduser() /
".cache" /
"pyhyperiso").resolve()
118 return (Path(tempfile.gettempdir()) /
"pyhyperiso").resolve()
122 """Convert a Python APIPath-like value to the bound C++ enum value."""
123 cpp_value = getattr(path_key,
"value", path_key)
124 if isinstance(cpp_value, str):
126 return getattr(_CppAPIPath, cpp_value)
127 except AttributeError
as exc:
128 raise ValueError(f
"Unknown APIPath name: {cpp_value}")
from exc
134 assets_root: Optional[PathLike] =
None,
135 cache_root: Optional[PathLike] =
None,
137 """Configure package assets and writable cache directories before init.
140 assets_root: Optional read-only assets directory. When omitted, the
141 wrapper first tries ``pyhyperiso/assets`` and then the historical
142 source-tree ``Assets`` directory.
143 cache_root: Optional writable root. ``MartyTemp`` and ``Spectrum``
144 are created below it. When omitted, a standard user cache root is
148 Path(os.fspath(assets_root)).expanduser().resolve()
149 if assets_root
is not None
153 if resolved_assets
is not None:
156 resolved_cache_root = (
157 Path(os.fspath(cache_root)).expanduser().resolve()
158 if cache_root
is not None
166 """Prepare an LHA path for the C++ layer.
168 Absolute paths are forwarded as absolute paths. Relative paths are kept
169 relative so that the C++ ``MemoryManager`` resolves them under the active
170 ``ASSETS_ROOT``. This is important for wheels where ``Assets`` no longer
171 lives next to the source checkout.
173 path = os.fspath(lha_file)
174 return os.path.abspath(path)
if os.path.isabs(path)
else path
176 def init(self, lha_file: PathLike, config: Optional[HyperisoConfig] =
None) ->
None:
177 """Initialize Hyperiso with an LHA file.
180 lha_file: Absolute LHA path, or path relative to the active
182 config: Optional initialization config. When omitted, the C++
183 default configuration is used and ``self.config`` is set to a
184 default :class:`HyperisoConfig` instance.
187 if config
is not None:
202 global_scale: bool =
False,
204 """Register an additional LHA block prototype before initialization."""
216 """Register an existing MARTY installation before initialization."""
220 """Register a SOFTSUSY executable or installation directory before initialization.
222 ``softsusy_path`` may point directly to ``softpoint.x`` or to a local
223 SOFTSUSY installation/source directory containing one of the usual
224 executable locations: ``softpoint.x``, ``bin/softpoint.x`` or
225 ``src/SOFTSUSY/softpoint.x``.
230 """Override selected Hyperiso filesystem paths before initialization.
233 path_overrides: Mapping from ``APIPath`` keys to replacement paths.
234 Keys may be this wrapper's ``APIPath`` enum, the low-level C++
235 ``APIPath`` enum, another wrapper enum exposing a ``.value``
236 C++ enum, or a string matching an ``APIPath`` name. Values may
237 be strings or ``os.PathLike`` objects.
241 for path_key, path_value
in path_overrides.items()
246 """Set the writable MARTY generated-code/cache directory before init."""
250 """Set the writable spectrum cache directory before init."""
253 def switch_lha(self, lha_file: PathLike, config: Optional[HyperisoConfig] =
None) ->
None:
254 """Switch the active LHA input file."""
256 if config
is not None:
263 "HyperisoMaster.switch_lha() requires a config before init() has been called."
269 """Return whether an external flag is active."""
274 """Return the physics model currently active in C++."""
278 """Return a compact representation including the active model."""
279 return f
"<PyHyperisoMaster model={self.model.name}>"
282__all__ = [
"HyperisoMaster",
"APIPath"]
None configure_default_paths(self, *Optional[PathLike] assets_root=None, Optional[PathLike] cache_root=None)
None pre_init_set_paths(self, Mapping[Any, PathLike] path_overrides)
None pre_init_set_softsusy_path(self, PathLike softsusy_path)
Path _default_cache_root()
Any _to_cpp_api_path(Any path_key)
None pre_init_set_marty_cache_dir(self, PathLike cache_dir)
None pre_init_set_marty_path(self, PathLike marty_path)
None pre_init_set_spectrum_cache_dir(self, PathLike cache_dir)
Optional[Path] _packaged_assets_root()
None __init__(self, *bool configure_default_paths=True, Optional[PathLike] assets_root=None, Optional[PathLike] cache_root=None)
None switch_lha(self, PathLike lha_file, Optional[HyperisoConfig] config=None)
None pre_init_add_block(self, str block_name, int item_count=2, int value_idx=1, int scale_idx=-1, int rg_idx=-1, int bin_idx=-1, bool global_scale=False)
None init(self, PathLike lha_file, Optional[HyperisoConfig] config=None)
Optional[Path] _legacy_source_assets_root()
bool check_flag(self, ExternalFlag flag)
str _resolve_lha_path(PathLike lha_file)