diff --git a/.constraints/py3.10.txt b/.constraints/py3.10.txt index 1b86e6bf..a766e4f8 100644 --- a/.constraints/py3.10.txt +++ b/.constraints/py3.10.txt @@ -4,10 +4,10 @@ # # pip-compile --extra=dev --no-annotate --output-file=.constraints/py3.10.txt --strip-extras setup.py # -absl-py==1.2.0 +absl-py==1.3.0 alabaster==0.7.12 -ampform==0.14.3 -anyio==3.6.1 +ampform==0.14.4 +anyio==3.6.2 aquirdturtle-collapsible-headings==3.1.0 argon2-cffi==21.3.0 argon2-cffi-bindings==21.2.0 @@ -51,7 +51,7 @@ iminuit==2.17.0 importlib-metadata==5.0.0 importlib-resources==5.10.0 iniconfig==1.1.1 -ipykernel==6.16.0 +ipykernel==6.16.1 ipython==8.5.0 ipython-genutils==0.2.0 ipywidgets==8.0.2 @@ -63,15 +63,15 @@ jinja2==3.1.2 json5==0.9.10 jsonschema==4.16.0 jupyter-cache==0.5.0 -jupyter-client==7.4.2 -jupyter-core==4.11.1 +jupyter-client==7.4.3 +jupyter-core==4.11.2 jupyter-server==1.21.0 jupyterlab==3.4.8 jupyterlab-code-formatter==1.5.3 jupyterlab-markup==1.1.0 jupyterlab-myst==0.1.6 jupyterlab-pygments==0.2.2 -jupyterlab-server==2.15.2 +jupyterlab-server==2.16.1 jupyterlab-widgets==3.0.3 kaleido==0.2.1 kiwisolver==1.4.4 @@ -89,19 +89,19 @@ mpmath==1.2.1 mypy-extensions==0.4.3 myst-nb==0.17.1 myst-parser==0.18.1 -nbclassic==0.4.6 +nbclassic==0.4.5 nbclient==0.5.13 -nbconvert==7.2.1 +nbconvert==7.2.2 nbformat==5.7.0 nbmake==1.3.0 nest-asyncio==1.5.6 nodeenv==1.7.0 -notebook==6.4.12 -notebook-shim==0.1.0 +notebook==6.5.1 +notebook-shim==0.2.0 numpy==1.23.4 opt-einsum==3.3.0 packaging==21.3 -pandas==1.5.0 +pandas==1.5.1 pandocfilters==1.5.0 parso==0.8.3 particle==0.20.1 @@ -113,9 +113,9 @@ platformdirs==2.5.2 plotly==5.10.0 pluggy==1.0.0 pre-commit==2.20.0 -prometheus-client==0.14.1 +prometheus-client==0.15.0 prompt-toolkit==3.0.31 -psutil==5.9.2 +psutil==5.9.3 ptyprocess==0.7.0 pure-eval==0.2.2 py==1.11.0 @@ -132,12 +132,12 @@ pytest-forked==1.4.0 pytest-xdist==2.5.0 python-constraint==1.4.0 python-dateutil==2.8.2 -pytz==2022.4 +pytz==2022.5 pyyaml==6.0 pyzmq==24.0.1 qrules==0.9.7 requests==2.28.1 -scipy==1.9.2 +scipy==1.9.3 send2trash==1.8.0 six==1.16.0 sniffio==1.3.0 @@ -149,6 +149,7 @@ sphinx-book-theme==0.3.3 sphinx-codeautolink==0.12.0 sphinx-copybutton==0.5.0 sphinx-design==0.3.0 +sphinx-reredirects==0.1.1 sphinx-togglebutton==0.3.2 sphinxcontrib-applehelp==1.0.2 sphinxcontrib-bibtex==2.5.0 @@ -158,7 +159,7 @@ sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 sphinxcontrib-svg2pdfconverter==1.2.1 -sqlalchemy==1.4.41 +sqlalchemy==1.4.42 stack-data==0.5.1 svgutils==0.3.4 sympy==1.11.1 @@ -166,13 +167,13 @@ tabulate==0.9.0 tenacity==8.1.0 tensorwaves==0.4.8 terminado==0.16.0 -tinycss2==1.1.1 +tinycss2==1.2.1 toml==0.10.2 tomli==2.0.1 tornado==6.2 tox==3.26.0 tqdm==4.64.1 -traitlets==5.4.0 +traitlets==5.5.0 typing-extensions==4.4.0 urllib3==1.26.12 virtualenv==20.16.5 diff --git a/.constraints/py3.7.txt b/.constraints/py3.7.txt index dafe1e20..a8861bd9 100644 --- a/.constraints/py3.7.txt +++ b/.constraints/py3.7.txt @@ -4,10 +4,10 @@ # # pip-compile --extra=dev --no-annotate --output-file=.constraints/py3.7.txt --strip-extras setup.py # -absl-py==1.2.0 +absl-py==1.3.0 alabaster==0.7.12 -ampform==0.14.3 -anyio==3.6.1 +ampform==0.14.4 +anyio==3.6.2 aquirdturtle-collapsible-headings==3.1.0 argon2-cffi==21.3.0 argon2-cffi-bindings==21.2.0 @@ -48,7 +48,7 @@ iminuit==2.17.0 importlib-metadata==5.0.0 ; python_version < "3.8.0" importlib-resources==5.10.0 iniconfig==1.1.1 -ipykernel==6.16.0 +ipykernel==6.16.1 ipython==7.34.0 ipython-genutils==0.2.0 ipywidgets==8.0.2 @@ -60,15 +60,15 @@ jinja2==3.1.2 json5==0.9.10 jsonschema==4.16.0 jupyter-cache==0.5.0 -jupyter-client==7.4.2 -jupyter-core==4.11.1 +jupyter-client==7.4.3 +jupyter-core==4.11.2 jupyter-server==1.21.0 jupyterlab==3.4.8 jupyterlab-code-formatter==1.5.3 jupyterlab-markup==1.1.0 jupyterlab-myst==0.1.6 jupyterlab-pygments==0.2.2 -jupyterlab-server==2.15.2 +jupyterlab-server==2.16.1 jupyterlab-widgets==3.0.3 kaleido==0.2.1 kiwisolver==1.4.4 @@ -86,15 +86,15 @@ mpmath==1.2.1 mypy-extensions==0.4.3 myst-nb==0.17.1 myst-parser==0.18.1 -nbclassic==0.4.6 +nbclassic==0.4.5 nbclient==0.5.13 -nbconvert==7.2.1 +nbconvert==7.2.2 nbformat==5.7.0 nbmake==1.3.0 nest-asyncio==1.5.6 nodeenv==1.7.0 -notebook==6.4.12 -notebook-shim==0.1.0 +notebook==6.5.1 +notebook-shim==0.2.0 numpy==1.21.6 opt-einsum==3.3.0 packaging==21.3 @@ -111,9 +111,9 @@ platformdirs==2.5.2 plotly==5.10.0 pluggy==1.0.0 pre-commit==2.20.0 -prometheus-client==0.14.1 +prometheus-client==0.15.0 prompt-toolkit==3.0.31 -psutil==5.9.2 +psutil==5.9.3 ptyprocess==0.7.0 py==1.11.0 pybtex==0.24.0 @@ -129,7 +129,7 @@ pytest-forked==1.4.0 pytest-xdist==2.5.0 python-constraint==1.4.0 python-dateutil==2.8.2 -pytz==2022.4 +pytz==2022.5 pyyaml==6.0 pyzmq==24.0.1 qrules==0.9.7 @@ -147,6 +147,7 @@ sphinx-book-theme==0.3.3 sphinx-codeautolink==0.12.0 sphinx-copybutton==0.5.0 sphinx-design==0.3.0 +sphinx-reredirects==0.1.1 sphinx-togglebutton==0.3.2 sphinxcontrib-applehelp==1.0.2 sphinxcontrib-bibtex==2.5.0 @@ -156,20 +157,20 @@ sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 sphinxcontrib-svg2pdfconverter==1.2.1 -sqlalchemy==1.4.41 +sqlalchemy==1.4.42 svgutils==0.3.4 sympy==1.10.1 tabulate==0.9.0 tenacity==8.1.0 tensorwaves==0.4.8 terminado==0.16.0 -tinycss2==1.1.1 +tinycss2==1.2.1 toml==0.10.2 tomli==2.0.1 tornado==6.2 tox==3.26.0 tqdm==4.64.1 -traitlets==5.4.0 +traitlets==5.5.0 typed-ast==1.5.4 typing-extensions==4.4.0 ; python_version < "3.8.0" urllib3==1.26.12 diff --git a/.constraints/py3.8.txt b/.constraints/py3.8.txt index 22c3d6fb..6eb278f4 100644 --- a/.constraints/py3.8.txt +++ b/.constraints/py3.8.txt @@ -4,10 +4,10 @@ # # pip-compile --extra=dev --no-annotate --output-file=.constraints/py3.8.txt --strip-extras setup.py # -absl-py==1.2.0 +absl-py==1.3.0 alabaster==0.7.12 -ampform==0.14.3 -anyio==3.6.1 +ampform==0.14.4 +anyio==3.6.2 aquirdturtle-collapsible-headings==3.1.0 argon2-cffi==21.3.0 argon2-cffi-bindings==21.2.0 @@ -51,7 +51,7 @@ iminuit==2.17.0 importlib-metadata==5.0.0 importlib-resources==5.10.0 iniconfig==1.1.1 -ipykernel==6.16.0 +ipykernel==6.16.1 ipython==8.5.0 ipython-genutils==0.2.0 ipywidgets==8.0.2 @@ -63,15 +63,15 @@ jinja2==3.1.2 json5==0.9.10 jsonschema==4.16.0 jupyter-cache==0.5.0 -jupyter-client==7.4.2 -jupyter-core==4.11.1 +jupyter-client==7.4.3 +jupyter-core==4.11.2 jupyter-server==1.21.0 jupyterlab==3.4.8 jupyterlab-code-formatter==1.5.3 jupyterlab-markup==1.1.0 jupyterlab-myst==0.1.6 jupyterlab-pygments==0.2.2 -jupyterlab-server==2.15.2 +jupyterlab-server==2.16.1 jupyterlab-widgets==3.0.3 kaleido==0.2.1 kiwisolver==1.4.4 @@ -89,19 +89,19 @@ mpmath==1.2.1 mypy-extensions==0.4.3 myst-nb==0.17.1 myst-parser==0.18.1 -nbclassic==0.4.6 +nbclassic==0.4.5 nbclient==0.5.13 -nbconvert==7.2.1 +nbconvert==7.2.2 nbformat==5.7.0 nbmake==1.3.0 nest-asyncio==1.5.6 nodeenv==1.7.0 -notebook==6.4.12 -notebook-shim==0.1.0 +notebook==6.5.1 +notebook-shim==0.2.0 numpy==1.23.4 opt-einsum==3.3.0 packaging==21.3 -pandas==1.5.0 +pandas==1.5.1 pandocfilters==1.5.0 parso==0.8.3 particle==0.20.1 @@ -114,9 +114,9 @@ platformdirs==2.5.2 plotly==5.10.0 pluggy==1.0.0 pre-commit==2.20.0 -prometheus-client==0.14.1 +prometheus-client==0.15.0 prompt-toolkit==3.0.31 -psutil==5.9.2 +psutil==5.9.3 ptyprocess==0.7.0 pure-eval==0.2.2 py==1.11.0 @@ -133,12 +133,12 @@ pytest-forked==1.4.0 pytest-xdist==2.5.0 python-constraint==1.4.0 python-dateutil==2.8.2 -pytz==2022.4 +pytz==2022.5 pyyaml==6.0 pyzmq==24.0.1 qrules==0.9.7 requests==2.28.1 -scipy==1.9.2 +scipy==1.9.3 send2trash==1.8.0 six==1.16.0 sniffio==1.3.0 @@ -150,6 +150,7 @@ sphinx-book-theme==0.3.3 sphinx-codeautolink==0.12.0 sphinx-copybutton==0.5.0 sphinx-design==0.3.0 +sphinx-reredirects==0.1.1 sphinx-togglebutton==0.3.2 sphinxcontrib-applehelp==1.0.2 sphinxcontrib-bibtex==2.5.0 @@ -159,7 +160,7 @@ sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 sphinxcontrib-svg2pdfconverter==1.2.1 -sqlalchemy==1.4.41 +sqlalchemy==1.4.42 stack-data==0.5.1 svgutils==0.3.4 sympy==1.11.1 @@ -167,13 +168,13 @@ tabulate==0.9.0 tenacity==8.1.0 tensorwaves==0.4.8 terminado==0.16.0 -tinycss2==1.1.1 +tinycss2==1.2.1 toml==0.10.2 tomli==2.0.1 tornado==6.2 tox==3.26.0 tqdm==4.64.1 -traitlets==5.4.0 +traitlets==5.5.0 typing-extensions==4.4.0 urllib3==1.26.12 virtualenv==20.16.5 diff --git a/.constraints/py3.9.txt b/.constraints/py3.9.txt index fe7e6332..590ff86e 100644 --- a/.constraints/py3.9.txt +++ b/.constraints/py3.9.txt @@ -4,10 +4,10 @@ # # pip-compile --extra=dev --no-annotate --output-file=.constraints/py3.9.txt --strip-extras setup.py # -absl-py==1.2.0 +absl-py==1.3.0 alabaster==0.7.12 -ampform==0.14.3 -anyio==3.6.1 +ampform==0.14.4 +anyio==3.6.2 aquirdturtle-collapsible-headings==3.1.0 argon2-cffi==21.3.0 argon2-cffi-bindings==21.2.0 @@ -51,7 +51,7 @@ iminuit==2.17.0 importlib-metadata==5.0.0 importlib-resources==5.10.0 iniconfig==1.1.1 -ipykernel==6.16.0 +ipykernel==6.16.1 ipython==8.5.0 ipython-genutils==0.2.0 ipywidgets==8.0.2 @@ -63,15 +63,15 @@ jinja2==3.1.2 json5==0.9.10 jsonschema==4.16.0 jupyter-cache==0.5.0 -jupyter-client==7.4.2 -jupyter-core==4.11.1 +jupyter-client==7.4.3 +jupyter-core==4.11.2 jupyter-server==1.21.0 jupyterlab==3.4.8 jupyterlab-code-formatter==1.5.3 jupyterlab-markup==1.1.0 jupyterlab-myst==0.1.6 jupyterlab-pygments==0.2.2 -jupyterlab-server==2.15.2 +jupyterlab-server==2.16.1 jupyterlab-widgets==3.0.3 kaleido==0.2.1 kiwisolver==1.4.4 @@ -89,19 +89,19 @@ mpmath==1.2.1 mypy-extensions==0.4.3 myst-nb==0.17.1 myst-parser==0.18.1 -nbclassic==0.4.6 +nbclassic==0.4.5 nbclient==0.5.13 -nbconvert==7.2.1 +nbconvert==7.2.2 nbformat==5.7.0 nbmake==1.3.0 nest-asyncio==1.5.6 nodeenv==1.7.0 -notebook==6.4.12 -notebook-shim==0.1.0 +notebook==6.5.1 +notebook-shim==0.2.0 numpy==1.23.4 opt-einsum==3.3.0 packaging==21.3 -pandas==1.5.0 +pandas==1.5.1 pandocfilters==1.5.0 parso==0.8.3 particle==0.20.1 @@ -113,9 +113,9 @@ platformdirs==2.5.2 plotly==5.10.0 pluggy==1.0.0 pre-commit==2.20.0 -prometheus-client==0.14.1 +prometheus-client==0.15.0 prompt-toolkit==3.0.31 -psutil==5.9.2 +psutil==5.9.3 ptyprocess==0.7.0 pure-eval==0.2.2 py==1.11.0 @@ -132,12 +132,12 @@ pytest-forked==1.4.0 pytest-xdist==2.5.0 python-constraint==1.4.0 python-dateutil==2.8.2 -pytz==2022.4 +pytz==2022.5 pyyaml==6.0 pyzmq==24.0.1 qrules==0.9.7 requests==2.28.1 -scipy==1.9.2 +scipy==1.9.3 send2trash==1.8.0 six==1.16.0 sniffio==1.3.0 @@ -149,6 +149,7 @@ sphinx-book-theme==0.3.3 sphinx-codeautolink==0.12.0 sphinx-copybutton==0.5.0 sphinx-design==0.3.0 +sphinx-reredirects==0.1.1 sphinx-togglebutton==0.3.2 sphinxcontrib-applehelp==1.0.2 sphinxcontrib-bibtex==2.5.0 @@ -158,7 +159,7 @@ sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 sphinxcontrib-svg2pdfconverter==1.2.1 -sqlalchemy==1.4.41 +sqlalchemy==1.4.42 stack-data==0.5.1 svgutils==0.3.4 sympy==1.11.1 @@ -166,13 +167,13 @@ tabulate==0.9.0 tenacity==8.1.0 tensorwaves==0.4.8 terminado==0.16.0 -tinycss2==1.1.1 +tinycss2==1.2.1 toml==0.10.2 tomli==2.0.1 tornado==6.2 tox==3.26.0 tqdm==4.64.1 -traitlets==5.4.0 +traitlets==5.5.0 typing-extensions==4.4.0 urllib3==1.26.12 virtualenv==20.16.5 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4c0386ae..13d34d24 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ repos: - id: isort - repo: https://github.com/nbQA-dev/nbQA - rev: 1.5.2 + rev: 1.5.3 hooks: - id: nbqa-black additional_dependencies: @@ -74,12 +74,12 @@ repos: metadata.vscode - repo: https://github.com/pre-commit/mirrors-prettier - rev: v3.0.0-alpha.1 + rev: v3.0.0-alpha.3 hooks: - id: prettier - repo: https://github.com/ComPWA/mirrors-pyright - rev: v1.1.275 + rev: v1.1.276 hooks: - id: pyright diff --git a/docs/appendix.md b/docs/appendix.md index babee7c6..00712dd1 100644 --- a/docs/appendix.md +++ b/docs/appendix.md @@ -9,5 +9,7 @@ appendix/benchmark appendix/serialization appendix/ls-model appendix/homomorphism -appendix/polarization-fit +zz.polarization-fit ``` + + diff --git a/docs/appendix/serialization.ipynb b/docs/appendix/serialization.ipynb index 4c251158..757fab8f 100644 --- a/docs/appendix/serialization.ipynb +++ b/docs/appendix/serialization.ipynb @@ -4,13 +4,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Serialization" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "# Serialization\n", + "\n", "```{autolink-concat}\n", "```" ] @@ -191,13 +186,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Exported polarimetry grids" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "## Exported polarimetry grids\n", + "\n", "Decided to use the `alpha-x-arrays.json` format. It can be exported with {func}`.export_polarimetry_field`." ] }, @@ -248,13 +238,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Import and interpolate" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "## Import and interpolate\n", + "\n", "::::{margin}\n", ":::{warning}\n", "{obj}`~numpy.nan` values have to be replaced with `0.0` using {func}`numpy.nan_to_num`.\n", @@ -388,6 +373,10 @@ "source": [ ":::{note}\n", "The interpolated values over this phase space sample have been visualized by interpolating again over a {obj}`~numpy.meshgrid` with {obj}`scipy.interpolate.griddata`.\n", + ":::\n", + "\n", + ":::{tip}\n", + "{doc}`/zz.polarization-fit` shows how this interpolation method can be used to determine the polarization $\\vec{P}$ from a given intensity distribution.\n", ":::" ] } diff --git a/docs/conf.py b/docs/conf.py index 9559096d..c98a2a3d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -243,6 +243,7 @@ def print_missing_file_warning(filename: str) -> None: ] extensions = [ "myst_nb", + "sphinx_reredirects", "sphinx.ext.autosectionlabel", "sphinx.ext.intersphinx", "sphinx.ext.napoleon", @@ -365,6 +366,9 @@ def print_missing_file_warning(filename: str) -> None: numfig = True primary_domain = "py" pygments_style = "sphinx" +redirects = { + "appendix/polarization-fit": "../zz.polarization-fit.html", +} suppress_warnings = [ "mystnb.mime_priority", # plotly figures in LaTeX build # https://github.com/executablebooks/MyST-NB/blob/4dcf7c5/docs/conf.py#L46-L47 diff --git a/docs/uncertainties.ipynb b/docs/uncertainties.ipynb index 092e87c6..5e8cfb65 100644 --- a/docs/uncertainties.ipynb +++ b/docs/uncertainties.ipynb @@ -2430,7 +2430,7 @@ "metadata": {}, "source": [ ":::{tip}\n", - "See {ref}`appendix/serialization:Import and interpolate` for how to use these grids in an an analysis.\n", + "See {ref}`appendix/serialization:Import and interpolate` for how to use these grids in an an analysis and see {doc}`/zz.polarization-fit` for how to use these fields to determine the polarization from a measured distribution.\n", ":::" ] } diff --git a/docs/appendix/polarization-fit.ipynb b/docs/zz.polarization-fit.ipynb similarity index 66% rename from docs/appendix/polarization-fit.ipynb rename to docs/zz.polarization-fit.ipynb index 79871124..5c8b6ec4 100644 --- a/docs/appendix/polarization-fit.ipynb +++ b/docs/zz.polarization-fit.ipynb @@ -8,20 +8,14 @@ "source": [ "# Determination of polarization\n", "\n", - "```{autolink-concat}\n", - "```\n", - "\n", - "Given the aligned polarimeter field $\\vec\\alpha$ and the corresponding intensity distribution $I_0$, the intensity distribution $I$ for a polarized decay can be computed as follows:\n", - "\n", - "$$\n", - "I\\left(\\phi,\\theta,\\chi; \\tau\\right) = I_0(\\tau)\\left(1+\\vec{P} R(\\phi,\\theta,\\chi) \\vec{\\alpha}(\\tau)\\right)\n", - "$$ (eq:master.intensity)\n", - "\n", - "with $R$ the rotation matrix over the decay plane orientation, represented in Euler angles $\\left(\\phi, \\theta, \\chi\\right)$.\n", - "\n", - "In this section, we show that it's possible to determine the polarization $\\vec{P}$ from a given intensity distribution $I$ of a $\\lambda_c$ decay if we the $\\vec\\alpha$ fields and the corresponding $I_0$ values of that $\\Lambda_c$ decay. Systematic uncertainties on $\\vec{P}$ are determined in a similar way as in {doc}`/uncertainties`: the same fit procedure is performed for each alternative model and the extrema on the resulting $\\vec{P}$-values are taken as the min-max systematic uncertainties.\n", + "::::{only} html\n", + ":::{margin}\n", + "This notebook has a `zz.` prefix because it has to be executed _after_ the polarimeter fields are exported in {doc}`/uncertainties`.\n", + ":::\n", + "::::\n", "\n", - "The intensity and alpha functions are computed from exact amplitude models, but they can be substituted by functions that interpolate the exported polarimeter fields from {ref}`uncertainties:Exported distributions` over a phase space sample. This would remove the need to formulate a complete amplitude model in order to determine polarization. See {ref}`appendix/serialization:Import and interpolate` for how to interpolate these exported distributions over the Dalitz plane." + "```{autolink-concat}\n", + "```" ] }, { @@ -45,26 +39,21 @@ "\n", "import logging\n", "import os\n", + "from functools import lru_cache\n", "from warnings import filterwarnings\n", "\n", "import iminuit\n", "import jax.numpy as jnp\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", - "import yaml\n", "from IPython.display import Latex, Markdown\n", - "from tensorwaves.interface import DataSample, Function\n", + "from scipy.interpolate import interp2d\n", + "from tensorwaves.interface import DataSample\n", "from tqdm.auto import tqdm\n", "\n", - "from polarimetry import formulate_polarimetry\n", - "from polarimetry.amplitude import AmplitudeModel, DalitzPlotDecompositionBuilder\n", - "from polarimetry.data import create_data_transformer, generate_phasespace_sample\n", - "from polarimetry.io import (\n", - " mute_jax_warnings,\n", - " perform_cached_doit,\n", - " perform_cached_lambdify,\n", - ")\n", - "from polarimetry.lhcb import load_model_builder, load_model_parameters\n", + "from polarimetry.data import generate_phasespace_sample\n", + "from polarimetry.io import import_polarimetry_field, mute_jax_warnings\n", + "from polarimetry.lhcb import load_model_builder\n", "from polarimetry.lhcb.particle import load_particles\n", "from polarimetry.plot import use_mpl_latex_fonts\n", "\n", @@ -79,53 +68,22 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": { - "mystnb": { - "code_prompt_show": "Formulate symbolic expressions for intensity and polarization" - }, - "tags": [ - "hide-cell", - "scroll-input" - ] + "tags": [] }, - "outputs": [], "source": [ - "def load_model(\n", - " file: str, model_choice: int | str = 0, reference_subsystem: int = 1\n", - ") -> tuple[AmplitudeModel, DalitzPlotDecompositionBuilder]:\n", - " particles = load_particles(\"../../data/particle-definitions.yaml\")\n", - " builder = load_model_builder(file, particles, model_choice)\n", - " parameters = load_model_parameters(file, builder.decay, model_choice, particles)\n", - " model = builder.formulate(reference_subsystem, cleanup_summations=True)\n", - " model.parameter_defaults.update(parameters)\n", - " return model, builder\n", - "\n", - "\n", - "MODEL_FILE = \"../../data/model-definitions.yaml\"\n", - "with open(MODEL_FILE) as f:\n", - " ALL_MODEL_TITLES = list(yaml.safe_load(f))\n", - "NOMINAL_MODEL_TITLE = ALL_MODEL_TITLES[0]\n", - "\n", - "MODELS = {}\n", - "INTENSITY_EXPRS = {}\n", - "POLARIMETRY_EXPRS = {}\n", - "for title in tqdm(ALL_MODEL_TITLES, desc=\"Formulating models\", disable=NO_TQDM):\n", - " if \"LS couplings\" in title:\n", - " continue\n", - " MODELS[title], builder = load_model(MODEL_FILE, model_choice=title)\n", - " folded_polarimetry_exprs = formulate_polarimetry(builder, reference_subsystem=1)\n", - " POLARIMETRY_EXPRS[title] = tuple(\n", - " perform_cached_doit(expr.doit().xreplace(MODELS[title].amplitudes))\n", - " for expr in tqdm(folded_polarimetry_exprs, disable=NO_TQDM, leave=False)\n", - " )\n", - " INTENSITY_EXPRS[title] = perform_cached_doit(MODELS[title].full_expression)\n", - " del title, builder, folded_polarimetry_exprs\n", + "Given the aligned polarimeter field $\\vec\\alpha$ and the corresponding intensity distribution $I_0$, the intensity distribution $I$ for a polarized decay can be computed as follows:\n", + "\n", + "$$\n", + "I\\left(\\phi,\\theta,\\chi; \\tau\\right) = I_0(\\tau)\\left(1+\\vec{P} R(\\phi,\\theta,\\chi) \\vec{\\alpha}(\\tau)\\right)\n", + "$$ (eq:master.intensity)\n", "\n", - "assert len(MODELS) == 17\n", - "assert len(INTENSITY_EXPRS) == 17\n", - "assert len(POLARIMETRY_EXPRS) == 17" + "with $R$ the rotation matrix over the decay plane orientation, represented in Euler angles $\\left(\\phi, \\theta, \\chi\\right)$.\n", + "\n", + "In this section, we show that it's possible to determine the polarization $\\vec{P}$ from a given intensity distribution $I$ of a $\\lambda_c$ decay if we the $\\vec\\alpha$ fields and the corresponding $I_0$ values of that $\\Lambda_c$ decay. We get $\\vec\\alpha$ and $I_0$ by interpolating the grid samples provided from {ref}`uncertainties:Exported distributions` using the method described in {ref}`appendix/serialization:Import and interpolate`.\n", + "\n", + "For this study, a phase space sample is uniformly generated over the Dalitz plane variables $\\tau$. The phase space sample is extended with uniform distributions over the decay plane angles $\\left(\\phi, \\theta, \\chi\\right)$, so that the phase space can be used to generate a hit-and-miss toy sample for a polarized intensity distribution." ] }, { @@ -133,7 +91,7 @@ "execution_count": null, "metadata": { "mystnb": { - "code_prompt_show": "Convert expressions to numerical functions" + "code_prompt_show": "Generate phase space sample" }, "tags": [ "hide-input" @@ -141,56 +99,72 @@ }, "outputs": [], "source": [ - "POLARIMETRY_FUNCS = {\n", - " title: tuple(\n", - " perform_cached_lambdify(expr.xreplace(MODELS[title].parameter_defaults))\n", - " for expr in tqdm(polarimetry_exprs, disable=NO_TQDM, leave=False)\n", - " )\n", - " for title, polarimetry_exprs in tqdm(POLARIMETRY_EXPRS.items(), disable=NO_TQDM)\n", - "}\n", - "INTENSITY_FUNCS = {\n", - " title: perform_cached_lambdify(expr.xreplace(MODELS[title].parameter_defaults))\n", - " for title, expr in tqdm(INTENSITY_EXPRS.items(), disable=NO_TQDM)\n", - "}\n", - "\n", - "NOMINAL_MODEL_TITLE = ALL_MODEL_TITLES[0]\n", - "NOMINAL_MODEL = MODELS[NOMINAL_MODEL_TITLE]\n", - "NOMINAL_INTENSITY_FUNC = INTENSITY_FUNCS[NOMINAL_MODEL_TITLE]\n", - "NOMINAL_POLARIMETRY_FUNCS = POLARIMETRY_FUNCS[NOMINAL_MODEL_TITLE]" + "DECAY = load_model_builder(\n", + " \"../data/model-definitions.yaml\",\n", + " load_particles(\"../data/particle-definitions.yaml\"),\n", + " model_id=0,\n", + ").decay\n", + "\n", + "N_EVENTS = 100_000\n", + "# Dalitz variables\n", + "PHSP = generate_phasespace_sample(DECAY, N_EVENTS, seed=0)\n", + "# Decay plane variables\n", + "PHSP[\"phi\"] = np.random.uniform(-np.pi, +np.pi, N_EVENTS)\n", + "PHSP[\"cos_theta\"] = np.random.uniform(-1, +1, N_EVENTS)\n", + "PHSP[\"chi\"] = np.random.uniform(-np.pi, +np.pi, N_EVENTS)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The phase space sample is uniformly generated over the Dalitz plane variables $\\tau$. In addition, we extend the phase space samples with a uniform distribution over the decay plane angles $\\left(\\phi, \\theta, \\chi\\right)$." + "We now generate an intensity distribution over the phase space sample given a certain[^1] value for $\\vec{P}$ using Eq. {eq}`eq:master.intensity` and by interpolating the $\\vec\\alpha$ and $I_0$ fields with the grid samples for the nominal model.\n", + "\n", + "[^1]: See [p. 18](https://arxiv.org/pdf/2208.03262.pdf#page=20) of _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)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "tags": [] + "jupyter": { + "source_hidden": true + }, + "mystnb": { + "code_prompt_show": "Code for interpolating α and I₀" + }, + "tags": [ + "scroll-input", + "hide-input" + ] }, "outputs": [], "source": [ - "N_EVENTS = 100_000\n", - "# Dalitz variables\n", - "PHSP = generate_phasespace_sample(NOMINAL_MODEL.decay, N_EVENTS, seed=0)\n", - "PHSP.update(create_data_transformer(NOMINAL_MODEL)(PHSP))\n", - "# Decay plane variables\n", - "PHSP[\"phi\"] = np.random.uniform(-np.pi, +np.pi, N_EVENTS)\n", - "PHSP[\"cos_theta\"] = np.random.uniform(-1, +1, N_EVENTS)\n", - "PHSP[\"chi\"] = np.random.uniform(-np.pi, +np.pi, N_EVENTS)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now generate an intensity distribution over the phase space sample given a certain[^1] value for $\\vec{P}$ using Eq. {eq}`eq:master.intensity`:\n", + "def interpolate_intensity(phsp: DataSample, model_id: int) -> jnp.ndarray:\n", + " x = PHSP[\"sigma1\"]\n", + " y = PHSP[\"sigma2\"]\n", + " return jnp.array(create_interpolated_function(model_id, \"intensity\")(x, y))\n", "\n", - "[^1]: See [p. 18](https://arxiv.org/pdf/2208.03262.pdf#page=20) of _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)" + "\n", + "def interpolate_polarimetry_field(phsp: DataSample, model_id: int) -> jnp.ndarray:\n", + " x = PHSP[\"sigma1\"]\n", + " y = PHSP[\"sigma2\"]\n", + " return jnp.array(\n", + " [create_interpolated_function(model_id, f\"alpha_{i}\")(x, y) for i in \"xyz\"]\n", + " )\n", + "\n", + "\n", + "@lru_cache(maxsize=0)\n", + "def create_interpolated_function(model_id: int, variable: str):\n", + " field_file = f\"_static/export/polarimetry-field-model-{model_id}.json\"\n", + " field_data = import_polarimetry_field(field_file)\n", + " interpolated_func = interp2d(\n", + " x=field_data[\"m^2_Kpi\"],\n", + " y=field_data[\"m^2_pK\"],\n", + " z=np.nan_to_num(field_data[variable]),\n", + " kind=\"linear\",\n", + " )\n", + " return np.vectorize(interpolated_func)" ] }, { @@ -214,18 +188,12 @@ " Px: float,\n", " Py: float,\n", " Pz: float,\n", - " intensity_func: Function[DataSample, jnp.ndarray],\n", - " polarimetry_funcs: tuple[\n", - " Function[DataSample, jnp.ndarray],\n", - " Function[DataSample, jnp.ndarray],\n", - " Function[DataSample, jnp.ndarray],\n", - " ],\n", + " I0: jnp.ndarray,\n", + " alpha: jnp.ndarray,\n", " phsp: DataSample,\n", ") -> jnp.array:\n", " P = jnp.array([Px, Py, Pz])\n", " R = compute_rotation_matrix(phsp)\n", - " alpha = jnp.array([func(phsp).real for func in polarimetry_funcs])\n", - " I0 = intensity_func(phsp)\n", " return I0 * (1 + jnp.einsum(\"i,ij...,j...->...\", P, R, alpha))\n", "\n", "\n", @@ -272,7 +240,10 @@ "source": [ "P = (+0.2165, +0.0108, -0.665)\n", "I = compute_polarized_intensity(\n", - " *P, NOMINAL_INTENSITY_FUNC, NOMINAL_POLARIMETRY_FUNCS, PHSP\n", + " *P,\n", + " I0=interpolate_intensity(PHSP, model_id=0),\n", + " alpha=interpolate_polarimetry_field(PHSP, model_id=0),\n", + " phsp=PHSP,\n", ")\n", "I /= jnp.mean(I) # normalized times N for log likelihood" ] @@ -332,7 +303,7 @@ "w_i = n\\,I_i\\,\\big/\\,\\sum_j^n I_j\\,,\n", "$$ (eq:intensity-as-nll-weight)\n", "\n", - "such that $\\sum w_i = n$." + "such that $\\sum w_i = n$. To propagate uncertainties, a fit is performed using the exported grids of each alternative model." ] }, { @@ -348,9 +319,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "jupyter": { - "source_hidden": true - }, "mystnb": { "code_prompt_show": "Fit polarization to generated distribution" }, @@ -360,33 +328,25 @@ }, "outputs": [], "source": [ - "def perform_fit(model_title: str) -> iminuit.Minuit:\n", - " progress_bar = tqdm(desc=model_title, disable=NO_TQDM, leave=False)\n", - " intensity_func = INTENSITY_FUNCS[model_title]\n", - " polarimetry_funcs = POLARIMETRY_FUNCS[model_title]\n", + "def perform_fit(phsp: DataSample, model_id: int) -> iminuit.Minuit:\n", + " I0 = interpolate_intensity(phsp, model_id)\n", + " alpha = interpolate_polarimetry_field(phsp, model_id)\n", "\n", " def weighted_nll(Px: float, Py: float, Pz: float) -> float:\n", - " I_new = compute_polarized_intensity(\n", - " Px, Py, Pz, intensity_func, polarimetry_funcs, PHSP\n", - " )\n", + " I_new = compute_polarized_intensity(Px, Py, Pz, I0, alpha, phsp)\n", " I_new /= jnp.sum(I_new)\n", - " progress_bar.update()\n", " estimator_value = -jnp.sum(jnp.log(I_new) * I)\n", - " progress_bar.set_postfix_str(\n", - " f\"NLL={estimator_value:.4g}, Px={Px:+.3f}, Py={Py:+.3f}, Pz={Pz:+.3f}\"\n", - " )\n", " return estimator_value\n", "\n", " optimizer = iminuit.Minuit(weighted_nll, *P_guess)\n", - " progress_bar.close()\n", " optimizer.errordef = optimizer.LIKELIHOOD\n", " return optimizer.migrad()\n", "\n", "\n", - "FIT_RESULTS = {\n", - " title: perform_fit(title)\n", - " for title in tqdm(MODELS, desc=\"Performing fit\", disable=NO_TQDM)\n", - "}" + "FIT_RESULTS = [\n", + " perform_fit(PHSP, i)\n", + " for i in tqdm(range(17), desc=\"Performing fits\", disable=NO_TQDM)\n", + "]" ] }, { @@ -405,7 +365,7 @@ }, "outputs": [], "source": [ - "FIT_RESULTS[NOMINAL_MODEL_TITLE]" + "FIT_RESULTS[0]" ] }, { @@ -422,9 +382,7 @@ }, "outputs": [], "source": [ - "P_fit_values = 100 * np.array(\n", - " [[p.value for p in fit_result.params] for fit_result in FIT_RESULTS.values()]\n", - ")\n", + "P_fit_values = 100 * np.array([[p.value for p in fit.params] for fit in FIT_RESULTS])\n", "P_fit_nominal = P_fit_values[0]\n", "P_max = (P_fit_values[1:] - P_fit_nominal).max(axis=0)\n", "P_min = (P_fit_values[1:] - P_fit_nominal).min(axis=0)\n", diff --git a/pyproject.toml b/pyproject.toml index 766cafd8..0f10d9d6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ black = [ flake8 = [ "--extend-ignore=E501,E731", "--per-file-ignores=docs/appendix/homomorphism*:E402", - "--per-file-ignores=docs/appendix/polarization-fit*:E741", + "--per-file-ignores=docs/zz.polarization-fit*:E741", ] isort = [ "--line-length=85", diff --git a/setup.cfg b/setup.cfg index 12f9ba91..1a4266c2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -42,6 +42,7 @@ doc = sphinx-codeautolink[ipython] sphinx-copybutton sphinx-design + sphinx-reredirects sphinx-togglebutton sphinxcontrib-bibtex >=2.2 # bibtex_reference_style sphinxcontrib-svg2pdfconverter