Skip to content
This repository has been archived by the owner on Oct 11, 2021. It is now read-only.

fix: correctly dump Breit-Wigner #395

Merged
merged 4 commits into from
Nov 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions docs/usage/workflow.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,49 @@
"list(amplitude_model.parameters)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The {class}`.AmplitudeModel` also contains a {attr}`~.AmplitudeModel.dynamics` section. By default, it only contains the dynamics for the initial state ― {class}`.NonDynamic`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"list(amplitude_model.dynamics)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"type(amplitude_model.dynamics[\"J/psi(1S)\"])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To set dynamics for specific resonances, use e.g. {meth}`.ParticleDynamics.set_breit_wigner`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for name in result.get_intermediate_particles().names:\n",
" amplitude_model.dynamics.set_breit_wigner(name)\n",
"{name: type(dyn) for name, dyn in amplitude_model.dynamics.items()}"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down
2 changes: 1 addition & 1 deletion src/expertsystem/io/_xml/_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def __build_particle_dynamics(
dynamics = ParticleDynamics(particles=particles, parameters=parameters)
type_mapping: Dict[str, Callable[[str], Dynamics]] = {
"nonResonant": dynamics.set_non_dynamic,
"RelativisticBreitWigner": dynamics.set_breit_wigner,
"relativisticBreitWigner": dynamics.set_breit_wigner,
}
for particle_def in definition:
decay_info: Optional[dict] = particle_def.get("DecayInfo")
Expand Down
3 changes: 3 additions & 0 deletions src/expertsystem/io/_xml/_dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
Node,
NonDynamic,
NormalizedIntensity,
RelativisticBreitWigner,
SequentialAmplitude,
StrengthIntensity,
)
Expand Down Expand Up @@ -182,6 +183,8 @@ def __kinematics_to_dict(kin: Kinematics) -> dict:
def __dynamics_to_dict(dynamics: Dynamics) -> dict:
if isinstance(dynamics, NonDynamic):
return {"Type": "nonResonant"}
if isinstance(dynamics, RelativisticBreitWigner):
return {"Type": "relativisticBreitWigner"}
raise NotImplementedError("No conversion for", dynamics)


Expand Down
34 changes: 23 additions & 11 deletions src/expertsystem/io/_yaml/_dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
Dynamics,
FitParameter,
FitParameters,
FormFactor,
HelicityDecay,
IncoherentIntensity,
Kinematics,
Expand All @@ -18,6 +19,7 @@
NonDynamic,
NormalizedIntensity,
ParticleDynamics,
RelativisticBreitWigner,
SequentialAmplitude,
StrengthIntensity,
)
Expand Down Expand Up @@ -158,21 +160,31 @@ def __dynamics_section_to_dict(particle_dynamics: ParticleDynamics) -> dict:


