Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
Mapper.py
Go to the documentation of this file.
1"""Python wrappers around C++ enum/name mappers.
2
3The C++ core exposes a family of mapper classes that convert between enum
4values, canonical names, and sometimes domain-specific identifiers. This module
5keeps those conversions available from Python while returning Python wrapper
6objects where appropriate, for example :class:`ObservableId` and
7:class:`LhaID`.
8"""
9
10from typing import AnyStr, Optional, Sequence, Union
11
12from pyhyperiso.phyperiso.pyhyperiso.common import (
13 ContributionTypeMapper as _CppContributionTypeMapper,
14)
15from pyhyperiso.phyperiso.pyhyperiso.common import DecayMapper as _CppDecayMapper
16from pyhyperiso.phyperiso.pyhyperiso.common import CustomObservableSpec as _CppCustomObservableSpec
17from pyhyperiso.phyperiso.pyhyperiso.common import _CppDecayId
18from pyhyperiso.phyperiso.pyhyperiso.common import GroupMapper as _CppGroupMapper
19from pyhyperiso.phyperiso.pyhyperiso.common import MassTypeMapper as _CppMassTypeMapper
20from pyhyperiso.phyperiso.pyhyperiso.common import ModelMapper as _CppModelMapper
21from pyhyperiso.phyperiso.pyhyperiso.common import ObservableMapper as _CppObservableMapper
22from pyhyperiso.phyperiso.pyhyperiso.common import OrderMapper as _CppOrderMapper
23from pyhyperiso.phyperiso.pyhyperiso.common import ParameterTypeMapper as _CppParameterTypeMapper
24from pyhyperiso.phyperiso.pyhyperiso.common import ScaleTypeMapper as _CppScaleTypeMapper
25from pyhyperiso.phyperiso.pyhyperiso.common import WCoefMapper as _CppWCoefMapper
26from pyhyperiso.phyperiso.pyhyperiso.common import WilsonBasisMapper as _CppWilsonBasisMapper
27
29 ContributionType,
30 Decays,
31 MassType,
32 Model,
33 Observables,
34 ParameterType,
35 QCDOrder,
36 ScaleType,
37 WCoeff,
38 WGroup,
39 WilsonBasis,
40)
41from pyhyperiso.core.Common.LhaID import LhaID
42
43try:
45 ObservableId,
46 DecayId,
47 WGroupId,
48 WCoefId,
49 _unwrap_optional,
50 )
51except ImportError:
52 from pyhyperiso.core.Common.SymbolId import ObservableId, WGroupId, WCoefId, _unwrap_optional
53
54 class DecayId:
55 """Python fallback wrapper around the bound C++ ``DecayId`` type.
56
57 Add the same class to ``pyhyperiso.core.Common.SymbolId`` if you prefer
58 keeping all symbol-id wrappers in one module.
59 """
60
61 def __init__(self, value: Union[str, "_CppDecayId"]):
62 if isinstance(value, _CppDecayId):
63 self._cpp_obj = value
64 else:
65 self._cpp_obj = _CppDecayId(str(value))
66
67 @property
68 def name(self) -> str:
69 """Return the canonical string stored by the C++ id."""
70 return str(self._cpp_obj)
71
72 def _to_cpp(self):
73 """Return the bound C++ object."""
74 return self._cpp_obj
75
76 def __str__(self) -> str:
77 return self.name
78
79 def __repr__(self) -> str:
80 return f"DecayId({self.name!r})"
81
82 def __eq__(self, other) -> bool:
83 if isinstance(other, DecayId):
84 return self.name.lower() == other.name.lower()
85 if isinstance(other, str):
86 return self.name.lower() == other.lower()
87 return False
88
89 def __hash__(self) -> int:
90 return hash(self.name.lower())
91
92
93def _cpp_lhaid_or_none(ext: Optional[LhaID]):
94 """Return the C++ ``LhaID`` object or ``None`` for optional mapper APIs."""
95 if ext is None:
96 return None
97 if isinstance(ext, LhaID):
98 return ext._cpp_obj
99 return ext
100
101
102def _wrap_observable_id(cpp_id) -> ObservableId:
103 """Wrap a bound C++ ``ObservableId`` as a Python ``ObservableId``."""
104 return ObservableId(str(cpp_id))
105
106
107def _wrap_decay_id(cpp_id) -> DecayId:
108 """Wrap a bound C++ ``DecayId`` as a Python ``DecayId``."""
109 return DecayId(str(cpp_id))
110
111
112def _wrap_wgroup_id(cpp_id) -> WGroupId:
113 """Wrap a bound C++ ``WGroupId`` as a Python ``WGroupId``."""
114 return WGroupId(str(cpp_id))
115
116
117def _wrap_wcoef_id(cpp_id) -> WCoefId:
118 """Wrap a bound C++ ``WCoefId`` as a Python ``WCoefId``."""
119 return WCoefId(str(cpp_id))
120
121
122def _unwrap_optional_or_none(cpp_optional, label: str):
123 """Return the value stored in a pybind optional, or ``None`` if empty."""
124 if cpp_optional is None:
125 return None
126 try:
127 return _unwrap_optional(cpp_optional, label)
128 except KeyError:
129 return None
130
131
133 """Python value object describing a custom observable registration.
134
135 Args:
136 canonical: Canonical observable name to register.
137 aliases: Optional aliases.
138 ext: Optional FLHA id.
139 """
140
142 self,
143 canonical: str,
144 aliases: Optional[Sequence[str]] = None,
145 ext: Optional[LhaID] = None,
146 ):
147 self.canonical = canonical
148 self.aliases = list(aliases or [])
149 self.ext = ext
150
151 def _to_cpp(self):
152 """Convert this spec to the bound C++ ``CustomObservableSpec``."""
153 return _CppCustomObservableSpec(
154 self.canonical,
155 self.aliases,
157 )
158
159 @classmethod
160 def from_any(cls, value: Union["CustomObservableSpec", dict, tuple]):
161 """Build a spec from a spec object, dict, or tuple.
162
163 Accepted tuple shapes are ``(canonical,)``, ``(canonical, aliases)``,
164 and ``(canonical, aliases, ext)``.
165 """
166 if isinstance(value, cls):
167 return value
168
169 if isinstance(value, dict):
170 return cls(
171 value["canonical"],
172 value.get("aliases"),
173 value.get("ext"),
174 )
175
176 if isinstance(value, tuple):
177 if len(value) == 1:
178 return cls(value[0])
179 if len(value) == 2:
180 return cls(value[0], value[1])
181 if len(value) == 3:
182 return cls(value[0], value[1], value[2])
183
184 raise TypeError(
185 "Custom observable spec must be CustomObservableSpec, dict, "
186 "or tuple(canonical[, aliases[, ext]])"
187 )
188
189
191 """Mapper for :class:`QCDOrder` values."""
192
193 def __init__(self):
194 pass
195
196 def str(self, obs_id: QCDOrder):
197 """Return the canonical C++ string for a QCD order.
198
199 Args:
200 obs_id: Python ``QCDOrder`` enum value.
201
202 Returns:
203 str: Canonical name stored by the C++ mapper.
204 """
205 return _CppOrderMapper.str(obs_id.value)
206
207 def id_of(self, obs_id: QCDOrder):
208 """Round-trip a QCD order through its canonical string.
209
210 Args:
211 obs_id: Python ``QCDOrder`` enum value.
212
213 Returns:
214 Any: Bound C++ enum/id returned by the mapper.
215 """
216 return _CppOrderMapper.id_of(self.str(obs_id))
217
218 def get_str(self):
219 """Return the C++ mapper's primary string table."""
220 return _CppOrderMapper.get_str()
221
222 def get_str_all(self):
223 """Return all string aliases known to the C++ mapper."""
224 return _CppOrderMapper.get_str_all()
225
226 def get_enum(self):
227 """Return enum values known to the C++ mapper."""
228 return [x for x in _CppOrderMapper.get_enum()]
229
230
232 """Mapper for :class:`ParameterType` namespaces."""
233
234 def __init__(self):
235 pass
236
237 def str(self, obs_id: ParameterType):
238 """Return the canonical string for a parameter namespace."""
239 return _CppParameterTypeMapper.str(obs_id.value)
240
241 def id_of(self, obs_id: ParameterType):
242 """Return the C++ id associated with a parameter namespace."""
243 return _CppParameterTypeMapper.id_of(self.str(obs_id))
244
245 def get_str(self):
246 """Return the C++ mapper's primary string table."""
247 return _CppParameterTypeMapper.get_str()
248
249 def get_str_all(self):
250 """Return all string aliases known to the C++ mapper."""
251 return _CppParameterTypeMapper.get_str_all()
252
253 def get_enum(self):
254 """Return enum values known to the C++ mapper."""
255 return [x for x in _CppParameterTypeMapper.get_enum()]
256
257
259 """Mapper for physics :class:`Model` values."""
260
261 def __init__(self):
262 pass
263
264 def str(self, obs_id: Model):
265 """Return the canonical model name."""
266 return _CppModelMapper.str(obs_id.value)
267
268 def id_of(self, obs_id: Model):
269 """Return the C++ id associated with a model."""
270 return _CppModelMapper.id_of(self.str(obs_id))
271
272 def get_str(self):
273 """Return the C++ mapper's primary string table."""
274 return _CppModelMapper.get_str()
275
276 def get_str_all(self):
277 """Return all string aliases known to the C++ mapper."""
278 return _CppModelMapper.get_str_all()
279
280 def get_enum(self):
281 """Return enum values known to the C++ mapper."""
282 return [x for x in _CppModelMapper.get_enum()]
283
284
286 """Mapper for Wilson-coefficient basis conventions."""
287
288 def __init__(self):
289 pass
290
291 def str(self, obs_id: WilsonBasis):
292 """Return the canonical string for a Wilson basis."""
293 return _CppWilsonBasisMapper.str(obs_id.value)
294
295 def id_of(self, obs_id: WilsonBasis):
296 """Return the C++ id associated with a Wilson basis."""
297 return _CppWilsonBasisMapper.id_of(self.str(obs_id))
298
299 def get_str(self):
300 """Return the C++ mapper's primary string table."""
301 return _CppWilsonBasisMapper.get_str()
302
303 def get_str_all(self):
304 """Return all string aliases known to the C++ mapper."""
305 return _CppWilsonBasisMapper.get_str_all()
306
307 def get_enum(self):
308 """Return enum values known to the C++ mapper."""
309 return [x for x in _CppWilsonBasisMapper.get_enum()]
310
311
313 """Mapper for Wilson-coefficient contribution components.
314
315 Contribution types typically distinguish SM-only, BSM-only, and total
316 coefficients in the Wilson pipeline.
317 """
318
319 def __init__(self):
320 pass
321
322 def str(self, obs_id: ContributionType):
323 """Return the canonical contribution-type string."""
324 return _CppContributionTypeMapper.str(obs_id.value)
325
326 def id_of(self, obs_id: ContributionType):
327 """Return the C++ id associated with a contribution type."""
328 return _CppContributionTypeMapper.id_of(self.str(obs_id))
329
330 def get_str(self):
331 """Return the C++ mapper's primary string table."""
332 return _CppContributionTypeMapper.get_str()
333
334 def get_str_all(self):
335 """Return all string aliases known to the C++ mapper."""
336 return _CppContributionTypeMapper.get_str_all()
337
338 def get_enum(self):
339 """Return enum values known to the C++ mapper."""
340 return [x for x in _CppContributionTypeMapper.get_enum()]
341
342
344 """Mapper for QCD mass conventions."""
345
346 def __init__(self):
347 pass
348
349 def str(self, obs_id: MassType):
350 """Return the canonical mass-type string."""
351 return _CppMassTypeMapper.str(obs_id.value)
352
353 def id_of(self, obs_id: MassType):
354 """Return the C++ id associated with a mass convention."""
355 return _CppMassTypeMapper.id_of(self.str(obs_id))
356
357 def get_str(self):
358 """Return the C++ mapper's primary string table."""
359 return _CppMassTypeMapper.get_str()
360
361 def get_str_all(self):
362 """Return all string aliases known to the C++ mapper."""
363 return _CppMassTypeMapper.get_str_all()
364
365 def get_enum(self):
366 """Return enum values known to the C++ mapper."""
367 return [x for x in _CppMassTypeMapper.get_enum()]
368
369
371 """Mapper for scale categories, such as matching and hadronic scales."""
372
373 def __init__(self):
374 pass
375
376 def str(self, obs_id: ScaleType):
377 """Return the canonical scale-type string."""
378 return _CppScaleTypeMapper.str(obs_id.value)
379
380 def id_of(self, obs_id: ScaleType):
381 """Return the C++ id associated with a scale category."""
382 return _CppScaleTypeMapper.id_of(self.str(obs_id))
383
384 def get_str(self):
385 """Return the C++ mapper's primary string table."""
386 return _CppScaleTypeMapper.get_str()
387
388 def get_str_all(self):
389 """Return all string aliases known to the C++ mapper."""
390 return _CppScaleTypeMapper.get_str_all()
391
392 def get_enum(self):
393 """Return enum values known to the C++ mapper."""
394 return [x for x in _CppScaleTypeMapper.get_enum()]
395
396
398 """Mapper for Wilson-coefficient groups.
399
400 The wrapper accepts both legacy :class:`WGroup` enums and runtime strings.
401 String lookups return :class:`WGroupId`, which is the preferred API for
402 custom groups and config/CLI driven workflows.
403 """
404
405 def __init__(self):
406 pass
407
408 @staticmethod
409 def str(group) -> str:
410 """Return the canonical string for a Wilson group enum or dynamic id."""
411 if isinstance(group, WGroup):
412 return _CppGroupMapper.str(group.value)
413 if isinstance(group, WGroupId):
414 return _CppGroupMapper.canonical(group._to_cpp())
415 raise TypeError("str() expects WGroup or WGroupId")
416
417 @staticmethod
418 def id_of(group) -> WGroupId:
419 """Resolve a group enum/name/alias to a dynamic :class:`WGroupId`."""
420 if isinstance(group, WGroupId):
421 return group
422 if isinstance(group, WGroup):
423 return _wrap_wgroup_id(_CppGroupMapper.to_id(group.value))
424 return _wrap_wgroup_id(_CppGroupMapper.id_of(str(group)))
425
426 @staticmethod
427 def to_id(group: WGroup) -> WGroupId:
428 """Convert a builtin Wilson-group enum to :class:`WGroupId`."""
429 return _wrap_wgroup_id(_CppGroupMapper.to_id(group.value))
430
431 @staticmethod
432 def canonical(group_id: WGroupId) -> str:
433 """Return the canonical name of a dynamic Wilson group id."""
434 return _CppGroupMapper.canonical(group_id._to_cpp())
435
436 @staticmethod
437 def block_name(group, scale: ScaleType, basis: WilsonBasis = WilsonBasis.STANDARD) -> str:
438 """Return the scale/basis block name used by Wilson parameter blocks."""
439 if isinstance(group, WGroup):
440 return _CppGroupMapper.str(group.value, scale.value, basis.value)
441 group_id = GroupMapper.id_of(group)
442 return _CppGroupMapper.str_id(group_id._to_cpp(), scale.value, basis.value)
443
444 @staticmethod
445 def register_custom(canonical: str, aliases=None, external: Optional[str] = None) -> bool:
446 """Register a custom Wilson group in the dynamic mapper.
447
448 Args:
449 canonical: Canonical group name.
450 aliases: Optional aliases accepted by :meth:`id_of`.
451 external: Optional external key used by C++ mapper extensions.
452 """
453 return _CppGroupMapper.register_custom(canonical, list(aliases or []), external)
454
455 def get_str(self):
456 """Return the C++ mapper's primary string table."""
457 return _CppGroupMapper.get_str()
458
459 def get_str_all(self):
460 """Return all string aliases known to the C++ mapper."""
461 return _CppGroupMapper.get_str_all()
462
463 def get_enum(self):
464 """Return builtin enum values known to the C++ mapper."""
465 return [WGroup(x) for x in _CppGroupMapper.get_enum()]
466
467
469 """Mapper for Wilson-coefficient identifiers.
470
471 Runtime lookups return :class:`WCoefId`, so custom coefficients do not need
472 a corresponding static :class:`WCoeff` enum value.
473 """
474
475 def __init__(self):
476 pass
477
478 @staticmethod
479 def str(coef) -> str:
480 """Return the canonical string for a Wilson coefficient."""
481 if isinstance(coef, WCoeff):
482 return _CppWCoefMapper.str(coef.value)
483 if isinstance(coef, WCoefId):
484 return _CppWCoefMapper.canonical(coef._to_cpp())
485 raise TypeError("str() expects WCoeff or WCoefId")
486
487 @staticmethod
488 def id_of(coef) -> WCoefId:
489 """Resolve a coefficient enum/name/alias to :class:`WCoefId`."""
490 if isinstance(coef, WCoefId):
491 return coef
492 if isinstance(coef, WCoeff):
493 return _wrap_wcoef_id(_CppWCoefMapper.to_id(coef.value))
494 return _wrap_wcoef_id(_CppWCoefMapper.id_of(str(coef)))
495
496 @staticmethod
497 def to_id(coef: WCoeff) -> WCoefId:
498 """Convert a builtin coefficient enum to :class:`WCoefId`."""
499 return _wrap_wcoef_id(_CppWCoefMapper.to_id(coef.value))
500
501 @staticmethod
502 def canonical(coef_id: WCoefId) -> str:
503 """Return the canonical name of a dynamic coefficient id."""
504 return _CppWCoefMapper.canonical(coef_id._to_cpp())
505
506 @staticmethod
507 def register_custom(canonical: str, aliases=None, flha=(0, 0)) -> bool:
508 """Register a custom Wilson coefficient.
509
510 Args:
511 canonical: Canonical coefficient name.
512 aliases: Optional aliases accepted by :meth:`id_of`.
513 flha: External FLHA pair used by Wilson input/output conventions.
514 """
515 return _CppWCoefMapper.register_custom(canonical, list(aliases or []), tuple(flha))
516
517 @staticmethod
518 def flha_base(coef) -> tuple[int, int]:
519 """Return the external FLHA base pair for a coefficient enum or id."""
520 if isinstance(coef, WCoeff):
521 return tuple(_CppWCoefMapper.flha_base(coef.value))
522 coef_id = WCoefMapper.id_of(coef)
523 return tuple(_CppWCoefMapper.flha_base(coef_id._to_cpp()))
524
525 @staticmethod
526 def flha_full(coef, order: QCDOrder, contribution: ContributionType) -> LhaID:
527 """Return the full FLHA identifier for a Wilson coefficient term."""
528 if not isinstance(order, QCDOrder):
529 raise TypeError("order must be a QCDOrder")
530 if not isinstance(contribution, ContributionType):
531 raise TypeError("contribution must be a ContributionType")
532 if isinstance(coef, WCoeff):
533 cpp_id = _CppWCoefMapper.flha_full(coef.value, order.value, contribution.value)
534 else:
535 coef_id = WCoefMapper.id_of(coef)
536 cpp_id = _CppWCoefMapper.flha_full(coef_id._to_cpp(), order.value, contribution.value)
537 return LhaID(cpp_id)
538
539 def get_str(self):
540 """Return the C++ mapper's primary string table."""
541 return _CppWCoefMapper.get_str()
542
543 def get_str_all(self):
544 """Return all string aliases known to the C++ mapper."""
545 return _CppWCoefMapper.get_str_all()
546
547 def get_enum(self):
548 """Return builtin enum values known to the C++ mapper."""
549 return [WCoeff(x) for x in _CppWCoefMapper.get_enum()]
550
551
553 """Mapper for builtin and custom observables.
554
555 Dynamic/user-facing code should use :class:`ObservableId`; the static
556 :class:`Observables` enum is kept for builtin legacy paths only.
557 """
558
559 def __init__(self):
560 pass
561
562 @staticmethod
563 def str(obs: Observables) -> str:
564 """Return the canonical C++ name for a builtin observable enum."""
565 return _CppObservableMapper.str(obs.value)
566
567 @staticmethod
568 def enum_elt_legacy(name: AnyStr) -> Observables:
569 """Resolve a builtin observable name to the static enum.
570
571 Custom observables cannot be represented by :class:`Observables`; use
572 :meth:`id_of` for dynamic lookup.
573 """
574 return Observables(_CppObservableMapper.enum_elt_legacy(name))
575
576 @staticmethod
577 def id_of(name: AnyStr) -> ObservableId:
578 """Resolve a canonical name or alias to an :class:`ObservableId`."""
579 return _wrap_observable_id(_CppObservableMapper.id_of(name))
580
581 @staticmethod
582 def to_id(obs: Observables) -> ObservableId:
583 """Convert a builtin observable enum to an :class:`ObservableId`."""
584 return _wrap_observable_id(_CppObservableMapper.to_id(obs.value))
585
586 @staticmethod
587 def canonical(obs_id: ObservableId) -> str:
588 """Return the canonical name of an internal observable id."""
589 return _CppObservableMapper.canonical(obs_id._to_cpp())
590
591 @staticmethod
592 def get_str():
593 """Return builtin observable names."""
594 return _CppObservableMapper.get_str()
595
596 @staticmethod
598 """Return builtin and custom observable names."""
599 return _CppObservableMapper.get_str_all()
600
601 @staticmethod
602 def get_enum():
603 """Return builtin observable enum values known to the mapper."""
604 return [Observables(x) for x in _CppObservableMapper.get_enum()]
605
606 @staticmethod
607 def from_flha(flha_id: LhaID) -> ObservableId:
608 """Convert an FLHA code to an observable id.
609
610 Raises:
611 KeyError: If no observable is associated with the FLHA code.
612 """
613 cpp_opt = _CppObservableMapper.from_flha(flha_id._cpp_obj)
614 cpp_id = _unwrap_optional(cpp_opt, "ObservableId from FLHA")
615 return _wrap_observable_id(cpp_id)
616
617 @staticmethod
618 def flha(obs) -> LhaID:
619 """Return the FLHA code associated with an observable.
620
621 Args:
622 obs: Either a builtin :class:`Observables` or an
623 :class:`ObservableId`.
624 """
625 if isinstance(obs, Observables):
626 return LhaID(_CppObservableMapper.flha(obs.value))
627 if isinstance(obs, ObservableId):
628 return LhaID(_CppObservableMapper.flha(obs._to_cpp()))
629 raise TypeError("flha() expects Observables or ObservableId")
630
631 @staticmethod
633 canonical: str,
634 parent_decay: Union[str, Decays, DecayId],
635 aliases: Optional[Sequence[str]] = None,
636 ext: Optional[LhaID] = None,
637 ) -> bool:
638 """Register a custom observable and attach it to a parent decay.
639
640 Args:
641 canonical: Canonical observable name.
642 parent_decay: Parent decay as name/alias, :class:`Decays`, or
643 :class:`DecayId`.
644 aliases: Optional observable aliases.
645 ext: Optional FLHA id.
646
647 Returns:
648 bool: ``True`` if the C++ registry accepted the symbol.
649 """
650 aliases = list(aliases or [])
651 cpp_ext = _cpp_lhaid_or_none(ext)
652
653 if isinstance(parent_decay, Decays):
654 return _CppObservableMapper.register_custom_with_decay_enum(
655 canonical,
656 parent_decay.value,
657 aliases,
658 cpp_ext,
659 )
660
661 if isinstance(parent_decay, DecayId):
662 return _CppObservableMapper.register_custom_with_decay_id(
663 canonical,
664 parent_decay._to_cpp(),
665 aliases,
666 cpp_ext,
667 )
668
669 return _CppObservableMapper.register_custom(
670 canonical,
671 str(parent_decay),
672 aliases,
673 cpp_ext,
674 )
675
676
678 """Mapper for builtin and custom decays."""
679
680 def __init__(self):
681 pass
682
683 @staticmethod
684 def str(decay: Union[Decays, DecayId]) -> str:
685 """Return the canonical string for a builtin enum or dynamic id."""
686 if isinstance(decay, Decays):
687 return _CppDecayMapper.str(decay.value)
688 if isinstance(decay, DecayId):
689 return _CppDecayMapper.canonical(decay._to_cpp())
690 raise TypeError("str() expects Decays or DecayId")
691
692 @staticmethod
693 def enum_elt_legacy(name: AnyStr) -> Decays:
694 """Resolve a builtin decay name to the static enum."""
695 return Decays(_CppDecayMapper.enum_elt_legacy(name))
696
697 @staticmethod
698 def id_of(decay: Union[AnyStr, Decays]) -> DecayId:
699 """Resolve a decay name/alias or enum to :class:`DecayId`."""
700 if isinstance(decay, Decays):
701 return DecayMapper.to_id(decay)
702 return _wrap_decay_id(_CppDecayMapper.id_of(decay))
703
704 @staticmethod
705 def to_id(decay: Decays) -> DecayId:
706 """Convert a builtin decay enum to a dynamic :class:`DecayId`."""
707 return _wrap_decay_id(_CppDecayMapper.to_id(decay.value))
708
709 @staticmethod
710 def canonical(decay_id: DecayId) -> str:
711 """Return the canonical name of a dynamic decay id."""
712 return _CppDecayMapper.canonical(decay_id._to_cpp())
713
714 @staticmethod
715 def get_str():
716 """Return builtin decay names."""
717 return _CppDecayMapper.get_str()
718
719 @staticmethod
721 """Return builtin and custom decay names."""
722 return _CppDecayMapper.get_str_all()
723
724 @staticmethod
725 def get_enum():
726 """Return builtin decay enum values."""
727 return [Decays(x) for x in _CppDecayMapper.get_enum()]
728
729 @staticmethod
730 def get_observables(decay: Union[Decays, DecayId, str]):
731 """Return observables attached to a decay.
732
733 Returns:
734 list[Observables] for builtin :class:`Decays` input, and
735 list[ObservableId] for :class:`DecayId` or string input.
736 """
737 if isinstance(decay, Decays):
738 return [Observables(o) for o in _CppDecayMapper.get_observables(decay.value)]
739
740 if isinstance(decay, DecayId):
741 return [
742 _wrap_observable_id(o) for o in _CppDecayMapper.get_observables(decay._to_cpp())
743 ]
744
745 return [_wrap_observable_id(o) for o in _CppDecayMapper.get_observables_by_name(str(decay))]
746
747 @staticmethod
748 def get_observable_ids(decay: Decays):
749 """Return builtin decay observables converted to :class:`ObservableId`."""
750 return [_wrap_observable_id(o) for o in _CppDecayMapper.get_observable_ids(decay.value)]
751
752 @staticmethod
753 def get_decay(obs: Observables) -> Decays:
754 """Return the builtin decay enum associated with a builtin observable."""
755 return Decays(_CppDecayMapper.get_decay(obs.value))
756
757 @staticmethod
758 def get_decay_id(obs: Union[Observables, ObservableId]) -> Optional[DecayId]:
759 """Return the dynamic parent decay id of an observable, if known."""
760 if isinstance(obs, Observables):
761 cpp_opt = _CppDecayMapper.get_decay_id(obs.value)
762 elif isinstance(obs, ObservableId):
763 cpp_opt = _CppDecayMapper.get_decay_id(obs._to_cpp())
764 else:
765 raise TypeError("get_decay_id() expects Observables or ObservableId")
766
767 cpp_id = _unwrap_optional_or_none(cpp_opt, "DecayId")
768 if cpp_id is None:
769 return None
770 return _wrap_decay_id(cpp_id)
771
772 @staticmethod
773 def get_decay_id_or_throw(obs: ObservableId) -> DecayId:
774 """Return the dynamic parent decay id or raise from C++ if absent."""
775 return _wrap_decay_id(_CppDecayMapper.get_decay_id_or_throw(obs._to_cpp()))
776
777 @staticmethod
778 def has_observables(decay: Union[Decays, DecayId, str]) -> bool:
779 """Return whether a decay has at least one observable."""
780 if isinstance(decay, Decays):
781 decay = DecayMapper.to_id(decay)
782 elif isinstance(decay, str):
783 decay = DecayMapper.id_of(decay)
784 if not isinstance(decay, DecayId):
785 raise TypeError("has_observables() expects Decays, DecayId, or str")
786 return _CppDecayMapper.has_observables(decay._to_cpp())
787
788 @staticmethod
790 canonical: str,
791 observables: Sequence[Union[CustomObservableSpec, dict, tuple]],
792 aliases: Optional[Sequence[str]] = None,
793 ) -> bool:
794 """Register a custom decay together with at least one observable."""
795 cpp_specs = [CustomObservableSpec.from_any(o)._to_cpp() for o in observables]
796 return _CppDecayMapper.register_custom_with_observables(
797 canonical,
798 cpp_specs,
799 list(aliases or []),
800 )
801
802
803__all__ = [
804 "OrderMapper",
805 "ParameterTypeMapper",
806 "ModelMapper",
807 "WilsonBasisMapper",
808 "ContributionTypeMapper",
809 "MassTypeMapper",
810 "ScaleTypeMapper",
811 "GroupMapper",
812 "WCoefMapper",
813 "WGroupId",
814 "WCoefId",
815 "ObservableMapper",
816 "DecayMapper",
817 "CustomObservableSpec",
818 "DecayId",
819]
static IdOf< DecayTag > to_id(Decays e)
Converts an enum value to an IdOf<Tag>.
static IdOf< WGroupTag > id_of(std::string_view s)
Resolves a string into an IdOf<Tag> via the registry.
from_any(cls, Union["CustomObservableSpec", dict, tuple] value)
Definition Mapper.py:160
__init__(self, str canonical, Optional[Sequence[str]] aliases=None, Optional[LhaID] ext=None)
Definition Mapper.py:146
__init__(self, Union[str, "_CppDecayId"] value)
Definition Mapper.py:61
bool register_custom_with_observables(str canonical, Sequence[Union[CustomObservableSpec, dict, tuple]] observables, Optional[Sequence[str]] aliases=None)
Definition Mapper.py:793
str str(Union[Decays, DecayId] decay)
Definition Mapper.py:684
DecayId get_decay_id_or_throw(ObservableId obs)
Definition Mapper.py:773
bool has_observables(Union[Decays, DecayId, str] decay)
Definition Mapper.py:778
Decays get_decay(Observables obs)
Definition Mapper.py:753
DecayId id_of(Union[AnyStr, Decays] decay)
Definition Mapper.py:698
get_observables(Union[Decays, DecayId, str] decay)
Definition Mapper.py:730
Optional[DecayId] get_decay_id(Union[Observables, ObservableId] obs)
Definition Mapper.py:758
str block_name(group, ScaleType scale, WilsonBasis basis=WilsonBasis.STANDARD)
Definition Mapper.py:437
str canonical(WGroupId group_id)
Definition Mapper.py:432
bool register_custom(str canonical, aliases=None, Optional[str] external=None)
Definition Mapper.py:445
ObservableId from_flha(LhaID flha_id)
Definition Mapper.py:607
ObservableId to_id(Observables obs)
Definition Mapper.py:582
bool register_custom(str canonical, Union[str, Decays, DecayId] parent_decay, Optional[Sequence[str]] aliases=None, Optional[LhaID] ext=None)
Definition Mapper.py:637
Observables enum_elt_legacy(AnyStr name)
Definition Mapper.py:568
LhaID flha_full(coef, QCDOrder order, ContributionType contribution)
Definition Mapper.py:526
bool register_custom(str canonical, aliases=None, flha=(0, 0))
Definition Mapper.py:507
_unwrap_optional_or_none(cpp_optional, str label)
Definition Mapper.py:122
WGroupId _wrap_wgroup_id(cpp_id)
Definition Mapper.py:112
_cpp_lhaid_or_none(Optional[LhaID] ext)
Definition Mapper.py:93
WCoefId _wrap_wcoef_id(cpp_id)
Definition Mapper.py:117
DecayId _wrap_decay_id(cpp_id)
Definition Mapper.py:107
ObservableId _wrap_observable_id(cpp_id)
Definition Mapper.py:102