1"""Python wrapper for Wilson coefficients, including dynamic lambda groups.
3The C++ ``WilsonInterface`` computes builtin Wilson groups and now also accepts
4runtime groups/coefficient ids. This module keeps the old enum-based API working
5while exposing the new ``WGroupId``/``WCoefId`` and custom-lambda workflow.
8from __future__
import annotations
10from typing
import Dict, Mapping, Sequence, Set
12from pyhyperiso.phyperiso.pyhyperiso.wilson.wilson_interface
import (
13 WilsonInterface
as _CppWilsonInterface,
14 CustomWilsonCoefficientConfig
as _CppCustomWilsonCoefficientConfig,
15 CustomWilsonGroupConfig
as _CppCustomWilsonGroupConfig,
35from pyhyperiso.core.Math.Scalar
import Scalar
39 return order.value
if isinstance(order, QCDOrder)
else order
43 return contribution.value
if isinstance(contribution, ContributionType)
else contribution
47 return basis.value
if isinstance(basis, WilsonBasis)
else basis
51 return {p.to_cpp()
if isinstance(p, ParamId)
else p
for p
in sources}
55 """Convert float/complex/Scalar to what the binding can pass as scalar_t."""
56 if isinstance(value, Scalar):
62 """Python view over the C++ ``ParamSrc`` callback object.
64 Users should receive this wrapper in custom Wilson matching callbacks instead
65 of the raw pybind object.
71 def has(self, pid: ParamId) -> bool:
72 """Return whether a parameter is available."""
73 return bool(self.
_cpp_obj.
has(pid.to_cpp()
if isinstance(pid, ParamId)
else pid))
75 def get_val(self, pid: ParamId) -> Scalar:
76 """Return a parameter value as a ``Scalar`` wrapper."""
77 return Scalar.from_cpp(
78 self.
_cpp_obj.
get_val(pid.to_cpp()
if isinstance(pid, ParamId)
else pid)
82 """Return the number of parameters in this view."""
87 """Python view over the C++ ``BlockSrc`` callback object."""
93 """Return whether a block exists in the view."""
96 def get_val(self, block: str, code) -> Scalar:
97 """Return a block value as a ``Scalar`` wrapper."""
98 if hasattr(code,
"to_cpp"):
103 """Return the number of blocks in this view."""
108 """Python wrapper for one lambda-backed Wilson coefficient.
111 coefficient: Dynamic coefficient id, builtin enum, or name/alias.
113 A matching lambda receives a C++ ``ParamSrc`` object. Use
114 ``src.get_val(pid.to_cpp())`` or ``src.get_val(ParameterType.SM.value,
115 "SMINPUTS", 6)`` inside the callback.
119 self.
_cpp_obj = _CppCustomWilsonCoefficientConfig(_cpp_coef_id(coefficient))
124 sources: Sequence[ParamId] | Set[ParamId],
126 contribution: ContributionType = ContributionType.SM,
127 ) ->
"CustomWilsonCoefficientConfig":
128 """Attach a matching lambda for one QCD order.
131 order: QCD order of the matching contribution.
132 sources: Parameter dependencies required by ``compute``.
133 compute: Callable ``compute(src) -> float | complex``.
134 contribution: SM/BSM component represented by this lambda.
137 def wrapped_compute(src):
149 """Return the bound C++ config object."""
154 """Python wrapper for a lambda-backed Wilson group.
157 group: Dynamic group id, builtin enum, or group name/alias.
158 matching_scale: Matching scale in GeV.
159 hadronic_scale: Hadronic/running scale in GeV.
160 order: Maximum QCD order supplied by the group.
161 contribution: Contribution component for the group.
166 group: WilsonGroupLike,
167 matching_scale: float = 81.0,
168 hadronic_scale: float = 4.8,
169 order: QCDOrder = QCDOrder.LO,
170 contribution: ContributionType = ContributionType.SM,
171 display_name: str =
"",
173 self.
_cpp_obj = _CppCustomWilsonGroupConfig(_cpp_group_id(group))
174 self.
_cpp_obj.matching_scale = float(matching_scale)
175 self.
_cpp_obj.hadronic_scale = float(hadronic_scale)
178 self.
_cpp_obj.display_name = display_name
181 self, coefficient: CustomWilsonCoefficientConfig
182 ) ->
"CustomWilsonGroupConfig":
183 """Append a coefficient config to this group."""
184 if isinstance(coefficient, CustomWilsonCoefficientConfig):
185 coefficient = coefficient.to_cpp()
193 sources: Mapping[ParameterType, Sequence[str]],
195 ) ->
"CustomWilsonGroupConfig":
196 """Attach a running lambda for one basis/order.
198 The callable receives ``(matching, block_src)`` and must return a mapping
199 ``{WCoefId_cpp: scalar}``. For simple dev use cases, keep
200 ``install_identity_running_if_empty=True`` and skip this method.
203 (k.value
if isinstance(k, ParameterType)
else k): list(v)
204 for k, v
in dict(sources).items()
207 def wrapped_running(matching, block_src):
209 QCDOrder(o): {
WCoefId(str(k)): Scalar.from_cpp(v)
for k, v
in vals.items()}
210 for o, vals
in matching.items()
214 (k._to_cpp()
if isinstance(k, WCoefId)
else _cpp_coef_id(k)):
_to_cpp_scalar(v)
215 for k, v
in dict(result).items()
225 """Whether C++ installs identity running if no running lambda is given."""
226 return bool(self.
_cpp_obj.install_identity_running_if_empty)
228 @install_identity_running_if_empty.setter
230 """Enable or disable automatic identity running for an empty group."""
231 self.
_cpp_obj.install_identity_running_if_empty = bool(value)
234 """Return the bound C++ config object."""
239 """User-facing wrapper for the C++ Wilson-coefficient interface."""
242 """Create an unbuilt Wilson interface."""
245 def build(self, config: WilsonBuildConfig) ->
None:
246 """Build the C++ Wilson pipeline from a ``WilsonBuildConfig``."""
250 """Add builtin or already-registered dynamic Wilson groups."""
254 """Add a lambda-backed custom Wilson group."""
255 if isinstance(config, CustomWilsonGroupConfig):
256 config = config.to_cpp()
261 """Set the matching scale ``mu_W``."""
265 """Set the hadronic running scale ``mu_h``."""
269 self, req_or_group, coeff=None, order=None, contribution=None, basis=None
271 if isinstance(req_or_group, WilsonRequest):
276 order
or QCDOrder.LO,
277 contribution
or ContributionType.TOTAL,
278 wilson_basis=basis
or WilsonBasis.STANDARD,
281 def get_M(self, req_or_group, coeff=None, order=None, contribution=None) -> Scalar:
282 """Return one matching coefficient at the requested QCD order."""
283 req = self.
_req(req_or_group, coeff, order, contribution)
284 return Scalar.from_cpp(
286 _cpp_group_id(req.group),
287 _cpp_coef_id(req.coefficient),
293 def get_FM(self, req_or_group, coeff=None, order=None, contribution=None) -> Scalar:
294 """Return one full matching coefficient summed up to ``order``."""
295 req = self.
_req(req_or_group, coeff, order, contribution)
296 return Scalar.from_cpp(
298 _cpp_group_id(req.group),
299 _cpp_coef_id(req.coefficient),
306 self, req_or_group, coeff=None, order=None, contribution=None, basis=WilsonBasis.STANDARD
308 """Return one running coefficient at the requested QCD order."""
309 req = self.
_req(req_or_group, coeff, order, contribution, basis)
310 return Scalar.from_cpp(
312 _cpp_group_id(req.group),
313 _cpp_coef_id(req.coefficient),
321 self, req_or_group, coeff=None, order=None, contribution=None, basis=WilsonBasis.STANDARD
323 """Return one full running coefficient summed up to ``order``."""
324 req = self.
_req(req_or_group, coeff, order, contribution, basis)
325 return Scalar.from_cpp(
327 _cpp_group_id(req.group),
328 _cpp_coef_id(req.coefficient),
336 self, group: WilsonGroupLike, coeff: WilsonCoefLike, contribution: ContributionType
337 ) -> Dict[QCDOrder, Scalar]:
338 """Return matching coefficients separated by QCD order."""
339 cpp_map = self.
_cpp_obj.get_sep_order_matching_coefficient(
342 return {
QCDOrder(order): Scalar.from_cpp(val)
for order, val
in cpp_map.items()}
346 group: WilsonGroupLike,
347 coeff: WilsonCoefLike,
348 contribution: ContributionType,
349 basis: WilsonBasis = WilsonBasis.STANDARD,
350 ) -> Dict[QCDOrder, Scalar]:
351 """Return running coefficients separated by QCD order."""
352 cpp_map = self.
_cpp_obj.get_sep_order_run_coefficient(
353 _cpp_group_id(group),
358 return {
QCDOrder(order): Scalar.from_cpp(val)
for order, val
in cpp_map.items()}
362 self, group: WGroup, order: QCDOrder, contribution: ContributionType
363 ) -> Dict[WCoeff, Scalar]:
364 """Return all builtin matching coefficients in one static group."""
365 cpp_map = self.
_cpp_obj.get_all_matching_coefficient(
366 group.value, order.value, contribution.value
368 return {
WCoeff(k): Scalar.from_cpp(v)
for k, v
in cpp_map.items()}
374 contribution: ContributionType,
375 basis: WilsonBasis = WilsonBasis.STANDARD,
376 ) -> Dict[WCoeff, Scalar]:
377 """Return all builtin running coefficients in one static group."""
378 cpp_map = self.
_cpp_obj.get_all_run_coefficient(
379 group.value, order.value, contribution.value, basis.value
381 return {
WCoeff(k): Scalar.from_cpp(v)
for k, v
in cpp_map.items()}
386 "CustomWilsonCoefficientConfig",
387 "CustomWilsonGroupConfig",
bool has_block(self, str block)
Scalar get_val(self, str block, code)
"CustomWilsonCoefficientConfig" set_matching(self, QCDOrder order, Sequence[ParamId]|Set[ParamId] sources, compute, ContributionType contribution=ContributionType.SM)
__init__(self, WilsonCoefLike coefficient)
__init__(self, WilsonGroupLike group, float matching_scale=81.0, float hadronic_scale=4.8, QCDOrder order=QCDOrder.LO, ContributionType contribution=ContributionType.SM, str display_name="")
"CustomWilsonGroupConfig" add_coefficient(self, CustomWilsonCoefficientConfig coefficient)
bool install_identity_running_if_empty(self)
"CustomWilsonGroupConfig" set_running(self, WilsonBasis basis, QCDOrder order, Mapping[ParameterType, Sequence[str]] sources, compute)
bool has(self, ParamId pid)
Scalar get_val(self, ParamId pid)
None set_matching_scale(self, float mu_W)
Scalar get_FR(self, req_or_group, coeff=None, order=None, contribution=None, basis=WilsonBasis.STANDARD)
Scalar get_FM(self, req_or_group, coeff=None, order=None, contribution=None)
None add_wilson_group(self, WilsonBuildConfig config)
Dict[QCDOrder, Scalar] get_sep_order_running(self, WilsonGroupLike group, WilsonCoefLike coeff, ContributionType contribution, WilsonBasis basis=WilsonBasis.STANDARD)
None build(self, WilsonBuildConfig config)
Dict[QCDOrder, Scalar] get_sep_order_matching(self, WilsonGroupLike group, WilsonCoefLike coeff, ContributionType contribution)
WilsonRequest _req(self, req_or_group, coeff=None, order=None, contribution=None, basis=None)
Scalar get_R(self, req_or_group, coeff=None, order=None, contribution=None, basis=WilsonBasis.STANDARD)
Dict[WCoeff, Scalar] get_all_running(self, WGroup group, QCDOrder order, ContributionType contribution, WilsonBasis basis=WilsonBasis.STANDARD)
Dict[WCoeff, Scalar] get_all_matching(self, WGroup group, QCDOrder order, ContributionType contribution)
"WilsonInterface" add_custom_group(self, CustomWilsonGroupConfig config)
None set_hadronic_scale(self, float mu_h)
Scalar get_M(self, req_or_group, coeff=None, order=None, contribution=None)
_cpp_contribution(ContributionType contribution)
_cpp_basis(WilsonBasis basis)
_cpp_order(QCDOrder order)
_cpp_sources(Sequence[ParamId]|Set[ParamId] sources)