diff --git a/docs/report/999.ipynb b/docs/report/999.ipynb index 112bdbc3..7666a536 100644 --- a/docs/report/999.ipynb +++ b/docs/report/999.ipynb @@ -60,10 +60,30 @@ "tags": [] }, "source": [ - ":::{note}Summary\n", + ":::{admonition} Summary\n", "- This document introduces Amplitude Analysis / Partial Wave Analysis (PWA) by demonstrating its application to a specific reaction channel and amplitude model. It aims to equip readers with a basic understanding of the full workflow and methodologies of PWA in hadron physics through a practical, hands-on example.\n", "- Only basic Python programming and libraries (e.g. `numpy`, `scipy`, etc.) are used to illustrate the more fundamental steps in a PWA.\n", - "- Before advancing to the complexities of symbolic expressions (computations) with tools such as `sympy` as illustrated in PWA101 v2.0 (see [here](https://compwa.github.io/gluex-nstar)), we will focus on Python basics. This will allow us to draw a comparison between basic Python programming and symbolic computations.\n", + "- Before advancing to the complexities of symbolic expressions (computations) with tools such as `sympy` as illustrated in PWA101 v2.0, we will focus on Python basics. This will allow us to draw a comparison between basic Python programming and symbolic computations.\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ":::{seealso}\n", + "[PWA101 v2.0](https://compwa.github.io/gluex-nstar): Doing PWA symbolically for the same (and similar) reaction.\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + ":::{note}\n", + "Calculations with 4-vectors in this report are performed with the [`vector`](https://vector.readthedocs.io/en/latest/usage/intro.html) package.\n", ":::" ] }, @@ -401,10 +421,10 @@ "tags": [] }, "source": [ - "We use the $\\gamma$ beam energy in the lab frame as the input:\n", + "We use the $\\gamma$ beam energy in the lab frame as input:\n", "\n", "$$\n", - "E_{\\gamma, lab} = 8.5 \\; GeV\n", + "E_{\\gamma, \\text{lab}} = 8.5 \\; \\text{GeV}\n", "$$ (beam_energy_label)\n", "\n", "From this, we can calculate the energy of the gamma in the CM frame as follows.\n", @@ -412,7 +432,7 @@ "The four-momentum of photon (beam) in the lab frame:\n", "\n", "$$\n", - "p_{\\gamma,lab} = (E_{\\gamma, lab}, \\vec{p}_{\\gamma,lab})\n", + "p_{\\gamma,\\text{lab}} = (E_{\\gamma, \\text{lab}}, \\vec{p}_{\\gamma,\\text{lab}})\n", "$$ (beam_four_momentum)\n", "\n", "Since photon is massless, \n", @@ -436,7 +456,7 @@ "The four-momentum of proton (target) in the lab frame:\n", "\n", "$$\n", - "p_{p,lab} = (m_p, \\vec{0})\n", + "p_{p,\\text{lab}} = (m_p, \\vec{0})\n", "$$ (four_momentum_target_lab)\n", "\n", "where $m_p$ is the proton mass.\n", @@ -444,7 +464,7 @@ "We have the total four-momentum in lab frame:\n", "\n", "$$\n", - "p_{tot,lab} = p_{\\gamma,lab} + p_{p,lab}\n", + "p_{\\text{tot},\\text{lab}} = p_{\\gamma,\\text{lab}} + p_{p,\\text{lab}}\n", "$$ (total_four_momentum_lab_frame)\n", "\n", "$$\n", @@ -454,7 +474,7 @@ "From the **lab frame** perspective, the CM total energy with expression in quantities from the **lab frame** is thus:\n", "\n", "$$\n", - "\\sqrt{s} = E_0 = m_0 = \\sqrt{2 E_{\\gamma,lab} m_p + m_p^2}\n", + "\\sqrt{s} = E_0 = m_0 = \\sqrt{2 E_{\\gamma,\\text{lab}} m_p + m_p^2}\n", "$$ (lab_frame_CM_total_energy)" ] }, @@ -555,7 +575,7 @@ "Thus, we then have the mass of the system $m_0$ (or $m_{p\\gamma}$ in this case) in CM frame:\n", "\n", "$$\n", - "E_{0} = m_0\\approx 4.102 \\;\\; GeV \n", + "E_{0} = m_0\\approx 4.102 \\;\\; \\text{GeV} \n", "$$" ] }, @@ -565,9 +585,11 @@ "tags": [] }, "source": [ + ":::{note}\n", "The [`phasespace`](https://github.com/zfit/phasespace) library is a Python package designed to simulate particle decays according to the principles of relativistic kinematics and phase space distributions. \n", "\n", - "We use the [`phasespace`](https://github.com/zfit/phasespace) to generate decay particles (4-momentum and weights):" + "We use the [`phasespace`](https://github.com/zfit/phasespace) to generate decay particles (4-momentum and weights):\n", + ":::" ] }, { @@ -589,8 +611,7 @@ "tags": [] }, "source": [ - ":::{admonition}\n", - "**weights**:\n", + ":::{admonition} **weights**:\n", "the statistical weights for each generated event. These weights represent how likely each particular event configuration (set of momenta and energies) is, based on phase space considerations.\n", ":::" ] @@ -599,8 +620,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - ":::{admonition}\n", - "**`particles`**:\n", + ":::{admonition} **`particles`**:\n", "this (python array) contains the information of the generated four-momenta (energy and momentum components) of the decay products for each event. \n", ":::" ] @@ -638,10 +658,24 @@ "n_final_state = 3" ] }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + ":::{tip}\n", + "The function block below is scrollable.\n", + ":::" + ] + }, { "cell_type": "code", "execution_count": null, "metadata": { + "jupyter": { + "source_hidden": true + }, "mystnb": { "code_prompt_show": "(Click to show) These are some functions that we defined for a structured process for generating phase space samples of particle decays and converting them into four-momentum vectors using TensorFlow and the phasespace Python package." }, @@ -733,7 +767,7 @@ " - Removing Excess\n", "\n", " \n", - " Once the target sample size is reached or exceeded, `remove_overflow` trims the sample to precisely match the requested size.\n", + " Once the target sample size is reached or exceeded, `remove_overflow()` trims the sample to precisely match the requested size.\n", "\n", "- Step 3, Convert to [Four-Momentum Vectors](https://vector.readthedocs.io/en/latest/api/backends/vector.backends.numpy.html#vector.backends.numpy.MomentumNumpy4D) (`to_vector()`)\n", " - Four-Momentum Representation\n", @@ -786,16 +820,15 @@ { "cell_type": "markdown", "metadata": { - "tags": [ - "remove-cell" - ] + "tags": [] }, "source": [ "To find $p_a$ and $p_b$ by 4-momentum conservation, energy conservation in this case.\n", "\n", "Given that:\n", "\n", - "\\begin{align}\n", + "```{math}\n", + ":label: m_a_m_b_p_a_x_p_a_z\n", "\n", "m_a = m_{\\gamma} =0 \\\\\n", "\n", @@ -805,109 +838,51 @@ "\n", "p_{a,z} = - p_{b,z}\n", "\n", - "\\end{align}\n", + "```\n", "\n", "Due to energy conservation, we have:\n", "\n", - "\\begin{align}\n", + "```{math}\n", + ":label: E_a_+_E_b_E_0\n", "\n", "E_a + E_b = E_1 + E_2 + E_3 = E_0 \\\\\n", "\n", "E_a+ E_b = \\sqrt{m_a^2 + p_a^2} + \\sqrt{m_b^2 + p_b^2} = E_0\n", "\n", - "\\end{align}\n", - "\n", + "```\n", "\n", "Since $m_a=0$ and $p_a = -p_b$, thus\n", - "$$\n", - "p_a + \\sqrt{m_b^2 + (-p_a)^2} = E_0\n", - "$$\n", - "\n", - "Reorganize and get,\n", - "$$\n", - "p_{a,z} + \\sqrt{m_p^2 + p_a^2} - E_0 = 0\n", - "$$\n", - "\n", - "thus\n", - "\n", - "$$\n", - "p_{a,z} = \\frac{E_0^2 - m_p^2}{2E_0}\n", - "$$\n", + "```{math}\n", + ":label: p_a_+_m_b_2_-_p_a_2\n", "\n", - "then\n", - "\n", - "\\begin{align}\n", - "p_{b,z} = -p_{a,z}\n", - "\n", - "E_a =p_a \\\\\n", - "\n", - "E_{b} = \\sqrt{m_b^2+p_b^2}\n", - "\\end{align}" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "To find $p_a$ and $p_b$ by 4-momentum conservation, energy conservation in this case.\n", - "\n", - "Given that:\n", - "\n", - "$m_a = m_{\\gamma} =0$,\n", - "\n", - "$m_b = m_p$,\n", - "\n", - "$p_{a,x} = p_{a,y} = 0 = p_{b,x} = p_{b,y}$\n", - "\n", - "and\n", - "\n", - "$p_{a,z} = - p_{b,z}$\n", - "\n", - "Due to energy conservation, we have:\n", - "\n", - "$$\n", - "E_a + E_b = E_1 + E_2 + E_3 = E_0\n", - "$$\n", - "\n", - "And\n", - "$$\n", - "E_a+ E_b = \\sqrt{m_a^2 + p_a^2} + \\sqrt{m_b^2 + p_b^2} = E_0\n", - "$$\n", - "\n", - "Since $m_a=0$ and $p_a = -p_b$, thus\n", - "\n", - "$$\n", "p_a + \\sqrt{m_b^2 + (-p_a)^2} = E_0\n", - "$$\n", + "```\n", "\n", - "Reorganize and get,\n", + "Reorganizing, we get,\n", + "```{math}\n", + ":label: p_a_z_m_p_2_p_a_2\n", "\n", - "$$\n", "p_{a,z} + \\sqrt{m_p^2 + p_a^2} - E_0 = 0\n", - "$$\n", - "\n", + "```\n", "thus\n", "\n", - "$$\n", + "```{math}\n", + ":label: p_a_z_E_0_2_-_m_p_2\n", + "\n", "p_{a,z} = \\frac{E_0^2 - m_p^2}{2E_0}\n", - "$$\n", + "```\n", "\n", "then\n", "\n", - "$$\n", - "p_{b,z} = -p_{a,z}\n", - "$$ (pz)\n", + "```{math}\n", + ":label: label_p_b_E_a_E_b\n", "\n", - "$$\n", - "E_a =p_a\n", - "$$ (Ea)\n", + "p_{b,z} = -p_{a,z} \\\\\n", + "\n", + "E_a =p_a \\\\\n", "\n", - "$$\n", "E_{b} = \\sqrt{m_b^2+p_b^2}\n", - "$$ (Eb)\n", - "\n" + "```" ] }, { @@ -916,13 +891,16 @@ "tags": [] }, "source": [ - "And now we can implement the function `compute_pa_pb` to compute four-momentum of $p_a$ and $p_b$ based on Equations {eq}`pz`, {eq}`Ea` and {eq}`Eb`." + "And now we can implement the function `compute_pa_pb()` to compute four-momentum of $p_a$ and $p_b$ based on Equations {eq}`label_p_b_E_a_E_b`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { + "jupyter": { + "source_hidden": true + }, "tags": [] }, "outputs": [], @@ -938,7 +916,7 @@ " E = np.ones(shape) * np.sqrt((p3_phsp.m.mean()) ** 2 + pz.mean() ** 2)\n", " pa_phsp = MomentumNumpy4D({\"E\": pz, \"px\": px, \"py\": py, \"pz\": pz})\n", " pb_phsp = MomentumNumpy4D({\"E\": E, \"px\": px, \"py\": py, \"pz\": -pz})\n", - " return [pa_phsp, pb_phsp]" + " return pa_phsp, pb_phsp" ] }, { @@ -987,7 +965,7 @@ "]:\n", " p1_phsp, p2_phsp, p3_phsp = generate_phsp_decay(size, seed, bunch_size)\n", " pa_phsp, pb_phsp = compute_pa_pb(p1_phsp, p2_phsp, p3_phsp)\n", - " return [p1_phsp, p2_phsp, p3_phsp, pa_phsp, pb_phsp]" + " return p1_phsp, p2_phsp, p3_phsp, pa_phsp, pb_phsp" ] }, { @@ -1025,15 +1003,6 @@ "u3_phsp = (pb_phsp - p3_phsp).m2" ] }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "Calculations with 4-vectors are performed with the [`vector`](https://vector.readthedocs.io/en/latest/usage/intro.html) package:" - ] - }, { "cell_type": "code", "execution_count": null, @@ -1045,7 +1014,8 @@ "code_prompt_show": "Code testing" }, "tags": [ - "hide-cell" + "hide-cell", + "scroll-input" ] }, "outputs": [], @@ -1059,44 +1029,10 @@ " + 2\n", " * (p1_phsp.px * p2_phsp.px + p1_phsp.py * p2_phsp.py + p1_phsp.pz * p2_phsp.pz)\n", " ),\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "jupyter": { - "source_hidden": true - }, - "mystnb": { - "code_prompt_show": "Code testing" - }, - "tags": [ - "hide-cell" - ] - }, - "outputs": [], - "source": [ - "np.testing.assert_almost_equal(p0_phsp.p2.max(), 0)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "jupyter": { - "source_hidden": true - }, - "mystnb": { - "code_prompt_show": "Code testing" - }, - "tags": [ - "hide-cell" - ] - }, - "outputs": [], - "source": [ + ")\n", + "\n", + "np.testing.assert_almost_equal(p0_phsp.p2.max(), 0)\n", + "\n", "np.testing.assert_almost_equal(\n", " t1_phsp,\n", " (pa_phsp.e - p1_phsp.e) ** 2\n", @@ -1144,15 +1080,18 @@ "tags": [] }, "source": [ - "To visualize the kinematic distributions and possible resonant structures in the three-body decay process, we construct a phase space Dalitz plot by plotting the squared invariant masses of the particle pairs. This plot provides a detailed view of the phase space, illustrating the allowed kinematic configurations of the decay products. By mapping out the phase space, we can identify patterns and potential resonant structures, offering insights into the underlying dynamics of the decay.\n", + "The sample is plotted to check whether the distribution looks even in the Dalitz plane (as shown below it is!).\n", "\n", - "Following this in later sections, we will present Dalitz plots for both experimental data and the fitted model. These plots will allow us to compare the theoretical predictions with actual observations, and to assess the accuracy and effectiveness of the fitted model in describing the decay process. Through these comparisons, we aim to gain a deeper understanding of the mechanisms driving the decay and the interactions between the decay products." + "Following this in later sections, we will present Dalitz plots for both experimental data and the fitted model. These plots will allow us to compare the theoretical predictions with actual observations, and to assess the accuracy and effectiveness of the fitted model in describing the decay process." ] }, { "cell_type": "code", "execution_count": null, "metadata": { + "jupyter": { + "source_hidden": true + }, "tags": [ "full-width", "hide-input" @@ -1195,12 +1134,15 @@ "tags": [] }, "source": [ - ":::{note}\n", - "There are different ways to represent the Dalitz plot, each with its advantages: **Scatter plot** or **2D histogram**.\n", + "\n", + ":::{tip}\n", + "There are different ways to represent the Dalitz plot, each with its advantages.\n", + "\n", + "- *Scatter Plot*: This method plots individual events as points, offering a clear view of the density and distribution of events within the phase space. It is particularly useful for visualizing smaller datasets or when high resolution is needed to identify specific features or clusters.\n", "\n", - "*Scatter Plot*: This method plots individual events as points, offering a clear view of the density and distribution of events within the phase space. It is particularly useful for visualizing smaller datasets or when high resolution is needed to identify specific features or clusters.\n", + "- *2D Histogram*: This approach divides the phase space into bins and counts the number of events within each bin, representing the density of events using a colour scale. It is effective for large datasets, providing a smooth and continuous representation of the phase space that highlights overall trends and structures.\n", "\n", - "*2D Histogram*: This approach divides the phase space into bins and counts the number of events within each bin, representing the density of events using a color scale. It is effective for large datasets, providing a smooth and continuous representation of the phase space that highlights overall trends and structures.\n", + "In conclusion, to check if the phase space sample is evenly distributed, a scatter plot is typically more straightforward and visually clear.\n", ":::" ] }, @@ -1213,6 +1155,67 @@ "## Calculation of Angles" ] }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "Before introducing CM and helicity angles, we first introduce **polar angles** and **azimuthal angles** in spherical coordinates." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "In the spherical coordinates, the **polar angles**:\n", + "\n", + "```{math}\n", + ":label: polar_angle_sh\n", + "\\theta = \\arccos \\frac{p_z}{|p|}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "In spherical coordinates are **azimuthal angles**:\n", + "\n", + "```{math}\n", + ":label: azimuthal_angle_sh\n", + "\\phi = \\arctan2(p_y , p_x)\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "full-width" + ] + }, + "source": [ + "```{image} https://github.com/ComPWA/gluex-nstar/assets/17490173/eca119ff-0dfc-4fbf-8868-48cde3db01d0\n", + ":width: 40%\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "In Equation {eq}`polar_angle_sh`, $p_z$ is equivalent to $z$, and $|p|$ is $r$ in figure above.\n", + "\n", + "In Equation {eq}`azimuthal_angle_sh`, $p_y$ equivalent to $y$, and $p_x$ is $x$ in figure above." + ] + }, { "cell_type": "markdown", "metadata": { @@ -1228,7 +1231,7 @@ "tags": [] }, "source": [ - "Angles in CM frame (CM Angles) are the polar and azimuthal angles right after the phase space generation and also after data generation in CM frame (i.e. the frame that satisfies the relations in {eq}`4momentum_label`), they are different than the helicity angles in the subsystem (which is after rotation and boost into the subsystem)." + "Angles in the CM frame (CM Angles) are the polar and azimuthal angles in the phase space generation and also in the data generation in the CM frame (i.e. the frame that satisfies the relations in Equation {eq}`4momentum_label`), they are different than the helicity angles in the subsystem (which is after rotation and boost into the subsystem)." ] }, { @@ -1237,7 +1240,8 @@ "tags": [] }, "source": [ - "The values for phase space can be obtained directly after the generation \n", + "The values for phase space can be obtained directly in the CM frame, without boosting into a different frame after the generation.\n", + "We denote these angles as:\n", "\n", "$(\\theta_1^{\\text{CM}}, \\theta_2^{\\text{CM}}, \\theta_3^{\\text{CM}}, \\phi_1^{\\text{CM}}, \\phi_2^{\\text{CM}}, \\phi_3^{\\text{CM}})$:" ] @@ -1273,11 +1277,69 @@ "tags": [] }, "source": [ - ":::{note}\n", - "**Helicity formalism**\n", + ":::{admonition} **Helicity formalism**\n", "\n", - "Helicity formalism is a crucial framework in particle physics for describing the spin states of particles in reactions and decays. It simplifies the analysis of complex processes by projecting the particle's spin onto its direction of motion, making it particularly useful for high-energy interactions. This formalism allows for a clear understanding of angular distributions and polarization effects, facilitating the calculation of transition amplitudes and providing insights into the underlying dynamics of particle interactions. Through helicity states and the use of Wigner D-matrices, physicists can effectively interpret experimental data and theoretical models in a more streamlined and intuitive manner.\n", + "The helicity formalism is a crucial framework or powerful tool in nuclear and particle physics for describing and analyzing the spin states of particles in reactions and decays. \n", + "\n", + "It simplifies the analysis of complex processes by projecting the particle's spin onto its direction of motion. This formalism allows for a clear understanding of angular distributions and polarization effects, facilitating the calculation of **transition amplitudes**, which can provide useful insight into particle interaction and dynamics.\n", + "\n", + "Through helicity states and the use of **Wigner D-matrices**, physicists can effectively interpret experimental data and theoretical models in a more streamlined and intuitive manner.\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + ":::{note}\n", + "**Helicity definition**:\n", + "\n", + "Helicity ($\\lambda$) is the projection of a particle's spin ($S$) onto its direction of motion ($p$). Mathematically, it's given by:\n", + "```{math}\n", + "\\lambda = \\frac{S \\cdot p}{|p|}\n", + "```\n", + "For massless particles, helicity is a Lorentz-invariant quantity, meaning it remains unchanged under boosts along the direction of motion.\n", + "\n", + "**Helicity states**:\n", + "\n", + "Helicity states are eigenstates of the helicity operator. For a particle moving in the z-direction, the helicity operator is \n", + "```{math}\n", + "S \\cdot \\hat{p}\n", + "```\n", + "These states simplify the description of particle interactions.\n", + "\n", + "**Wigner D-matrices**:\n", + "\n", + "Wigner D-matrices are used in the helicity formalism to describe the rotation of spin states. \n", + "These matrices depend on the Euler angles of the rotation and are denoted by \n", + "```{math}\n", + "D^j_{m'm} (α,β,γ) = e^{-im'α} d^j_{m'm}(β) e^{-imγ},\n", + "```\n", + " where $j$ is the spin, $m'$ and $m$ are the magnetic quantum numbers, and\n", + " ```{math}\n", + "d^j_{m'm}(β) = D^j_{m'm} (0,β,0)\n", + "```\n", + "is an element of the orthogonal Wigner's (small) d-matrix.\n", + "\n", + "They play a crucial role in transforming between different reference frames and in calculating the angular dependence of transition amplitudes.\n", + "\n", + "**Transition Amplitudes**:\n", + "\n", + "The transition amplitude for a process is expressed in terms of helicity states. \n", + "This reduces the complexity of the calculations as it aligns the spins of the particles with their momenta.\n", + "For example, the decay of a particle into two others can be described by the helicity amplitudes, which are functions of the helicities of the initial and final state particles.\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ":::{seealso}\n", + "[Section of helicity formalism in TR-015(Spin alignment implementation)](https://compwa.github.io/report/015.html#helicity-formalism)\n", "\n", + "[Helicity versus canonical in Ampform](https://ampform.readthedocs.io/stable/usage/helicity/formalism.html)\n", ":::" ] }, @@ -1287,7 +1349,7 @@ "tags": [] }, "source": [ - ":::{note}\n", + ":::{admonition} Production and decay plane\n", "The **production plane** is defined by the momenta of the incoming particles that participate in the production of a particular state or particle. For example, in a collision between two particles \n", "A and \n", "B producing a particle \n", @@ -1313,24 +1375,19 @@ "tags": [] }, "source": [ - "The Helicity angle between decay products(Polar Angles), by definition:\n", + ":::{important}\n", "\n", - "$$\n", - "\\theta = \\arccos \\frac{p_z}{|p|}\n", - "$$" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "The Helicity angle with the production plane and decay plane(Azimuthal Angles), by definition:\n", + "The helicity angles $\\Omega_i$ are pairs of Euler angles $\\Omega_i = \\left(\\theta_i, \\phi_i\\right)$:\n", + "- Opening angle $\\theta_1 \\equiv \\theta^{12}_1$ of four-momentum $p_1$ is the angle between $p'_1 \\equiv p^{12}_1$ and $p_{12}$ or $-p_3$\n", + " - which means these are the angles between decay products in general.\n", + "- The angle $\\phi_1 \\equiv \\phi^{12}_1$ defines the angle between the **production plane** spanned by $p_{12}$ and $p_3$ and the **decay plane** spanned by $p^{(\\prime)}_1$ and $p^{(\\prime)}_2$.\n", + " - which means these are the angles between the production and decay plane.\n", "\n", - "$$\n", - "\\phi = \\arctan2(p_y , p_x)\n", - "$$" + "- The helicity angles of the other subsystems are defined by cyclic permutation of the indices, such that $\\theta_2 \\equiv \\theta^{12}_2$ and $\\theta_3 \\equiv \\theta^{31}_1$.\n", + "\n", + "\n", + "These angles are in helicity formalism, the calculation involved rotation and boost into the subsystem as follows.\n", + ":::" ] }, { @@ -1339,9 +1396,7 @@ "tags": [] }, "source": [ - ":::{important}\n", - "Theses angles are in helicity formalism, the calculation involved rotation and boost into the subsystem as followings.\n", - ":::" + "Before boosting (in CM frame):" ] }, { @@ -1350,7 +1405,7 @@ "tags": [] }, "source": [ - "Before boosting (in CM frame)" + "" ] }, { @@ -1359,7 +1414,7 @@ "tags": [] }, "source": [ - "" + "After Boosting into system$_{12}$ rest frame:" ] }, { @@ -1368,16 +1423,16 @@ "tags": [] }, "source": [ - "After Boosted into system$_{12}$ rest frame (it is similar for boosting into system$_{23}$ and system$_{31}$)" + "" ] }, { "cell_type": "markdown", - "metadata": { - "tags": [] - }, + "metadata": {}, "source": [ - "" + ":::{note}\n", + "It is similar image for boosting into system$_{23}$ and system$_{31}$.\n", + ":::" ] }, { @@ -1386,13 +1441,7 @@ "tags": [] }, "source": [ - "The helicity angles $\\Omega_i$ are pairs of Euler angles $\\Omega_i = \\left(\\theta_i, \\phi_i\\right)$:\n", - "- Opening angle $\\theta_1 \\equiv \\theta^{12}_1$ of four-momentum $p_1$ is the angle between $p'_1 \\equiv p^{12}_1$ and $p_{12}$ or $-p_3$.\n", - "- The angle $\\phi_1 \\equiv \\phi^{12}_1$ defines the angle between the **production plane** spanned by $p_{12}$ and $p_3$ and the **decay plane** spanned by $p^{(\\prime)}_1$ and $p^{(\\prime)}_2$.\n", - "\n", - "The helicity angles of the other subsystems are defined by cyclic permutation of the indices, such that $\\theta_2 \\equiv \\theta^{12}_2$ and $\\theta_3 \\equiv \\theta^{31}_1$.\n", - "\n", - "To calculate the helicity angles $\\theta$ and $\\phi$, a combination of boost and rotation (in Y and Z axis) in CM frame is defined:" + "To calculate the helicity angles $\\theta$ and $\\phi$, a combination of boost and rotation (in Y and Z axis) in the CM frame is defined:" ] }, { @@ -1407,7 +1456,7 @@ " return p_i.rotateZ(-p_ij.phi).rotateY(-p_ij.theta).boostZ(-p_ij.beta).theta\n", "\n", "\n", - "def phi_helicity(p_i, p_ij):\n", + "def phi_helicity(p_i: MomentumNumpy4D, p_ij: MomentumNumpy4D):\n", " return p_i.rotateZ(-p_ij.phi).rotateY(-p_ij.theta).boostZ(-p_ij.beta).phi" ] }, @@ -1646,21 +1695,23 @@ "tags": [] }, "source": [ - "The calculation of $Y_l^m(\\phi, \\theta)$ is done via `scipy.special.sph_harm(m, l, phi, theta)` \n", + "The calculation of $Y_l^m(\\phi, \\theta)$ is done via [`scipy.special.sph_harm(m, l, phi, theta)`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.sph_harm.html) \n", "\n", "We have changed the use of symbol $\\phi$ and $\\theta$ according to the more common used definition in physics.\n", "\n", - "here the notation of $\\theta$ and $\\phi$ are not using the same as in `scipy` special function [scipy.special.sph_harm](https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.sph_harm.html)\n", + "Here the notation of $\\theta$ and $\\phi$ are not using the same as in `scipy` special function [scipy.special.sph_harm()](https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.sph_harm.html)\n", "\n", - "(in `scipy` $\\theta$ is the azimuthal from -$\\pi$ to $\\pi$ and $\\phi$ is the polar angle from 0 to $\\pi$)\n", + "(in `scipy`, $\\theta$ is the azimuthal from -$\\pi$ to $\\pi$ and $\\phi$ is the polar angle from 0 to $\\pi$)\n", "\n", "where the notation we used here is more common in physics:\n", - "\n", "- $\\phi$ is the azimuthal from -$\\pi$ to $\\pi$ in this document (where in `scipy` it is represented as $\\theta$ and ranged from 0 to $2\\pi$)\n", "\n", "- $\\theta$ is the polar angle from 0 to $\\pi$ in this document (where in `scipy` it is represented as $\\phi$ with the same range)\n", "\n", - "$Y_l^m(\\phi, \\theta) = \\sqrt{\\frac{2n+1}{4\\pi}\\frac{(n-m)!}{(n+m)!}}e^{im\\phi}P_l^m(\\cos(\\theta))$" + "```{math}\n", + ":label: spherical_harmonics_def\n", + "Y_l^m(\\phi, \\theta) = \\sqrt{\\frac{2n+1}{4\\pi}\\frac{(n-m)!}{(n+m)!}}e^{im\\phi}P_l^m(\\cos(\\theta))\n", + "```" ] }, { @@ -1669,7 +1720,16 @@ "tags": [] }, "source": [ - "The default values of coefficients $a_i$, $b_i$, and $c_i$ in the spherical harmonics:" + "In the following, we accordingly define functions to compute three terms of spherical harmonics in Equation {eq}`BW_SH_label`, and the explicit form of spherical harmonics as shown in Equation {eq}`spherical_harmonics_def`." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "Firstly, the term in $A^{12}$:" ] }, { @@ -1680,17 +1740,23 @@ }, "outputs": [], "source": [ - "initial_SH_parameters = dict(\n", - " a_minus2=0,\n", - " a_minus1=0.5,\n", - " a_0=3.5,\n", - " a_plus1=4,\n", - " a_plus2=2.5,\n", - " b_minus1=-1.5,\n", - " b_0=4,\n", - " b_plus1=0.5,\n", - " c_0=2.5,\n", - ")" + "def compute_spherical_harmonics12(\n", + " theta: np.ndarray,\n", + " phi: np.ndarray,\n", + " a_minus2,\n", + " a_minus1,\n", + " a_0,\n", + " a_plus1,\n", + " a_plus2,\n", + " **kwargs,\n", + ") -> np.ndarray:\n", + " return (\n", + " a_plus2 * sp.special.sph_harm(2, 2, phi, theta)\n", + " + a_plus1 * sp.special.sph_harm(1, 2, phi, theta)\n", + " + a_0 * sp.special.sph_harm(0, 2, phi, theta)\n", + " + a_minus1 * sp.special.sph_harm(-1, 2, phi, theta)\n", + " + a_minus2 * sp.special.sph_harm(-2, 2, phi, theta)\n", + " )" ] }, { @@ -1699,7 +1765,7 @@ "tags": [] }, "source": [ - "Assign the initial default values for $a_m$" + "The default values of coefficients $a_i$, $b_i$, and $c_i$ in the spherical harmonics:" ] }, { @@ -1710,11 +1776,17 @@ }, "outputs": [], "source": [ - "a_minus2 = initial_SH_parameters.get(\"a_minus2\")\n", - "a_minus1 = initial_SH_parameters.get(\"a_minus1\")\n", - "a_0 = initial_SH_parameters.get(\"a_0\")\n", - "a_plus1 = initial_SH_parameters.get(\"a_plus1\")\n", - "a_plus2 = initial_SH_parameters.get(\"a_plus2\")" + "initial_SH_parameters = dict(\n", + " a_minus2=0,\n", + " a_minus1=0.5,\n", + " a_0=3.5,\n", + " a_plus1=4,\n", + " a_plus2=2.5,\n", + " b_minus1=-1.5,\n", + " b_0=4,\n", + " b_plus1=0.5,\n", + " c_0=2.5,\n", + ")" ] }, { @@ -1723,7 +1795,7 @@ "tags": [] }, "source": [ - "We define functions to compute three terms of spherical harmonics in equation {eq}`BW_SH_label`." + "Assign the initial default values for $a_m$" ] }, { @@ -1734,23 +1806,11 @@ }, "outputs": [], "source": [ - "def compute_spherical_harmonics12(\n", - " theta: np.ndarray,\n", - " phi: np.ndarray,\n", - " a_minus2,\n", - " a_minus1,\n", - " a_0,\n", - " a_plus1,\n", - " a_plus2,\n", - " **kwargs,\n", - ") -> np.ndarray:\n", - " return (\n", - " a_plus2 * sp.special.sph_harm(2, 2, phi, theta)\n", - " + a_plus1 * sp.special.sph_harm(1, 2, phi, theta)\n", - " + a_0 * sp.special.sph_harm(0, 2, phi, theta)\n", - " + a_minus1 * sp.special.sph_harm(-1, 2, phi, theta)\n", - " + a_minus2 * sp.special.sph_harm(-2, 2, phi, theta)\n", - " )" + "a_minus2 = initial_SH_parameters.get(\"a_minus2\")\n", + "a_minus1 = initial_SH_parameters.get(\"a_minus1\")\n", + "a_0 = initial_SH_parameters.get(\"a_0\")\n", + "a_plus1 = initial_SH_parameters.get(\"a_plus1\")\n", + "a_plus2 = initial_SH_parameters.get(\"a_plus2\")" ] }, { @@ -1769,7 +1829,6 @@ " PHI,\n", " THETA,\n", " **initial_SH_parameters,\n", - " # PHI, THETA, a_minus2, a_minus1, a_0, a_plus1, a_plus2\n", ")" ] }, @@ -1851,7 +1910,7 @@ "tags": [] }, "source": [ - "Assign the initial default values for $b_m$" + "Next, the term in $A^{23}$" ] }, { @@ -1862,9 +1921,23 @@ }, "outputs": [], "source": [ - "b_minus1 = initial_SH_parameters.get(\"b_minus1\")\n", - "b_0 = initial_SH_parameters.get(\"b_0\")\n", - "b_plus1 = initial_SH_parameters.get(\"b_plus1\")" + "def compute_spherical_harmonics23(\n", + " theta: np.ndarray, phi: np.ndarray, b_minus1, b_0, b_plus1, **kwargs\n", + ") -> np.ndarray:\n", + " return (\n", + " b_plus1 * sp.special.sph_harm(1, 1, phi, theta)\n", + " + b_0 * sp.special.sph_harm(0, 1, phi, theta)\n", + " + b_minus1 * sp.special.sph_harm(-1, 1, phi, theta)\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "Assign the initial default values for $b_m$" ] }, { @@ -1875,14 +1948,9 @@ }, "outputs": [], "source": [ - "def compute_spherical_harmonics23(\n", - " theta: np.ndarray, phi: np.ndarray, b_minus1, b_0, b_plus1, **kwargs\n", - ") -> np.ndarray:\n", - " return (\n", - " b_plus1 * sp.special.sph_harm(1, 1, phi, theta)\n", - " + b_0 * sp.special.sph_harm(0, 1, phi, theta)\n", - " + b_minus1 * sp.special.sph_harm(-1, 1, phi, theta)\n", - " )" + "b_minus1 = initial_SH_parameters.get(\"b_minus1\")\n", + "b_0 = initial_SH_parameters.get(\"b_0\")\n", + "b_plus1 = initial_SH_parameters.get(\"b_plus1\")" ] }, { @@ -1949,7 +2017,7 @@ "tags": [] }, "source": [ - "Assign the initial default value for $c_0$" + "Lastly, the corresponding term in $A^{31}$" ] }, { @@ -1960,7 +2028,19 @@ }, "outputs": [], "source": [ - "c_0 = initial_SH_parameters.get(\"c_0\")" + "def compute_spherical_harmonics31(\n", + " theta: np.ndarray, phi: np.ndarray, c_0, **kwargs\n", + ") -> np.ndarray:\n", + " return c_0 * sp.special.sph_harm(0, 0, phi, theta)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "Assign the initial default value for $c_0$" ] }, { @@ -1971,10 +2051,7 @@ }, "outputs": [], "source": [ - "def compute_spherical_harmonics31(\n", - " theta: np.ndarray, phi: np.ndarray, c_0, **kwargs\n", - ") -> np.ndarray:\n", - " return c_0 * sp.special.sph_harm(0, 0, phi, theta)" + "c_0 = initial_SH_parameters.get(\"c_0\")" ] }, { @@ -1983,9 +2060,7 @@ "tags": [] }, "source": [ - ":::{note}\n", - "\n", - "**Extra Information**\n", + ":::{admonition} **Extra Information**\n", "\n", "Alternatively,\n", "we can also calculate the spherical harmonics using the Wigner d-function,\n", @@ -1999,7 +2074,13 @@ "cell_type": "code", "execution_count": null, "metadata": { - "tags": [] + "mystnb": { + "code_prompt_show": "Example function for calculating spherical harmonics using the Wigner d-function" + }, + "tags": [ + "hide-cell", + "scroll-input" + ] }, "outputs": [], "source": [