1"""Identifiers for observables evaluated over a finite kinematic bin."""
3from dataclasses
import dataclass, field
4from typing
import Tuple, Union, Any
6from pyhyperiso.phyperiso.pyhyperiso
import common
14 """Python wrapper around the C++ ``BinnedObservableId`` composite identifier.
16 A ``BinnedObservableId`` uniquely identifies a *binned* observable by:
17 - an unbinned observable id (``ObservableId``),
18 - a bin range ``(low, high)`` stored as a pair of doubles.
20 This mirrors the C++ struct::
22 struct BinnedObservableId {
24 std::pair<double,double> p;
29 s (Union[ObservableId, str]): Unbinned observable identifier.
30 - If a ``str`` is provided, it is converted to ``ObservableId(str)``.
31 p (Tuple[float, float]): Bin range (low, high). Defaults to (0.0, 0.0).
34 s (ObservableId): Unbinned observable identifier (Python wrapper).
35 p (Tuple[float, float]): Bin range.
36 _cpp_obj (common.BinnedObservableId): Underlying bound C++ object.
39 - ``flha()`` returns a bound C++ ``LhaID``.
40 - ``from_flha()`` reconstructs a binned id from such an ``LhaID``.
41 - Equality/ordering are implemented in C++ (== and <). This wrapper forwards them.
44 s: Union[ObservableId, str] = field(default_factory=
lambda:
ObservableId(
"NULL"))
45 p: Tuple[float, float] = (0.0, 0.0)
46 _cpp_obj: common.BinnedObservableId = field(init=
False, repr=
False)
49 """Normalize inputs and construct the underlying C++ object.
52 TypeError: If ``p`` is not a pair (low, high).
55 if isinstance(self.
ss, str):
57 elif isinstance(self.
ss, Observables):
59 elif not isinstance(self.
ss, ObservableId):
60 raise TypeError(f
"s must be ObservableId or str, got {type(self.s)}")
63 if not (isinstance(self.
pp, (tuple, list, set))
and len(self.
pp) == 2):
64 raise TypeError(
"p must be a (low, high) pair")
65 if isinstance(self.
pp, set):
66 low, high = sorted(float(value)
for value
in self.
pp)
68 low = float(self.
pp[0])
69 high = float(self.
pp[1])
73 s_cpp = self.
ss._to_cpp()
75 if low == 0.0
and high == 0.0:
81 """Convert this binned id to its FLHA/LHA representation.
84 common.LhaID: Bound C++ ``LhaID`` for the binned observable.
87 RuntimeError: If the mapping from ``ObservableId`` to FLHA is unknown.
92 def from_flha(cls, lhaid: Any) ->
"BinnedObservableId":
93 """Construct a ``BinnedObservableId`` from a binned FLHA/LHA id.
96 lhaid: A bound C++ ``LhaID`` or a wrapper exposing ``to_cpp()``.
99 BinnedObservableId: Wrapped instance reconstructed from the id.
102 RuntimeError: If the id cannot be decoded or the mapping is unknown.
104 lhaid_cpp = lhaid.to_cpp()
if hasattr(lhaid,
"to_cpp")
else lhaid
105 cpp_obj = common.BinnedObservableId.from_flha(lhaid_cpp)
109 def from_cpp(cls, cpp_obj: common.BinnedObservableId) ->
"BinnedObservableId":
110 """Wrap an existing bound C++ ``BinnedObservableId`` instance.
113 cpp_obj (common.BinnedObservableId): C++ object coming from pybind.
116 BinnedObservableId: Python wrapper around the provided C++ object.
118 inst = cls.__new__(cls)
119 inst._cpp_obj = cpp_obj
122 inst.p = (float(cpp_obj.p[0]), float(cpp_obj.p[1]))
125 def to_cpp(self) -> common.BinnedObservableId:
126 """Return the underlying bound C++ object."""
130 """Serialize this identifier into a debug-friendly dict."""
131 return {
"s": str(self.
ss),
"p": self.
pp}
134 """Return a debug representation."""
135 return f
"BinnedObservableId(s={self.s!s}, p={self.p})"
138 """Return a human-readable representation."""
139 return f
"{self.s} [{self.p[0]}, {self.p[1]}]"
142 """Value equality using the underlying C++ implementation."""
143 if not isinstance(other, BinnedObservableId):
144 return NotImplemented
147 def __lt__(self, other:
"BinnedObservableId") -> bool:
148 """Strict ordering using the underlying C++ implementation."""
149 if not isinstance(other, BinnedObservableId):
150 return NotImplemented
154 """Hash using the underlying C++ hash (bound __hash__) if available.
156 Falls back to hashing (s, p) in Python if needed.
161 return hash((str(self.
ss), float(self.
pp[0]), float(self.
pp[1])))
static IdOf< ObservableTag > to_id(Observables e)
Converts an enum value to an IdOf<Tag>.
bool __eq__(self, object other)
"BinnedObservableId" from_flha(cls, Any lhaid)
bool __lt__(self, "BinnedObservableId" other)
common.BinnedObservableId to_cpp(self)
"BinnedObservableId" from_cpp(cls, common.BinnedObservableId cpp_obj)