Skip to content

Commit

Permalink
DecayChain.from_dict only supports single decay chains (#339)
Browse files Browse the repository at this point in the history
* DecayChain.from_dict only supports single decay chains

* Ensure this fact is properly tested

* style: pre-commit fixes

* Fix indentation

* Fix for doctests

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
eduardo-rodrigues and pre-commit-ci[bot] authored Jun 30, 2023
1 parent 9596465 commit ac89e78
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 3 deletions.
72 changes: 69 additions & 3 deletions src/decaylanguage/decay/decay.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,17 +477,81 @@ def _build_decay_modes(
Given the input dict representation of a `DecayChain`
it returns a dict of mother particles and their final states as `DecayMode` instances.
Parameters
----------
decay_modes: dict
A dict to be populated with the decay modes `DecayMode`
built from the input decay chain dictionary.
dc_dict: dict
The input decay chain dictionary.
Note
----
Only single chains are supported, meaning every decaying particle
can only define a single decay mode.
Examples
--------
The simple example with no sub-decays:
>>> dc_dict = {
... "anti-D0": [
... {
... "bf": 1.0,
... "fs": ["K+", "pi-"],
... "model": "PHSP",
... "model_params": ""
... }
... ]
... }
>>> # It provides
>>> decay_modes = {}
>>> _build_decay_modes(decay_modes, dc_dict)
>>> decay_modes
{'anti-D0': <DecayMode: daughters=K+ pi-, BF=1.0>}
A more complicated example with a sub-decay and more than one mode
{
"anti-D*0": [
{
"bf": 0.619,
"fs": [
{
"anti-D0": [
{
"bf": 1.0,
"fs": ["K+", "pi-"],
"model": "PHSP",
"model_params": ""
}
]
},
"pi0"
],
"model": "VSS",
"model_params": ""
}
]
}
provides
{'anti-D0': <DecayMode: daughters=K+ pi-, BF=1.0>,
'anti-D*0': <DecayMode: daughters=anti-D0 pi0, BF=0.619>}
"""
mother = list(dc_dict.keys())[0]
dms = dc_dict[mother]

for dm in dms:
# Single decay chains are allowed, which means a particle cannot have 2 decay modes
if mother in decay_modes:
raise RuntimeError("Input is not a single decay chain!") from None

try:
fs = dm["fs"]
except Exception as e:
raise RuntimeError(
"Internal dict representation not in the expected format - no 'fs' key is present!"
) from e

assert isinstance(fs, list)
if _has_no_subdecay(fs):
decay_modes[mother] = DecayMode.from_dict(dm)
Expand Down Expand Up @@ -663,17 +727,19 @@ def _get_fs(decay: DecayModeDict) -> list[Any]:

class DecayChain:
"""
Class holding a particle decay chain, which is typically a top-level decay
Class holding a particle (single) decay chain, which is typically a top-level decay
(mother particle, branching fraction and final-state particles)
and a set of sub-decays for any non-stable particle in the top-level decay.
The whole chain can be seen as a mother particle and a list of decay modes.
The whole chain can be seen as a mother particle and a list of chained decay modes.
This class is the main building block for the digital representation
of full decay chains.
Note
----
This class does not assume any kind of particle names (EvtGen, PDG).
1) Only single chains are supported, meaning every decaying particle
can only define a single decay mode.
2) This class does not assume any kind of particle names (EvtGen, PDG).
It is nevertheless advised to default use EvtGen names for consistency
with the defaults used in the related classes `DecayMode` and `DaughtersDict`,
unless there is a good motivation not to.
Expand Down
21 changes: 21 additions & 0 deletions tests/decay/test_decay.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,27 @@ def test_DecayChain_constructor_from_dict():
assert DecayChain.from_dict(dc_dict).to_dict() == dc_dict


def test_DecayChain_constructor_from_dict_multiple_final_states():
dc_dict = {
"MyD-": [
{
"bf": 0.905,
"fs": ["K+", "pi-", "pi-"],
"model": "D_DALITZ",
"model_params": "",
},
{
"bf": 0.095,
"fs": ["K+", "K-", "pi-"],
"model": "D_DALITZ",
"model_params": "",
},
]
}
with pytest.raises(RuntimeError):
_ = DecayChain.from_dict(dc_dict)


def test_DecayChain_constructor_from_dict_RuntimeError(dc2):
# For the sake of example remove some parts of a valid dict
bad_dict_repr = dc2.to_dict()["D*+"][0]
Expand Down

0 comments on commit ac89e78

Please sign in to comment.