Skip to content

Commit

Permalink
implement Resonance class and import isobars.json
Browse files Browse the repository at this point in the history
  • Loading branch information
redeboer committed May 1, 2022
1 parent fa7c913 commit 81db4f2
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 1 deletion.
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ install_requires =
ampform >=0.14.0
numpy
sympy >=1.10 # module sympy.printing.numpy and array expressions with shape kwarg
typing-extensions; python_version <"3.8.0"
packages = find:
package_dir =
=src
Expand Down
33 changes: 33 additions & 0 deletions src/polarization/dynamics.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
# pyright: reportPrivateUsage=false
from __future__ import annotations

import sys

import sympy as sp
from ampform.sympy import (
UnevaluatedExpression,
create_expression,
implement_doit_method,
make_commutative,
)
from attrs import frozen

from polarization.decay import Particle

if sys.version_info < (3, 8):
from typing_extensions import Literal
else:
from typing import Literal


@make_commutative
Expand Down Expand Up @@ -125,3 +137,24 @@ def evaluate(self):
def _latex(self, printer, *args):
z, L = map(printer._print, self.args)
return Rf"F_{{{L}}}\left({z}\right)"


@frozen
class Resonance:
particle: Particle
mass_range: tuple[float, float]
width_range: tuple[float, float]
lineshape: Literal["BreitWignerMinL", "BuggBreitWignerMinL", "Flatte1405"]

@property
def mass(self) -> float:
return _compute_average(self.mass_range)

@property
def width(self) -> float:
return _compute_average(self.width_range)


def _compute_average(range_def: float | tuple[float, float]) -> float:
_min, _max = range_def
return (_max + _min) / 2
56 changes: 56 additions & 0 deletions src/polarization/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,20 @@
"""
from __future__ import annotations

import sys
from collections import abc
from functools import singledispatch
from typing import Iterable, Mapping

import sympy as sp

from polarization.decay import IsobarNode, Particle
from polarization.dynamics import Resonance

if sys.version_info < (3, 8):
from typing_extensions import Literal, TypedDict
else:
from typing import Literal, TypedDict


@singledispatch
Expand Down Expand Up @@ -101,3 +108,52 @@ def _(obj: Particle, render_jp: bool = False) -> str:
parity = "-1" if obj.parity < 0 else "+1"
return f"{{{obj.spin}}}^{{{parity}}}"
return obj.name


def to_resonance_dict(definition: dict[str, ResonanceJSON]) -> dict[str, Resonance]:
return {
name: to_resonance(name, resonance_def)
for name, resonance_def in definition.items()
}


def to_resonance(name: str, definition: ResonanceJSON) -> Resonance:
spin, parity = _to_jp_pair(definition["jp"])
return Resonance(
Particle(name, spin, parity),
mass_range=_to_float_range(definition["mass"]),
width_range=_to_float_range(definition["width"]),
lineshape=definition["lineshape"],
)


def _to_float_range(input_str: str) -> tuple[float, float]:
"""
>>> _convert_mass_string("1405.1")
(1405.1, 1405.1)
>>> _convert_mass_string("1900-2100")
(1900.0, 2100.0)
"""
if "-" in input_str:
_min, _max, *_ = map(float, input_str.split("-"))
else:
_min = _max = float(input_str)
return _min, _max


def _to_jp_pair(input_str: str) -> tuple[sp.Rational, int]:
"""
>>> _convert_jp_string("3/2^-")
(3/2, -1)
>>> _convert_jp_string("0^+")
(0, 1)
"""
spin, parity_sign = input_str.split("^")
return sp.Rational(spin), int(f"{parity_sign}1")


class ResonanceJSON(TypedDict):
jp: str
mass: str
width: str
lineshape: Literal["BreitWignerMinL", "BuggBreitWignerMinL", "Flatte1405"]
24 changes: 23 additions & 1 deletion tests/test_io.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import json
from pathlib import Path

from polarization.decay import IsobarNode, Particle
from polarization.io import as_latex
from polarization.io import as_latex, to_resonance_dict

# https://compwa-org--129.org.readthedocs.build/report/018.html#resonances-and-ls-scheme
Λc = Particle(R"\Lambda_c^+", spin=0.5, parity=+1)
Expand All @@ -26,3 +29,22 @@ def test_as_latex_isobar_node():
node = IsobarNode(Λ1520, p, K, interaction=(2, 1))
latex = as_latex(node)
assert latex == R"\Lambda(1520) \xrightarrow[S=1]{L=2} p K^-"


def test_import_isobar_definitions():
pwd = Path(__file__).absolute().parent
data_dir = pwd.parent / "data"
with open(data_dir / "isobars.json") as stream:
data = json.load(stream)
isobar_definitions = data["isobars"]
resonances = to_resonance_dict(isobar_definitions)
assert len(resonances) == 12
Λ2000 = resonances["L(2000)"]
assert Λ2000.particle.name == "L(2000)"
assert Λ2000.particle.spin == 0.5
assert Λ2000.particle.parity == -1
assert Λ2000.mass_range == (1900, 2100)
assert Λ2000.mass == 2000
assert Λ2000.width_range == (20, 400)
assert Λ2000.width == 210
assert Λ2000.lineshape == "BreitWignerMinL"

0 comments on commit 81db4f2

Please sign in to comment.