1111import textwrap
1212from importlib .metadata import version as get_package_version
1313from pathlib import Path
14- from typing import TYPE_CHECKING
14+ from typing import TYPE_CHECKING , cast
1515
1616import attrs
1717import graphviz # sphinx.ext.graphviz does not work well on RTD
1818import qrules
1919import sympy as sp
2020from sympy .printing .numpy import NumPyPrinter
2121
22+ from ampform .dynamics .form_factor import FormFactor
2223from ampform .dynamics .phasespace import (
24+ ChewMandelstamIntegral ,
25+ ChewMandelstamSWave ,
26+ EqualMassPhaseSpaceFactor ,
2327 PhaseSpaceFactor ,
28+ PhaseSpaceFactorAbs ,
29+ PhaseSpaceFactorComplex ,
2430 PhaseSpaceFactorKallen ,
31+ PhaseSpaceFactorPWave ,
2532 PhaseSpaceFactorSplitSqrt ,
2633 PhaseSpaceFactorSWave ,
2734)
3340 BreakupMomentumKallen ,
3441 BreakupMomentumSplitSqrt ,
3542 BreakupMomentumSquared ,
43+ Kallen ,
3644)
3745from ampform .sympy ._array_expressions import ArrayMultiplication
3846from ampform .sympy ._cache import get_readable_hash , make_hashable
47+ from ampform .sympy .math import ComplexSqrt
3948
4049if TYPE_CHECKING :
4150 from collections .abc import Callable
4958
5059
5160def append_phsp_doit (
52- phsp_factor : PhaseSpaceFactorProtocol ,
53- wide : bool = True ,
54- ) -> Callable [[], None ]:
55- def _extend () -> None :
56- s , m1 , m2 = sp .symbols ("s m1 m2" , nonnegative = True )
57- expr = phsp_factor (s , m1 , m2 )
58- _append_latex_doit_definition (expr , full_width = wide )
61+ _phsp_factor : PhaseSpaceFactorProtocol ,
62+ * ,
63+ extra_args : list [sp .Symbol ] | None = None ,
64+ subexpression : list [sp .Expr ] | sp .Expr | None = None ,
65+ wide : bool = False ,
66+ ) -> None :
67+ expr = _phsp_factor (s , m1 , m2 , * (extra_args or []))
68+ _append_latex_doit_definition (expr , full_width = wide )
69+ if subexpression is not None :
70+ if not isinstance (subexpression , list ):
71+ subexpression = [subexpression ]
72+ items = []
73+ for expr in subexpression :
74+ expression_type = f"{ type (expr ).__name__ } "
75+ items .append (f":math:`{ sp .latex (expr )} ` defined by `.{ expression_type } `" )
76+ match len (items ):
77+ case 1 :
78+ appended_text = items [0 ]
79+ case 2 :
80+ appended_text = f"{ items [0 ]} and { items [1 ]} "
81+ case _:
82+ appended_text = ", " .join (items [:- 1 ]) + f", and { items [- 1 ]} "
83+ _append_to_docstring (_phsp_factor , f"\n \n with { appended_text } ." )
84+
85+
86+ def _append_latex_doit_definition (
87+ expr : sp .Expr ,
88+ deep : bool = False ,
89+ full_width : bool = False ,
90+ inline : bool = False ,
91+ ) -> None :
92+ if inline :
93+ return _append_to_docstring (
94+ type (expr ),
95+ f":math:`{ sp .latex (expr )} ={ sp .latex (expr .doit (deep = deep ))} `" ,
96+ )
97+ latex = _create_latex_doit_definition (expr , deep )
98+ extras = ""
99+ if full_width :
100+ extras = """
101+ :class: full-width
102+ """
103+ return _append_to_docstring (
104+ type (expr ),
105+ f"""\n
106+ .. math::
107+ :label: { type (expr ).__name__ } { extras }
108+
109+ { latex }
110+ """ ,
111+ )
112+
113+
114+ def _append_to_docstring (class_type : Callable | type , appended_text : str ) -> None :
115+ appended_text = textwrap .dedent (appended_text )
116+ if class_type .__doc__ is None :
117+ class_type .__doc__ = appended_text
118+ else :
119+ class_type .__doc__ += appended_text
59120
60- return _extend
121+
122+ def _create_latex_doit_definition (expr : sp .Expr , deep : bool = False ) -> str :
123+ latex = aslatex ({expr : expr .doit (deep = deep )})
124+ return textwrap .indent (latex , prefix = 8 * " " )
125+
126+
127+ s , m1 , m2 , x , y , z = cast ("list[sp.Symbol]" , sp .symbols ("s m1 m2 x:z" ))
128+ ell = sp .Symbol ("ell" , integer = True , nonnegative = True )
129+ append_phsp_doit (BreakupMomentum )
130+ append_phsp_doit (BreakupMomentumComplex , subexpression = ComplexSqrt (x ))
131+ append_phsp_doit (BreakupMomentumKallen , subexpression = Kallen (x , y , z ))
132+ append_phsp_doit (BreakupMomentumSplitSqrt )
133+ append_phsp_doit (BreakupMomentumSquared )
134+ append_phsp_doit (
135+ EqualMassPhaseSpaceFactor ,
136+ subexpression = PhaseSpaceFactorAbs (s , m1 , m2 ),
137+ )
138+ append_phsp_doit (PhaseSpaceFactor )
139+ append_phsp_doit (PhaseSpaceFactorAbs , subexpression = BreakupMomentumSquared (s , m1 , m2 ))
140+ append_phsp_doit (PhaseSpaceFactorComplex , subexpression = ComplexSqrt (x ))
141+ append_phsp_doit (PhaseSpaceFactorKallen , subexpression = Kallen (x , y , z ))
142+ append_phsp_doit (PhaseSpaceFactorSplitSqrt )
143+ append_phsp_doit (
144+ ChewMandelstamSWave ,
145+ subexpression = BreakupMomentumComplex (s , m1 , m2 ),
146+ wide = True ,
147+ )
148+ append_phsp_doit (
149+ ChewMandelstamIntegral ,
150+ extra_args = [ell ],
151+ subexpression = [FormFactor (x , m1 , m2 , ell ), PhaseSpaceFactor (x , m1 , m2 )],
152+ wide = True ,
153+ )
154+ append_phsp_doit (
155+ PhaseSpaceFactorSWave ,
156+ subexpression = ChewMandelstamSWave (s , m1 , m2 ),
157+ )
158+ append_phsp_doit (
159+ PhaseSpaceFactorPWave ,
160+ subexpression = ChewMandelstamIntegral (s , m1 , m2 , ell ),
161+ )
61162
62163
63164def extend_docstrings () -> None :
@@ -83,17 +184,6 @@ def extend_docstrings() -> None:
83184 definition ()
84185
85186
86- extend_BreakupMomentum = append_phsp_doit (BreakupMomentum )
87- extend_BreakupMomentumComplex = append_phsp_doit (BreakupMomentumComplex )
88- extend_BreakupMomentumKallen = append_phsp_doit (BreakupMomentumKallen )
89- extend_BreakupMomentumSplitSqrt = append_phsp_doit (BreakupMomentumSplitSqrt )
90- extend_BreakupMomentumSquared = append_phsp_doit (BreakupMomentumSquared )
91- extend_PhaseSpaceFactor = append_phsp_doit (PhaseSpaceFactor )
92- extend_PhaseSpaceFactorKallen = append_phsp_doit (PhaseSpaceFactorKallen )
93- extend_PhaseSpaceFactorSplitSqrt = append_phsp_doit (PhaseSpaceFactorSplitSqrt )
94- extend_PhaseSpaceFactorSWave = append_phsp_doit (PhaseSpaceFactorSWave , wide = True )
95-
96-
97187def extend_BlattWeisskopfSquared () -> None :
98188 from ampform .dynamics .form_factor import BlattWeisskopfSquared , SphericalHankel1
99189
@@ -205,17 +295,7 @@ def extend_BoostZMatrix() -> None:
205295 )
206296
207297
208- def extend_ChewMandelstamIntegral () -> None :
209- from ampform .dynamics .phasespace import ChewMandelstamIntegral
210-
211- s , m_a , m_b , ell = sp .symbols (R"s m_a m_b \ell" )
212- expr = ChewMandelstamIntegral (s , m_a , m_b , ell )
213- _append_latex_doit_definition (expr )
214-
215-
216298def extend_ComplexSqrt () -> None :
217- from ampform .sympy .math import ComplexSqrt
218-
219299 x = sp .Symbol ("x" , real = True )
220300 expr = ComplexSqrt (x )
221301 _append_to_docstring (
@@ -245,25 +325,6 @@ def extend_compute_third_mandelstam() -> None:
245325 )
246326
247327
248- def extend_EqualMassPhaseSpaceFactor () -> None :
249- from ampform .dynamics .phasespace import (
250- EqualMassPhaseSpaceFactor ,
251- PhaseSpaceFactorAbs ,
252- )
253-
254- s , m_a , m_b = sp .symbols (R"s, m_a, m_b" )
255- expr = EqualMassPhaseSpaceFactor (s , m_a , m_b )
256- _append_latex_doit_definition (expr )
257- rho_hat = PhaseSpaceFactorAbs (s , m_a , m_b )
258- _append_to_docstring (
259- EqualMassPhaseSpaceFactor ,
260- f"""
261- with :math:`{ sp .latex (rho_hat )} ` defined by `.PhaseSpaceFactorAbs`
262- :eq:`PhaseSpaceFactorAbs`.
263- """ ,
264- )
265-
266-
267328def extend_EnergyDependentWidth () -> None :
268329 from ampform .dynamics import EnergyDependentWidth
269330
@@ -275,8 +336,7 @@ def extend_EnergyDependentWidth() -> None:
275336 """ ,
276337 )
277338 L = sp .Symbol ("L" , integer = True )
278- symbols : tuple [sp .Symbol , ...] = sp .symbols ("s m0 Gamma0 m_a m_b" )
279- s , m0 , w0 , m_a , m_b = symbols
339+ s , m0 , w0 , m_a , m_b = sp .symbols ("s m0 Gamma0 m_a m_b" )
280340 expr = EnergyDependentWidth (
281341 s = s ,
282342 mass0 = m0 ,
@@ -328,15 +388,12 @@ def extend_EuclideanNorm() -> None:
328388
329389
330390def extend_FormFactor () -> None :
331- from ampform .dynamics .form_factor import FormFactor
332-
333391 s , m_a , m_b , L , d = sp .symbols ("s m_a m_b L d" )
334392 form_factor = FormFactor (s , m_a , m_b , angular_momentum = L , meson_radius = d )
335393 _append_latex_doit_definition (form_factor )
336394
337395
338396def extend_Kallen () -> None :
339- from ampform .kinematics .phasespace import Kallen
340397
341398 x , y , z = sp .symbols ("x:z" )
342399 expr = Kallen (x , y , z )
@@ -390,34 +447,6 @@ def extend_is_within_phasespace() -> None:
390447 )
391448
392449
393- def extend_PhaseSpaceFactorAbs () -> None :
394- from ampform .dynamics .phasespace import PhaseSpaceFactorAbs
395-
396- s , m_a , m_b = sp .symbols ("s, m_a, m_b" )
397- expr = PhaseSpaceFactorAbs (s , m_a , m_b )
398- _append_latex_doit_definition (expr )
399- _append_to_docstring (
400- PhaseSpaceFactorAbs ,
401- """
402- with :math:`q^2(s)` defined as :eq:`BreakupMomentumSquared`.
403- """ ,
404- )
405-
406-
407- def extend_PhaseSpaceFactorComplex () -> None :
408- from ampform .dynamics .phasespace import PhaseSpaceFactorComplex
409-
410- s , m_a , m_b = sp .symbols ("s, m_a, m_b" )
411- expr = PhaseSpaceFactorComplex (s , m_a , m_b )
412- _append_latex_doit_definition (expr )
413- _append_to_docstring (
414- PhaseSpaceFactorComplex ,
415- """
416- with :math:`q^2(s)` defined as :eq:`BreakupMomentumSquared`.
417- """ ,
418- )
419-
420-
421450def extend_Phi () -> None :
422451 from ampform .kinematics .angles import Phi
423452
@@ -510,26 +539,6 @@ def extend_ThreeMomentum() -> None:
510539 _append_code_rendering (expr )
511540
512541
513- def extend_chew_mandelstam_s_wave () -> None :
514- from ampform .dynamics .phasespace import chew_mandelstam_s_wave
515-
516- s , m_a , m_b = sp .symbols ("s m_a m_b" )
517- expr = chew_mandelstam_s_wave (s , m_a , m_b )
518- _append_to_docstring (
519- chew_mandelstam_s_wave ,
520- Rf"""
521-
522- .. math:: { sp .latex (expr )}
523- :class: full-width
524- :label: chew_mandelstam_s_wave
525-
526- with :math:`q^2(s)` defined as :eq:`BreakupMomentumSquared`.
527-
528- .. seealso:: :doc:`compwa-report:003/index`
529- """ ,
530- )
531-
532-
533542def extend_formulate_isobar_cg_coefficients () -> None :
534543 from ampform .helicity import formulate_isobar_cg_coefficients
535544
@@ -645,7 +654,7 @@ def extend_relativistic_breit_wigner_with_ff() -> None:
645654 _append_to_docstring (
646655 relativistic_breit_wigner_with_ff ,
647656 Rf"""
648- The general form of a relativistic Breit- Wigner with Blatt- Weisskopf form factor is:
657+ The general form of a relativistic Breit– Wigner with Blatt– Weisskopf form factor is:
649658
650659 .. math:: { sp .latex (rel_bw_with_ff )}
651660 :label: relativistic_breit_wigner_with_ff
@@ -696,47 +705,6 @@ def __get_text_width(text: str) -> int:
696705 return max (widths )
697706
698707
699- def _append_latex_doit_definition (
700- expr : sp .Expr ,
701- deep : bool = False ,
702- full_width : bool = False ,
703- inline : bool = False ,
704- ) -> None :
705- if inline :
706- return _append_to_docstring (
707- type (expr ),
708- f":math:`{ sp .latex (expr )} ={ sp .latex (expr .doit (deep = deep ))} `" ,
709- )
710- latex = _create_latex_doit_definition (expr , deep )
711- extras = ""
712- if full_width :
713- extras = """
714- :class: full-width
715- """
716- return _append_to_docstring (
717- type (expr ),
718- f"""\n
719- .. math::
720- :label: { type (expr ).__name__ } { extras }
721-
722- { latex }
723- """ ,
724- )
725-
726-
727- def _create_latex_doit_definition (expr : sp .Expr , deep : bool = False ) -> str :
728- latex = aslatex ({expr : expr .doit (deep = deep )})
729- return textwrap .indent (latex , prefix = 8 * " " )
730-
731-
732- def _append_to_docstring (class_type : Callable | type , appended_text : str ) -> None :
733- appended_text = textwrap .dedent (appended_text )
734- if class_type .__doc__ is None :
735- class_type .__doc__ = appended_text
736- else :
737- class_type .__doc__ += appended_text
738-
739-
740708def __generate_transitions_cached (
741709 initial_state : list [tuple [str , list [float ]] | str ],
742710 final_state : list [tuple [str , list [float ]] | str ],
0 commit comments