Analytic continuation

Note

Improvements to analytic continuation in AmpForm are currently being developed in [TR-003] Chew-Mandelstam and [TR-004] Analyticity (WIP).

Analytic continuation allows one to handle resonances just below threshold (\(m_0 < m_a + m_b\) in Eq. (9)). In practice, this entails using a specific function for \(\rho\) in Eq. (6).

Definitions

Three usual choices for \(\rho\) are the following:

import sympy as sp
from IPython.display import Math

1) Break-up momentum

The sqrt() or ComplexSqrt of BreakupMomentumSquared:

from ampform.dynamics import BreakupMomentumSquared

s, m_a, m_b = sp.symbols("s, m_a, m_b", real=True)
q_squared = BreakupMomentumSquared(s, m_a, m_b)
Math(sp.multiline_latex(q_squared, q_squared.doit(), environment="eqnarray"))
\[\displaystyle \begin{eqnarray} q^2\left(s\right) & = & \frac{\left(s - \left(m_{a} - m_{b}\right)^{2}\right) \left(s - \left(m_{a} + m_{b}\right)^{2}\right)}{4 s} \end{eqnarray}\]

2) ‘Normal’ phase space factor

The ‘normal’ PhaseSpaceFactor (the denominator makes the difference to (6)!):

from ampform.dynamics import PhaseSpaceFactor

rho = PhaseSpaceFactor(s, m_a, m_b)
Math(sp.multiline_latex(rho, rho.evaluate(), environment="eqnarray"))
\[\displaystyle \begin{eqnarray} \rho\left(s\right) & = & \frac{\sqrt{q^2\left(s\right)}}{8 \pi \sqrt{s}} \end{eqnarray}\]

3) ‘Complex’ phase space factor

A PhaseSpaceFactorComplex that uses ComplexSqrt:

from ampform.dynamics import PhaseSpaceFactorComplex

rho_c = PhaseSpaceFactorComplex(s, m_a, m_b)
Math(sp.multiline_latex(rho_c, rho_c.evaluate(), environment="eqnarray"))
\[\displaystyle \begin{eqnarray} \rho^\mathrm{c}\left(s\right) & = & \frac{\sqrt[\mathrm{c}]{q^2\left(s\right)}}{8 \pi \sqrt{s}} \end{eqnarray}\]

4) ‘Analytic continuation’ of the phase space factor

The following ‘case-by-case’ analytic continuation, PhaseSpaceFactorAnalytic:

from ampform.dynamics import PhaseSpaceFactorAnalytic

rho_ac = PhaseSpaceFactorAnalytic(s, m_a, m_b)
Math(sp.multiline_latex(rho_ac, rho_ac.evaluate(), environment="eqnarray"))
\[\begin{split}\displaystyle \begin{eqnarray} \rho^\mathrm{ac}\left(s\right) & = & \begin{cases} \frac{i \log{\left(\left|{\frac{\hat{\rho}\left(s\right) + 1}{\hat{\rho}\left(s\right) - 1}}\right| \right)} \hat{\rho}\left(s\right)}{\pi} & \text{for}\: s < 0 \\\frac{i \log{\left(\left|{\frac{\hat{\rho}\left(s\right) + 1}{\hat{\rho}\left(s\right) - 1}}\right| \right)} \hat{\rho}\left(s\right)}{\pi} + \hat{\rho}\left(s\right) & \text{for}\: s > \left(m_{a} + m_{b}\right)^{2} \\\frac{2 i \operatorname{atan}{\left(\frac{1}{\hat{\rho}\left(s\right)} \right)} \hat{\rho}\left(s\right)}{\pi} & \text{otherwise} \end{cases} \end{eqnarray}\end{split}\]

with

from ampform.dynamics import PhaseSpaceFactorAbs

rho_hat = PhaseSpaceFactorAbs(s, m_a, m_b)
Math(sp.multiline_latex(rho_hat, rho_hat.evaluate(), environment="eqnarray"))
\[\displaystyle \begin{eqnarray} \hat{\rho}\left(s\right) & = & \frac{\sqrt{\left|{q^2\left(s\right)}\right|}}{8 \pi \sqrt{s}} \end{eqnarray}\]

(Mind the absolute value.)

Visualization

%matplotlib widget
import matplotlib.pyplot as plt
import mpl_interactions.ipyplot as iplt
import numpy as np

import symplot
from ampform.dynamics import ComplexSqrt

m = sp.Symbol("m", real=True)
rho_c = PhaseSpaceFactorComplex(m**2, m_a, m_b)
rho_ac = PhaseSpaceFactorAnalytic(m**2, m_a, m_b)
np_rho_c, sliders = symplot.prepare_sliders(
    plot_symbol=m, expression=rho_c.doit()
)
np_rho_ac = sp.lambdify((m, m_a, m_b), rho_ac.doit())
np_breakup_momentum = sp.lambdify(
    (m, m_a, m_b), ComplexSqrt(q_squared.subs(s, m**2).doit())
)
plot_domain = np.linspace(0, 3, 500)
sliders.set_ranges(
    m_a=(0, 2, 200),
    m_b=(0, 2, 200),
)
sliders.set_values(
    m_a=0.6,
    m_b=1.25,
)
fig, axes = plt.subplots(1, 3, figsize=[10, 4], tight_layout=True)
fig.canvas.toolbar_visible = False

ax_q, ax_rho, ax_rho_ac = axes
for ax in axes:
    ax.set_xlabel("$m$")

ylim_q = (-0.04, 1.0)
ylim_rho = (-0.002, 0.05)


def func_imag(func, *args, **kwargs):
    return lambda *args, **kwargs: func(*args, **kwargs).imag


def func_real(func, *args, **kwargs):
    return lambda *args, **kwargs: func(*args, **kwargs).real


q_math = ComplexSqrt(sp.Symbol("q^2"))
ax_q.set_title(f"${sp.latex(q_math)}$")
controls = iplt.plot(
    plot_domain,
    func_real(np_breakup_momentum),
    label="real",
    **sliders,
    ylim=ylim_q,
    ax=ax_q,
    alpha=0.7,
)
iplt.plot(
    plot_domain,
    func_imag(np_breakup_momentum),
    label="imaginary",
    controls=controls,
    ylim=ylim_q,
    ax=ax_q,
    alpha=0.7,
)

ax_rho.set_title(f"${sp.latex(rho_c)}$")
iplt.plot(
    plot_domain,
    func_real(np_rho_c),
    label="real",
    controls=controls,
    ylim=ylim_rho,
    ax=ax_rho,
    alpha=0.7,
)
iplt.plot(
    plot_domain,
    func_imag(np_rho_c),
    label="imaginary",
    controls=controls,
    ylim=ylim_rho,
    ax=ax_rho,
    alpha=0.7,
)

ax_rho_ac.set_title("analytic")
iplt.plot(
    plot_domain,
    func_real(np_rho_ac),
    label="real",
    controls=controls,
    ylim=ylim_rho,
    ax=ax_rho_ac,
    alpha=0.7,
)
iplt.plot(
    plot_domain,
    func_imag(np_rho_ac),
    label="imaginary",
    controls=controls,
    ylim=ylim_rho,
    ax=ax_rho_ac,
    alpha=0.7,
)
plt.legend(loc="upper right")

plt.show()
../../_images/analytic-continuation_30_0.svg