def __dynamics_to_dict(dynamics: Dynamics) -> dict:
output: dict = {"Type": dynamics.__class__.__name__}
if isinstance(dynamics, NonDynamic):
if isinstance(dynamics.form_factor, BlattWeisskopf):
form_factor = {
output.update(__form_factor_to_dict(dynamics.form_factor))
return output
if isinstance(dynamics, RelativisticBreitWigner):
output["PoleParameters"] = {
"Real": dynamics.pole_position.name,
"Imaginary": dynamics.pole_width.name,
}
output.update(__form_factor_to_dict(dynamics.form_factor))
return output
raise NotImplementedError("No conversion for", dynamics)


def __form_factor_to_dict(form_factor: Optional[FormFactor]) -> dict:
if form_factor is None:
return dict()
if isinstance(form_factor, BlattWeisskopf):
return {
"FormFactor": {
"Type": "BlattWeisskopf",
"MesonRadius": dynamics.form_factor.meson_radius.value,
"MesonRadius": form_factor.meson_radius.name,
}
else:
raise NotImplementedError(
"No conversion for", dynamics.form_factor
)
return {
"Type": "NonDynamic",
"FormFactor": form_factor,
}
raise NotImplementedError("No conversion for", dynamics)
raise NotImplementedError("No conversion for", form_factor)


def __intensity_to_dict( # pylint: disable=too-many-return-statements
Expand Down
21 changes: 3 additions & 18 deletions src/expertsystem/schemas/yaml/amplitude-model.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@
"patternProperties": {
"^.*$": {
"type": "object",
"required": ["Type", "FormFactor"],
"additionalProperties": false,
"required": ["Type"],
"additionalProperties": true,
"properties": {
"Type": {
"enum": ["NonDynamic", "Flatté", "RelativisticBreitWigner"]
Expand All @@ -96,22 +96,7 @@
"additionalProperties": false,
"properties": {
"Type": { "const": "BlattWeisskopf" },
"MesonRadius": {
"anyOf": [
{ "type": "number" },
{
"type": "object",
"required": ["Value"],
"additionalProperties": false,
"properties": {
"Value": { "type": "number" },
"Min": { "type": "number" },
"Max": { "type": "number" },
"Fix": { "type": "boolean" }
}
}
]
}
"MesonRadius": { "type": "string" }
}
}
}
Expand Down
36 changes: 34 additions & 2 deletions tests/unit/amplitude/expected_recipe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,26 @@ Parameters:
- Name: &par5 Phase_J/psi(1S)_to_f(0)(1500)_0+gamma_1;f(0)(1500)_to_pi0_0+pi0_0;
Type: Phase
Value: 0.0
- Name: MesonRadius_J/psi(1S)
- Name: &par6 MesonRadius_J/psi(1S)
Type: MesonRadius
Value: 1.0
Fix: true
- Name: &par7 Position_f(0)(980)
Value: 0.99
- Name: &par8 Width_f(0)(980)
Value: 0.06
- Name: &par9 MesonRadius_f(0)(980)
Value: 1.0
Fix: true
Type: MesonRadius
spflueger marked this conversation as resolved.
Show resolved Hide resolved
- Name: &par10 Position_f(0)(1500)
Value: 1.506
- Name: &par11 Width_f(0)(1500)
Value: 0.112
- Name: &par12 MesonRadius_f(0)(1500)
Value: 1.0
Fix: true
Type: MesonRadius

Intensity:
Class: StrengthIntensity
Expand Down Expand Up @@ -412,4 +428,20 @@ Dynamics:
Type: NonDynamic
FormFactor:
Type: BlattWeisskopf
MesonRadius: 1.0
MesonRadius: *par6
f(0)(980):
Type: RelativisticBreitWigner
PoleParameters:
Real: *par7
Imaginary: *par8
FormFactor:
Type: BlattWeisskopf
MesonRadius: *par9
f(0)(1500):
Type: RelativisticBreitWigner
PoleParameters:
Real: *par10
Imaginary: *par11
FormFactor:
Type: BlattWeisskopf
MesonRadius: *par12
2 changes: 1 addition & 1 deletion tests/unit/amplitude/test_yaml_canonical.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def test_particle_section(imported_dict):

def test_parameter_section(imported_dict):
parameter_list = imported_dict["Parameters"]
assert len(parameter_list) == 6
assert len(parameter_list) == 12
for parameter in parameter_list:
assert "Name" in parameter
assert "Value" in parameter
Expand Down
27 changes: 17 additions & 10 deletions tests/unit/amplitude/test_yaml_helicity.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def test_create_recipe_dict(
jpsi_to_gamma_pi_pi_helicity_amplitude_model: AmplitudeModel,
):
assert len(jpsi_to_gamma_pi_pi_helicity_amplitude_model.particles) == 5
assert len(jpsi_to_gamma_pi_pi_helicity_amplitude_model.dynamics) == 1
assert len(jpsi_to_gamma_pi_pi_helicity_amplitude_model.dynamics) == 3


def test_particle_section(imported_dict):
Expand Down Expand Up @@ -91,32 +91,39 @@ def test_kinematics_section(imported_dict):

def test_parameter_section(imported_dict):
parameter_list = imported_dict["Parameters"]
assert len(parameter_list) == 6
assert len(parameter_list) == 12
for parameter in parameter_list:
assert "Name" in parameter
assert "Value" in parameter
assert "Type" in parameter
assert parameter.get("Fix", True)


def test_dynamics_section(imported_dict):
parameter_list: list = imported_dict["Parameters"]

def get_parameter(parameter_name: str) -> dict:
for par in parameter_list:
name = par["Name"]
if name == parameter_name:
return par
raise LookupError(f'Could not find parameter "{parameter_name}"')

dynamics = imported_dict["Dynamics"]
assert len(dynamics) == 1
assert len(dynamics) == 3

j_psi = dynamics["J/psi(1S)"]
assert j_psi["Type"] == "NonDynamic"
assert j_psi["FormFactor"]["Type"] == "BlattWeisskopf"
assert j_psi["FormFactor"]["MesonRadius"] == 1.0
assert get_parameter(j_psi["FormFactor"]["MesonRadius"])["Value"] == 1.0

f0_980 = dynamics.get("f(0)(980)", None)
if f0_980:
assert f0_980["Type"] == "RelativisticBreitWigner"
assert f0_980["FormFactor"]["Type"] == "BlattWeisskopf"
assert f0_980["FormFactor"]["MesonRadius"] == {
"Max": 2.0,
"Min": 0.0,
"Value": 1.0,
}
assert f0_980["FormFactor"]["MesonRadius"] == "MesonRadius_f(0)(980)"
assert (
get_parameter(f0_980["FormFactor"]["MesonRadius"])["Value"] == 1.0
)


def test_intensity_section(imported_dict):
Expand Down
11 changes: 9 additions & 2 deletions tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,18 @@ def jpsi_to_gamma_pi_pi_helicity_solutions() -> Result:
def jpsi_to_gamma_pi_pi_canonical_amplitude_model(
jpsi_to_gamma_pi_pi_canonical_solutions: Result,
) -> AmplitudeModel:
return es.amplitude.generate(jpsi_to_gamma_pi_pi_canonical_solutions)
return __create_model(jpsi_to_gamma_pi_pi_canonical_solutions)


@pytest.fixture(scope="session")
def jpsi_to_gamma_pi_pi_helicity_amplitude_model(
jpsi_to_gamma_pi_pi_helicity_solutions: Result,
) -> AmplitudeModel:
return es.amplitude.generate(jpsi_to_gamma_pi_pi_helicity_solutions)
return __create_model(jpsi_to_gamma_pi_pi_helicity_solutions)


def __create_model(result: Result) -> AmplitudeModel:
model = es.amplitude.generate(result)
for name in result.get_intermediate_particles().names:
model.dynamics.set_breit_wigner(name)
return model