Skip to content

Commit

Permalink
Enhance the dec file "Particle" statement to allow for optional widths (
Browse files Browse the repository at this point in the history
#414)

* Make the width optional in a 'Particle' statement, as in EvtGen

* Test the new functionality

* Enhance code to deal with optional width parameter

* Fix for MyPy
  • Loading branch information
eduardo-rodrigues authored Jan 9, 2024
1 parent 336b305 commit 024fe4a
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/decaylanguage/data/decfile.lark
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ cdecay : "CDecay" LABEL

define : "Define" LABEL SIGNED_NUMBER

particle_def: "Particle" LABEL SIGNED_NUMBER SIGNED_NUMBER // Set the mass and width of a particle (in GeV)
particle_def: "Particle" LABEL SIGNED_NUMBER SIGNED_NUMBER? // Set the mass and width (optional) of a particle (in GeV)

alias : "Alias" LABEL LABEL

Expand Down
40 changes: 34 additions & 6 deletions src/decaylanguage/dec/dec.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,14 +455,17 @@ def dict_charge_conjugates(self) -> dict[str, str]:
def get_particle_property_definitions(self) -> dict[str, dict[str, float]]:
"""
Return a dictionary of all particle property definitions
in the input parsed file, of the form "Particle <PARTICLE> <MASS> <WIDTH>",
in the input parsed file, of the form "Particle <PARTICLE> <MASS> <WIDTH>"
or "Particle <PARTICLE> <MASS>",
as {'PARTICLE1': {'mass': MASS1, 'width': WIDTH1},
'PARTICLE2': {'mass': MASS2, 'width': WIDTH2}, ...}.
Note
----
Particles are often defined via aliases and post-processing may be needed
to match the mass and width to the actual particle.
1) Particles are often defined via aliases and post-processing may be needed
to match the mass and width to the actual particle.
2) The mass (width) parameter is compulsory (optional).
When not specified, the width is taken from the particle or alias.
"""
self._check_parsing()
return get_particle_property_definitions(self._parsed_dec_file)
Expand Down Expand Up @@ -1287,7 +1290,7 @@ def find_charge_conjugate_match(
from "ChargeConj" statements in a decay file.
The name `ChargeConj(pname)` is returned if all matching "routes" fail,
see `charge_conjugate_name(...) function.`
see `charge_conjugate_name(...)` function.
"""
# Check the list of particle-antiparticle matches provided ;-)
if dict_cc_names:
Expand Down Expand Up @@ -1623,20 +1626,45 @@ def get_charge_conjugate_defs(parsed_file: Tree) -> dict[str, str]:
def get_particle_property_definitions(parsed_file: Tree) -> dict[str, dict[str, float]]:
"""
Return a dictionary of all particle property definitions
in the input parsed file, of the form "Particle <PARTICLE> <MASS> <WIDTH>",
in the input parsed file, of the form "Particle <PARTICLE> <MASS> <WIDTH>"
or "Particle <PARTICLE> <MASS>",
as {'PARTICLE1': {'mass': MASS1, 'width': WIDTH1},
'PARTICLE2': {'mass': MASS2, 'width': WIDTH2}, ...}.
Note
----
1) Particles are often defined via aliases and post-processing may be needed
to match the mass and width to the actual particle.
2) The mass (width) parameter is compulsory (optional).
When not specified, the width is taken from the particle or alias.
Parameters
----------
parsed_file: Lark Tree instance
Input parsed file.
"""
# Get particle aliases since "Particle" statements often use name aliases
aliases = get_aliases(parsed_file)

def get_set_width_or_default(children: list[Tree]) -> float:
if len(children) > 2:
return float(children[2].value)

# Get the particle name or the alias
token_name: str = children[0].value
try:
pname: str = aliases.get(token_name, token_name) if aliases else token_name
return Particle.from_evtgen_name(pname).width # type: ignore[return-value]
except Exception as err:
raise RuntimeError(
f"Particle name/alias {token_name!r} not found! Check your dec file(s)!"
) from err

try:
return {
tree.children[0].value: {
"mass": float(tree.children[1].value),
"width": float(tree.children[2].value),
"width": get_set_width_or_default(tree.children),
}
for tree in parsed_file.find_data("particle_def")
}
Expand Down
3 changes: 3 additions & 0 deletions tests/data/defs-aliases-chargeconj.dec
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,9 @@ LSNONRELBW rho0
BlattWeisskopf rho0 3.0
IncludeBirthFactor rho0 no
IncludeDecayFactor rho0 yes
# Redefined particles only need to specify the mass, and the width is optional
Alias MyRho0 rho0
Particle MyRho0 0.8

# Pythia 8 parameter modifications
# (Very important that there are no blank spaces in the parameter string!)
Expand Down
3 changes: 2 additions & 1 deletion tests/dec/test_dec.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def test_aliases_parsing():
p = DecFileParser(DIR / "../data/defs-aliases-chargeconj.dec")
p.parse()

assert len(p.dict_aliases()) == 135
assert len(p.dict_aliases()) == 136


def test_model_aliases_parsing():
Expand Down Expand Up @@ -197,6 +197,7 @@ def test_particle_property_definitions():
"MyK*0": {"mass": 0.892, "width": 0.051},
"MyPhi": {"mass": 1.02, "width": 0.004},
"rho0": {"mass": 0.8, "width": 0.2},
"MyRho0": {"mass": 0.8, "width": 149.1},
}


Expand Down

0 comments on commit 024fe4a

Please sign in to comment.