Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BREAK: adapt implementation to AmpForm-DPD v0.2 #371

Merged
merged 13 commits into from
Jan 1, 2025
1 change: 0 additions & 1 deletion .binder/postBuild
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ pixi_packages="$(NO_COLOR= pixi list --explicit --no-install | awk 'NR > 1 {prin
if [[ -n "$pixi_packages" ]]; then
pixi global install $pixi_packages
fi
export PYTHONHASHSEED="0"
pixi clean cache --yes

uv export \
Expand Down
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"Colab",
"Sigmapi",
"allclose",
"astuple",
"avrgd",
"ccrcr",
"cmin",
Expand Down
2 changes: 1 addition & 1 deletion .cspell/this-project.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
AmpForm
aslatex
autoupdate
batchmode
Expand Down Expand Up @@ -30,7 +31,6 @@ PyPI
pyproject
pyright
pytest
PYTHONHASHSEED
Remco
texlive
toctree
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/ci-docs.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
env:
FORCE_COLOR: "1"
JULIA_CI: "true"
PYTHONHASHSEED: "0"
PYTHON_VERSION: "3.9"
UV_SYSTEM_PYTHON: "1"

Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ concurrency:
cancel-in-progress: |-
${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) }}

env:
PYTHONHASHSEED: "0"

on:
push:
branches:
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,6 @@ repos:
- id: pyright

- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.5.11
rev: 0.5.13
hooks:
- id: uv-lock
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
[![Supported Python versions](https://img.shields.io/pypi/pyversions/polarimetry-lc2pkpi)](https://pypi.org/project/polarimetry-lc2pkpi)
[![Binder](https://static.mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/ComPWA/polarimetry/stable?urlpath=lab)

This repository a symbolic amplitude model for the decay $\Lambda^+_c \to p \pi^+ K^-$ that is aligned with [Dalitz-plot decomposition](https://journals.aps.org/prd/abstract/10.1103/PhysRevD.101.034033) and computes an align polarimeter vector field $\vec\alpha$. Helicity couplings and other parameter values are taken from a recent study by the LHCb Collaboration[^1] and its [supplementary material](https://cds.cern.ch/record/2824328/files).
This repository contains the source code for "$\Lambda_c^+$ polarimetry using the dominant hadronic mode" (2023) by the LHCb Collaboration ([10.1007/JHEP07(2023)228](<https://doi.org/10.1007/JHEP07(2023)228>)). It uses [`ampform-dpd`](https://github.com/ComPWA/ampform-dpd) to formulate symbolic amplitude models for the decay $\Lambda^+_c \to p \pi^+ K^-$ that are aligned with [Dalitz-plot decomposition](https://journals.aps.org/prd/abstract/10.1103/PhysRevD.101.034033). The aligned amplitudes are used to compute polarimeter vector field $\vec\alpha$ over the Dalitz plane. Helicity couplings and other parameter values are taken from a recent study by the LHCb Collaboration[^1] and its [supplementary material](https://cds.cern.ch/record/2824328/files).

<!-- cspell:ignore semileptonic -->

[^1]: Amplitude analysis of the $\Lambda^+_c \to p K^- \pi^+$ decay and $\Lambda^+_c$ baryon polarization measurement in semileptonic beauty hadron decays (2022) [[link]](https://inspirehep.net/literature/2132745)

## Installation

It's recommended to develop this code base with [VSCode](https://code.visualstudio.com) and install the developer environment with Conda:
It's recommended to develop this code base with [VS&nbsp;Code](https://code.visualstudio.com) and install the developer environment with Conda:

```shell
conda env create
Expand Down
2 changes: 1 addition & 1 deletion docs/appendix/widget.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@
" ])\n",
"\n",
" def get_subscript(p):\n",
" return f\"{p.name} \\\\to p K^-\" if \"1405\" in p.name else p.name\n",
" return Rf\"{p.name} \\to K^- p\" if \"1405\" in p.name else p.name\n",
"\n",
" grouped_sliders = []\n",
" for p in RESONANCES:\n",
Expand Down
3 changes: 3 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ def print(self) -> None:
"BuggBreitWigner": "ampform_dpd.dynamics.BuggBreitWigner",
"DalitzPlotDecompositionBuilder": "ampform_dpd.DalitzPlotDecompositionBuilder",
"DataSample": ("obj", "tensorwaves.interface.DataSample"),
"FinalStateID": ("obj", "ampform_dpd.decay.FinalStateID"),
"FlattéSWave": "ampform_dpd.dynamics.FlattéSWave",
"Function": ("obj", "tensorwaves.interface.Function"),
"implement_doit_method": "ampform.sympy.implement_doit_method",
Expand All @@ -256,6 +257,7 @@ def print(self) -> None:
"Particle": "ampform_dpd.decay.Particle",
"Path": "pathlib.Path",
"Pattern": "typing.Pattern",
"polarimetry.lhcb._T": "typing.TypeVar",
"PoolSum": "ampform.sympy.PoolSum",
"PositionalArgumentFunction": "tensorwaves.function.PositionalArgumentFunction",
"QuadContourSet": "matplotlib.contour.QuadContourSet",
Expand Down Expand Up @@ -450,6 +452,7 @@ def print(self) -> None:
"https://arxiv.org/pdf/2208.03262.pdf",
"https://arxiv.org/pdf/hep-ex/0510019.pdf",
"https://doi.org/10.1103/PhysRevD.101.034033",
"https://indico.cern.ch/event/1187317",
"https://journals.aps.org/prd/pdf/10.1103/PhysRevD.101.034033",
"https://www.bookfinder.com",
]
Expand Down
12 changes: 4 additions & 8 deletions docs/resonance-polarimetry.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"from functools import cache\n",
"from math import ceil, sqrt\n",
"from textwrap import dedent, wrap\n",
"from typing import Literal\n",
"\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
Expand All @@ -50,7 +49,7 @@
"from ampform.io import aslatex\n",
"from ampform.sympy import PoolSum, perform_cached_doit\n",
"from ampform_dpd import AmplitudeModel\n",
"from ampform_dpd.decay import Particle\n",
"from ampform_dpd.decay import FinalStateID, Particle\n",
"from ampform_dpd.io import perform_cached_lambdify, simplify_latex_rendering\n",
"from IPython.display import Latex, Math\n",
"from plotly.subplots import make_subplots\n",
Expand All @@ -69,9 +68,6 @@
")\n",
"from polarimetry.lhcb.particle import load_particles\n",
"\n",
"SubSystemID = Literal[1, 2, 3]\n",
"\n",
"\n",
"simplify_latex_rendering()\n",
"FUNCTION_CACHE: dict[sp.Expr, ParametrizedFunction] = {}\n",
"MODEL_FILE = \"../data/model-definitions.yaml\"\n",
Expand Down Expand Up @@ -114,7 +110,7 @@
},
"outputs": [],
"source": [
"def formulate_all_models() -> dict[str, dict[SubSystemID, AmplitudeModel]]:\n",
"def formulate_all_models() -> dict[str, dict[FinalStateID, AmplitudeModel]]:\n",
" with open(MODEL_FILE) as f:\n",
" data = yaml.load(f, Loader=yaml.SafeLoader)\n",
" allowed_model_titles = list(data)\n",
Expand Down Expand Up @@ -308,7 +304,7 @@
},
"outputs": [],
"source": [
"def create_bootstraps() -> dict[SubSystemID, dict[str, ParameterType]]:\n",
"def create_bootstraps() -> dict[FinalStateID, dict[str, ParameterType]]:\n",
" bootstraps = {\n",
" ref: ParameterBootstrap(MODEL_FILE, DECAY, NOMINAL_MODEL_TITLE)\n",
" for ref, model in NOMINAL_MODEL.items()\n",
Expand Down Expand Up @@ -366,7 +362,7 @@
"\n",
"\n",
"def get_resonance_to_reference() -> dict[Particle, int]:\n",
" subsystem_ids: dict[str, SubSystemID] = dict(K=1, L=2, D=3)\n",
" subsystem_ids: dict[str, FinalStateID] = dict(K=1, L=2, D=3)\n",
" resonances = [\n",
" c.resonance\n",
" for c in sorted(\n",
Expand Down
36 changes: 18 additions & 18 deletions pixi.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions pixi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ platforms = [
"osx-arm64",
]

[activation]
env = {PYTHONHASHSEED = "0"}

[dependencies]
julia = {channel = "https://repo.prefix.dev/julia-forge", version = "*"}
uv = "*"
6 changes: 2 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ dependencies = [
"IPython",
"PyYAML",
"ampform >=0.14.8", # @unevaluated decorator
"ampform-dpd ~=0.1.6",
"ampform-dpd~=0.2.0",
"attrs >=20.1.0",
"matplotlib",
"numpy",
Expand Down Expand Up @@ -404,8 +404,6 @@ commands =
pytest {posargs}
description = Run all unit tests
passenv = *
setenv =
PYTHONHASHSEED = 0

[testenv:doc]
allowlist_externals =
Expand Down Expand Up @@ -513,7 +511,7 @@ setenv =
allowlist_externals =
pytest
commands =
pytest --nbmake --nbmake-timeout=3600 {posargs:docs}
pytest --nbmake --nbmake-timeout=0 {posargs:docs}
description = Run all notebooks with pytest

[testenv:sty]
Expand Down
5 changes: 3 additions & 2 deletions src/polarimetry/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING, Literal
from typing import TYPE_CHECKING

import sympy as sp
from ampform.sympy import PoolSum
Expand All @@ -24,10 +24,11 @@

if TYPE_CHECKING:
from ampform_dpd import AmplitudeModel, DalitzPlotDecompositionBuilder
from ampform_dpd.decay import FinalStateID


def formulate_polarimetry(
builder: DalitzPlotDecompositionBuilder, reference_subsystem: Literal[1, 2, 3] = 1
builder: DalitzPlotDecompositionBuilder, reference_subsystem: FinalStateID = 1
) -> tuple[PoolSum, PoolSum, PoolSum]:
half = sp.Rational(1, 2)
if builder.decay.initial_state.spin != half:
Expand Down
23 changes: 12 additions & 11 deletions src/polarimetry/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Literal
from typing import TYPE_CHECKING, Any

import jax.numpy as jnp
import sympy as sp
from ampform.kinematics.phasespace import is_within_phasespace
from ampform_dpd import create_mass_symbol_mapping, formulate_third_mandelstam
from ampform_dpd.decay import ThreeBodyDecay
from tensorwaves.data import IntensityDistributionGenerator, NumpyDomainGenerator
from tensorwaves.data.rng import NumpyUniformRNG
from tensorwaves.data.transform import SympyDataTransformer
from tensorwaves.function.sympy import create_function

if TYPE_CHECKING:
from ampform_dpd import AmplitudeModel
from ampform_dpd.decay import ThreeBodyDecay
from ampform_dpd.decay import FinalStateID, ThreeBodyDecay
from tensorwaves.function import PositionalArgumentFunction
from tensorwaves.interface import DataSample

Expand All @@ -36,8 +37,8 @@ def create_data_transformer(

def create_phase_space_filter(
decay: ThreeBodyDecay,
x_mandelstam: Literal[1, 2, 3] = 1,
y_mandelstam: Literal[1, 2, 3] = 2,
x_mandelstam: FinalStateID = 1,
y_mandelstam: FinalStateID = 2,
outside_value=sp.nan,
) -> PositionalArgumentFunction:
m0, m1, m2, m3 = create_mass_symbol_mapping(decay).values()
Expand All @@ -50,8 +51,8 @@ def create_phase_space_filter(
def generate_meshgrid_sample(
decay: ThreeBodyDecay,
resolution: int,
x_mandelstam: Literal[1, 2, 3] = 1,
y_mandelstam: Literal[1, 2, 3] = 2,
x_mandelstam: FinalStateID = 1,
y_mandelstam: FinalStateID = 2,
) -> DataSample:
"""Generate a `numpy.meshgrid` sample for plotting with `matplotlib.pyplot`."""
boundaries = compute_dalitz_boundaries(decay)
Expand All @@ -70,8 +71,8 @@ def generate_sub_meshgrid_sample( # noqa: PLR0917
resolution: int,
x_range: tuple[float, float],
y_range: tuple[float, float],
x_mandelstam: Literal[1, 2, 3] = 1,
y_mandelstam: Literal[1, 2, 3] = 2,
x_mandelstam: FinalStateID = 1,
y_mandelstam: FinalStateID = 2,
) -> DataSample:
sigma_x, sigma_y = jnp.meshgrid(
jnp.linspace(*x_range, num=resolution),
Expand Down Expand Up @@ -122,16 +123,16 @@ def compute_dalitz_boundaries(

def __create_compute_compute_sigma_z(
decay: ThreeBodyDecay,
x_mandelstam: Literal[1, 2, 3] = 1,
y_mandelstam: Literal[1, 2, 3] = 2,
x_mandelstam: FinalStateID = 1,
y_mandelstam: FinalStateID = 2,
) -> PositionalArgumentFunction:
masses = create_mass_symbol_mapping(decay)
sigma_k = formulate_third_mandelstam(decay, x_mandelstam, y_mandelstam)
return create_function(sigma_k.xreplace(masses), backend="jax", use_cse=True)


def __get_third_mandelstam_index(
x_mandelstam: Literal[1, 2, 3], y_mandelstam: Literal[1, 2, 3]
x_mandelstam: FinalStateID, y_mandelstam: FinalStateID
):
if x_mandelstam == y_mandelstam:
msg = "x_mandelstam and y_mandelstam must be different"
Expand Down
Loading