Welcome to TFPWA’s documentation!
TFPWA is a generic software package intended for Partial Wave Analysis (PWA). It is developed using TensorFlow2 and the calculation is accelerated by GPU. Users may modify the configuration file (in YML format) and write simple scripts to complete the whole analysis. A detailed configuration file sample (with all usable parameters) can be found here.
Install
To use TFPWA, we need some dependent packages. There are two main ways,
conda
and virtualenv
you can choose one of them. Or you can choose other method in 5. Other install method.
1. vitrual environment
To avoid conflict of dependence, we recommed to use vitrual environment. there are two main vitrual environment for python packages, conda and virtualenv. You can choose one of them. Since conda include cudatoolkit for gpu, we recommed it for user.
1.1 conda
1.1.1 Get miniconda for python3 from miniconda3 and install it.
1.1.2 Create a virtual environment by
conda create -n tfpwa
, the -n <name>
option will create a environment named by <name>
. You can also use -p <path>
option to create environment in the <path>
directory.
1.1.3 You can activate the environment by
conda activate tfpwa
and then you can install packages in the conda environment
1.1.4 You can exit the environment by
conda deactivate
1.2 virtualenv
1.2.1 You should have a python3 first.
1.2.2 Install virtualenv
python3 -m pip install --user virtualenv
1.2.3 Create a virtual environment
python3 -m virtualenv ./tfpwa
, it will store in the path tfpwa
1.2.4 You can activate the environment by
source ./tfpwa/bin/activete
1.2.5 You can exit the environment by
deactivate
2. tensorflow2
The most important package is tensorflow2. We recommed to install tensorflow first. You can following the install instructions in tensorflow website (or tensorflow.org).
2.1 conda
Here we provide the simple way to install tensorflow2 gpu version in conda environment
conda install tensorflow-gpu=2.4
it will also install cudatoolkit.
2.2 virtualenv
When using virtualenv
, there is also simple way to install tensorflow2
python -m pip install tensorflow
, but you should check you CUDA installation for GPU.
Note
You can use -i https://pypi.tuna.tsinghua.edu.cn/simple
option to use pypi mirror site.
3. Other dependences
Other dependences of TFPWA is simple.
3.1 Get TFPWA package
Get the packages using
git clone https://github.com/jiangyi15/tf-pwa
3.2 conda
3.2.1 other dependences
In conda environment, go into the directory of tf-pwa
, you can install the rest dependences by
conda install --file requirements-min.txt
Note
we recommed Ampere card users to install with
tensorflow_2_6_requirements.txt
(see this
technical FAQ).
conda install --file tensorflow_2_6_requirements.txt -c conda-forge
3.2.2 TFPWA
install TFPWA
python -m pip install -e ./ --no-deps
Use --no-deps
to make sure that no PyPI package will be installed.
Using -e
, so it can be updated by git pull
directly.
3.3 virtualenv
In virtualenv, You can install dependences and TFPWA together.
python3 -m pip install -e ./
Using -e
, so it can be updated by git pull
directly.
4. (option) Other dependences.
There are some option packages, such as
uproot
for reading root file.
4.1 conda
It can be installed as
conda install uproot -c conda-forge
4.2 virtualenv
It can be installed as
python -m pip install uproot
5. Other install method.
We also provided other install method.
5.1 conda channel (experimental)
A pre-built conda package (Linux only) is also provided, just run following command to install it.
conda config --add channels jiangyi15
conda install tf-pwa
5.2 pip
When using pip
, you will need to install CUDA to use GPU. Just run the
following command :
python3 -m pip install -e .
6. For developer
To contribute to the project, please also install additional developer tools with:
python3 -m pip install -e .[dev]
Amplitude
Helicity Formula
Each Decay has Amplitude like
For a chain decay, amplitude can be combined as
with angle aligned
the sum of resonances
then the differential cross-section
Amplitude Combination Rules
For a decay process A -> R B, R -> C D
, we can get different part of amplitude:
- Particle:
Initial state: \(1\)
Final state: \(D(\alpha, \beta, \gamma)\)
Propagator: \(R(m)\)
- Decay:
Two body decay (
A -> R B
): \(H_{\lambda_R,\lambda_B} D_{\lambda_A, \lambda_R - \lambda_B} (\varphi, \theta,0)\)
Now we can use combination rules to build amplitude for the whole process.
- Probability Density:
\(P = |\tilde{A}|^2\) (modular square)
- Decay Group:
\(\tilde{A} = a_1 A_{R_1} + a_2 A_{R_2} + \cdots\) (addition)
- Decay Chain:
\(A_{R} = A_1 \times R \times A_2 \cdots\) (multiplication)
Decay: \(A_i = HD(\varphi, \theta, 0)\)
Particle: \(R(m)\)
The indices part is quantum number, and it can be summed automatically.
Default Amplitude Model
The defalut model for Decay is helicity amplitude
The LS coupling formula is used
\(g_{ls}\) are the fit parameters, the first one is fixed. \(q\) and \(q_0\) is the momentum in rest frame for invariant mass and resonance mass.
\(B_{l}'(q, q0, d)\) (Bprime
) is Blatt-Weisskopf barrier factors. \(d\) is \(3.0 \mathrm{GeV}^{-1}\) by default.
Resonances model use Relativistic Breit-Wigner function
with running width
By using the combination rules, the amplitude is built automatically.
Custom Model
TF-PWA support custom model of Particle
, just implement the Particle.get_amp
method for a class inherited from Particle
as:
from tf_pwa.amp import register_particle, Particle
@register_particle("MyModel")
class MyParticle(Particle):
def get_amp(self, *args, **kwargs):
print(args, kwargs)
return 1.0
Then it can be used in config.yml
(or Resonances.yml
) as model: MyModel
.
We can get the data used for amplitude, and add some calculations such as Breit-Wigner.
from tf_pwa.amp import register_particle, Particle
import tensorflow as tf
@register_particle("BW")
class SimpleBW(Particle):
def get_amp(self, *args, **kwargs):
"""
Breit-Wigner formula
"""
m = args[0]["m"]
m0 = self.get_mass()
g0 = self.get_width()
delta_m = m0*m0 - m * m
one = tf.ones_like(m)
ret = 1/tf.complex(delta_m, m0 * g0 * one)
return ret
Note, we used one
to make sure the shape to be same.
We can also add parameters in the Model
init_params
using self.add_var(...)
.
@register_particle("Line")
class LineModel(Particle):
def init_params(self):
super(LineModel, self).init_params()
self.a = self.add_var("a")
def get_amp(self, data, *args, **kwargs):
""" model as m + a """
m = data["m"]
zeros = tf.zeros_like(m)
return tf.complex( m + self.a(), zeros)
Then a parameters {particle_name}_a
will appear in the parameters, we use self.a()
to get the value in get_amp
.
Note, the type of return value should be tf.complex
. All builtin model is located in tf_pwa/amp.py
.
Simple Resonance (experimental)
There is a simple method to define Resonance model, like
from tf_pwa.amp import simple_resonance, FloatParams
@simple_resonance("Line_2", params=["a"])
def r_line(m, a: FloatParams = 1.0):
return m + a
Those code will build a class similar as Line model define before.
By using inspect
module, we can get the FullArgSpec
of a function.
For a keyword arguments with type annotation as FloatParams
, it will be treated as a fit paraments.
Note
the first arguments have to be the invariant mass m
of the resonance.
Decay Topology
A decay chain is a simple tree, from top particle to final particles.
So the decay chain can be describing as Node (Decay
) and Line (Particle
)
Topology identity: The combination of final particles
For example, the combination of decay chain A->RC,R->BD and A->ZB,R->CD is
{A: [B, C, D], R: [B, D], B: [B], C: [C], D: [D]}
and
{A: [B, C, D], Z: [C, D], B: [B], C: [C], D: [D]}
The item R and Z is not same, so there are two different topology.
{{A: [B, C, D], B: [B], C: [C], D: [D]}}
is the direct A->BCD decay.
From particles to enumerate all possible decay chain topology:
From a basic line, inserting lines to create a full graph.
from a line: A -> B
,
insert a line (node0 -> C
) and a node (node0
):
1. A -> node0, node0 -> B, node0 -> C
insert a line :
1. A -> node0, node0 -> B, node0 -> node1, node1 -> C, node1 -> D
2. A -> node1, node1 -> node0, node0 -> B, node0 -> C, node1 -> D
3. A -> node0, node0 -> node1, node1 -> B, node0 -> C, node1 -> D
there are the three possible decay chains of A -> B,C,D
1. A -> R+B, R -> C+D
2. A -> R+D, R -> B+C
3. A -> R+C, R -> B+D
the process is unique for different final particles
Each inserting process delete a line and add three new line, So for decay process has \(n\) final particles, there are \((2n-3)!!\) possible decay topology.
Resonances Parameters
This section is about how do the Resonances.yml
work.
From Resonacces.yml
to the real model, there will be following steps.
loaded by config.yml, it is will be combined the defination in
config.yml
particle parts.For examples,
config.yml
haveparticle: $include: Resonances.yml Psi4040: float: mg
then
Resonances.yml
itemPsi4040: J: 1 float: m
will become
{"Psi4040": {"J": 1, "float": "mg"}}
replace some alias, (
m0 -> mass
,g0 -> width
, …)If it is used in decay chain, then create
Particle
object.The particle class is
cls = get_particle_model(item["model"])
, and the object iscls(**item)
.All parameters wull be stored in
config.particle_property[name]
.
All aviable parameters can be devied into the flowowing 3 sets.
Common Parameters
Parameters defined in BaseParticle
are common parameters including spin, parity, mass and width.
name |
default value |
comment |
---|---|---|
|
0 |
spin, int or half-integral |
|
-1 |
P-parity, +1 or -1 |
|
None |
C-Parity, +1 or -1 |
|
None |
mass, float, it is always required because of the calcultion of \(q_0\) |
|
None |
width, float |
|
None |
possible spin projections,`[-J, …, J]`, list |
Model Parameters
Parameters defined in the real model. Available Resonances Model
There are many parameters defined by the user, the those parameters will be pass to model class,
such as the paramthers for __init__(self, **kwargs)
method.
For examples, the default model (BWR
, BaseParticle
) have following parameters:
name |
default value |
comment |
---|---|---|
|
True |
if using running width, bool |
|
None, auto deteminated |
running width angular momentum, int |
Other Parameters
There are also some other parameters which is used to control the program running.
For examples, simple constrains, the following parameters are using by ConfigLoader
as constrains.
name |
default value |
comment |
---|---|---|
|
None |
mass range |
|
None |
width range |
|
float paramsters list |
Another examples are parameters to build decay chain for particle R
.
name |
default value |
comment |
---|---|---|
|
|
parameters pass to |
|
|
parameters pass to |
|
|
Particle model for |
There are also other common used parameters.
name |
default value |
comment |
---|---|---|
|
control plot legend with latex string, string |
Phase Space
\(N\) body decay phase space can be defined as
or integrate \(p^0\) as
by using the property of \(\delta\)-function,
where \(x_i\) is the root of \(f(x)=0\).
Phase space has the follow chain rule,
where \(q = \sum_{i=m+1}^{n}p_i\) is the invariant mass of particles \(m+1,\cdots,n\).
The two body decay is simple in the center mass frame \(P=(M,0,0,0)\),
where \(\mathrm{d} \Omega = \mathrm{d}(\cos\theta)\mathrm{d}\varphi\) and
The three body decay in the center mass frame \(P=(M,0,0,0),q^\star=(m_{23},0,0,0)\),
The n body decay in the center mass frame \(P=(M,0,0,0)\),
where
with those limit
Phase Space Generator
For n body phase space
take a weeker condition
has the simple limit at the factor term
Generate \(M_i\) with the factor
Generate \(\mathrm{d}\Omega = \mathrm{d}\cos\theta \mathrm{d}\varphi\)
boost \(p^\star=(\sqrt{|\vec{p*}|^2 + m^2} ,|\vec{p^\star}|\cos\theta\cos\varphi,|\vec{p^\star}|\sin\theta\sin\varphi,|\vec{p^\star}|\cos\theta,)\) to a same farme.
Resolution in Partial Wave Analysis
Resolution is the effect of detector. To Consider the resolution properly, We need to take a general look about the detector process. We can divide the process of detector into two parts. The first part is acceptance, with the probability for truth value \(x\) as \(\epsilon_{T} (x)\). The second part is resolution, it means the measurement value \(y\) will be a random number base on truth value \(x\). It is a conditional probability as \(R_{T}(y|x)\). The conditional probability is normalized as \(\int R_{T}(y|x) \mathrm{d} y = 1\). So, the total effect of detector is transition function
When we have a distribution of truth value with probability \(p(x)\), then we can get the distribution of measurement value with probability
Using the Bayes Rule, we can rewrite \(T(x,y)\) as
where
\(R(x|y)\) is the posterior probability, that means the probability of a certain \(y\) is from \(x\). \(\epsilon_{R}(y)\) is the projection of \(y\) for \(T(x,y)\), and is also the normalize factor for \(R(x|y)\).
Then, the probability \(p'(y)\) can be rewritten as
To consider the resolution, we need to determine \(R(x|y)\). Generally, we use simulation to determine \(R(x|y)\). When \(p(x)=1\) is a flat distribution, then the joint distribution of \(x\) and \(y\) has the probability density \(T(x,y)\). We can build a model for this distribution. To get \(R(x|y)\), we only need to do a normalization for \(T(x,y)\).
In PWA, we usually use the MC to do the normalization for signal probability density. We need to calculate the integration of \(p'(y)\) as
The final negative log-likelihood with considering resolution is
The last part is a constant, we can ignore it in fit. In the numerical form, it can be written as
For the second part, which we already have MC sample with \(x \sim \epsilon_{T}(x)\), we can use MC sample to do the sum directly. For the first part, we can generate some \(x\) (\(M\) times) for every \(y\) (\(N\) events). Using the generated samples (\(MN\) events), we can calculate though the summation.
In addition, we can insert some importance information for the summation as
We need to keep the normalization. For example, we can use Gauss-Hermite quadrature.
In a simple situation, we only use mass for the variable for resolution function. We can build the datasets by replacing the mass by random number based on the resolution function, keeping the same for other variables and using some constrains.
Once we get such datasets, we can use the likelihood method to fit the dataset with resolution. There is an example in checks.
Some examples
Note
Go to the end to download the full example code
Examples for particle model
decay system is model as
- DecayGroup
DecayChain
Decay
Particle
16 import matplotlib.pyplot as plt
17
18 from tf_pwa.amp import Decay, DecayChain, DecayGroup, Particle
19 from tf_pwa.vis import plot_decay_struct
We can easy create some instance of Particle and then combine them as Decay
25 a = Particle("A")
26 b = Particle("B")
27 c = Particle("C")
28 d = Particle("D")
29
30 r = Particle("R")
31
32 dec1 = Decay(a, [r, b])
33 dec2 = Decay(r, [c, d])
DecayChain is a list of Decays.
39 decay_chain = DecayChain([dec1, dec2])
40 decay_chain
[A->R+B, R->C+D]
We can plot it using matplotlib.
45 plot_decay_struct(decay_chain)
46 plt.show()

DecayGroup is a list of DecayChain with the same initial and final states
51 decay_group = DecayGroup([decay_chain])
52 decay_group
[[A->R+B, R->C+D]]
We can build a simple function to infer the charge from final states.
58 def charge_infer(dec, charge_map):
59 # use particle equal condition
60 cached_charge = {Particle(k): v for k, v in charge_map.items()}
61 # loop for all decays in decay chain
62 for i, dec_i in dec.depth_first(False):
63 # all out particles has charge
64 assert all(i in cached_charge for i in dec_i.outs)
65 # the charge or core particle is the sum of
66 cached_charge[dec_i.core] = sum(cached_charge[i] for i in dec_i.outs)
67 return cached_charge
68
69
70 charges = {
71 "B": -1,
72 "C": 0,
73 "D": 1,
74 }
75
76 charge_infer(decay_chain, charges)
{B: -1, C: 0, D: 1, R: 1, A: 0}
See more in cal_chain_boost
.
Total running time of the script: (0 minutes 0.062 seconds)
Note
Go to the end to download the full example code
Examples for Plotter class
Ploter is the new api for partial wave plots.
First, we can build a simple config.
12 config_str = """
13
14 decay:
15 A:
16 - [R1, B]
17 - [R2, C]
18 - [R3, D]
19 R1: [C, D]
20 R2: [B, D]
21 R3: [B, C]
22
23 particle:
24 $top:
25 A: { mass: 1.86, J: 0, P: -1}
26 $finals:
27 B: { mass: 0.494, J: 0, P: -1}
28 C: { mass: 0.139, J: 0, P: -1}
29 D: { mass: 0.139, J: 0, P: -1}
30 R1: [ R1_a, R1_b ]
31 R1_a: { mass: 0.7, width: 0.05, J: 1, P: -1}
32 R1_b: { mass: 0.5, width: 0.05, J: 0, P: +1}
33 R2: { mass: 0.824, width: 0.05, J: 0, P: +1}
34 R3: { mass: 0.824, width: 0.05, J: 0, P: +1}
35
36
37 plot:
38 mass:
39 R1:
40 display: "m(R1)"
41 R2:
42 display: "m(R2)"
43 """
44
45 import matplotlib.pyplot as plt
46 import yaml
47
48 from tf_pwa.config_loader import ConfigLoader
49
50 config = ConfigLoader(yaml.full_load(config_str))
We set parameters to a blance value. And we can generate some toy data and calclute the weights
56 input_params = {
57 "A->R1_a.BR1_a->C.D_total_0r": 6.0,
58 "A->R1_b.BR1_b->C.D_total_0r": 1.0,
59 "A->R2.CR2->B.D_total_0r": 2.0,
60 "A->R3.DR3->B.C_total_0r": 1.0,
61 }
62 config.set_params(input_params)
63
64 data = config.generate_toy(1000)
65 phsp = config.generate_phsp(10000)
7.2%[▓▓▓>----------------------------------------------] 0.58/8.12s eff: 90.000000%
76.9%[▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓>-----------] 1.82/2.37s eff: 5.968929%
103.6%[▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓>] 2.48/2.39s eff: 4.202139%
100.0%[▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 2.48/2.48s eff: 4.255232%
plotter can be created directly from config
71 plotter = config.get_plotter(datasets={"data": [data], "phsp": [phsp]})
Ploting all partial waves is simple.
76 plotter.plot_frame("m_R1")
77 plt.show()

Also we can plot other variables in data
82 from tf_pwa.data import data_index
83
84 m2 = config.get_data_index("mass", "R2")
85 m3 = config.get_data_index("mass", "R3")
86
87
88 def f(data):
89 return data_index(data, m2) - data_index(data, m3)
90
91
92 plt.clf()
93 plotter.plot_var(f)
94 plt.xlabel("m(R2)+m(R3)")
95 plt.show()

There are 3 main parts in a Plotter
PlotAllData: datasets with weights There is three level: (1). idx: Datasets for combine fit (2). type: data, mc, or bg (3). observations and weights: weights are used for partial wave
Frame: function to get obsevations It is samilar to RooFit’s Frame.
Styles: Plot style for differenct componets
The plot process is as follow:
Plotter.plot_item, extra_plot_item, and hidden_plot_item provide the list of histograms for plotting.
Loop over all data to get the observations though frame.
Frame provide the binning, weights from datas. Their combination is histogram
Plot on the axis with style
Total running time of the script: (0 minutes 4.105 seconds)
Note
Go to the end to download the full example code
Particle and amplitude
Amplitude = DecayGroup + Variable
We will use following parameters for a toy model
11 from tf_pwa.amp import DecayChain, DecayGroup, get_decay, get_particle
12
13 resonances = {
14 "R0": {"J": 0, "P": 1, "mass": 1.0, "width": 0.07},
15 "R1": {"J": 0, "P": 1, "mass": 1.0, "width": 0.07},
16 "R2": {"J": 1, "P": -1, "mass": 1.225, "width": 0.08},
17 }
18
19 a, b, c, d = [get_particle(i, J=0, P=-1) for i in "ABCD"]
20 r1, r2, r3 = [get_particle(i, **resonances[i]) for i in resonances.keys()]
21
22
23 decay_group = DecayGroup(
24 [
25 DecayChain([get_decay(a, [r1, c]), get_decay(r1, [b, d])]),
26 DecayChain([get_decay(a, [r2, b]), get_decay(r2, [c, d])]),
27 DecayChain([get_decay(a, [r3, b]), get_decay(r3, [c, d])]),
28 ]
29 )
The above parts can be represented as config.yml used by ConfigLoader.
We can get AmplitudeModel form decay_group and a optional Variables Managerager. It has parameters, so we can get and set parameters for the amplitude model
36 from tf_pwa.amp import AmplitudeModel
37 from tf_pwa.variable import VarsManager
38
39 vm = VarsManager()
40 amp = AmplitudeModel(decay_group, vm=vm)
41
42 print(amp.get_params())
43 amp.set_params(
44 {
45 "A->R0.CR0->B.D_total_0r": 1.0,
46 "A->R1.BR1->C.D_total_0r": 1.0,
47 "A->R2.BR2->C.D_total_0r": 7.0,
48 }
49 )
{'R0_mass': 1.0, 'R0_width': 0.07, 'R1_mass': 1.0, 'R1_width': 0.07, 'R2_mass': 1.225, 'R2_width': 0.08, 'A->R0.CR0->B.D_total_0r': 0.6138840266381949, 'A->R0.CR0->B.D_total_0i': 2.783531635482605, 'A->R0.C_g_ls_0r': 1.0, 'A->R0.C_g_ls_0i': 0.0, 'R0->B.D_g_ls_0r': 1.0, 'R0->B.D_g_ls_0i': 0.0, 'A->R1.BR1->C.D_total_0r': 1.5697110122530802, 'A->R1.BR1->C.D_total_0i': -2.325437511822794, 'A->R1.B_g_ls_0r': 1.0, 'A->R1.B_g_ls_0i': 0.0, 'R1->C.D_g_ls_0r': 1.0, 'R1->C.D_g_ls_0i': 0.0, 'A->R2.BR2->C.D_total_0r': 1.148745906442389, 'A->R2.BR2->C.D_total_0i': -0.3814382213664924, 'A->R2.B_g_ls_0r': 1.0, 'A->R2.B_g_ls_0i': 0.0, 'R2->C.D_g_ls_0r': 1.0, 'R2->C.D_g_ls_0i': 0.0}
For the calculation, we generate some phase space data.
54 from tf_pwa.phasespace import PhaseSpaceGenerator
55
56 m_A, m_B, m_C, m_D = 1.8, 0.18, 0.18, 0.18
57 p1, p2, p3 = PhaseSpaceGenerator(m_A, [m_B, m_C, m_D]).generate(100000)
and the calculate helicity angle from the data
62 from tf_pwa.cal_angle import cal_angle_from_momentum
63
64 data = cal_angle_from_momentum({b: p1, c: p2, d: p3}, decay_group)
we can index mass from data as
69 from tf_pwa.data import data_index
70
71 m_bd = data_index(data, ("particle", "(B, D)", "m"))
72 # m_bc = data_index(data, ("particle", "(B, C)", "m"))
73 m_cd = data_index(data, ("particle", "(C, D)", "m"))
Note
If DecayGroup do not include resonant of (B, C), the data will not include its mass too. We can use different DecayGroup for cal_angle and AmplitudeModel when they have the same initial and final particle.
The amplitde square is calculated by amplitude model simply as
83 amp_s2 = amp(data)
/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/checkouts/latest/docs/../tf_pwa/amp/core.py:822: UserWarning: no mass for particle A, set it to 1.8000000229705984
warnings.warn(
/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/checkouts/latest/docs/../tf_pwa/amp/core.py:822: UserWarning: no mass for particle C, set it to 0.17999999999999977
warnings.warn(
/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/checkouts/latest/docs/../tf_pwa/amp/core.py:822: UserWarning: no mass for particle B, set it to 0.17999999999999977
warnings.warn(
/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/checkouts/latest/docs/../tf_pwa/amp/core.py:822: UserWarning: no mass for particle D, set it to 0.17999999999999977
warnings.warn(
Now by using matplotlib we can get the Dalitz plot as
88 import matplotlib.pyplot as plt
89
90 plt.clf()
91 plt.hist2d(
92 m_bd.numpy() ** 2,
93 m_cd.numpy() ** 2,
94 weights=amp_s2.numpy(),
95 bins=60,
96 cmin=1,
97 cmap="jet",
98 )
99 plt.colorbar()
100 plt.xlabel("$m^2(BD)$")
101 plt.ylabel("$m^2(CD)$")
102 plt.show()

Total running time of the script: (0 minutes 3.127 seconds)
Note
Go to the end to download the full example code
Examples for error propagation
Hear we use the same config in particle_amplitude.py
9 config_str = """
10 decay:
11 A:
12 - [R1, B]
13 - [R2, C]
14 - [R3, D]
15 R1: [C, D]
16 R2: [B, D]
17 R3: [B, C]
18
19 particle:
20 $top:
21 A: { mass: 1.86, J: 0, P: -1}
22 $finals:
23 B: { mass: 0.494, J: 0, P: -1}
24 C: { mass: 0.139, J: 0, P: -1}
25 D: { mass: 0.139, J: 0, P: -1}
26 R1: [ R1_a, R1_b ]
27 R1_a: { mass: 0.7, width: 0.05, J: 1, P: -1}
28 R1_b: { mass: 0.5, width: 0.05, J: 0, P: +1}
29 R2: { mass: 0.824, width: 0.05, J: 0, P: +1}
30 R3: { mass: 0.824, width: 0.05, J: 0, P: +1}
31
32 """
33
34 import matplotlib.pyplot as plt
35 import yaml
36
37 from tf_pwa.config_loader import ConfigLoader
38 from tf_pwa.histogram import Hist1D
39
40 config = ConfigLoader(yaml.full_load(config_str))
41 input_params = {
42 "A->R1_a.BR1_a->C.D_total_0r": 6.0,
43 "A->R1_b.BR1_b->C.D_total_0r": 1.0,
44 "A->R2.CR2->B.D_total_0r": 2.0,
45 "A->R3.DR3->B.C_total_0r": 1.0,
46 }
47 config.set_params(input_params)
48
49 data = config.generate_toy(1000)
50 phsp = config.generate_phsp(10000)
5.5%[▓▓>-----------------------------------------------] 0.52/9.42s eff: 90.000000%
110.7%[▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓>] 1.81/1.64s eff: 4.578904%
100.0%[▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 1.81/1.81s eff: 4.631333%
After we calculated the parameters error, we will have an error matrix config.inv_he
(using the inverse hessain).
It is possible to save such matrix directly by numpy.save
and to load it by numpy.load
.
57 config.get_params_error(data=[data], phsp=[phsp])
Using Model
Time for calculating errors: 0.8861398696899414
hesse_error: [0.06558544780415564, 0.11914595662721354, 0.13531564139886007, 0.09479811115059283, 0.0854211280015047, 0.11878489556009565]
{'A->R1_b.BR1_b->C.D_total_0r': 0.06558544780415564, 'A->R1_b.BR1_b->C.D_total_0i': 0.11914595662721354, 'A->R2.CR2->B.D_total_0r': 0.13531564139886007, 'A->R2.CR2->B.D_total_0i': 0.09479811115059283, 'A->R3.DR3->B.C_total_0r': 0.0854211280015047, 'A->R3.DR3->B.C_total_0i': 0.11878489556009565}
We can use the following method to profamance the error propagation
by adding some calculation here. We need to use tensorflow
functions instead of those of math
or numpy
.
68 import tensorflow as tf
69
70 with config.params_trans() as pt:
71 a2_r = pt["A->R2.CR2->B.D_total_0r"]
72 a2_i = pt["A->R2.CR2->B.D_total_0r"]
73 a2_x = a2_r * tf.cos(a2_i)
And then we can calculate the error we needed as
78 print(a2_x.numpy(), pt.get_error(a2_x).numpy())
-0.8322936730942848 0.3023955051699835
We can also calculate some more complex examples, such as the ratio in mass range (0.75, 0.85) over full phace space. Even further, we can get the error of error in the meaning of error propagation.
84 from tf_pwa.data import data_mask
85
86 m_R2 = phsp.get_mass("(B, D)")
87 cut_cond = (m_R2 < 0.85) & (m_R2 > 0.75)
88
89 amp = config.get_amplitude()
90
91 with config.params_trans() as pt1:
92 with config.params_trans() as pt:
93 int_mc = tf.reduce_sum(amp(phsp))
94 cut_phsp = data_mask(phsp, cut_cond)
95 cut_int_mc = tf.reduce_sum(amp(cut_phsp))
96 ratio = cut_int_mc / int_mc
97 error = pt.get_error(ratio)
98
99 print(ratio.numpy(), "+/-", error.numpy())
100 print(error.numpy(), "+/-", pt1.get_error(error).numpy())
0.35104833872972147 +/- 0.011604506959542505
0.011604506959542505 +/- 0.000678080364691487
Total running time of the script: (0 minutes 4.427 seconds)
Note
Go to the end to download the full example code
Examples for config.yml file
Configuration file config.yml
use YAML (https://yaml.org) format to describe decay process.
The main parts of config.yml is decay
and particle
.
The decay
part describe the particle (or an id of a list of particle)
decay into which particles, it can be a list of a list of list.
A list means that there is ony one decay mode, A list of list is the list of possible decay mode.
The list item can be the particle name (or a dict to describe the decay parameters).
All name should appear in particle
part.
The particle
part describe the parameters of particles.
There are two special parts $top
and $finals
describe the top and finals particles.
The other parts are lists of particle name or dicts of particle parameters.
The list is the same type particle in decay part.
The dict is the parameters of the particle name.
22 config_str = """
23
24 decay:
25 A:
26 - [R1, B]
27 - [R2, C]
28 - [R3, D]
29 R1: [C, D]
30 R2: [B, D]
31 R3: [B, C]
32
33 particle:
34 $top:
35 A: { mass: 1.86, J: 0, P: -1}
36 $finals:
37 B: { mass: 0.494, J: 0, P: -1}
38 C: { mass: 0.139, J: 0, P: -1}
39 D: { mass: 0.139, J: 0, P: -1}
40 R1: [ R1_a, R1_b ]
41 R1_a: { mass: 0.7, width: 0.05, J: 1, P: -1}
42 R1_b: { mass: 0.5, width: 0.05, J: 0, P: +1}
43 R2: { mass: 0.824, width: 0.05, J: 0, P: +1}
44 R3: { mass: 0.824, width: 0.05, J: 0, P: +1}
45
46 """
The config file can be loaded by yaml
library.
52 import matplotlib.pyplot as plt
53 import yaml
54
55 from tf_pwa.config_loader import ConfigLoader
56 from tf_pwa.histogram import Hist1D
The simple way to create config is write it to config.yml
file
and then you can load it as config = ConfigLoader("config.yml")
.
Here we used config_str directly.
64 config = ConfigLoader(yaml.full_load(config_str))
We set parameters to a blance value. And we can generate some toy data and calclute the weights
The full params can be found by print(config.get_params())
.
71 input_params = {
72 "A->R1_a.BR1_a->C.D_total_0r": 6.0,
73 "A->R1_b.BR1_b->C.D_total_0r": 1.0,
74 "A->R2.CR2->B.D_total_0r": 2.0,
75 "A->R3.DR3->B.C_total_0r": 1.0,
76 }
77 config.set_params(input_params)
True
Here we generate some toy data and phsp mc to show the model
82 data = config.generate_toy(1000)
83 phsp = config.generate_phsp(10000)
8.1%[▓▓▓▓>---------------------------------------------] 0.97/11.93s eff: 90.000000%
71.9%[▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓>--------------] 2.58/3.59s eff: 6.704824%
99.8%[▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓>] 3.36/3.37s eff: 4.417178%
99.9%[▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓>] 4.20/4.21s eff: 4.288106%
100.1%[▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓>] 4.65/4.65s eff: 4.283022%
100.0%[▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 4.65/4.65s eff: 4.286998%
You can also fit the data fit to the data We can omit the args when writen in config.yml
90 fit_result = config.fit([data], [phsp])
91 # After the fit, you can get the uncertaities as
92 err = config.get_params_error(fit_result, [data], [phsp])
Using Model
decay chains included:
[A->R1_a+B, R1_a->C+D] ls: ((1, 1),) ((1, 0),)
[A->R1_b+B, R1_b->C+D] ls: ((0, 0),) ((0, 0),)
[A->R2+C, R2->B+D] ls: ((0, 0),) ((0, 0),)
[A->R3+D, R3->B+C] ls: ((0, 0),) ((0, 0),)
########### initial parameters
{
"R1_a_mass": 0.7,
"R1_a_width": 0.05,
"R1_b_mass": 0.5,
"R1_b_width": 0.05,
"R2_mass": 0.824,
"R2_width": 0.05,
"R3_mass": 0.824,
"R3_width": 0.05,
"A->R1_a.BR1_a->C.D_total_0r": 6.0,
"A->R1_a.BR1_a->C.D_total_0i": 0.0,
"A->R1_a.B_g_ls_0r": 1.0,
"A->R1_a.B_g_ls_0i": 0.0,
"R1_a->C.D_g_ls_0r": 1.0,
"R1_a->C.D_g_ls_0i": 0.0,
"A->R1_b.BR1_b->C.D_total_0r": 1.0,
"A->R1_b.BR1_b->C.D_total_0i": 0.516643955083139,
"A->R1_b.B_g_ls_0r": 1.0,
"A->R1_b.B_g_ls_0i": 0.0,
"R1_b->C.D_g_ls_0r": 1.0,
"R1_b->C.D_g_ls_0i": 0.0,
"A->R2.CR2->B.D_total_0r": 2.0,
"A->R2.CR2->B.D_total_0i": -0.26028593362777164,
"A->R2.C_g_ls_0r": 1.0,
"A->R2.C_g_ls_0i": 0.0,
"R2->B.D_g_ls_0r": 1.0,
"R2->B.D_g_ls_0i": 0.0,
"A->R3.DR3->B.C_total_0r": 1.0,
"A->R3.DR3->B.C_total_0i": -1.0457317099708843,
"A->R3.D_g_ls_0r": 1.0,
"A->R3.D_g_ls_0i": 0.0,
"R3->B.C_g_ls_0r": 1.0,
"R3->B.C_g_ls_0i": 0.0
}
initial NLL: tf.Tensor(-898.9759028507142, shape=(), dtype=float64)
nll_grad cost time: 0.28310203552246094
nll_grad cost time: 0.28862833976745605
nll_grad cost time: 0.27806568145751953
tf.Tensor(-901.460626870271, shape=(), dtype=float64)
nll_grad cost time: 0.2856414318084717
nll_grad cost time: 0.2775142192840576
tf.Tensor(-901.815060346682, shape=(), dtype=float64)
nll_grad cost time: 0.2881302833557129
nll_grad cost time: 0.28783345222473145
tf.Tensor(-901.9367900284606, shape=(), dtype=float64)
nll_grad cost time: 0.28736352920532227
tf.Tensor(-902.0098959860925, shape=(), dtype=float64)
nll_grad cost time: 0.2935178279876709
nll_grad cost time: 0.33831048011779785
tf.Tensor(-902.030860420351, shape=(), dtype=float64)
nll_grad cost time: 0.2984912395477295
tf.Tensor(-902.0696796974553, shape=(), dtype=float64)
nll_grad cost time: 0.28069138526916504
tf.Tensor(-902.141046997479, shape=(), dtype=float64)
nll_grad cost time: 0.28609156608581543
tf.Tensor(-902.2618542507471, shape=(), dtype=float64)
nll_grad cost time: 0.2896087169647217
tf.Tensor(-902.3651921552173, shape=(), dtype=float64)
nll_grad cost time: 0.2835099697113037
tf.Tensor(-902.3652799088104, shape=(), dtype=float64)
nll_grad cost time: 0.2927987575531006
tf.Tensor(-902.3652800520076, shape=(), dtype=float64)
Optimization terminated successfully.
Current function value: -902.365280
Iterations: 11
Function evaluations: 16
Gradient evaluations: 16
message: Optimization terminated successfully.
success: True
status: 0
fun: -902.3652800520076
x: [ 9.766e-01 4.223e-01 1.971e+00 -2.059e-01 8.730e-01
-9.470e-01]
nit: 11
jac: [-1.030e-04 2.390e-05 9.793e-05 -1.628e-04 -3.810e-04
7.891e-05]
hess_inv: [[ 3.297e-03 -2.805e-06 ... 1.934e-03 6.066e-04]
[-2.805e-06 1.673e-02 ... -2.936e-05 1.131e-02]
...
[ 1.934e-03 -2.936e-05 ... 4.916e-03 -1.384e-03]
[ 6.066e-04 1.131e-02 ... -1.384e-03 2.133e-02]]
nfev: 16
njev: 16
fit cost time: 4.949615240097046
Using Model
Time for calculating errors: 0.716533899307251
hesse_error: [0.05697192711142273, 0.1287701442709621, 0.11039188141067978, 0.10222381278776968, 0.06877040102743294, 0.14535930067646324]
we can see that thre fit results consistant with inputs, the first one is fixed.
97 for var in input_params:
98 print(
99 f"in: {input_params[var]} => out: {fit_result.params[var]} +/- {err.get(var, 0.)}"
100 )
in: 6.0 => out: 6.0 +/- 0.0
in: 1.0 => out: 0.9765715965740237 +/- 0.05697192711142273
in: 2.0 => out: 1.9707491735520626 +/- 0.11039188141067978
in: 1.0 => out: 0.8729589460098967 +/- 0.06877040102743294
We can use the amplitude to plot the fit results
105 amp = config.get_amplitude()
This is the total \(|A|^2\)
110 weight = amp(phsp)
This is the \(|A_i|^2\) for each decay chain
115 partial_weight = amp.partial_weight(phsp)
We can plot the data, Hist1D include some plot method base on matplotlib.
120 data_hist = Hist1D.histogram(
121 data.get_mass("(C, D)"), bins=60, range=(0.25, 1.45)
122 )
Read the mass var from phsp.
127 mass_phsp = phsp.get_mass("(C, D)")
For helicity angle it can be read as phsp.get_angle("(C, D)", "C")
The first arg is used to deteminate the decay chain. (decay chain include all particles)
The second arg is used to deteminate the angle in decay chain.
The return value is a dict as {"alpha": phi, "beta": theta, "gamma": 0}
136 phsp_hist = Hist1D.histogram(
137 mass_phsp, weights=weight, bins=60, range=(0.25, 1.45)
138 )
139 scale = phsp_hist.scale_to(data_hist)
140
141 pw_hist = []
142 for w in partial_weight:
143 # here we used more bins for a smooth plot
144 hist = Hist1D.histogram(
145 mass_phsp, weights=w, bins=60 * 2, range=(0.25, 1.45)
146 )
147 pw_hist.append(scale * hist * 2)
Then we can plot the histogram into matplotlib
152 for hist, dec in zip(pw_hist, config.get_decay()):
153 hist.draw_kde(label=str(dec))
154 phsp_hist.draw(label="total amplitude")
155 data_hist.draw_error(label="toy data", color="black")
156
157 plt.legend()
158 plt.ylim((0, None))
159 plt.xlabel("M(CD)/ GeV")
160 plt.ylabel("Events/ 20 MeV")
161 plt.show()

Total running time of the script: (0 minutes 11.825 seconds)
Setup for Developer Enveriment
Note
Before the developing, creating a standalone enveriment is recommanded (see https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#creating-an-environment-with-commands for more).
The main steps are similar as normal install, only two extra things need to be done.
The first things is writing tests, and tests your code. We use pytest (https://docs.pytest.org/en/stable/) framework, You should install it.
conda install pytest pytest-cov pytest-benchmark
The other things is pre-commit
. it need for developing.
You can install
pre-commit
as
conda install pre-commit
and
then enable
pre-commit
in the source dir
conda install pylint # local dependences
pre-commit install
You can check if pre-commit is working well by running
pre-commit run -a
It may take some time to install required package.
Note
If there are some GLIBC_XXX
errors at this step, you can try to install node.js
.
Note
For developer using editor with formatter, you should be careful for the options.
The following are all commands needed
# create environment
conda create -n tfpwa2 python=3.7 -y
conda activate tfpwa2
# install tf-pwa
conda install --file requirements-min.txt -y
python -m pip install -e . --no-deps
# install pytest
conda install pytest pytest-cov -y
# install pylint local
conda install pylint
# install pre-commit
conda install pre-commit -c conda-forge -y
pre-commit install
API
tf_pwa
Partial Wave Analysis program using Tensorflow
Submodules and Subpackages
amp
Basic Amplitude Calculations. A partial wave analysis process has following structure:
- DecayGroup: addition (+)
- DecayChain: multiplication (x)
Decay, Particle(Propagator)
Submodules and Subpackages
Kmatrix
- class KmatrixSingleChannelParticle(*args, **kwargs)[source]
Bases:
Particle
K matrix model for single channel multi pole.
\[K = \sum_{i} \frac{m_i \Gamma_i(m)}{m_i^2 - m^2 }\]\[P = \sum_{i} \frac{\beta_i m_0 \Gamma_0 }{ m_i^2 - m^2}\]the barrier factor is included in gls
\[R(m) = (1-iK)^{-1} P\]requird
mass_list: [pole1, pole2]
andwidth_list: [width1, width2]
.(
Source code
,png
,hires.png
,pdf
)- model_name = 'KMatrixSingleChannel'
- class KmatrixSplitLSParticle(*args, **kwargs)[source]
Bases:
Particle
K matrix model for single channel multi pole and the same channel with different (l, s) coupling.
\[K_{a,b} = \sum_{i} \frac{m_i \sqrt{\Gamma_{a,i}(m)\Gamma_{b,i}(m)}}{m_i^2 - m^2 }\]\[P_{b} = \sum_{i} \frac{\beta_i m_0 \Gamma_{b,i0} }{ m_i^2 - m^2}\]the barrier factor is included in gls
\[R(m) = (1-iK)^{-1} P\]- model_name = 'KMatrixSplitLS'
- class ParticleDecayLSKmatrix(*args, **kwargs)[source]
Bases:
HelicityDecay
- model_name = 'LS-decay-Kmatrix'
amp
- class AbsPDF(*args, name='', vm=None, polar=None, use_tf_function=False, no_id_cached=False, jit_compile=False, **kwargs)[source]
Bases:
object
- property trainable_variables
- property variables
- class AmplitudeModel(decay_group, **kwargs)[source]
Bases:
BaseAmplitudeModel
- class CachedAmpAmplitudeModel(decay_group, **kwargs)[source]
Bases:
BaseAmplitudeModel
- class CachedShapeAmplitudeModel(*args, **kwargs)[source]
Bases:
BaseAmplitudeModel
- class FactorAmplitudeModel(*args, **kwargs)[source]
Bases:
BaseAmplitudeModel
- class P4DirectlyAmplitudeModel(decay_group, **kwargs)[source]
Bases:
BaseAmplitudeModel
ampgen_FOCUS
ampgen_pipi_swave
- class PiPiSwaveKmatrix(name, **kwargs)[source]
Bases:
Particle
pipi S wave model from AmpGen (https://github.com/GooFit/AmpGen/blob/master/src/Lineshapes/kMatrix.cpp). using the parameters from
DtoKKpipi_v2.opt
(https://github.com/GooFit/AmpGen/blob/master/options/DtoKKpipi_v2.opt)(
Source code
,png
,hires.png
,pdf
)- model_name = 'pipi_Swave'
- phsp_fourPi(s)[source]
Parameterisation of the 4pi phase space taken from
Laura
(https://laura.hepforge.org/ or Ref. https://arxiv.org/abs/1711.09854)
base
Basic amplitude model
- class HelicityDecayCPV(*args, has_barrier_factor=True, l_list=None, barrier_factor_mass=False, has_ql=True, has_bprime=True, aligned=False, allow_cc=True, ls_list=None, barrier_factor_norm=False, params_polar=None, below_threshold=False, force_min_l=False, params_head=None, no_q0=False, helicity_inner_full=False, ls_selector=None, **kwargs)[source]
Bases:
HelicityDecay
decay model for CPV
- model_name = 'gls-cpv'
- class HelicityDecayNP(*args, has_barrier_factor=True, l_list=None, barrier_factor_mass=False, has_ql=True, has_bprime=True, aligned=False, allow_cc=True, ls_list=None, barrier_factor_norm=False, params_polar=None, below_threshold=False, force_min_l=False, params_head=None, no_q0=False, helicity_inner_full=False, ls_selector=None, **kwargs)[source]
Bases:
HelicityDecay
Full helicity amplitude
\[A = H_{m_1, m_2} D_{m_0, m_1-m_2}^{J_0 *}(\varphi, \theta,0)\]fit parameters is \(H_{m_1, m_2}\).
- model_name = 'helicity_full'
- class HelicityDecayNPbf(*args, has_barrier_factor=True, l_list=None, barrier_factor_mass=False, has_ql=True, has_bprime=True, aligned=False, allow_cc=True, ls_list=None, barrier_factor_norm=False, params_polar=None, below_threshold=False, force_min_l=False, params_head=None, no_q0=False, helicity_inner_full=False, ls_selector=None, **kwargs)[source]
Bases:
HelicityDecayNP
- model_name = 'helicity_full-bf'
- class HelicityDecayP(*args, has_barrier_factor=True, l_list=None, barrier_factor_mass=False, has_ql=True, has_bprime=True, aligned=False, allow_cc=True, ls_list=None, barrier_factor_norm=False, params_polar=None, below_threshold=False, force_min_l=False, params_head=None, no_q0=False, helicity_inner_full=False, ls_selector=None, **kwargs)[source]
Bases:
HelicityDecayNP
\[H_{- m1, - m2} = P_0 P_1 P_2 (-1)^{J_1 + J_2 - J_0} H_{m1, m2}\]- model_name = 'helicity_parity'
- class HelicityDecayReduceH0(*args, has_barrier_factor=True, l_list=None, barrier_factor_mass=False, has_ql=True, has_bprime=True, aligned=False, allow_cc=True, ls_list=None, barrier_factor_norm=False, params_polar=None, below_threshold=False, force_min_l=False, params_head=None, no_q0=False, helicity_inner_full=False, ls_selector=None, **kwargs)[source]
Bases:
HelicityDecay
decay model that remove helicity =0 for massless particles
- model_name = 'gls_reduce_h0'
- class ParticleBW(*args, running_width=True, bw_l=None, width_norm=False, params_head=None, **kwargs)[source]
Bases:
Particle
\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 \Gamma_0}\](
Source code
,png
,hires.png
,pdf
)- model_name = 'BW'
- class ParticleBWR2(*args, running_width=True, bw_l=None, width_norm=False, params_head=None, **kwargs)[source]
Bases:
Particle
\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 \Gamma(m)}\]The difference of
BWR
,BWR2
is the behavior when mass is below the threshold ( \(m_0 = 0.1 < 0.1 + 0.1 = m_1 + m_2\)).(
Source code
,png
,hires.png
,pdf
)- model_name = 'BWR2'
- class ParticleBWRBelowThreshold(*args, running_width=True, bw_l=None, width_norm=False, params_head=None, **kwargs)[source]
Bases:
Particle
\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 \Gamma(m)}\]- model_name = 'BWR_below'
- class ParticleBWRCoupling(*args, running_width=True, bw_l=None, width_norm=False, params_head=None, **kwargs)[source]
Bases:
Particle
Force \(q_0=1/d\) to avoid below theshold condition for
BWR
model, and remove other constant parts, then the \(\Gamma_0\) is coupling parameters.\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 \Gamma_0 \frac{q}{m} q^{2l} B_L'^2(q, 1/d, d)}\](
Source code
,png
,hires.png
,pdf
)- model_name = 'BWR_coupling'
- class ParticleBWR_normal(*args, running_width=True, bw_l=None, width_norm=False, params_head=None, **kwargs)[source]
Bases:
Particle
\[R(m) = \frac{\sqrt{m_0 \Gamma(m)}}{m_0^2 - m^2 - i m_0 \Gamma(m)}\]- model_name = 'BWR_normal'
- class ParticleDecay(*args, has_barrier_factor=True, l_list=None, barrier_factor_mass=False, has_ql=True, has_bprime=True, aligned=False, allow_cc=True, ls_list=None, barrier_factor_norm=False, params_polar=None, below_threshold=False, force_min_l=False, params_head=None, no_q0=False, helicity_inner_full=False, ls_selector=None, **kwargs)[source]
Bases:
HelicityDecay
- model_name = 'particle-decay'
- class ParticleExp(*args, running_width=True, bw_l=None, width_norm=False, params_head=None, **kwargs)[source]
Bases:
Particle
\[R(m) = e^{-|a| m}\]- model_name = 'exp'
- class ParticleExpCom(*args, running_width=True, bw_l=None, width_norm=False, params_head=None, **kwargs)[source]
Bases:
Particle
\[R(m) = e^{-(a+ib) m^2}\]lineshape when \(a=1.0, b=10.\)
(
Source code
,png
,hires.png
,pdf
)- model_name = 'exp_com'
- class ParticleGS(*args, **kwargs)[source]
Bases:
Particle
Gounaris G.J., Sakurai J.J., Phys. Rev. Lett., 21 (1968), pp. 244-247
c_daug2Mass
: mass for daughter particle 2 (\(\pi^{+}\)) 0.13957039c_daug3Mass
: mass for daughter particle 3 (\(\pi^{0}\)) 0.1349768\[R(m) = \frac{1 + D \Gamma_0 / m_0}{(m_0^2 -m^2) + f(m) - i m_0 \Gamma(m)}\]\[f(m) = \Gamma_0 \frac{m_0 ^2 }{q_0^3} \left[q^2 [h(m)-h(m_0)] + (m_0^2 - m^2) q_0^2 \frac{d h}{d m}|_{m0} \right]\]\[h(m) = \frac{2}{\pi} \frac{q}{m} \ln \left(\frac{m+2q}{2m_{\pi}} \right)\]\[\frac{d h}{d m}|_{m0} = h(m_0) [(8q_0^2)^{-1} - (2m_0^2)^{-1}] + (2\pi m_0^2)^{-1}\]\[D = \frac{f(0)}{\Gamma_0 m_0} = \frac{3}{\pi}\frac{m_\pi^2}{q_0^2} \ln \left(\frac{m_0 + 2q_0}{2 m_\pi }\right) + \frac{m_0}{2\pi q_0} - \frac{m_\pi^2 m_0}{\pi q_0^3}\]- model_name = 'GS_rho'
- class ParticleKmatrix(*args, running_width=True, bw_l=None, width_norm=False, params_head=None, **kwargs)[source]
Bases:
Particle
- model_name = 'Kmatrix'
- class ParticleLass(*args, running_width=True, bw_l=None, width_norm=False, params_head=None, **kwargs)[source]
Bases:
Particle
- get_amp(data, data_c=None, **kwargs)[source]
- \[R(m) = \frac{m}{q cot \delta_B - i q} + e^{2i \delta_B}\frac{m_0 \Gamma_0 \frac{m_0}{q_0}} {(m_0^2 - m^2) - i m_0\Gamma_0 \frac{q}{m}\frac{m_0}{q_0}}\]\[cot \delta_B = \frac{1}{a q} + \frac{1}{2} r q\]\[e^{2i\delta_B} = \cos 2 \delta_B + i \sin 2\delta_B = \frac{cot^2\delta_B -1 }{cot^2 \delta_B +1} + i \frac{2 cot \delta_B }{cot^2 \delta_B +1 }\]
- model_name = 'LASS'
- class ParticleOne(*args, running_width=True, bw_l=None, width_norm=False, params_head=None, **kwargs)[source]
Bases:
Particle
\[R(m) = 1\](
Source code
,png
,hires.png
,pdf
)- model_name = 'one'
core
Basic Amplitude Calculations. A partial wave analysis process has following structure:
- DecayGroup: addition (+)
- DecayChain: multiplication (x)
Decay, Particle(Propagator)
- class AmpDecay(core, outs, name=None, disable=False, p_break=False, c_break=True, curve_style=None, **kwargs)[source]
-
base class for decay with amplitude
- class AmpDecayChain(*args, is_cp=False, aligned=True, **kwargs)[source]
Bases:
DecayChain
,AmpBase
- class AngSam3Decay(core, outs, name=None, disable=False, p_break=False, c_break=True, curve_style=None, **kwargs)[source]
-
- model_name = 'default'
- class DecayChain(*args, is_cp=False, aligned=True, **kwargs)[source]
Bases:
AmpDecayChain
A list of Decay as a chain decay
- model_name = 'default'
- class DecayGroup(chains)[source]
Bases:
DecayGroup
,AmpBase
A Group of Decay Chains with the same final particles.
- class HelicityDecay(*args, has_barrier_factor=True, l_list=None, barrier_factor_mass=False, has_ql=True, has_bprime=True, aligned=False, allow_cc=True, ls_list=None, barrier_factor_norm=False, params_polar=None, below_threshold=False, force_min_l=False, params_head=None, no_q0=False, helicity_inner_full=False, ls_selector=None, **kwargs)[source]
Bases:
AmpDecay
default decay model
The total amplitude is
\[A = H_{\lambda_{B},\lambda_{C}}^{A \rightarrow B+C} D^{J_A*}_{\lambda_{A}, \lambda_{B}-\lambda_{C}} (\varphi,\theta,0)\]The helicity coupling is
\[H_{\lambda_{B},\lambda_{C}}^{A \rightarrow B+C} = \sum_{ls} g_{ls} \sqrt{\frac{2l+1}{2 J_{A}+1}} \langle l 0; s \delta|J_{A} \delta\rangle \langle J_{B} \lambda_{B} ;J_{C} -\lambda_{C} | s \delta \rangle q^{l} B_{l}'(q, q_0, d)\]The fit parameters is \(g_{ls}\)
There are some options
(1).
has_bprime=False
will remove the \(B_{l}'(q, q_0, d)\) part.(2).
has_barrier_factor=False
will remove the \(q^{l} B_{l}'(q, q_0, d)\) part.(3).
barrier_factor_norm=True
will replace \(q^l\) with \((q/q_{0})^l\)(4).
below_threshold=True
will replace the mass used to calculate \(q_0\) with\[m_0^{eff} = m^{min} + \frac{m^{max} - m^{min}}{2}(1+tanh \frac{m_0 - \frac{m^{max} + m^{min}}{2}}{m^{max} - m^{min}})\](5).
l_list=[l1, l2]
andls_list=[[l1, s1], [l2, s2]]
options give the list of all possible LS used in the decay.(6).
no_q0=True
will set the \(q_0=1\).- get_cg_matrix(out_sym=False)[source]
The matrix indexed by \([(l,s),(\lambda_b,\lambda_c)]\). The matrix element is
\[\sqrt{\frac{ 2 l + 1 }{ 2 j_a + 1 }} \langle j_b, j_c, \lambda_b, - \lambda_c | s, \lambda_b - \lambda_c \rangle \langle l, s, 0, \lambda_b - \lambda_c | j_a, \lambda_b - \lambda_c \rangle\]This is actually the pre-factor of \(g_ls\) in the amplitude formula.
- Returns:
2-d array of real numbers
- model_name = 'default'
- class Particle(*args, running_width=True, bw_l=None, width_norm=False, params_head=None, **kwargs)[source]
Bases:
BaseParticle
,AmpBase
\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 \Gamma(m)}\]Argand diagram
(
Source code
,png
,hires.png
,pdf
)Pole position
(
Source code
,png
,hires.png
,pdf
)- model_name = 'BWR'
- class ParticleX(*args, running_width=True, bw_l=None, width_norm=False, params_head=None, **kwargs)[source]
Bases:
Particle
simple particle model for mass, (used in expr)
\[R(m) = m\](
Source code
,png
,hires.png
,pdf
)- model_name = 'x'
- regist_decay(name=None, num_outs=2, f=None)
register a decay model
- Params name:
model name used in configuration
- Params f:
Model class
- regist_particle(name=None, f=None)
register a particle model
- Params name:
model name used in configuration
- Params f:
Model class
- register_decay(name=None, num_outs=2, f=None)[source]
register a decay model
- Params name:
model name used in configuration
- Params f:
Model class
- register_decay_chain(name=None, f=None)[source]
register a decay model
- Params name:
model name used in configuration
- Params f:
Model class
- register_particle(name=None, f=None)[source]
register a particle model
- Params name:
model name used in configuration
- Params f:
Model class
cov_ten
- class CovTenDecayChain(*args, is_cp=False, aligned=True, **kwargs)[source]
Bases:
DecayChain
- model_name = 'cov_ten'
- class CovTenDecayNew(*args, **kwargs)[source]
Bases:
HelicityDecay
Decay Class for covariant tensor formula
- class CovTenDecaySimple(*args, **kwargs)[source]
Bases:
CovTenDecayNew
Decay Class for covariant tensor formula
- model_name = 'cov_ten_simple'
flatte
- class ParticleFlate2(*args, im_sign=-1, l_list=None, has_bprime=True, no_m0=False, no_q0=False, cut_phsp=False, **kwargs)[source]
Bases:
ParticleFlateGen
General Flatte like formula.
\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 [\sum_{i} \color{red}{g_i^2}\color{black} \frac{q_i}{m} \times \frac{m_0}{|q_{i0}|} \times \frac{|q_i|^{2l_i}}{|q_{i0}|^{2l_i}} B_{l_i}'^2(|q_i|,|q_{i0}|,d)]}\]\[\begin{split}q_i = \begin{cases} \frac{\sqrt{(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) >= 0 \\ \frac{i\sqrt{|(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)|}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) < 0 \\ \end{cases}\end{split}\]It has the same options as
FlatteGen
.(
Source code
,png
,hires.png
,pdf
)- model_name = 'Flatte2'
- class ParticleFlateGen(*args, im_sign=-1, l_list=None, has_bprime=True, no_m0=False, no_q0=False, cut_phsp=False, **kwargs)[source]
Bases:
ParticleFlatte
More General Flatte like formula
\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 [\sum_{i} g_i \frac{q_i}{m} \times \frac{m_0}{|q_{i0}|} \times \frac{|q_i|^{2l_i}}{|q_{i0}|^{2l_i}} B_{l_i}'^2(|q_i|,|q_{i0}|,d)]}\]\[\begin{split}q_i = \begin{cases} \frac{\sqrt{(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) >= 0 \\ \frac{i\sqrt{|(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)|}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) < 0 \\ \end{cases}\end{split}\]Required input arguments
mass_list: [[m11, m12], [m21, m22]]
for \(m_{i,1}, m_{i,2}\). And addition argumentsl_list: [l1, l2]
for \(l_i\)has_bprime=False
to remove \(B_{l_i}'^2(|q_i|,|q_{i0}|,d)\).cut_phsp=True
to set \(q_i = 0\) when \((m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) < 0\)The plot use parameters \(m_0=0.7, m_{0,1}=m_{0,2}=0.1, m_{1,1}=m_{1,2}=0.3, g_0=0.3,g_1=0.2,l_0=0,l_1=1\).
(
Source code
,png
,hires.png
,pdf
)no_m0=True
to set \(i m_0 => i\) in the width part.no_q0=True
to remove \(\frac{m_0}{|q_{i0}|}\) and set others \(q_{i0}=1\).(
Source code
,png
,hires.png
,pdf
)- model_name = 'FlatteGen'
- class ParticleFlatte(*args, mass_list=None, im_sign=1, **kwargs)[source]
Bases:
Particle
Flatte like formula
\[R(m) = \frac{1}{m_0^2 - m^2 + i m_0 (\sum_{i} g_i \frac{q_i}{m})}\]\[\begin{split}q_i = \begin{cases} \frac{\sqrt{(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) >= 0 \\ \frac{i\sqrt{|(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)|}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) < 0 \\ \end{cases}\end{split}\](
Source code
,png
,hires.png
,pdf
)Required input arguments
mass_list: [[m11, m12], [m21, m22]]
for \(m_{i,1}, m_{i,2}\).- model_name = 'Flatte'
- class ParticleFlatteC(*args, im_sign=-1, **kwargs)[source]
Bases:
ParticleFlatte
Flatte like formula
\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 (\sum_{i} g_i \frac{q_i}{m})}\]\[\begin{split}q_i = \begin{cases} \frac{\sqrt{(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) >= 0 \\ \frac{i\sqrt{|(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)|}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) < 0 \\ \end{cases}\end{split}\]Required input arguments
mass_list: [[m11, m12], [m21, m22]]
for \(m_{i,1}, m_{i,2}\).(
Source code
,png
,hires.png
,pdf
)- model_name = 'FlatteC'
interpolation
- class HistParticle(*args, **kwargs)[source]
Bases:
InterpolationParticle
- class Interp(*args, **kwargs)[source]
Bases:
InterpolationParticle
linear interpolation for complex number
- model_name = 'interp_c'
- class Interp1D3(*args, **kwargs)[source]
Bases:
InterpolationParticle
Piecewise third order interpolation
- model_name = 'interp1d3'
- class Interp1DLang(*args, **kwargs)[source]
Bases:
InterpolationParticle
Lagrange interpolation
- model_name = 'interp_lagrange'
- class Interp1DSpline(*args, **kwargs)[source]
Bases:
InterpolationParticle
Spline interpolation function for model independent resonance
- model_name = 'spline_c'
- class Interp1DSplineIdx(*args, **kwargs)[source]
Bases:
InterpolationParticle
Spline function in index way.
use
min_m: 0.19 max_m: 0.91 interp_N: 8 with_bound: True
for mass range [0.19, 0.91] and 8 interpolation points
The first and last are fixed to zero unless set
with_bound: True
.This is an example of \(k\exp (i k)\) for point k.
(
Source code
,png
,hires.png
,pdf
)- model_name = 'spline_c_idx'
- class InterpHist(*args, **kwargs)[source]
Bases:
InterpolationParticle
Interpolation for each bins as constant
- model_name = 'interp_hist'
- class InterpHistIdx(*args, **kwargs)[source]
Bases:
HistParticle
Interpolation for each bins as constant
use
min_m: 0.19 max_m: 0.91 interp_N: 8 with_bound: True
for mass range [0.19, 0.91] and 7 bins
The first and last are fixed to zero unless set
with_bound: True
.This is an example of \(k\exp (i k)\) for point k.
(
Source code
,png
,hires.png
,pdf
)- model_name = 'hist_idx'
- class InterpL3(*args, **kwargs)[source]
Bases:
InterpolationParticle
- model_name = 'interp_l3'
- class InterpLinearNpy(*args, **kwargs)[source]
Bases:
InterpolationParticle
Linear interpolation model from a
npy
file with array of [mi, re(ai), im(ai)]. Requiredfile: path_of_file.npy
, for the path ofnpy
file.The example is
exp(5 I m)
.(
Source code
,png
,hires.png
,pdf
)- model_name = 'linear_npy'
- class InterpLinearTxt(*args, **kwargs)[source]
Bases:
InterpLinearNpy
Linear interpolation model from a
txt
file with array of [mi, re(ai), im(ai)]. Requiredfile: path_of_file.txt
, for the path oftxt
file.The example is
exp(5 I m)
.(
Source code
,png
,hires.png
,pdf
)- model_name = 'linear_txt'
- class InterpSPPCHIP(*args, **kwargs)[source]
Bases:
InterpolationParticle
Shape-Preserving Piecewise Cubic Hermite Interpolation Polynomial. It is monotonic in each interval.
(
Source code
,png
,hires.png
,pdf
)- model_name = 'sppchip'
- spline_xi_matrix(xi, bc_type='not-a-knot')[source]
build matrix of xi for spline interpolation solve equation
\[S_i'(x_i) = S_{i-1}'(x_i)\]and two bound condition. \(S_0'(x_0) = S_{n-1}'(x_n) = 0\)
- sppchip(m, xi, y, idx=None, matrix=None)[source]
Shape-Preserving Piecewise Cubic Hermite Interpolation Polynomial. It is monotonic in each interval.
>>> from scipy.interpolate import pchip_interpolate >>> x_observed = np.linspace(0.0, 10.0, 11) >>> y_observed = np.sin(x_observed) >>> x = np.linspace(min(x_observed), max(x_observed)-1e-12, num=100) >>> y = pchip_interpolate(x_observed, y_observed, x) >>> assert np.allclose(y, sppchip(x, x_observed, y_observed).numpy())
kmatrix_simple
- class KmatrixSimple(*args, **kwargs)[source]
Bases:
KmatrixSplitLSParticle
simple Kmatrix formula.
K-matrix
\[K_{i,j} = \sum_{a} \frac{g_{i,a} g_{j,a}}{m_a^2 - m^2+i\epsilon}\]P-vector
\[P_{i} = \sum_{a} \frac{\beta_{a} g_{i,a}}{m_a^2 - m^2 +i\epsilon} + f_{bkg,i}\]total amplitude
\[R(m) = n (1 - K i \rho n^2)^{-1} P\]barrief factor
\[n_{ii} = q_i^l B'_l(q_i, 1/d, d)\]phase space factor
\[\rho_{ii} = q_i/m\]\(q_i\) is 0 when below threshold
- model_name = 'KmatrixSimple'
preprocess
- class BasePreProcessor(decay_struct, root_config=None, model='defualt', **kwargs)[source]
Bases:
HeavyCall
- class CachedAmpPreProcessor(*args, **kwargs)[source]
Bases:
BasePreProcessor
- class CachedAnglePreProcessor(*args, **kwargs)[source]
Bases:
BasePreProcessor
- class CachedShapePreProcessor(*args, **kwargs)[source]
Bases:
CachedAmpPreProcessor
split_ls
- class ParticleBWRLS(*args, **kwargs)[source]
Bases:
ParticleLS
Breit Wigner with split ls running width
\[R_i (m) = \frac{g_i}{m_0^2 - m^2 - im_0 \Gamma_0 \frac{\rho}{\rho_0} (\sum_{i} g_i^2)}\], \(\rho = 2q/m\), the partial width factor is
\[g_i = \gamma_i \frac{q^l}{q_0^l} B_{l_i}'(q,q_0,d)\]and keep normalize as
\[\sum_{i} \gamma_i^2 = 1.\]The normalize is done by (\(\cos \theta_0, \sin\theta_0 \cos \theta_1, \cdots, \prod_i \sin\theta_i\))
- model_name = 'BWR_LS'
- class ParticleBWRLS2(*args, **kwargs)[source]
Bases:
ParticleLS
Breit Wigner with split ls running width, each one use their own l,
\[R_i (m) = \frac{1}{m_0^2 - m^2 - im_0 \Gamma_0 \frac{\rho}{\rho_0} (g_i^2)}\], \(\rho = 2q/m\), the partial width factor is
\[g_i = \gamma_i \frac{q^l}{q_0^l} B_{l_i}'(q,q_0,d)\]- model_name = 'BWR_LS2'
- class ParticleDecayLS(*args, **kwargs)[source]
Bases:
HelicityDecay
- model_name = 'LS-decay'
- class ParticleMultiBW(*args, **kwargs)[source]
Bases:
ParticleMultiBWR
Combine Multi BW into one particle
- model_name = 'MultiBW'
- class ParticleMultiBWR(*args, **kwargs)[source]
Bases:
ParticleLS
Combine Multi BWR into one particle
(
Source code
,png
,hires.png
,pdf
)- model_name = 'MultiBWR'
app
Submodules and Subpackages
config_loader
Submodules and Subpackages
base_config
config_loader
- class ConfigLoader(file_name, vm=None, share_dict=None)[source]
Bases:
BaseConfig
class for loading config.yml
- attach_fix_params_error(params: dict, V_b=None) ndarray [source]
The minimal condition
\[-\frac{\partial\ln L(a,b)}{\partial a} = 0,\]can be treated as a implect function \(a(b)\). The gradients is
\[\frac{\partial a }{\partial b} = - (\frac{\partial^2 \ln L(a,b)}{\partial a \partial a })^{-1} \frac{\partial \ln L(a,b)}{\partial a\partial b }.\]The uncertanties from b with error matrix \(V_b\) can propagate to a as
\[V_a = \frac{\partial a }{\partial b} V_b \frac{\partial a }{\partial b}\]This matrix will be added to the config.inv_he.
- cal_bins_numbers(adapter, data, phsp, read_data, bg=None, bg_weight=None)
- cal_chi2(read_data=None, bins=[[2, 2], [2, 2], [2, 2]], mass=['R_BD', 'R_CD'])
- cal_fitfractions(params={}, mcdata=None, res=None, exclude_res=[], batch=25000, method='old')[source]
- fit(data=None, phsp=None, bg=None, inmc=None, batch=65000, method='BFGS', check_grad=False, improve=False, reweight=False, maxiter=None, jac=True, print_init_nll=True, callback=None, grad_scale=1.0, gtol=0.001)[source]
- generate_SDP(node, N=1000, include_charge=False, legacy=True)
- generate_SDP_p(node, N=1000, legacy=False)
- generate_phsp(N=1000, include_charge=False, cal_max=False)
- generate_phsp_p(N=1000, cal_max=False)
- generate_toy(N=1000, force=True, gen=None, gen_p=None, importance_f=None, max_N=100000, include_charge=False, cal_phsp_max=False)
A more accurate method for generating toy data.
- Parameters:
N – number of events.
force – if romove extra data generated.
gen – optional function for generate phase space, the return value is same as config.get_data.
gen_p – optional function for generate phase space, the return value is dict as
{B: pb, C: pc, D: pd}
.max_N – max number of events for every try.
- generate_toy2(*args, **kwargs)
- generate_toy_o(N=1000, force=True, max_N=100000)
- generate_toy_p(N=1000, force=True, gen_p=None, importance_f=None, max_N=100000, include_charge=False, cal_phsp_max=False)
generate toy data momentum.
- get_SDP_generator(node, include_charge=False, legacy=True)
- get_SDP_p_generator(node, legacy=True)
- get_all_frame()
- get_all_plotdatas(data=None, phsp=None, bg=None, res=None, use_weighted=False)
- get_chain_property(idx, display=True)
Get chain name and curve style in plot
- get_dalitz(a, b)
- get_dalitz_boundary(a, b, N=1000)
- get_params_error(params=None, data=None, phsp=None, bg=None, inmc=None, batch=10000, using_cached=False, method=None, force_pos=True, correct_params=None)[source]
calculate parameters error
- get_particle_function(name, d_norm=False)
- get_phsp_generator(include_charge=False, nodes=[])
- get_phsp_p_generator(nodes=[])
- get_plotter(legend_file=None, res=None, datasets=None, use_weighted=False)
- plot_adaptive_2dpull(var1, var2, binning=[[2, 2], [2, 2], [2, 2]], ax=<module 'matplotlib.pyplot' from '/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/envs/latest/lib/python3.10/site-packages/matplotlib/pyplot.py'>, where={}, cut_zero=True, plot_scatter=True, scatter_style={'c': 'black', 's': 1}, **kwargs)
- plot_partial_wave(params=None, data=None, phsp=None, bg=None, prefix='figure/', res=None, save_root=False, chains_id_method=None, phsp_rec=None, cut_function=<function <lambda>>, plot_function=None, **kwargs)
plot partial wave plots
- Parameters:
self – ConfigLoader object
params – params, dict or FitResutls
data – data sample, a list of CalAngleData
phsp – phase space sample, a list of CalAngleData (the same size as data)
bg – background sample, a list of CalAngleData (the same size as data)
prefix – figure saving folder and nameing prefix
res – combination of resonaces in partial wave, list of (list of (string for resoances name or int for decay chain index))
save_root – if save weights in a root file, bool
chains_id_method – method of how legend label display, string
bin_scale – more binning in partial waves for a smooth histogram. int
batch – batching in calculating weights, int
smooth – if plot smooth binned kde shape or histogram, bool
single_legend – if save all legend in a file “legend.pdf”, bool
plot_pull – if plot the pull distribution, bool
format – save figure with image format, string (such as “.png”, “.jpeg”)
linestyle_file – legend linestyle configuration file name (YAML format), string (such as “legend.yml”)
- plot_partial_wave_interf(res1, res2, **kwargs)
data
- class MultiData(*args, **kwargs)[source]
Bases:
SimpleData
data_root_lhcb
decay_config
- class DecayConfig(dic, share_dict={})[source]
Bases:
BaseConfig
- decay_chain_cut_list = {}
- decay_cut_list = {'ls_cut': <function decay_cut_ls>, 'mass_cut': <function decay_cut_mass>}
extra
multi_config
particle_function
plot
- hist_line(data, weights, bins, xrange=None, inter=1, kind='UnivariateSpline')[source]
interpolate data from hostgram into a line
>>> import numpy as np >>> import matplotlib.pyplot >>> z = np.random.normal(size=1000) >>> x, y = hist_line(z, None, 50) >>> a = plt.plot(x, y)
- hist_line_step(data, weights, bins, xrange=None, inter=1, kind='quadratic')[source]
>>> import numpy as np >>> import matplotlib.pyplot >>> z = np.random.normal(size=1000) >>> x, y = hist_line_step(z, None, 50) >>> a = plt.step(x, y)
- plot_adaptive_2dpull(config, var1, var2, binning=[[2, 2], [2, 2], [2, 2]], ax=<module 'matplotlib.pyplot' from '/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/envs/latest/lib/python3.10/site-packages/matplotlib/pyplot.py'>, where={}, cut_zero=True, plot_scatter=True, scatter_style={'c': 'black', 's': 1}, **kwargs)[source]
- plot_function_2dpull(data_dict, phsp_dict, bg_dict, var1='x', var2='y', binning=[[2, 2], [2, 2], [2, 2]], where={}, ax=<module 'matplotlib.pyplot' from '/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/envs/latest/lib/python3.10/site-packages/matplotlib/pyplot.py'>, cut_zero=True, plot_scatter=True, scatter_style={'c': 'black', 's': 1}, cmap='jet', **kwargs)[source]
- plot_partial_wave(self, params=None, data=None, phsp=None, bg=None, prefix='figure/', res=None, save_root=False, chains_id_method=None, phsp_rec=None, cut_function=<function <lambda>>, plot_function=None, **kwargs)[source]
plot partial wave plots
- Parameters:
self – ConfigLoader object
params – params, dict or FitResutls
data – data sample, a list of CalAngleData
phsp – phase space sample, a list of CalAngleData (the same size as data)
bg – background sample, a list of CalAngleData (the same size as data)
prefix – figure saving folder and nameing prefix
res – combination of resonaces in partial wave, list of (list of (string for resoances name or int for decay chain index))
save_root – if save weights in a root file, bool
chains_id_method – method of how legend label display, string
bin_scale – more binning in partial waves for a smooth histogram. int
batch – batching in calculating weights, int
smooth – if plot smooth binned kde shape or histogram, bool
single_legend – if save all legend in a file “legend.pdf”, bool
plot_pull – if plot the pull distribution, bool
format – save figure with image format, string (such as “.png”, “.jpeg”)
linestyle_file – legend linestyle configuration file name (YAML format), string (such as “legend.yml”)
plotter
- class Frame(var, x_range=None, nbins=None, name=None, display=None, trans=None, **extra)[source]
Bases:
object
- class PlotData(dataset, weight=None, partial_weight=None, use_weighted=False)[source]
Bases:
object
- class Plotter(config, legend_file=None, res=None, datasets=None, use_weighted=False)[source]
Bases:
object
- get_all_hist(frame, idx=None, bin_scale=3)[source]
create all partial wave histogram for observation frame.
- old_style(extra_config=None, color_first=True)[source]
context for base style, see matplotlib.rcParams for more configuration
- Parameters:
extra_config (ditc, optional) – new configs, defaults to None
color_first (bool, optional) – order of color and linestyle, defaults to True
- plot_frame(name, idx=None, ax=<module 'matplotlib.pyplot' from '/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/envs/latest/lib/python3.10/site-packages/matplotlib/pyplot.py'>, bin_scale=3)[source]
plot frame for all partial wave
- plot_frame_with_pull(name, idx=None, bin_scale=3, pull_config=None)[source]
plot frame with pull for all partial wave
- plot_var(frame, idx=None, ax=<module 'matplotlib.pyplot' from '/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/envs/latest/lib/python3.10/site-packages/matplotlib/pyplot.py'>, bin_scale=3)[source]
plot data observation for all partial wave
- save_all_frame(prefix='figure/', format='png', idx=None, plot_pull=False, pull_config=None)[source]
Save all frame in with prefix. like ConfigLoader.plot_partial_waves
- Parameters:
prefix (str, optional) – prefix for file name, defaults to “figure/”
format (str, optional) – figure format, defaults to “png”
idx (int, optional) – dataset index, defaults to None
plot_pull (bool, optional) – if plot pulls, defaults to False
pull_config (dict, optional) – configuration for plot pulls, defaults to None
sample
- class AfterGenerator(gen, f_after=<function AfterGenerator.<lambda>>)[source]
Bases:
BaseGenerator
- build_phsp_chain_sorted(st, final_mi, nodes)[source]
{A: [B,C, D], R: [B,C]} + {R: M} => ((mr, (mb, mc)), md)
- generate_toy(config, N=1000, force=True, gen=None, gen_p=None, importance_f=None, max_N=100000, include_charge=False, cal_phsp_max=False)[source]
A more accurate method for generating toy data.
- Parameters:
N – number of events.
force – if romove extra data generated.
gen – optional function for generate phase space, the return value is same as config.get_data.
gen_p – optional function for generate phase space, the return value is dict as
{B: pb, C: pc, D: pd}
.max_N – max number of events for every try.
data_trans
Submodules and Subpackages
dalitz
helicity_angle
- class HelicityAngle(decay_chain)[source]
Bases:
object
general implement for angle to monmentum trasform
- class HelicityAngle1(decay_chain)[source]
Bases:
object
simple implement for angle to monmentum trasform
experimental
Submodules and Subpackages
build_amp
extra_amp
extra_data
extra_function
- extra_function(f0=None, using_numpy=True)[source]
Using extra function with numerical differentiation.
It can be used for numpy function or numba.vectorize function interface.
>>> import numpy as np >>> sin2 = extra_function(np.sin) >>> a = tf.Variable([1.0,2.0], dtype="float64") >>> with tf.GradientTape(persistent=True) as tape0: ... with tf.GradientTape(persistent=True) as tape: ... b = sin2(a) ... g, = tape.gradient(b, [a,]) ... >>> h, = tape0.gradient(g, [a,]) >>> assert np.allclose(np.sin([1.0,2.0]), b.numpy()) >>> assert np.allclose(np.cos([1.0,2.0]), g.numpy()) >>> assert np.sum(np.abs(-np.sin([1.0,2.0]) - h.numpy())) < 1e-3
The numerical accuracy is not so well for second derivative.
factor_system
Module for factor system.
`
A = a1 ( B x C x D) + a2 (E x F)
B = b1 B1 + b2 B2
`
is a tree structure
`
A -> [(a1, [(b1, B1), (b2, B2)], C, D), (a2, E, F)]
`
Each component is a path for root to a leaf.
`
(a1, b1), (a1, b2), (a2,)
`
We can add some options to change the possible combination. (TODO)
opt_int
wrap_function
generator
Submodules and Subpackages
breit_wigner
generator
- class ARGenerator(phsp, amp, max_weight=None)[source]
Bases:
BaseGenerator
Acceptance-Rejection Sampling
interp_nd
linear_interpolation
- class LinearInterp(x, y, epsilon=1e-10)[source]
Bases:
BaseGenerator
linear intepolation function for sampling
- DataType
alias of
ndarray
- class LinearInterpImportance(f, x)[source]
Bases:
BaseGenerator
- DataType
alias of
ndarray
plane_2d
- class Interp2D(x, y, z)[source]
Bases:
TriangleGenerator
- class TriangleGenerator(x, y, z)[source]
Bases:
object
- cal_coeffs()[source]
z = a x + b y + c
[ x_1 , y_1 , 1 ] [a] [z_1] [ x_2 , y_2 , 1 ] [b] = [z_2] [ x_3 , y_3 , 1 ] [c] = [z_3]
z_c = a x + b y + c
s^2 = (x-x_c)**2 + (y-y_c)**2 s = 1/b sqrt(a**2+b**2)(x-x_c) x = b s / sqrt(a**2+b**2) + x_c
square_dalitz_plot
- class SDPGenerator(m0, mi, legacy=True)[source]
Bases:
BaseGenerator
- generate_SDP(m0, mi, N=1000, legacy=True)[source]
generate square dalitz plot ditribution for 1,2
The legacy mode will include a cut off in the threshold.
(
Source code
,png
,hires.png
,pdf
)
- square_dalitz_cut(p)[source]
Copy from EvtGen old version
\[|J| = 4 p q m_{12} \frac{\partial m_{12}}{\partial m'} \frac{\partial \cos\theta_{12}}{\partial \theta'}\]\[\frac{\partial m_{12}}{\partial m'} = -\frac{\pi}{2} \sin (\pi m') (m_{12}^{max} - m_{12}^{min})\]\[\frac{\partial \cos\theta_{12}}{\partial \theta'} = -\pi \sin (\pi \theta')\]
model
Submodules and Subpackages
cfit
- class ModelCfitExtended(amp, w_bkg=0.001, bg_f=None, eff_f=None)[source]
Bases:
Model
- nll(data, mcdata, weight: Tensor = 1.0, batch=None, bg=None, mc_weight=None)[source]
Calculate NLL.
\[\begin{split}-\ln L = -\sum_{x_i \in data } w_i \ln P(x_i;\theta_k) \\ P(x_i;\theta_k) = (1-f_{bg})Amp(x_i; \theta_k) + f_{bg} Bg(x_{i};\theta_k)\end{split}\]\[-\ln L_{2} = -\ln ( L \lambda^{N_{data}} / {N_{data}}! e^{-\lambda}) = -\ L - N_{data} \ln \lambda + \lambda + C\]\[\lambda = 1/(1-f_{bg}) \int Amp(x_i; \theta_k) d \Phi\]- Parameters:
data – Data array
mcdata – MCdata array
weight – Weight of data???
batch – The length of array to calculate as a vector at a time. How to fold the data array may depend on the GPU computability.
bg – Background data array. It can be set to
None
if there is no such thing.
- Returns:
Real number. The value of NLL.
- nll_grad_batch(data, mcdata, weight, mc_weight)[source]
- \[P = (1-frac) \frac{amp(data)}{\sum amp(phsp)} + frac \frac{bg(data)}{\sum bg(phsp)}\]\[nll = - \sum log(p)\]\[\frac{\partial nll}{\partial \theta} = -\sum \frac{1}{p} \frac{\partial p}{\partial \theta} = - \sum \frac{\partial \ln \bar{p}}{\partial \theta } +\frac{\partial nll}{\partial I_{sig} } \frac{\partial I_{sig} }{\partial \theta} +\frac{\partial nll}{\partial I_{bg}}\frac{\partial I_{sig}}{\partial \theta}\]
- nll_grad_hessian(data, mcdata, weight=1.0, batch=24000, bg=None, mc_weight=1.0)[source]
The parameters are the same with
self.nll()
, but it will return Hessian as well.\[\frac{\partial^2 f}{\partial x_i \partial x_j} = \frac{\partial y_k}{\partial x_i} \frac{\partial^2 f}{\partial y_k \partial y_l} \frac{\partial y_l}{\partial x_j} + \frac{\partial f}{\partial y_k} \frac{\partial^2 y_k}{\partial x_i \partial x_j}\]\[y = \{x_i; I_{sig}, I_{bg}\}\]\[\frac{\partial y_k }{\partial x_i} = (\delta_{ik};\frac{\partial I_{sig}}{\partial x_i}, \frac{\partial I_{bg}}{\partial x_i})\]- Return NLL:
Real number. The value of NLL.
- Return gradients:
List of real numbers. The gradients for each variable.
- Return Hessian:
2-D Array of real numbers. The Hessian matrix of the variables.
- class Model_cfit(amp, w_bkg=0.001, bg_f=None, eff_f=None, resolution_size=1)[source]
Bases:
Model
- nll(data, mcdata, weight: Tensor = 1.0, batch=None, bg=None, mc_weight=None)[source]
Calculate NLL.
\[\begin{split}-\ln L = -\sum_{x_i \in data } w_i \ln P(x_i;\theta_k) \\ P(x_i;\theta_k) = (1-f_{bg})Amp(x_i; \theta_k) + f_{bg} Bg(x_{i};\theta_k)\end{split}\]- Parameters:
data – Data array
mcdata – MCdata array
weight – Weight of data???
batch – The length of array to calculate as a vector at a time. How to fold the data array may depend on the GPU computability.
bg – Background data array. It can be set to
None
if there is no such thing.
- Returns:
Real number. The value of NLL.
- nll_grad_batch(data, mcdata, weight, mc_weight)[source]
- \[P = (1-frac) \frac{amp(data)}{\sum amp(phsp)} + frac \frac{bg(data)}{\sum bg(phsp)}\]\[nll = - \sum log(p)\]\[\frac{\partial nll}{\partial \theta} = -\sum \frac{1}{p} \frac{\partial p}{\partial \theta} = - \sum \frac{\partial \ln \bar{p}}{\partial \theta } +\frac{\partial nll}{\partial I_{sig} } \frac{\partial I_{sig} }{\partial \theta} +\frac{\partial nll}{\partial I_{bg}}\frac{\partial I_{sig}}{\partial \theta}\]
- nll_grad_hessian(data, mcdata, weight=1.0, batch=24000, bg=None, mc_weight=1.0)[source]
The parameters are the same with
self.nll()
, but it will return Hessian as well.\[\frac{\partial^2 f}{\partial x_i \partial x_j} = \frac{\partial y_k}{\partial x_i} \frac{\partial^2 f}{\partial y_k \partial y_l} \frac{\partial y_l}{\partial x_j} + \frac{\partial f}{\partial y_k} \frac{\partial^2 y_k}{\partial x_i \partial x_j}\]\[y = \{x_i; I_{sig}, I_{bg}\}\]\[\frac{\partial y_k }{\partial x_i} = (\delta_{ik};\frac{\partial I_{sig}}{\partial x_i}, \frac{\partial I_{bg}}{\partial x_i})\]- Return NLL:
Real number. The value of NLL.
- Return gradients:
List of real numbers. The gradients for each variable.
- Return Hessian:
2-D Array of real numbers. The Hessian matrix of the variables.
- class Model_cfit_cached(amp, w_bkg=0.001, bg_f=None, eff_f=None)[source]
Bases:
Model_cfit
- nll_grad_batch(data, mcdata, weight, mc_weight)[source]
- \[P = (1-frac) \frac{amp(data)}{\sum amp(phsp)} + frac \frac{bg(data)}{\sum bg(phsp)}\]\[nll = - \sum log(p)\]\[\frac{\partial nll}{\partial \theta} = -\sum \frac{1}{p} \frac{\partial p}{\partial \theta} = - \sum \frac{\partial \ln \bar{p}}{\partial \theta } +\frac{\partial nll}{\partial I_{sig} } \frac{\partial I_{sig} }{\partial \theta} +\frac{\partial nll}{\partial I_{bg}}\frac{\partial I_{sig}}{\partial \theta}\]
custom
- class BaseCustomModel(amp, w_bkg=1.0, resolution_size=1, extended=False, **kwargs)[source]
Bases:
Model
- nll(data, mcdata, weight: Tensor = 1.0, batch=None, bg=None, mc_weight=1.0)[source]
Calculate NLL.
\[-\ln L = -\sum_{x_i \in data } w_i \ln f(x_i;\theta_k) + (\sum w_j ) \ln \sum_{x_i \in mc } f(x_i;\theta_k)\]- Parameters:
data – Data array
mcdata – MCdata array
weight – Weight of data???
batch – The length of array to calculate as a vector at a time. How to fold the data array may depend on the GPU computability.
bg – Background data array. It can be set to
None
if there is no such thing.
- Returns:
Real number. The value of NLL.
- nll_grad_batch(data, mcdata, weight, mc_weight)[source]
batch version of
self.nll_grad()
\[- \frac{\partial \ln L}{\partial \theta_k } = -\sum_{x_i \in data } w_i \frac{\partial}{\partial \theta_k} \ln f(x_i;\theta_k) + (\sum w_j ) \left( \frac{ \partial }{\partial \theta_k} \sum_{x_i \in mc} f(x_i;\theta_k) \right) \frac{1}{ \sum_{x_i \in mc} f(x_i;\theta_k) }\]- Parameters:
data
mcdata
weight
mc_weight
- Returns:
- nll_grad_hessian(data, mcdata, weight=1.0, batch=24000, bg=None, mc_weight=1.0)[source]
The parameters are the same with
self.nll()
, but it will return Hessian as well.- Return NLL:
Real number. The value of NLL.
- Return gradients:
List of real numbers. The gradients for each variable.
- Return Hessian:
2-D Array of real numbers. The Hessian matrix of the variables.
- class SimpleCFitModel(amp, w_bkg=1.0, resolution_size=1, extended=False, **kwargs)[source]
Bases:
BaseCustomModel
- required_params = ['bg_frac']
- class SimpleChi2Model(amp, w_bkg=1.0, resolution_size=1, extended=False, **kwargs)[source]
Bases:
BaseCustomModel
fit amp = weight directly. Required set extended = True.
- class SimpleClipNllModel(amp, w_bkg=1.0, resolution_size=1, extended=False, **kwargs)[source]
Bases:
SimpleNllModel
- class SimpleNllFracModel(amp, w_bkg=1.0, resolution_size=1, extended=False, **kwargs)[source]
Bases:
BaseCustomModel
- required_params = ['constr_frac', 'bg_frac']
model
This module provides methods to calculate NLL(Negative Log-Likelihood) as well as its derivatives.
- class BaseModel(signal, resolution_size=1, extended=False)[source]
Bases:
object
This class implements methods to calculate NLL as well as its derivatives for an amplitude model. It may include data for both signal and background.
- Parameters:
signal – Signal Model
- grad_hessp_batch(p, data, mcdata, weight, mc_weight)[source]
self.nll_grad()
is replaced by this one???\[- \frac{\partial \ln L}{\partial \theta_k } = -\sum_{x_i \in data } w_i \frac{\partial}{\partial \theta_k} \ln f(x_i;\theta_k) + (\sum w_j ) \left( \frac{ \partial }{\partial \theta_k} \sum_{x_i \in mc} f(x_i;\theta_k) \right) \frac{1}{ \sum_{x_i \in mc} f(x_i;\theta_k) }\]- Parameters:
data
mcdata
weight
mc_weight
- Returns:
- nll_grad_batch(data, mcdata, weight, mc_weight)[source]
self.nll_grad()
is replaced by this one???\[- \frac{\partial \ln L}{\partial \theta_k } = -\sum_{x_i \in data } w_i \frac{\partial}{\partial \theta_k} \ln f(x_i;\theta_k) + (\sum w_j ) \left( \frac{ \partial }{\partial \theta_k} \sum_{x_i \in mc} f(x_i;\theta_k) \right) \frac{1}{ \sum_{x_i \in mc} f(x_i;\theta_k) }\]- Parameters:
data
mcdata
weight
mc_weight
- Returns:
- nll_grad_hessian(data, mcdata, batch=25000)[source]
The parameters are the same with
self.nll()
, but it will return Hessian as well.- Return NLL:
Real number. The value of NLL.
- Return gradients:
List of real numbers. The gradients for each variable.
- Return Hessian:
2-D Array of real numbers. The Hessian matrix of the variables.
- property trainable_variables
- class CombineFCN(model=None, data=None, mcdata=None, bg=None, fcns=None, batch=65000, gauss_constr={})[source]
Bases:
object
This class implements methods to calculate the NLL as well as its derivatives for a general function.
- Parameters:
model – List of model object.
data – List of data array.
mcdata – list of MCdata array.
bg – list of Background array.
batch – The length of array to calculate as a vector at a time. How to fold the data array may depend on the GPU computability.
- get_grad(x={})[source]
- Parameters:
x – List. Values of variables.
- Return gradients:
List of real numbers. The gradients for each variable.
- get_grad_hessp(x, p, batch)[source]
- Parameters:
x – List. Values of variables.
- Return nll:
Real number. The value of NLL.
- Return gradients:
List of real numbers. The gradients for each variable.
- get_nll(x={})[source]
- Parameters:
x – List. Values of variables.
- Return nll:
Real number. The value of NLL.
- get_nll_grad(x={})[source]
- Parameters:
x – List. Values of variables.
- Return nll:
Real number. The value of NLL.
- Return gradients:
List of real numbers. The gradients for each variable.
- class ConstrainModel(amp, w_bkg=1.0, constrain={})[source]
Bases:
Model
negative log likelihood model with constrains
- get_constrain_grad()[source]
- constrain: Gauss(mean,sigma)
by add a term \(\frac{d}{d\theta_i}\frac{(\theta_i-\bar{\theta_i})^2}{2\sigma^2} = \frac{\theta_i-\bar{\theta_i}}{\sigma^2}\)
- get_constrain_term()[source]
- constrain: Gauss(mean,sigma)
by add a term \(\frac{(\theta_i-\bar{\theta_i})^2}{2\sigma^2}\)
- nll(data, mcdata, weight=1.0, bg=None, batch=None)[source]
calculate negative log-likelihood
\[-\ln L = -\sum_{x_i \in data } w_i \ln f(x_i;\theta_i) + (\sum w_i ) \ln \sum_{x_i \in mc } f(x_i;\theta_i) + cons\]
- nll_gradient(data, mcdata, weight=1.0, batch=None, bg=None)[source]
calculate negative log-likelihood with gradient
\[\frac{\partial }{\partial \theta_i }(-\ln L) = -\sum_{x_i \in data } w_i \frac{\partial }{\partial \theta_i } \ln f(x_i;\theta_i) + \frac{\sum w_i }{\sum_{x_i \in mc }f(x_i;\theta_i)} \sum_{x_i \in mc } \frac{\partial }{\partial \theta_i } f(x_i;\theta_i) + cons\]
- class FCN(model, data, mcdata, bg=None, batch=65000, inmc=None, gauss_constr={})[source]
Bases:
object
This class implements methods to calculate the NLL as well as its derivatives for a general function.
- Parameters:
model – Model object.
data – Data array.
mcdata – MCdata array.
bg – Background array.
batch – The length of array to calculate as a vector at a time. How to fold the data array may depend on the GPU computability.
- get_grad(x={})[source]
- Parameters:
x – List. Values of variables.
- Return gradients:
List of real numbers. The gradients for each variable.
- get_nll(x={})[source]
- Parameters:
x – List. Values of variables.
- Return nll:
Real number. The value of NLL.
- get_nll_grad(x={})[source]
- Parameters:
x – List. Values of variables.
- Return nll:
Real number. The value of NLL.
- Return gradients:
List of real numbers. The gradients for each variable.
- class GaussianConstr(vm, constraint={})[source]
Bases:
object
- get_constrain_grad()[source]
- constraint: Gauss(mean,sigma)
by add a term \(\frac{d}{d\theta_i}\frac{(\theta_i-\bar{\theta_i})^2}{2\sigma^2} = \frac{\theta_i-\bar{\theta_i}}{\sigma^2}\)
- class MixLogLikehoodFCN(model, data, mcdata, bg=None, batch=65000, gauss_constr={})[source]
Bases:
CombineFCN
This class implements methods to calculate the NLL as well as its derivatives for a general function.
- Parameters:
model – List of model object.
data – List of data array.
mcdata – list of MCdata array.
bg – list of Background array.
batch – The length of array to calculate as a vector at a time. How to fold the data array may depend on the GPU computability.
- class Model(amp, w_bkg=1.0, resolution_size=1, extended=False, **kwargs)[source]
Bases:
object
This class implements methods to calculate NLL as well as its derivatives for an amplitude model. It may include data for both signal and background.
- Parameters:
amp –
AllAmplitude
object. The amplitude model.w_bkg – Real number. The weight of background.
- get_weight_data(data, weight=None, bg=None, alpha=True)[source]
Blend data and background data together multiplied by their weights.
- Parameters:
data – Data array
weight – Weight for data
bg – Data array for background
alpha – Boolean. If it’s true,
weight
will be multiplied by a factor \(\alpha=\)???
- Returns:
Data, weight. Their length both equals
len(data)+len(bg)
.
- grad_hessp_batch(p, data, mcdata, weight, mc_weight)[source]
self.nll_grad()
is replaced by this one???\[- \frac{\partial \ln L}{\partial \theta_k } = -\sum_{x_i \in data } w_i \frac{\partial}{\partial \theta_k} \ln f(x_i;\theta_k) + (\sum w_j ) \left( \frac{ \partial }{\partial \theta_k} \sum_{x_i \in mc} f(x_i;\theta_k) \right) \frac{1}{ \sum_{x_i \in mc} f(x_i;\theta_k) }\]- Parameters:
data
mcdata
weight
mc_weight
- Returns:
- nll(data, mcdata, weight: Tensor = 1.0, batch=None, bg=None, mc_weight=1.0)[source]
Calculate NLL.
\[-\ln L = -\sum_{x_i \in data } w_i \ln f(x_i;\theta_k) + (\sum w_j ) \ln \sum_{x_i \in mc } f(x_i;\theta_k)\]- Parameters:
data – Data array
mcdata – MCdata array
weight – Weight of data???
batch – The length of array to calculate as a vector at a time. How to fold the data array may depend on the GPU computability.
bg – Background data array. It can be set to
None
if there is no such thing.
- Returns:
Real number. The value of NLL.
- nll_grad(data, mcdata, weight=1.0, batch=65000, bg=None, mc_weight=1.0)[source]
Calculate NLL and its gradients.
\[- \frac{\partial \ln L}{\partial \theta_k } = -\sum_{x_i \in data } w_i \frac{\partial}{\partial \theta_k} \ln f(x_i;\theta_k) + (\sum w_j ) \left( \frac{ \partial }{\partial \theta_k} \sum_{x_i \in mc} f(x_i;\theta_k) \right) \frac{1}{ \sum_{x_i \in mc} f(x_i;\theta_k) }\]The parameters are the same with
self.nll()
, but it will return gradients as well.- Return NLL:
Real number. The value of NLL.
- Return gradients:
List of real numbers. The gradients for each variable.
- nll_grad_batch(data, mcdata, weight, mc_weight)[source]
batch version of
self.nll_grad()
\[- \frac{\partial \ln L}{\partial \theta_k } = -\sum_{x_i \in data } w_i \frac{\partial}{\partial \theta_k} \ln f(x_i;\theta_k) + (\sum w_j ) \left( \frac{ \partial }{\partial \theta_k} \sum_{x_i \in mc} f(x_i;\theta_k) \right) \frac{1}{ \sum_{x_i \in mc} f(x_i;\theta_k) }\]- Parameters:
data
mcdata
weight
mc_weight
- Returns:
- nll_grad_hessian(data, mcdata, weight=1.0, batch=24000, bg=None, mc_weight=1.0)[source]
The parameters are the same with
self.nll()
, but it will return Hessian as well.- Return NLL:
Real number. The value of NLL.
- Return gradients:
List of real numbers. The gradients for each variable.
- Return Hessian:
2-D Array of real numbers. The Hessian matrix of the variables.
- class Model_new(amp, w_bkg=1.0, w_inmc=0, float_wmc=False)[source]
Bases:
Model
This class implements methods to calculate NLL as well as its derivatives for an amplitude model. It may include data for both signal and background.
- Parameters:
amp –
AllAmplitude
object. The amplitude model.w_bkg – Real number. The weight of background.
- get_weight_data(data, weight=1.0, bg=None, inmc=None, alpha=True)[source]
Blend data and background data together multiplied by their weights.
- Parameters:
data – Data array
weight – Weight for data
bg – Data array for background
alpha – Boolean. If it’s true,
weight
will be multiplied by a factor \(\alpha=\)???
- Returns:
Data, weight. Their length both equals
len(data)+len(bg)
.
- nll(data, mcdata, weight: Tensor = 1.0, batch=None, bg=None)[source]
Calculate NLL.
\[-\ln L = -\sum_{x_i \in data } w_i \ln f(x_i;\theta_k) + (\sum w_j ) \ln \sum_{x_i \in mc } f(x_i;\theta_k)\]- Parameters:
data – Data array
mcdata – MCdata array
weight – Weight of data???
batch – The length of array to calculate as a vector at a time. How to fold the data array may depend on the GPU computability.
bg – Background data array. It can be set to
None
if there is no such thing.
- Returns:
Real number. The value of NLL.
- nll_grad_hessian(data, mcdata, weight, mc_weight)[source]
The parameters are the same with
self.nll()
, but it will return Hessian as well.- Return NLL:
Real number. The value of NLL.
- Return gradients:
List of real numbers. The gradients for each variable.
- Return Hessian:
2-D Array of real numbers. The Hessian matrix of the variables.
- sum_grad_hessp(f, p, data, var, weight=1.0, trans=<function identity>, resolution_size=1, args=(), kwargs=None)[source]
The parameters are the same with
sum_gradient()
, but this function will return hessian as well, which is the matrix of the second-order derivative.- Returns:
Real number NLL, list gradient, 2-D list hessian
- sum_gradient(f, data, var, weight=1.0, trans=<function identity>, resolution_size=1, args=(), kwargs=None)[source]
NLL is the sum of trans(f(data)):math:
*`weight; gradient is the derivatives for each variable in ``var`
.- Parameters:
f – Function. The amplitude PDF.
data – Data array
var – List of strings. Names of the trainable variables in the PDF.
weight – Weight factor for each data point. It’s either a real number or an array of the same shape with
data
.trans – Function. Transformation of
data
before multiplied byweight
.kwargs – Further arguments for
f
.
- Returns:
Real number NLL, list gradient
- sum_gradient_new(amp, data, mcdata, weight, mcweight, var, trans=<function log>, w_flatmc=<function <lambda>>, args=(), kwargs=None)[source]
NLL is the sum of trans(f(data)):math:
*`weight; gradient is the derivatives for each variable in ``var`
.- Parameters:
f – Function. The amplitude PDF.
data – Data array
var – List of strings. Names of the trainable variables in the PDF.
weight – Weight factor for each data point. It’s either a real number or an array of the same shape with
data
.trans – Function. Transformation of
data
before multiplied byweight
.kwargs – Further arguments for
f
.
- Returns:
Real number NLL, list gradient
- sum_hessian(f, data, var, weight=1.0, trans=<function identity>, resolution_size=1, args=(), kwargs=None)[source]
The parameters are the same with
sum_gradient()
, but this function will return hessian as well, which is the matrix of the second-order derivative.- Returns:
Real number NLL, list gradient, 2-D list hessian
- sum_hessian_new(amp, data, mcdata, weight, mcweight, var, trans=<function log>, w_flatmc=<function <lambda>>, args=(), kwargs=None)[source]
The parameters are the same with
sum_gradient()
, but this function will return hessian as well, which is the matrix of the second-order derivative.- Returns:
Real number NLL, list gradient, 2-D list hessian
opt_int
- class ModelCachedAmp(amp, w_bkg=1.0)[source]
Bases:
Model
This class implements methods to calculate NLL as well as its derivatives for an amplitude model with Cached Int. It may include data for both signal and background. Cached Int well cause wrong results when float parameters include mass or width.
- Parameters:
amp –
AllAmplitude
object. The amplitude model.w_bkg – Real number. The weight of background.
- grad_hessp_batch(p, data, mcdata, weight, mc_weight)[source]
self.nll_grad()
is replaced by this one???\[- \frac{\partial \ln L}{\partial \theta_k } = -\sum_{x_i \in data } w_i \frac{\partial}{\partial \theta_k} \ln f(x_i;\theta_k) + (\sum w_j ) \left( \frac{ \partial }{\partial \theta_k} \sum_{x_i \in mc} f(x_i;\theta_k) \right) \frac{1}{ \sum_{x_i \in mc} f(x_i;\theta_k) }\]- Parameters:
data
mcdata
weight
mc_weight
- Returns:
- nll_grad_batch(data, mcdata, weight, mc_weight)[source]
self.nll_grad()
is replaced by this one???\[- \frac{\partial \ln L}{\partial \theta_k } = -\sum_{x_i \in data } w_i \frac{\partial}{\partial \theta_k} \ln f(x_i;\theta_k) + (\sum w_j ) \left( \frac{ \partial }{\partial \theta_k} \sum_{x_i \in mc} f(x_i;\theta_k) \right) \frac{1}{ \sum_{x_i \in mc} f(x_i;\theta_k) }\]- Parameters:
data
mcdata
weight
mc_weight
- Returns:
- class ModelCachedInt(amp, w_bkg=1.0)[source]
Bases:
Model
This class implements methods to calculate NLL as well as its derivatives for an amplitude model with Cached Int. It may include data for both signal and background. Cached Int well cause wrong results when float parameters include mass or width.
- Parameters:
amp –
AllAmplitude
object. The amplitude model.w_bkg – Real number. The weight of background.
- nll_grad_batch(data, mcdata, weight, mc_weight)[source]
self.nll_grad()
is replaced by this one???\[- \frac{\partial \ln L}{\partial \theta_k } = -\sum_{x_i \in data } w_i \frac{\partial}{\partial \theta_k} \ln f(x_i;\theta_k) + (\sum w_j ) \left( \frac{ \partial }{\partial \theta_k} \sum_{x_i \in mc} f(x_i;\theta_k) \right) \frac{1}{ \sum_{x_i \in mc} f(x_i;\theta_k) }\]- Parameters:
data
mcdata
weight
mc_weight
- Returns:
- nll_grad_hessian(data, mcdata, weight=1.0, batch=24000, bg=None, mc_weight=1.0)[source]
The parameters are the same with
self.nll()
, but it will return Hessian as well.- Return NLL:
Real number. The value of NLL.
- Return gradients:
List of real numbers. The gradients for each variable.
- Return Hessian:
2-D Array of real numbers. The Hessian matrix of the variables.
- sum_grad_hessp_data2(f, p, var, data, data2, weight=1.0, trans=<function identity>, resolution_size=1, args=(), kwargs=None)[source]
The parameters are the same with
sum_gradient()
, but this function will return hessian as well, which is the matrix of the second-order derivative.- Returns:
Real number NLL, list gradient, 2-D list hessian
- sum_gradient(fs, var, weight=1.0, trans=<function identity>, args=(), kwargs=None)[source]
NLL is the sum of trans(f(data)):math:
*`weight; gradient is the derivatives for each variable in ``var`
.- Parameters:
f – Function. The amplitude PDF.
var – List of strings. Names of the trainable variables in the PDF.
weight – Weight factor for each data point. It’s either a real number or an array of the same shape with
data
.trans – Function. Transformation of
data
before multiplied byweight
.kwargs – Further arguments for
f
.
- Returns:
Real number NLL, list gradient
- sum_gradient_data2(f, var, data, cached_data, weight=1.0, trans=<function identity>, args=(), kwargs=None)[source]
NLL is the sum of trans(f(data)):math:
*`weight; gradient is the derivatives for each variable in ``var`
.- Parameters:
f – Function. The amplitude PDF.
var – List of strings. Names of the trainable variables in the PDF.
weight – Weight factor for each data point. It’s either a real number or an array of the same shape with
data
.trans – Function. Transformation of
data
before multiplied byweight
.kwargs – Further arguments for
f
.
- Returns:
Real number NLL, list gradient
adaptive_bins
adaptive split data into bins.
- class AdaptiveBound(base_data, bins, base_bound=None)[source]
Bases:
object
adaptive bound cut for data value
- static loop_split_bound(datas, n, base_bound=None)[source]
loop for multi_split_bound, so
n
is list of list of int
- static multi_split_bound(datas, n, base_bound=None)[source]
multi data for single_split_bound, so
n
is list of int>>> data = np.array([[1.0, 2.0, 1.4, 3.1], [2.0, 1.0, 3.0, 1.0]]) >>> bound, _ = AdaptiveBound.multi_split_bound(data, [2, 1]) >>> [(i[0][0]+1e-6, i[1][0]+1e-6) for i in bound] [(1.0..., 1.7...), (1.7..., 3.1...)]
angle
This module implements three classes Vector3, LorentzVector, EulerAngle .
- class AlignmentAngle(alpha=0.0, beta=0.0, gamma=0.0)[source]
Bases:
EulerAngle
- class EulerAngle(alpha=0.0, beta=0.0, gamma=0.0)[source]
Bases:
dict
This class provides methods for Eular angle \((\alpha,\beta,\gamma)\)
- static angle_zx_z_getx(z1, x1, z2)[source]
The Eular angle from coordinate 1 to coordinate 2. Only the z-axis is provided for coordinate 2, so \(\gamma\) is set to be 0.
- Parameters:
z1 – Vector3 z-axis of the initial coordinate
x1 – Vector3 x-axis of the initial coordinate
z2 – Vector3 z-axis of the final coordinate
- Return eular_angle:
EularAngle object with \(\gamma=0\).
- Return x2:
Vector3 object, which is the x-axis of the final coordinate when \(\gamma=0\).
- static angle_zx_zx(z1, x1, z2, x2)[source]
The Euler angle from coordinate 1 to coordinate 2 (right-hand coordinates).
- Parameters:
z1 – Vector3 z-axis of the initial coordinate
x1 – Vector3 x-axis of the initial coordinate
z2 – Vector3 z-axis of the final coordinate
x2 – Vector3 x-axis of the final coordinate
- Returns:
Euler Angle object
- static angle_zx_zzz_getx(z, x, zi)[source]
The Eular angle from coordinate 1 to coordinate 2. Z-axis of coordinate 2 is the normal vector of a plane.
- Parameters:
z1 – Vector3 z-axis of the initial coordinate
x1 – Vector3 x-axis of the initial coordinate
z – list of Vector3 of the plane point.
- Return eular_angle:
EularAngle object.
- Return x2:
list of Vector3 object, which is the x-axis of the final coordinate in zi.
- class LorentzVector[source]
Bases:
Tensor
This class provides methods for Lorentz vectors (T,X,Y,Z). or -T???
- class Vector3[source]
Bases:
Tensor
This class provides methods for 3-d vectors (X,Y,Z)
- angle_from(x, y)[source]
The angle from x-axis providing the x,y axis to define a 3-d coordinate.
x -> self | / | ang / | / | / | / | / |/ -------- y
- Parameters:
x – A Vector3 instance as x-axis
y – A Vector3 instance as y-axis. It should be perpendicular to the x-axis.
applications
This module provides functions that implements user-friendly interface to the functions and methods in other modules. It acts like a synthesis of all the other modules of their own physical purposes. In general, users only need to import functions in this module to implement their physical analysis instead of going into every modules. There are some example files where you can figure out how it is used.
- cal_hesse_error(fcn, params={}, check_posi_def=True, force_pos=True, save_npy=True)[source]
This function calculates the errors of all trainable variables. The errors are given by the square root of the diagonal of the inverse Hessian matrix.
- Parameters:
model – Model.
- Return hesse_error:
List of errors.
- Return inv_he:
The inverse Hessian matrix.
- cal_significance(nll1, nll2, ndf)[source]
This function calculates the statistical significance.
- Parameters:
nll1 – Float. NLL of the first PDF.
nll2 – Float. NLL of the second PDF.
ndf – The difference of the degrees of freedom of the two PDF.
- Returns:
Float. The statistical significance
- compare_result(value1, value2, error1, error2=None, figname=None, yrange=None, periodic_vars=None)[source]
Compare two groups of fitting results. If only one error is provided, the figure is \(\frac{\mu_1-\mu_2}{\sigma_1}\); if both errors are provided, the figure is \(\frac{\mu_1-\mu_2}{\sqrt{\sigma_1^2+\sigma_2^2}}\).
- Parameters:
value1 – Dictionary
value2 – Dictionary
error1 – Dictionary
error2 – Dictionary. By default it’s
None
.figname – String. The output file
yrange – Float. If it’s not given, there is no y-axis limit in the figure.
periodic_vars – List of strings. The periodic variables.
- Returns:
Dictionary of quality figure of each variable.
- corr_coef_matrix(err_mtx)[source]
This function obtains correlation coefficients matrix of all trainable variables from
*.npy
file.- Parameters:
err_mtx – Array or string (name of the npy file).
- Returns:
Numpy 2-d array. The correlation coefficient matrix.
- fit(Use='scipy', **kwargs)[source]
Fit the amplitude model using
scipy
,iminuit
orpymultinest
. It importsfit_scipy
,fit_minuit
,fit_multinest
from module tf_pwa.fit.- Parameters:
Use – String. If it’s
"scipy"
, it will callfit_scipy
; if it’s"minuit"
, it will callfit_minuit
; if it’s"multinest"
, it will callfit_multinest
.kwargs – The arguments will be passed to the three functions above.
For
fit_scipy
- Parameters:
fcn – FCN object to be minimized.
method – String. Options in
scipy.optimize
. For now, it implements interface to such as “BFGS”, “L-BFGS-B”, “basinhopping”.bounds_dict – Dictionary of boundary constrain to variables.
kwargs – Other arguments passed on to
scipy.optimize
functions.
- Returns:
FitResult object, List of NLLs, List of point arrays.
For
fit_minuit
- Parameters:
fcn – FCN object to be minimized.
bounds_dict – Dictionary of boundary constrain to variables.
hesse – Boolean. Whether to call
hesse()
aftermigrad()
. It’sTrue
by default.minos – Boolean. Whether to call
minos()
afterhesse()
. It’sFalse
by default.
- Returns:
Minuit object
For
fit_multinest
(WIP)- Parameters:
fcn – FCN object to be minimized.
- fit_fractions(amp, mcdata, inv_he=None, params=None, batch=25000, res=None, method='old')[source]
This function calculate fit fractions of the resonances as well as their coherent pairs. It imports
cal_fitfractions
andcal_fitfractions_no_grad
from module tf_pwa.fitfractions.\[FF_{i} = \frac{\int |A_i|^2 d\Omega }{ \int |\sum_{i}A_i|^2 d\Omega }\approx \frac{\sum |A_i|^2 }{\sum|\sum_{i} A_{i}|^2}\]gradients???:
\[FF_{i,j} = \frac{\int 2Re(A_i A_j*) d\Omega }{ \int |\sum_{i}A_i|^2 d\Omega } = \frac{\int |A_i +A_j|^2 d\Omega }{ \int |\sum_{i}A_i|^2 d\Omega } - FF_{i} - FF_{j}\]hessians:
\[\frac{\partial }{\partial \theta_i }\frac{f(\theta_i)}{g(\theta_i)} = \frac{\partial f(\theta_i)}{\partial \theta_i} \frac{1}{g(\theta_i)} - \frac{\partial g(\theta_i)}{\partial \theta_i} \frac{f(\theta_i)}{g^2(\theta_i)}\]- Parameters:
amp – Amplitude object.
mcdata – MCdata array.
inv_he – The inverse of Hessian matrix. If it’s not given, the errors will not be calculated.
- Return frac:
Dictionary of fit fractions for each resonance.
- Return err_frac:
Dictionary of their errors. If
inv_he
isNone
, it will be a dictionary ofNone
.
- force_pos_def(h)[source]
from pricession lost hessian matrix eigen value is small
dot(H, v[:,i] = e[i] v[:,i] dot(H, v)[:,i] = e[i] v[:,i] dot(inv(v), dot(H, v)) = diag(e) H = dot(v, dot(diag(e), inv(v))
- gen_data(amp, Ndata, mcfile, Nbg=0, wbg=0, Poisson_fluc=False, bgfile=None, genfile=None, particles=None)[source]
This function is used to generate toy data according to an amplitude model.
- Parameters:
amp – AmplitudeModel???
particles – List of final particles
Ndata – Integer. Number of data
mcfile – String. The MC sample file used to generate signal data.
Nbg – Integer. Number of background. By default it’s 0.
wbg – Float. Weight of background. By default it’s 0.
Poisson_fluc – Boolean. If it’s
True
, The number of data will be decided by a Poisson distribution around the given value.bgfile – String. The background sample file used to generate a certain number of background data.
genfile – String. The file to store the generated toy.
- Returns:
tensorflow.Tensor. The generated toy data.
- gen_mc(mother, daughters, number, outfile=None)[source]
This function generates phase-space MC data (without considering the effect of detector performance). It imports
PhaseSpaceGenerator
from module tf_pwa.phasespace.- Parameters:
mother – Float. The invariant mass of the mother particle.
daughters – List of float. The invariant masses of the daughter particles.
number – Integer. The number of MC data generated.
outfile – String. The file to store the generated MC.
- Returns:
Numpy array. The generated MC data.
- likelihood_profile(m, var_names, bins=20, minos=True)[source]
Calculate the likelihood profile for a variable.
- Parameters:
m – Minuit object
var_names – Either a string or a list of strings
bins – Integer
minos – Boolean. If it’s
False
, the function will callMinuit.profile()
to derive the 1-d scan of var_names; if it’sTrue
, the function will callMinuit.mnprofile()
to derive the likelihood profile, which is much more time-consuming.
- Returns:
Dictionary indexed by var_names. It contains the return of either
Minuit.mnprofile()
orMinuit.profile()
.
- num_hess_inv_3point(fcn, params={}, _epsilon=0.0005)[source]
This function calculates the errors of all trainable variables. The errors are given by the square root of the diagonal of the inverse Hessian matrix.
- Parameters:
model – Model.
- Return hesse_error:
List of errors.
- Return inv_he:
The inverse Hessian matrix.
- plot_pull(data, name, nbins=20, norm=False, value=None, error=None)[source]
This function is used to plot the pull for a data sample.
- Parameters:
data – List
name – String. Name of the sample
nbins – Integer. Number of bins in the histogram
norm – Boolean. Whether to normalize the histogram
value – Float. Mean value in normalization
error – Float or list. Sigma value(s) in normalization
- Returns:
The fitted mu, sigma, as well as their errors
breit_wigner
This module provides functions to describe the lineshapes of the intermediate particles, namely generalized Breit-Wigner function. Users can also define new lineshape using the function wrapper regist_lineshape().
- BW(m, m0, g0, *args)[source]
Breit-Wigner function
\[BW(m) = \frac{1}{m_0^2 - m^2 - i m_0 \Gamma_0 }\]
- BWR(m, m0, g0, q, q0, L, d)[source]
Relativistic Breit-Wigner function (with running width). It’s also set as the default lineshape.
\[BW(m) = \frac{1}{m_0^2 - m^2 - i m_0 \Gamma(m)}\]
- BWR2(m, m0, g0, q2, q02, L, d)[source]
Relativistic Breit-Wigner function (with running width). Allow complex \(\Gamma\).
\[BW(m) = \frac{1}{m_0^2 - m^2 - i m_0 \Gamma(m)}\]
- BWR_normal(m, m0, g0, q2, q02, L, d)[source]
Relativistic Breit-Wigner function (with running width) with a normal factor.
\[BW(m) = \frac{\sqrt{m_0 \Gamma(m)}}{m_0^2 - m^2 - i m_0 \Gamma(m)}\]
- Bprime(L, q, q0, d)[source]
Blatt-Weisskopf barrier factors. E.g. the first three orders
\(L\)
\(B_L'(q,q_0,d)\)
0
1
1
\(\sqrt{\frac{(q_0d)^2+1}{(qd)^2+1}}\)
2
\(\sqrt{\frac{(q_0d)^4+3*(q_0d)^2+9}{(qd)^4+3*(qd)^2+9}}\)
\(d\) is 3.0 by default.
- Bprime_num(L, q, d)[source]
The numerator (as well as the denominator) inside the square root in the barrier factor
- Bprime_polynomial(l, z)[source]
It stores the Blatt-Weisskopf polynomial up to the fifth order (\(L=5\))
- Parameters:
l – The order
z – The variable in the polynomial
- Returns:
The calculated value
- Gamma(m, gamma0, q, q0, L, m0, d)[source]
Running width in the RBW
\[\Gamma(m) = \Gamma_0 \left(\frac{q}{q_0}\right)^{2L+1}\frac{m_0}{m} B_{L}'^2(q,q_0,d)\]
- Gamma2(m, gamma0, q2, q02, L, m0, d)[source]
Running width in the RBW
\[\Gamma(m) = \Gamma_0 \left(\frac{q}{q_0}\right)^{2L+1}\frac{m_0}{m} B_{L}'^2(q,q_0,d)\]
- barrier_factor(l, q, q0, d=3.0, axis=0)[source]
Barrier factor multiplied with \(q^L\), which is used as a combination in the amplitude expressions. The values are cached for \(L\) ranging from 0 to l.
- get_bprime_coeff(l)[source]
The coefficients of polynomial in Bprime function.
\[|\theta_{l}(jw)|^2 = \sum_{i=0}^{l} c_i w^{2 i}\]
- regist_lineshape(name=None)[source]
It will be used as a wrapper to define various Breit-Wigner functions
- Parameters:
name – String name of the BW function
- Returns:
A function used in a wrapper
cal_angle
This module provides functions which are useful when calculating the angular variables.
The full data structure provided is
{
"particle": {
A: {"p": ..., "m": ...},
(C, D): {"p": ..., "m": ...},
...
},
"decay":{
[A->(C, D)+B, (C, D)->C+D]:
{
A->(C, D)+B: {
(C, D): {
"ang": {
"alpha":[...],
"beta": [...],
"gamma": [...]
},
"z": [[x1,y1,z1],...],
"x": [[x2,y2,z2],...]
},
B: {...}
},
(C, D)->C+D: {
C: {
...,
"aligned_angle": {
"alpha": [...],
"beta": [...],
"gamma": [...]
}
},
D: {...}
},
A->(B, D)+C: {...},
(B, D)->B+D: {...}
},
...
}
}
Inner nodes are named as tuple of particles.
- Getp(M_0, M_1, M_2)[source]
Consider a two-body decay \(M_0\rightarrow M_1M_2\). In the rest frame of \(M_0\), the momentum of \(M_1\) and \(M_2\) are definite.
- Parameters:
M_0 – The invariant mass of \(M_0\)
M_1 – The invariant mass of \(M_1\)
M_2 – The invariant mass of \(M_2\)
- Returns:
the momentum of \(M_1\) (or \(M_2\))
- Getp2(M_0, M_1, M_2)[source]
Consider a two-body decay \(M_0\rightarrow M_1M_2\). In the rest frame of \(M_0\), the momentum of \(M_1\) and \(M_2\) are definite.
- Parameters:
M_0 – The invariant mass of \(M_0\)
M_1 – The invariant mass of \(M_1\)
M_2 – The invariant mass of \(M_2\)
- Returns:
the momentum of \(M_1\) (or \(M_2\))
- add_mass(data: dict, _decay_chain: DecayChain | None = None) dict [source]
- add particles mass array for data momentum.
{top:{p:momentum},inner:{p:..},outs:{p:..}} => {top:{p:momentum,m:mass},…}
- add_relative_momentum(data: dict)[source]
add add rest frame momentum scalar from data momentum.
from
{"particle": {A: {"m": ...}, ...}, "decay": {A->B+C: {...}, ...}
to
{"particle": {A: {"m": ...}, ...},"decay": {[A->B+C,...]: {A->B+C:{...,"|q|": ...},...},...}
- add_weight(data: dict, weight: float = 1.0) dict [source]
- add inner data weights for data.
{…} => {…, “weight”: weights}
- cal_angle(data, decay_group: DecayGroup, using_topology=True, random_z=True, r_boost=True, final_rest=True, align_ref=None, only_left_angle=False)
Calculate helicity angle for particle momentum, add aligned angle.
- Params data:
dict as {particle: {“p”:…}}
- Returns:
Dictionary of data
- cal_angle_from_momentum(p, decs: DecayGroup, using_topology=True, center_mass=False, r_boost=True, random_z=False, batch=65000, align_ref=None, only_left_angle=False) CalAngleData [source]
Transform 4-momentum data in files for the amplitude model automatically via DecayGroup.
- Parameters:
p – 4-momentum data
decs – DecayGroup
- Returns:
Dictionary of data
- cal_angle_from_momentum_base(p, decs: DecayGroup, using_topology=True, center_mass=False, r_boost=True, random_z=False, batch=65000, align_ref=None, only_left_angle=False) CalAngleData [source]
Transform 4-momentum data in files for the amplitude model automatically via DecayGroup.
- Parameters:
p – 4-momentum data
decs – DecayGroup
- Returns:
Dictionary of data
- cal_angle_from_momentum_id_swap(p, decs: DecayGroup, using_topology=True, center_mass=False, r_boost=True, random_z=False, batch=65000, align_ref=None, only_left_angle=False) CalAngleData [source]
- cal_angle_from_momentum_single(p, decs: DecayGroup, using_topology=True, center_mass=False, r_boost=True, random_z=True, align_ref=None, only_left_angle=False) CalAngleData [source]
Transform 4-momentum data in files for the amplitude model automatically via DecayGroup.
- Parameters:
p – 4-momentum data
decs – DecayGroup
- Returns:
Dictionary of data
- cal_angle_from_particle(data, decay_group: DecayGroup, using_topology=True, random_z=True, r_boost=True, final_rest=True, align_ref=None, only_left_angle=False)[source]
Calculate helicity angle for particle momentum, add aligned angle.
- Params data:
dict as {particle: {“p”:…}}
- Returns:
Dictionary of data
- cal_chain_boost(data, decay_chain: DecayChain) dict [source]
calculate chain boost for a decay chain
- cal_helicity_angle(data: dict, decay_chain: DecayChain, base_z=array([0., 0., 1.]), base_x=array([1., 0., 0.])) dict [source]
Calculate helicity angle for A -> B + C: \(\theta_{B}^{A}, \phi_{B}^{A}\) from momentum.
from
{A:{p:momentum},B:{p:...},C:{p:...}}
to
{A->B+C:{B:{"ang":{"alpha":...,"beta":...,"gamma":...},"x":...,"z"},...}}
- cal_single_boost(data, decay_chain: DecayChain) dict [source]
- get_key_content(dic, key_path)[source]
get key content. E.g. get_key_content(data, ‘/particle/(B, C)/m’)
>>> data = {"particle": {"(B, C)": {"p": 0.1, "m": 1.0},"B":1.0}} >>> get_key_content(data, '/particle/(B, C)/m') 1.0
- get_keys(dic, key_path='')[source]
get_keys of nested dictionary
>>> a = {"a": 1, "b": {"c": 2}} >>> get_keys(a) ['/a', '/b/c']
- get_relative_momentum(data: dict, decay_chain: DecayChain)[source]
add add rest frame momentum scalar from data momentum.
from
{"particle": {A: {"m": ...}, ...}, "decay": {A->B+C: {...}, ...}
to
{"particle": {A: {"m": ...}, ...},"decay": {A->B+C:{...,"|q|": ...},...}
- infer_momentum(data, decay_chain: DecayChain) dict [source]
- infer momentum of all particles in the decay chain from outer particles momentum.
{outs:{p:momentum}} => {top:{p:momentum},inner:{p:..},outs:{p:..}}
- prepare_data_from_decay(fnames, decs, particles=None, dtype=None, charges=None, **kwargs)[source]
Transform 4-momentum data in files for the amplitude model automatically via DecayGroup.
- Parameters:
fnames – File name(s).
decs – DecayGroup
particles – List of Particle. The final particles.
dtype – Data type.
- Returns:
Dictionary
cg
This module provides the function cg_coef() to calculate the Clebsch-Gordan coefficients \(\langle j_1m_1j_2m_2|JM\rangle\).
This function has interface to SymPy functions if it’s installed correctly. Otherwise, it will depend on the input file tf_pwa/cg_table.json.
- cg_coef(jb, jc, mb, mc, ja, ma)[source]
It returns the CG coefficient \(\langle j_bm_bj_cm_c|j_am_a\rangle\), as in a decay from particle a to b and c. It will either call sympy.physics.quantum.cg() or get_cg_coef().
- get_cg_coef(j1, j2, m1, m2, j, m)[source]
If SymPy is not installed, [deprecation] cg_coef() will call this function and derive the CG coefficient by searching into tf_pwa/cg_table.json.
In fact, tf_pwa/cg_table.json only stores some of the coefficients, the others will be obtained by this function using some symmetry properties of the CG table.
Note
tf_pwa/cg_table.json only contains the cases where \(j_1,j_2\leqslant4\), but this should be enough for most cases in PWA.
config
- get_config(name, default=<tf_pwa.config._Default object>)
get a configuration.
- regist_config(name, var=None)
regist a configuration.
- set_config(name, var)
set a configuration.
- using_amplitude(var)
cov_ten_ir
data
module for describing data process.
All data structure is describing as nested combination of dict
or list
for ndarray
.
Data process is a translation from data structure to another data structure or typical ndarray
.
Data cache can be implemented based on the dynamic features of list
and dict
.
The full data structure is
{
"particle":{
"A":{"p":...,"m":...}
...
},
"decay":[
{
"A->R1+B": {
"R1": {
"ang": {
"alpha":[...],
"beta": [...],
"gamma": [...]
},
"z": [[x1,y1,z1],...],
"x": [[x2,y2,z2],...]
},
"B" : {...}
},
"R->C+D": {
"C": {
...,
"aligned_angle":{
"alpha":[...],
"beta":[...],
"gamma":[...]
}
},
"D": {...}
},
},
{
"A->R2+C": {...},
"R2->B+D": {...}
},
...
],
"weight": [...]
}
- data_cut(data, expr, var_map=None)[source]
cut data with boolean expression
- Parameters:
data – data need to cut
expr – cut expression
var_map – variable map between parameters in expr and data, [option]
- Returns:
data after being cut,
- data_generator(data, fun=<function _data_split>, args=(), kwargs=None, MAX_ITER=1000)[source]
Data generator: call
fun
to eachdata
as a generator. The extra arguments will be passed tofun
.
- data_map(data, fun, args=(), kwargs=None)[source]
Apply fun for each data. It returns the same structure.
- data_mask(data, select)[source]
This function using boolean mask to select data.
- Parameters:
data – data to select
select – 1-d boolean array for selection
- Returns:
data after selection
- data_shape(data, axis=0, all_list=False)[source]
Get data size.
- Parameters:
data – Data array
axis – Integer. ???
all_list – Boolean. ???
- Returns:
- data_split(data, batch_size, axis=0)[source]
Split
data
forbatch_size
each inaxis
.- Parameters:
data – structured data
batch_size – Integer, data size for each split data
axis – Integer, axis for split, [option]
- Returns:
a generator for split data
>>> data = {"a": [np.array([1.0, 2.0]), np.array([3.0, 4.0])], "b": {"c": np.array([5.0, 6.0])}, "d": [], "e": {}} >>> for i, data_i in enumerate(data_split(data, 1)): ... print(i, data_to_numpy(data_i)) ... 0 {'a': [array([1.]), array([3.])], 'b': {'c': array([5.])}, 'd': [], 'e': {}} 1 {'a': [array([2.]), array([4.])], 'b': {'c': array([6.])}, 'd': [], 'e': {}}
- flatten_dict_data(data, fun=<built-in method format of str object>)[source]
Flatten data as dict with structure named as
fun
.
- load_dat_file(fnames, particles, dtype=None, split=None, order=None, _force_list=False, mmap_mode=None)[source]
Load
*.dat
file(s) of 4-momenta of the final particles.- Parameters:
fnames – String or list of strings. File names.
particles – List of Particle. Final particles.
dtype – Data type.
split – sizes of each splited dat files
order – transpose order
- Returns:
Dictionary of data indexed by Particle.
- load_data(file_name, **kwargs)[source]
Load data file from save_data. The arguments will be passed to
numpy.load()
.
- save_data(file_name, obj, **kwargs)[source]
Save structured data to files. The arguments will be passed to
numpy.save()
.
- save_dataz(file_name, obj, **kwargs)[source]
Save compressed structured data to files. The arguments will be passed to
numpy.save()
.
- split_generator(data, batch_size, axis=0)
Split
data
forbatch_size
each inaxis
.- Parameters:
data – structured data
batch_size – Integer, data size for each split data
axis – Integer, axis for split, [option]
- Returns:
a generator for split data
>>> data = {"a": [np.array([1.0, 2.0]), np.array([3.0, 4.0])], "b": {"c": np.array([5.0, 6.0])}, "d": [], "e": {}} >>> for i, data_i in enumerate(data_split(data, 1)): ... print(i, data_to_numpy(data_i)) ... 0 {'a': [array([1.]), array([3.])], 'b': {'c': array([5.])}, 'd': [], 'e': {}} 1 {'a': [array([2.]), array([4.])], 'b': {'c': array([6.])}, 'd': [], 'e': {}}
dec_parser
module for parsing decay card *.dec
file
dfun
This module provides functions to calculate the Wigner D-function.
\(D^{j}_{m_1,m_2}(\alpha,\beta,\gamma)=e^{-im_1\alpha}d^{j}_{m_1,m_2}(\beta)e^{-im_2\gamma}\), where the expression of the Wigner d-function is
where the weight \(w_{l}^{(j,m_1,m_2)}\) in each term satisfies
when \(k=\frac{l+m_2-m_1}{2} \in [\max(0,m_2-m_1),\min(j-m_1,j+m_2)]\), and otherwise \(w^{(j,m_1,m_2)}_{l} = 0\).
- D_matrix_conj(alpha, beta, gamma, j)[source]
The conjugated D-matrix element with indices (\(m_1,m_2\)) is
\[D^{j}_{m_1,m_2}(\alpha, \beta, \gamma)^\star = e^{i m_1 \alpha} d^{j}_{m_1,m_2}(\beta) e^{i m_2 \gamma}\]- Parameters:
alpha – Array
beta – Array
gamma – Array
j – Integer \(2j\) in the formula
- Returns:
Array of the conjugated D-matrices. Same shape as alpha, beta, and gamma
- Dfun_delta(d, ja, la, lb, lc=(0,))[source]
The decay from particle a to b and c requires \(|l_b-l_c|\leqslant j\)
\(D_{ma,mb-mc} = \delta[(m1,m2)->(ma, mb,mc))] D_{m1,m2}\)
- Dfun_delta_v2(d, ja, la, lb, lc=(0,))[source]
The decay from particle a to b and c requires \(|l_b-l_c|\leqslant j\)
\(D_{ma,mb-mc} = \delta[(m1,m2)->(ma, mb,mc))] D_{m1,m2}\)
- delta_D_trans(j, la, lb, lc)[source]
The decay from particle a to b and c requires \(|l_b-l_c|\leqslant j\)
(ja,ja) -> (ja,jb,jc)???
- exp_i(theta, mi)[source]
\(e^{im\theta}\)
- Parameters:
theta – Array \(\theta\) in the formula
mi – Integer or half-integer \(m\) in the formula
- Returns:
Array of tf.complex. Same length as theta
- get_D_matrix_for_angle(angle, j, cached=True)[source]
Interface to D_matrix_conj()
- Parameters:
angle – Dict of angle data {“alpha”,”beta”,”gamma”}
j – Integer \(2j\) in the formula
cached – Haven’t been used???
- Returns:
Array of the conjugated D-matrices. Same length as the angle data
- get_D_matrix_lambda(angle, ja, la, lb, lc=None)[source]
Get the D-matrix element
- Parameters:
angle – Dict of angle data {“alpha”,”beta”,”gamma”}
ja
la
lb
lc
- Returns:
- small_d_matrix(theta, j)[source]
The matrix element of \(d^{j}(\theta)\) is \(d^{j}_{m_1,m_2}(\theta) = \sum_{l=0}^{2j} w_{l}^{(j,m_1,m_2)}\sin^{l}(\frac{\theta}{2}) \cos^{2j-l}(\frac{\theta}{2})\)
- Parameters:
theta – Array \(\theta\) in the formula
j – Integer \(2j\) in the formula???
- Returns:
The d-matrices array. Same length as theta
- small_d_weight(j)[source]
For a certain j, the weight coefficient with index (\(m_1,m_2,l\)) is \(w^{(j,m_1,m_2)}_{l} = (-1)^{m_1-m_2+k}\frac{\sqrt{(j+m_1)!(j-m_1)!(j+m_2)!(j-m_2)!}}{(j-m_1-k)!(j+m_2-k)!(m_1-m_2+k)!k!}\), and \(l\) is an integer ranging from 0 to \(2j\).
- Parameters:
j – Integer \(2j\) in the formula???
- Returns:
Of the shape (j +1, j +1, j +1). The indices correspond to (\(l,m_1,m_2\))
einsum
err_num
expermental
fit
- exception LargeNumberError[source]
Bases:
ValueError
- fit_minuit_v1(fcn, bounds_dict={}, hesse=True, minos=False, **kwargs)[source]
- Parameters:
fcn
bounds_dict
hesse
minos
- Returns:
fit_improve
- exception LineSearchWarning[source]
Bases:
RuntimeWarning
- fmin_bfgs_f(f_g, x0, B0=None, M=2, gtol=1e-05, Delta=10.0, maxiter=None, callback=None, norm_ord=inf, **_kwargs)[source]
test BFGS with nonmonote line search
- line_search_nonmonote(f, myfprime, xk, pk, gfk=None, old_fval=None, fk=None, old_old_fval=None, args=(), c1=0.5, maxiter=10)[source]
- line_search_wolfe2(f, myfprime, xk, pk, gfk=None, fk=None, old_fval=None, old_old_fval=None, args=(), c1=0.0001, c2=0.9, amax=None, extra_condition=None, maxiter=10)[source]
Find alpha that satisfies strong Wolfe conditions.
- Parameters:
f (callable f(x,*args)) – Objective function.
myfprime (callable f'(x,*args)) – Objective function gradient.
xk (ndarray) – Starting point.
pk (ndarray) – Search direction.
gfk (ndarray, optional) – Gradient value for x=xk (xk being the current parameter estimate). Will be recomputed if omitted.
old_fval (float, optional) – Function value for x=xk. Will be recomputed if omitted.
old_old_fval (float, optional) – Function value for the point preceding x=xk
args (tuple, optional) – Additional arguments passed to objective function.
c1 (float, optional) – Parameter for Armijo condition rule.
c2 (float, optional) – Parameter for curvature condition rule.
amax (float, optional) – Maximum step size
extra_condition (callable, optional) – A callable of the form
extra_condition(alpha, x, f, g)
returning a boolean. Arguments are the proposed stepalpha
and the correspondingx
,f
andg
values. The line search accepts the value ofalpha
only if this callable returnsTrue
. If the callable returnsFalse
for the step length, the algorithm will continue with new iterates. The callable is only called for iterates satisfying the strong Wolfe conditions.maxiter (int, optional) – Maximum number of iterations to perform
- Returns:
alpha (float or None) – Alpha for which
x_new = x0 + alpha * pk
, or None if the line search algorithm did not converge.fc (int) – Number of function evaluations made.
gc (int) – Number of gradient evaluations made.
new_fval (float or None) – New function value
f(x_new)=f(x0+alpha*pk)
, or None if the line search algorithm did not converge.old_fval (float) – Old function value
f(x0)
.new_slope (float or None) – The local slope along the search direction at the new value
<myfprime(x_new), pk>
, or None if the line search algorithm did not converge.
Notes
Uses the line search algorithm to enforce strong Wolfe conditions. See Wright and Nocedal, ‘Numerical Optimization’, 1999, pg. 59-60.
For the zoom phase it uses an algorithm by […].
- minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None)[source]
- scalar_search_wolfe2(phi, derphi, phi0=None, old_phi0=None, derphi0=None, c1=0.0001, c2=0.9, amax=None, extra_condition=None, maxiter=10)[source]
Find alpha that satisfies strong Wolfe conditions.
alpha > 0 is assumed to be a descent direction.
- Parameters:
phi (callable phi(alpha)) – Objective scalar function.
derphi (callable phi'(alpha)) – Objective function derivative. Returns a scalar.
phi0 (float, optional) – Value of phi at 0
old_phi0 (float, optional) – Value of phi at previous point
derphi0 (float, optional) – Value of derphi at 0
c1 (float, optional) – Parameter for Armijo condition rule.
c2 (float, optional) – Parameter for curvature condition rule.
amax (float, optional) – Maximum step size
extra_condition (callable, optional) – A callable of the form
extra_condition(alpha, phi_value)
returning a boolean. The line search accepts the value ofalpha
only if this callable returnsTrue
. If the callable returnsFalse
for the step length, the algorithm will continue with new iterates. The callable is only called for iterates satisfying the strong Wolfe conditions.maxiter (int, optional) – Maximum number of iterations to perform
- Returns:
alpha_star (float or None) – Best alpha, or None if the line search algorithm did not converge.
phi_star (float) – phi at alpha_star
phi0 (float) – phi at 0
derphi_star (float or None) – derphi at alpha_star, or None if the line search algorithm did not converge.
Notes
Uses the line search algorithm to enforce strong Wolfe conditions. See Wright and Nocedal, ‘Numerical Optimization’, 1999, pg. 59-60.
For the zoom phase it uses an algorithm by […].
fitfractions
- cal_fitfractions(amp, mcdata, res=None, batch=None, args=(), kwargs=None)[source]
defination:
\[FF_{i} = \frac{\int |A_i|^2 d\Omega }{ \int |\sum_{i}A_i|^2 d\Omega } \approx \frac{\sum |A_i|^2 }{\sum|\sum_{i} A_{i}|^2}\]interference fitfraction:
\[FF_{i,j} = \frac{\int 2Re(A_i A_j*) d\Omega }{ \int |\sum_{i}A_i|^2 d\Omega } = \frac{\int |A_i +A_j|^2 d\Omega }{ \int |\sum_{i}A_i|^2 d\Omega } - FF_{i} - FF_{j}\]gradients (for error transfer):
\[\frac{\partial }{\partial \theta_i }\frac{f(\theta_i)}{g(\theta_i)} = \frac{\partial f(\theta_i)}{\partial \theta_i} \frac{1}{g(\theta_i)} - \frac{\partial g(\theta_i)}{\partial \theta_i} \frac{f(\theta_i)}{g^2(\theta_i)}\]
- cal_fitfractions_no_grad(amp, mcdata, res=None, batch=None, args=(), kwargs=None)[source]
calculate fit fractions without gradients.
- sum_gradient(amp, data, var, weight=1.0, func=<function <lambda>>, grad=True, args=(), kwargs=None)[source]
- sum_no_gradient(amp, data, var, weight=1.0, func=<function <lambda>>, *, grad=False, args=(), kwargs=None)
formula
function
gpu_info
histogram
- class Hist1D(binning, count, error=None)[source]
Bases:
object
- property bin_center
- property bin_width
- draw(ax=<module 'matplotlib.pyplot' from '/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/envs/latest/lib/python3.10/site-packages/matplotlib/pyplot.py'>, **kwargs)[source]
- draw_bar(ax=<module 'matplotlib.pyplot' from '/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/envs/latest/lib/python3.10/site-packages/matplotlib/pyplot.py'>, **kwargs)[source]
- draw_error(ax=<module 'matplotlib.pyplot' from '/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/envs/latest/lib/python3.10/site-packages/matplotlib/pyplot.py'>, fmt='none', **kwargs)[source]
- draw_fill(ax=<module 'matplotlib.pyplot' from '/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/envs/latest/lib/python3.10/site-packages/matplotlib/pyplot.py'>, kind='gauss', bin_scale=1.0, **kwargs)[source]
- draw_hist(ax=<module 'matplotlib.pyplot' from '/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/envs/latest/lib/python3.10/site-packages/matplotlib/pyplot.py'>, **kwargs)[source]
- draw_kde(ax=<module 'matplotlib.pyplot' from '/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/envs/latest/lib/python3.10/site-packages/matplotlib/pyplot.py'>, kind='gauss', bin_scale=1.0, **kwargs)[source]
- draw_line(ax=<module 'matplotlib.pyplot' from '/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/envs/latest/lib/python3.10/site-packages/matplotlib/pyplot.py'>, num=1000, kind='UnivariateSpline', **kwargs)[source]
- draw_pull(ax=<module 'matplotlib.pyplot' from '/home/docs/checkouts/readthedocs.org/user_builds/tf-pwa/envs/latest/lib/python3.10/site-packages/matplotlib/pyplot.py'>, **kwargs)[source]
- class WeightedData(m, *args, weights=None, **kwargs)[source]
Bases:
Hist1D
- interp_hist(binning, y, num=1000, kind='UnivariateSpline')[source]
interpolate data from hostgram into a line
main
params_trans
particle
This module implements classes to describe particles and decays.
- class BaseDecay(core, outs, name=None, disable=False, p_break=False, c_break=True, curve_style=None, **kwargs)[source]
Bases:
object
Base Decay object
- Parameters:
core – Particle. The mother particle
outs – List of Particle. The daughter particles
name – String. Name of the decay
disable – Boolean. If it’s True???
- property name
- class BaseParticle(name, J=0, P=-1, C=None, spins=None, mass=None, width=None, id_=None, disable=False, **kwargs)[source]
Bases:
object
Base Particle object. Name is “name[:id]”.
- Parameters:
name – String. Name of the particle
J – Integer or half-integer. The total spin
P – 1 or -1. The parity
spins – List. The spin quantum numbers. If it’s not provided,
spins
will betuple(range(-J, J + 1))
.mass – Real variable
width – Real variable
- add_creator(d)[source]
Add a decay reaction where the particle is created.
- Parameters:
d – BaseDecay object
- property name
- class Decay(core, outs, name=None, disable=False, p_break=False, c_break=True, curve_style=None, **kwargs)[source]
Bases:
BaseDecay
General Decay object
- barrier_factor(q, q0)[source]
The cached barrier factors with \(d=3.0\) for all \(l\). For barrier factor, refer to tf_pwa.breit_wigner.Bprime(L, q, q0, d)
- Parameters:
q – Data array
q0 – Real number
- Returns:
1-d array for every data point
- generate_params(name=None, _ls=True)[source]
Generate the name of the variable for every (l,s) pair. In PWA, the variable is usually expressed as \(g_ls\).
- Parameters:
name – String. It is the name of the decay by default
_ls –
???
- Returns:
List of strings
- get_cg_matrix()[source]
The matrix indexed by \([(l,s),(\lambda_b,\lambda_c)]\). The matrix element is
\[\sqrt{\frac{ 2 l + 1 }{ 2 j_a + 1 }} \langle j_b, j_c, \lambda_b, - \lambda_c | s, \lambda_b - \lambda_c \rangle \langle l, s, 0, \lambda_b - \lambda_c | j_a, \lambda_b - \lambda_c \rangle\]This is actually the pre-factor of \(g_ls\) in the amplitude formula.
- Returns:
2-d array of real numbers
- class DecayChain(chain)[source]
Bases:
object
A decay chain. E.g. \(A\rightarrow BC, B\rightarrow DE\)
- Parameters:
chain –
???
- static from_particles(top, finals)[source]
Build possible decay chain Topology. E.g. a -> [b,c,d] => [[a->rb,r->cd],[a->rc,r->bd],[a->rd,r->bc]]
- Parameters:
top – Particle
finals – List of Particle
- Returns:
DecayChain
- static from_sorted_table(decay_dict)[source]
Create decay chain from a topology independent structure. E.g. {a:[b,c,d],r:[c,d],b:[b],c:[c],d:[d]} => [a->rb,r->cd]
- Parameters:
decay_dict – Dictionary
- Returns:
DecayChain
- sorted_table()[source]
A topology independent structure. E.g. [a->rb,r->cd] => {a:[b,c,d],r:[c,d],b:[b],c:[c],d:[d]}
- Returns:
Dictionary indexed by Particle
- sorted_table_layers()[source]
Get the layer of decay chain as sorted table. Or the list of particle with the same number of final particles. So, the first item is always None. E.g. [a->rb,r->cd] => [None, [(b, [b]), (c, [c]), (d, [d])], [(r, [c, d])], [(a, [b, c, d])]]
- Returns:
List of dictionary
- standard_topology()[source]
standard topology structure of the decay chain, all inner particle will be replace as a tuple of out particles. for example [A->R+C, R->B+D], is [A->(B, D)+C, (B, D)->B+D]
- topology_id(identical=True)[source]
topology identy
- Parameters:
identical – allow identical particle in finals
- Returns:
- class DecayGroup(chains)[source]
Bases:
object
A group of two-body decays.
- Parameters:
chains – List of DecayChain
- GetA2BC_LS_list(ja, jb, jc, pa=None, pb=None, pc=None, p_break=False, ca=None)[source]
The \(L-S\) coupling for the decay \(A\rightarrow BC\), where \(L\) is the orbital angular momentum of \(B\) and \(B\), and \(S\) is the superposition of their spins. It’s required that \(|J_B-J_C|\leq S \leq J_B+J_C\) and \(|L-S|\leq J_A \leq L+S\). It’s also required by the conservation of P parity that \(L\) is keep \(P_A = P_B P_C (-1)^{l}\).
- Parameters:
ja –
J
of particleA
jb –
J
of particleB
jc –
J
of particleC
pa –
P
of particleA
pb –
P
of particleB
pc –
P
of particleC
p_break – allow p voilate
ca – enabel c partity select c=(-1)^(l+s)
- Returns:
List of \((l,s)\) pairs.
- cross_combine(x)[source]
Combine every two of a list, as well as give every one of them.??? Can be put to utils.py
- Parameters:
x
- Returns:
phasespace
- class ChainGenerator(m0, mi)[source]
Bases:
object
struct = m0 -> [m1, m2, m3] # (m0, [m1, m2, m3]) m0 -> float mi -> float | struct
- class PhaseSpaceGenerator(m0, mass)[source]
Bases:
object
Phase Space Generator for n-body decay
- generate(n_iter: int, force=True, flatten=True, importances=True) list [source]
generate
n_iter
events- Parameters:
n_iter – number of events
force – switch for cutting generated data to required size
flatten – switch for sampling with weights
- Returns:
daughters 4-momentum, list of ndarray with shape (n_iter, 4)
- generate_momentum(mass, n_iter=None)[source]
generate random momentum from mass, boost them to a same rest frame
- generate_momentum_i(m0, m1, m2, n_iter, p_list=[])[source]
\(|p|\) = m0,m1,m2 in m0 rest frame :param p_list: extra list for momentum need to boost
- get_weight(ms, importances=True)[source]
calculate weight of mass
\[w = \frac{1}{w_{max}} \frac{1}{M}\prod_{i=0}^{n-2} q(M_i,M_{i+1},m_{i+1})\]
- generate_phsp(m0, mi, N=1000)[source]
general method to generate decay chain phase sapce >>> (a, b), c = generate_phsp(1.0, ( … (0.3, (0.1, 0.1)), … 0.2), … N = 10) >>> assert np.allclose(LorentzVector.M(a+b+c), 1.0)
- phsp_volume(m0, mi, **kwargs)[source]
Calculate the integration value for
\[\int 1 d\Phi = \frac{1}{2(2\pi)^{2n-3}M} \int |p_{1}| \prod_{i=1}^{n-2}|p_{i+1}^{*}| d M_i\]>>> phsp_volume(3.0, [0.1, 0.1]) <tf.Tensor: shape=(), dtype=float64, numpy=0.039...> >>> phsp_volume(3.0, [0.1, 0.1], return_error=True) (<tf.Tensor: shape=(), dtype=float64, numpy=0.039...>, array(0.)) >>> value = phsp_volume(3.0, [0.1, 0.2, 0.3]) >>> value, err = phsp_volume(3.0, [0.1, 0.2, 0.3], return_error=True) >>> assert abs(value - 0.0009592187960824385) < err * 3
root_io
significance
- normal_quantile(p)[source]
Computes quantiles for standard normal distribution N(0, 1) at probability p
- prob(chi_2, ndf)[source]
Computation of the probability for a certain Chi-squared (chi2) and number of degrees of freedom (ndf).
Calculations are based on the incomplete gamma function P(a,x), where a=ndf/2 and x=chi2/2.
P(a,x) represents the probability that the observed Chi-squared for a correct model should be less than the value chi2.
The returned probability corresponds to 1-P(a,x), which denotes the probability that an observed Chi-squared exceeds the value chi2 by chance, even for a correct model.
tensorflow_wrapper
transform
- class LinearTrans(x: list | str, k: float = 1.0, b: float = 0.0, **kwargs)[source]
Bases:
BaseTransform
- create_trans(item: dict) BaseTransform [source]
utils
This module provides some functions that may be useful in other modules.
- check_positive_definite(m)[source]
check if matrix m is postive definite
>>> check_positive_definite([[1.0,0.0],[0.0, 0.1]]) True
>>> check_positive_definite([[1.0,0.0],[1.0,-0.1]]) eigvalues: [-0.1 1. ] False
- combine_asym_error(errs, N=10000)[source]
combine asymmetry uncertanties using convolution
>>> a, b = combine_asym_error([[-0.4, 0.4], 0.3]) >>> assert abs(a+0.5) < 0.01 >>> assert abs(b-0.5) < 0.01
- error_print(x, err=None, dig=None)[source]
It returns a format string “value +/- error”. The precision is modified according to
err
- Parameters:
x – Value
err – Error
- Returns:
String
- fit_normal(data, weights=None)[source]
Fit data distribution with Gaussian distribution. Though minimize the negative log likelihood function
\[- \ln L = \frac{1}{2}\sum w_i \frac{(\mu - x_i )^2}{\sigma^2} + (\sum w_i) \ln (\sqrt{2\pi} \sigma )\]the fit result can be solved as
\[\frac{\partial (-\ln L)}{\partial \mu} = 0 \Rightarrow \bar{\mu} = \frac{\sum w_i x_i}{ \sigma^2 \sum w_i}\]\[\frac{\partial (-\ln L)}{\partial \sigma} = 0 \Rightarrow \bar{\sigma} = \sqrt{\frac{\sum w_i (\bar{\mu} - x_i)^2}{\sum w_i}}\]From hessian
\[\frac{\partial^2 (-\ln L)}{\partial \mu^2} = \frac{\sum w_i}{\sigma^2}\]\[\frac{\partial^2 (-\ln L)}{\partial \sigma^2} = 3\sum \frac{\sum w_i (\mu - x)^2}{\sigma^4} - \frac{\sum w_i}{\sigma^2}\]the error matrix can wrotten as [[ \(\bar{\sigma}^2/N\) , 0], [0, \(\bar{\sigma}^2/(2N)\) ]] .
- flatten_dict_data(data, fun=<built-in method format of str object>)[source]
Flatten nested dictionary data into one layer dictionary.
- Returns:
Dictionary
- flatten_np_data(data)
- load_config_file(name)[source]
Load config file such as Resonances.yml.
- Parameters:
name – File name. Either yml file or json file.
- Returns:
Dictionary read from the file.
- search_interval(px, cl=0.6826894921370859, xrange=(0, 1))[source]
Search interval (a, b) that satisfly \(p(a)=p(b)\) and
\[\frac{\int_{a}^{b} p(x) dx}{\int_{x_{min]}^{x_{max}} p(x) dx} = cl\]>>> x = np.linspace(-10, 10, 10000) >>> a, b = search_interval(np.exp(-x**2/2), xrange=(-10, 10)) >>> assert abs(a+1) < 0.01 >>> assert abs(b-1) < 0.01
- std_periodic_var(p, mid=0.0, pi=3.141592653589793)[source]
Transform a periodic variable into its range.
>>> std_periodic_var(math.pi) -3.1415...
>>> std_periodic_var(2*math.pi + 0.01) 0.0...
- Parameters:
p – Value
mid – The middle value
pi – Half-range
- Returns:
The transformed value
variable
This module implements classes and methods to manage the variables in fitting.
- class Bound(a=None, b=None, func=None)[source]
Bases:
object
This class provides methods to implement the boundary constraint for a variable. It has dependence on SymPy . The boundary-transforming function can transform a variable x defined in the real domain to a variable y defined in a limited range (a,b). y should be the physical parameter but x is the one used while fitting.
- Parameters:
a – Real number. The lower boundary
b – Real number. The upper boundary
func – String. The boundary-transforming function. By default, if neither a or b is None, func is “(b-a)*(sin(x)+1)/2+a”; else if only a is None, func is “b+1-sqrt(x**2+1)”; else if only b is None, func is “a-1+sqrt(x**2+1)”; else func is “x”.
a, b, func can be refered by self.lower, self.upper, self.func.
- get_d2ydx2(val)[source]
To calculate the derivative \(\frac{dy}{dx}\).
- Parameters:
val – Real number x
- Returns:
Real number \(\frac{dy}{dx}\)
- get_dydx(val)[source]
To calculate the derivative \(\frac{dy}{dx}\).
- Parameters:
val – Real number x
- Returns:
Real number \(\frac{dy}{dx}\)
- class Variable(name, shape=None, cplx=False, vm=None, overwrite=True, is_cp=False, **kwargs)[source]
Bases:
object
This class has interface to VarsManager. It is convenient for users to define a group of real variables, since it may be more perceptually intuitive to define them together.
By calling the instance of this class, it returns the value of this variable. The type is tf.Tensor.
- Parameters:
name – The name of the variable group
shape – The shape of the group. E.g. for a 4*3*2 matrix, shape is [4,3,2]. By default, shape is [] for a real variable.
cplx – Boolean. Whether the variable (or the variables) are complex or not.
vm – VarsManager. It is by default the one automatically defined in the global scope by the program.
overwrite – Boolean. If it’s
True
, the program will not throw a warning when overwrite a variable with the same name.kwargs – Other arguments that may be used when calling self.real_var() or self.cplx_var()
- cplx_cpvar(polar=True, fix=False, fix_vals=(1.0, 0.0, 0.0, 0.0), value=0.0)[source]
It implements interface to
VarsManager.add_complex_var()
, but supports variables that are not of non-shape.- Parameters:
polar – Boolean. Whether the variable is defined in polar coordinate or in Cartesian coordinate.
fix – Boolean. Whether the variable is fixed. It’s enabled only if
self.shape is None
.fix_vals – Length-4 tuple. The value of the fixed complex variable is
fix_vals[0]+fix_vals[1]j
.
- cplx_var(polar=None, fix=False, fix_vals=(1.0, 0.0))[source]
It implements interface to
VarsManager.add_complex_var()
, but supports variables that are not of non-shape.- Parameters:
polar – Boolean. Whether the variable is defined in polar coordinate or in Cartesian coordinate.
fix – Boolean. Whether the variable is fixed. It’s enabled only if
self.shape is None
.fix_vals – Length-2 tuple. The value of the fixed complex variable is
fix_vals[0]+fix_vals[1]j
.
- fixed(value=None)[source]
Fix this Variable. Note only non-shape real Variable supports this method.
- Parameters:
value – Real number. The fixed value
Share the radium component to another Variable of the same shape. Only complex Variable supports this method.
- Parameters:
Var – Variable.
- real_var(value=None, range_=None, fix=False)[source]
It implements interface to
VarsManager.add_real_var()
, but supports variables that are not of non-shape.- Parameters:
value – Real number. The value of all real components.
range – Length-2 array. The length of all real components.
fix – Boolean. Whether the variable is fixed.
- sameas(Var)[source]
Set the Variable to be the same with another Variable of the same shape.
- Parameters:
Var – Variable.
- set_bound(bound, func=None, overwrite=False)[source]
Set boundary for this Variable. Note only non-shape real Variable supports this method.
- Parameters:
bound – Length-2 tuple.
func – String. Refer to class tf_pwa.variable.Bound.
overwrite – Boolean. If it’s
True
, the program will not throw a warning when overwrite a variable with the same name.
- set_fix_idx(fix_idx=None, fix_vals=None, free_idx=None)[source]
- Parameters:
fix_idx – Interger or list of integers. Which complex component in the innermost layer of the variable is fixed. E.g. If
self.shape==[2,3,4]
andfix_idx==[1,2]
, then Variable()[i][j][1] and Variable()[i][j][2] will be the fixed value.fix_vals – Float or length-2 float list for complex variable. The fixed value.
free_idx – Interger or list of integers. Which complex component in the innermost layer of the variable is set free. E.g. If
self.shape==[2,3,4]
andfix_idx==[0]
, then Variable()[i][j][0] will be set free.
- property value
Ndarray of
self.shape
.- Type:
return
- property variables
Names of the real variables contained in this Variable instance.
- Returns:
List of string.
- class VarsManager(name='', dtype=tf.float64, multi_gpu=None)[source]
Bases:
object
This class provides methods to operate the variables in fitting. Every variable is a 1-d tf.Variable of dtype (tf.float64 by default).
All variables are stored in a dictionary self.variables. The indices of the dictionary are the variables’ names, so name property in tf.Variable does not matter. All methods intended to change the variables are operating self.variables directly.
Besides, all trainable variables’ names will be stored in a list self.trainable_vars.
- add_cartesiancp_var(name, polar=None, trainable=True, fix_vals=(1.0, 0.0, 0.0, 0.0))[source]
Add a complex variable. Two real variables named name+’r’ and name+’i’ will be added into self.variables. The initial values will be given automatically according to its form of coordinate.
- Parameters:
name – The name of the complex variable.
polar – Boolean. If it’s True, name+’r’ and name+’i’ are defined in polar coordinate; otherwise they are defined in Cartesian coordinate.
trainable – Boolean. If it’s True, real variables name+’r’ and name+’i’ will be trainable.
fix_vals – Length-4 array. If trainable=False, the fixed values for name+’r’ and name+’i’ are fix_vals[0], fix_vals[1] respectively.
- add_complex_var(name, polar=None, trainable=True, fix_vals=(1.0, 0.0))[source]
Add a complex variable. Two real variables named name+’r’ and name+’i’ will be added into self.variables. The initial values will be given automatically according to its form of coordinate.
- Parameters:
name – The name of the complex variable.
polar – Boolean. If it’s True, name+’r’ and name+’i’ are defined in polar coordinate; otherwise they are defined in Cartesian coordinate.
trainable – Boolean. If it’s True, real variables name+’r’ and name+’i’ will be trainable.
fix_vals – Length-2 array. If trainable=False, the fixed values for name+’r’ and name+’i’ are fix_vals[0], fix_vals[1] respectively.
- add_real_var(name, value=None, range_=None, trainable=True)[source]
Add a real variable named name into self.variables. If value and range_ are not provided, the initial value is set to be a uniform random number between 0 and 1.
- Parameters:
name – The name of the variable, the index of this variable in self.variables
value – The initial value.
range – Length-2 array. It’s useless if value is given. Otherwise the initial value is set to be a uniform random number between range_[0] and range_[0].
trainable – Boolean. If it’s True, the variable is trainable while fitting.
- get(name, val_in_fit=True)[source]
Get a real variable. If
val_in_fit is True
, this is the variable used in fitting, not considering its boundary transformation.- Parameters:
name – String
- Returns:
tf.Variable
- get_all_dic(trainable_only=False)[source]
Get a dictionary of all variables.
- Parameters:
trainable_only – Boolean. If it’s True, the dictionary only contains the trainable variables.
- Returns:
Dictionary
- get_all_val(val_in_fit=False)[source]
Get the values of all trainable variables.
- Parameters:
val_in_fit – Boolean. If it’s True, the values will be the ones that are actually used in fitting (thus may not be the physical values because of the boundary transformation).
- Returns:
List of real numbers.
- remove_var(name)[source]
Remove a variable from self.variables. More specifically, two variables (name+’r’ and name+’i’) will be removed if it’s complex.
- Parameters:
name – The name of the variable
- rename_var(name, new_name, cplx=False)[source]
Rename a variable.
- Parameters:
name – Name of the variable
new_name – New name
cplx – Boolean. Users should indicate if this variable is complex or not.
- rp2xy_all(name_list=None)[source]
If name_list is not provided, this method will transform all complex variables into Cartesian coordinate.
- Parameters:
name_list – List of names of complex variables
- set(name, value, val_in_fit=True)[source]
Set value for a real variable. If
val_in_fit is True
, this is the variable used in fitting, not considering its boundary transformation.- Parameters:
name – String
value – Real number
- set_all(vals, val_in_fit=False)[source]
Set values for some variables.
- Parameters:
vals – It can be either a dictionary or a list of real numbers. If it’s a list, the values correspond to all trainable variables in order.
- set_bound(bound_dic, func=None, overwrite=False)[source]
Set boundary for the trainable variables. The variables will be constrained in their ranges while fitting.
- Parameters:
bound_dic – Dictionary. E.g. {“name1”:(-1.0,1.0), “name2”:(None,1.0)}. In this example, None means it has no lower limit.
func – String. Users can provide a string to describe the transforming function. For details, refer to class tf_pwa.variable.Bound.
overwrite – Boolean. If it’s
True
, the program will not throw a warning when overwrite a variable with the same name.
- set_fix(name, value=None, unfix=False)[source]
Fix or unfix a variable (change the trainability) :param name: The name of the variable :param value: The fixed value. It’s useless if unfix=True. :param unfix: Boolean. If it’s True, the variable will become trainable rather than be fixed.
- set_same(name_list, cplx=False)[source]
Set some variables to be the same.
- Parameters:
name_list – List of strings. Name of the variables.
cplx – Boolean. Whether the variables are complex or real.
If some complex variables want to share their radia variable while their phase variable are still different. Users can set this type of constrain using this method.
- Parameters:
name_list – List of strings. Note the strings should be the name of the complex variables rather than of their radium parts.
- set_trans_var(xvals)[source]
\(y = y(x)\)
- Parameters:
fcn_grad – The return of class tf_pwa.model???
- Returns:
- std_polar(name)[source]
Transform a complex variable into standard polar coordinate, which mean its radium part is positive, and its phase part is between \(-\pi\) to \(\pi\). :param name: String
- property trainable_variables
List of tf.Variable. It is similar to tf.keras.Model.trainable_variables.
- trans_error_matrix(hess_inv, xvals)[source]
Bound trans for error matrix \(F(x)=F(y(x))\), \(V_y = y' V_x y'\)
- Returns:
- trans_f_grad_hess(f)[source]
\(F(x)=F(y(x))\), \(G(x)=\frac{dF}{dx}=\frac{dF}{dy}\frac{dy}{dx}\)
- Parameters:
fcn_grad – The return of class tf_pwa.model???
- Returns:
- trans_fcn_grad(fcn_grad)[source]
\(F(x)=F(y(x))\), \(G(x)=\frac{dF}{dx}=\frac{dF}{dy}\frac{dy}{dx}\)
- Parameters:
fcn_grad – The return of class tf_pwa.model???
- Returns:
- trans_grad_hessp(f)[source]
\(F(x)=F(y(x))\), \(G(x)=\frac{dF}{dx}=\frac{dF}{dy}\frac{dy}{dx}\)
- Parameters:
fcn_grad – The return of class tf_pwa.model???
- Returns:
- combineVM(vm1, vm2, name='', same_list=None)[source]
This function combines two VarsManager objects into one. (WIP)
- Parameters:
name – The name of this combined VarsManager
same_list – To make some variables in the two VarsManager to be the same. E.g. if
same_list = ["var",["var1","var2"]]
, then “var” in vm1 and vm2 will be the same, and “var1” in vm1 and “var2” in vm2 will be the same.
version
vis
- class DotGenerator(top)[source]
Bases:
object
- dot_default_edge = ' "{}" -> "{}";\n'
- dot_default_node = ' "{}" [shape=none];\n'
- dot_head = '\ndigraph {\n rankdir=LR;\n node [shape=point];\n edge [arrowhead=none, labelfloat=true];\n'
- dot_label_edge = ' "{}" -> "{}" [label="{}"];\n'
- dot_ranksame = ' {{ rank=same {} }};\n'
- dot_tail = '}\n'
weight_smear
See also
Available Resonances Model
1. "default", "BWR"
(Particle
)
\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 \Gamma(m)}\]Argand diagram
(
Source code
,png
,hires.png
,![]()
Pole position
(
Source code
,png
,hires.png
,![]()
2. "x"
(ParticleX
)
simple particle model for mass, (used in expr)
3. "BWR2"
(ParticleBWR2
)
\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 \Gamma(m)}\]The difference of
BWR
,BWR2
is the behavior when mass is below the threshold ( \(m_0 = 0.1 < 0.1 + 0.1 = m_1 + m_2\)).(
Source code
,png
,hires.png
,![]()
4. "BWR_below"
(ParticleBWRBelowThreshold
)
\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 \Gamma(m)}\]
5. "BWR_coupling"
(ParticleBWRCoupling
)
Force \(q_0=1/d\) to avoid below theshold condition for
BWR
model, and remove other constant parts, then the \(\Gamma_0\) is coupling parameters.\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 \Gamma_0 \frac{q}{m} q^{2l} B_L'^2(q, 1/d, d)}\](
Source code
,png
,hires.png
,![]()
6. "BWR_normal"
(ParticleBWR_normal
)
\[R(m) = \frac{\sqrt{m_0 \Gamma(m)}}{m_0^2 - m^2 - i m_0 \Gamma(m)}\]
7. "GS_rho"
(ParticleGS
)
Gounaris G.J., Sakurai J.J., Phys. Rev. Lett., 21 (1968), pp. 244-247
c_daug2Mass
: mass for daughter particle 2 (\(\pi^{+}\)) 0.13957039
c_daug3Mass
: mass for daughter particle 3 (\(\pi^{0}\)) 0.1349768\[R(m) = \frac{1 + D \Gamma_0 / m_0}{(m_0^2 -m^2) + f(m) - i m_0 \Gamma(m)}\]\[f(m) = \Gamma_0 \frac{m_0 ^2 }{q_0^3} \left[q^2 [h(m)-h(m_0)] + (m_0^2 - m^2) q_0^2 \frac{d h}{d m}|_{m0} \right]\]\[h(m) = \frac{2}{\pi} \frac{q}{m} \ln \left(\frac{m+2q}{2m_{\pi}} \right)\]\[\frac{d h}{d m}|_{m0} = h(m_0) [(8q_0^2)^{-1} - (2m_0^2)^{-1}] + (2\pi m_0^2)^{-1}\]\[D = \frac{f(0)}{\Gamma_0 m_0} = \frac{3}{\pi}\frac{m_\pi^2}{q_0^2} \ln \left(\frac{m_0 + 2q_0}{2 m_\pi }\right) + \frac{m_0}{2\pi q_0} - \frac{m_\pi^2 m_0}{\pi q_0^3}\]
8. "BW"
(ParticleBW
)
9. "LASS"
(ParticleLass
)
\[R(m) = \frac{m}{q cot \delta_B - i q} + e^{2i \delta_B}\frac{m_0 \Gamma_0 \frac{m_0}{q_0}} {(m_0^2 - m^2) - i m_0\Gamma_0 \frac{q}{m}\frac{m_0}{q_0}}\]\[cot \delta_B = \frac{1}{a q} + \frac{1}{2} r q\]\[e^{2i\delta_B} = \cos 2 \delta_B + i \sin 2\delta_B = \frac{cot^2\delta_B -1 }{cot^2 \delta_B +1} + i \frac{2 cot \delta_B }{cot^2 \delta_B +1 }\]
10. "one"
(ParticleOne
)
11. "exp"
(ParticleExp
)
\[R(m) = e^{-|a| m}\]
12. "exp_com"
(ParticleExpCom
)
13. "poly"
(ParticlePoly
)
\[R(m) = \sum c_i (m-m_0)^{n-i}\]lineshape when \(c_0=1, c_1=c_2=0\)
(
Source code
,png
,hires.png
,![]()
14. "Flatte"
(ParticleFlatte
)
Flatte like formula
\[R(m) = \frac{1}{m_0^2 - m^2 + i m_0 (\sum_{i} g_i \frac{q_i}{m})}\]\[\begin{split}q_i = \begin{cases} \frac{\sqrt{(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) >= 0 \\ \frac{i\sqrt{|(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)|}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) < 0 \\ \end{cases}\end{split}\](
Source code
,png
,hires.png
,![]()
Required input arguments
mass_list: [[m11, m12], [m21, m22]]
for \(m_{i,1}, m_{i,2}\).
15. "FlatteC"
(ParticleFlatteC
)
Flatte like formula
\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 (\sum_{i} g_i \frac{q_i}{m})}\]\[\begin{split}q_i = \begin{cases} \frac{\sqrt{(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) >= 0 \\ \frac{i\sqrt{|(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)|}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) < 0 \\ \end{cases}\end{split}\]Required input arguments
mass_list: [[m11, m12], [m21, m22]]
for \(m_{i,1}, m_{i,2}\).(
Source code
,png
,hires.png
,![]()
16. "FlatteGen"
(ParticleFlateGen
)
More General Flatte like formula
\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 [\sum_{i} g_i \frac{q_i}{m} \times \frac{m_0}{|q_{i0}|} \times \frac{|q_i|^{2l_i}}{|q_{i0}|^{2l_i}} B_{l_i}'^2(|q_i|,|q_{i0}|,d)]}\]\[\begin{split}q_i = \begin{cases} \frac{\sqrt{(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) >= 0 \\ \frac{i\sqrt{|(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)|}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) < 0 \\ \end{cases}\end{split}\]Required input arguments
mass_list: [[m11, m12], [m21, m22]]
for \(m_{i,1}, m_{i,2}\). And addition argumentsl_list: [l1, l2]
for \(l_i\)
has_bprime=False
to remove \(B_{l_i}'^2(|q_i|,|q_{i0}|,d)\).
cut_phsp=True
to set \(q_i = 0\) when \((m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) < 0\)The plot use parameters \(m_0=0.7, m_{0,1}=m_{0,2}=0.1, m_{1,1}=m_{1,2}=0.3, g_0=0.3,g_1=0.2,l_0=0,l_1=1\).
(
Source code
,png
,hires.png
,![]()
no_m0=True
to set \(i m_0 => i\) in the width part.
no_q0=True
to remove \(\frac{m_0}{|q_{i0}|}\) and set others \(q_{i0}=1\).(
Source code
,png
,hires.png
,![]()
17. "Flatte2"
(ParticleFlate2
)
General Flatte like formula.
\[R(m) = \frac{1}{m_0^2 - m^2 - i m_0 [\sum_{i} \color{red}{g_i^2}\color{black} \frac{q_i}{m} \times \frac{m_0}{|q_{i0}|} \times \frac{|q_i|^{2l_i}}{|q_{i0}|^{2l_i}} B_{l_i}'^2(|q_i|,|q_{i0}|,d)]}\]\[\begin{split}q_i = \begin{cases} \frac{\sqrt{(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) >= 0 \\ \frac{i\sqrt{|(m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2)|}}{2m} & (m^2-(m_{i,1}+m_{i,2})^2)(m^2-(m_{i,1}-m_{i,2})^2) < 0 \\ \end{cases}\end{split}\]It has the same options as
FlatteGen
.(
Source code
,png
,hires.png
,![]()
18. "KMatrixSingleChannel"
(KmatrixSingleChannelParticle
)
K matrix model for single channel multi pole.
\[K = \sum_{i} \frac{m_i \Gamma_i(m)}{m_i^2 - m^2 }\]\[P = \sum_{i} \frac{\beta_i m_0 \Gamma_0 }{ m_i^2 - m^2}\]the barrier factor is included in gls
\[R(m) = (1-iK)^{-1} P\]requird
mass_list: [pole1, pole2]
andwidth_list: [width1, width2]
.(
Source code
,png
,hires.png
,![]()
19. "KMatrixSplitLS"
(KmatrixSplitLSParticle
)
K matrix model for single channel multi pole and the same channel with different (l, s) coupling.
\[K_{a,b} = \sum_{i} \frac{m_i \sqrt{\Gamma_{a,i}(m)\Gamma_{b,i}(m)}}{m_i^2 - m^2 }\]\[P_{b} = \sum_{i} \frac{\beta_i m_0 \Gamma_{b,i0} }{ m_i^2 - m^2}\]the barrier factor is included in gls
\[R(m) = (1-iK)^{-1} P\]
20. "KmatrixSimple"
(KmatrixSimple
)
simple Kmatrix formula.
K-matrix
\[K_{i,j} = \sum_{a} \frac{g_{i,a} g_{j,a}}{m_a^2 - m^2+i\epsilon}\]P-vector
\[P_{i} = \sum_{a} \frac{\beta_{a} g_{i,a}}{m_a^2 - m^2 +i\epsilon} + f_{bkg,i}\]total amplitude
\[R(m) = n (1 - K i \rho n^2)^{-1} P\]barrief factor
\[n_{ii} = q_i^l B'_l(q_i, 1/d, d)\]phase space factor
\[\rho_{ii} = q_i/m\]\(q_i\) is 0 when below threshold
21. "BWR_LS"
(ParticleBWRLS
)
Breit Wigner with split ls running width
\[R_i (m) = \frac{g_i}{m_0^2 - m^2 - im_0 \Gamma_0 \frac{\rho}{\rho_0} (\sum_{i} g_i^2)}\], \(\rho = 2q/m\), the partial width factor is
\[g_i = \gamma_i \frac{q^l}{q_0^l} B_{l_i}'(q,q_0,d)\]and keep normalize as
\[\sum_{i} \gamma_i^2 = 1.\]The normalize is done by (\(\cos \theta_0, \sin\theta_0 \cos \theta_1, \cdots, \prod_i \sin\theta_i\))
22. "BWR_LS2"
(ParticleBWRLS2
)
Breit Wigner with split ls running width, each one use their own l,
\[R_i (m) = \frac{1}{m_0^2 - m^2 - im_0 \Gamma_0 \frac{\rho}{\rho_0} (g_i^2)}\], \(\rho = 2q/m\), the partial width factor is
\[g_i = \gamma_i \frac{q^l}{q_0^l} B_{l_i}'(q,q_0,d)\]
23. "MultiBWR"
(ParticleMultiBWR
)
24. "MultiBW"
(ParticleMultiBW
)
Combine Multi BW into one particle
25. "linear_npy"
(InterpLinearNpy
)
Linear interpolation model from a
npy
file with array of [mi, re(ai), im(ai)]. Requiredfile: path_of_file.npy
, for the path ofnpy
file.The example is
exp(5 I m)
.(
Source code
,png
,hires.png
,![]()
26. "linear_txt"
(InterpLinearTxt
)
- Linear interpolation model from a
txt
file with array of [mi, re(ai), im(ai)].Required
file: path_of_file.txt
, for the path oftxt
file.The example is
exp(5 I m)
.(
Source code
,png
,hires.png
,![]()
27. "interp"
(Interp
)
linear interpolation for real number
28. "interp_c"
(Interp
)
linear interpolation for complex number
29. "spline_c"
(Interp1DSpline
)
Spline interpolation function for model independent resonance
30. "interp1d3"
(Interp1D3
)
Piecewise third order interpolation
31. "interp_lagrange"
(Interp1DLang
)
Lagrange interpolation
32. "interp_hist"
(InterpHist
)
Interpolation for each bins as constant
33. "hist_idx"
(InterpHistIdx
)
Interpolation for each bins as constant
use
min_m: 0.19 max_m: 0.91 interp_N: 8 with_bound: Truefor mass range [0.19, 0.91] and 7 bins
The first and last are fixed to zero unless set
with_bound: True
.This is an example of \(k\exp (i k)\) for point k.
(
Source code
,png
,hires.png
,![]()
34. "spline_c_idx"
(Interp1DSplineIdx
)
Spline function in index way.
use
min_m: 0.19 max_m: 0.91 interp_N: 8 with_bound: Truefor mass range [0.19, 0.91] and 8 interpolation points
The first and last are fixed to zero unless set
with_bound: True
.This is an example of \(k\exp (i k)\) for point k.
(
Source code
,png
,hires.png
,![]()
35. "sppchip"
(InterpSPPCHIP
)
Shape-Preserving Piecewise Cubic Hermite Interpolation Polynomial. It is monotonic in each interval.
(
Source code
,png
,hires.png
,![]()
Available Decay Model
2-body decays
1. "gls-bf", "default"
(HelicityDecay
)
default decay model
The total amplitude is
\[A = H_{\lambda_{B},\lambda_{C}}^{A \rightarrow B+C} D^{J_A*}_{\lambda_{A}, \lambda_{B}-\lambda_{C}} (\varphi,\theta,0)\]The helicity coupling is
\[H_{\lambda_{B},\lambda_{C}}^{A \rightarrow B+C} = \sum_{ls} g_{ls} \sqrt{\frac{2l+1}{2 J_{A}+1}} \langle l 0; s \delta|J_{A} \delta\rangle \langle J_{B} \lambda_{B} ;J_{C} -\lambda_{C} | s \delta \rangle q^{l} B_{l}'(q, q_0, d)\]The fit parameters is \(g_{ls}\)
There are some options
(1).
has_bprime=False
will remove the \(B_{l}'(q, q_0, d)\) part.(2).
has_barrier_factor=False
will remove the \(q^{l} B_{l}'(q, q_0, d)\) part.(3).
barrier_factor_norm=True
will replace \(q^l\) with \((q/q_{0})^l\)(4).
below_threshold=True
will replace the mass used to calculate \(q_0\) with\[m_0^{eff} = m^{min} + \frac{m^{max} - m^{min}}{2}(1+tanh \frac{m_0 - \frac{m^{max} + m^{min}}{2}}{m^{max} - m^{min}})\](5).
l_list=[l1, l2]
andls_list=[[l1, s1], [l2, s2]]
options give the list of all possible LS used in the decay.(6).
no_q0=True
will set the \(q_0=1\).
2. "helicity_full"
(HelicityDecayNP
)
Full helicity amplitude
\[A = H_{m_1, m_2} D_{m_0, m_1-m_2}^{J_0 *}(\varphi, \theta,0)\]fit parameters is \(H_{m_1, m_2}\).
3. "helicity_parity"
(HelicityDecayP
)
\[H_{- m1, - m2} = P_0 P_1 P_2 (-1)^{J_1 + J_2 - J_0} H_{m1, m2}\]
4. "gls-cpv"
(HelicityDecayCPV
)
decay model for CPV
5. "gls_reduce_h0"
(HelicityDecayReduceH0
)
decay model that remove helicity =0 for massless particles
Tensorflow and Cudatoolkit Version
- Why are there two separate conda requirements file?
requirements-min.txt
limits the tensorflow version up to2.2
. Beyond this version,conda
will install the wrong dependency versions, in particularcudatoolkit
versions and sometimespython3
.tensorflow_2_6_requirements.txt
manually selects the correctpython
andcudatoolkit
versions to match thetensorflow-2.6.0
build onconda-forge
.
- Should I use the latest
tensorflow
version? We highly recommend Ampere card users (RTX 30 series for example), to install their
conda
environments withtensorflow_2_6_requirements.txt
which usescudatoolkit
version 11.2.
- Should I use the latest
- Why should Ampere use
cudatoolkit
version > 11.0? To avoid a few minutes of overhead due to JIT compilation.
cudatoolkit
version < 11.0 does not have pre-compiled CUDA binaries for Ampere architecture. So oldercudatoolkit
versions have to JIT compile the PTX code everytimetensorflow
uses the GPU hence the overhead.See this explanation about old CUDA versions and JIT compile.
- Why should Ampere use
- Will you update the
tensorflow_2_X_requirements.txt
file regularly to the latest available version on `conda`? We do not guarantee any regular updates on
tensorflow_2_X_requirements.txt
.We will update this should particular build become unavailable on
conda
or a new release of GPUs require atensorflow
andcudatoolkit
update. Please notify us if this is the case.
- Will you update the
FAQ
1. Precission Loss
message: Desired error not nescessarily achieved due to precision loss.
Check the jac value,
1.1 If all absulute value is small. it is acceptable beacuse of the precision.
1.2 If some absulte value is large. It is the bad parameters or problem in models.
1.3 Avoid negative weights
2. NaN value in fit
message: NaN result encountered.
2.1 Check the data.
There a script (scripts/check_nan.py) to check it.
2.1.1 No stange value in data, (nan, infs …).
2.1.2 The data order should be \(E, p_x, p_y,p_z\), \(E\) is the first.
2.1.3 The mass should be valid, \(E^2 - p_x^2 - p_y^2 - p_z^2 > 0\), and for any combinations of final particles, mab > ma + mb.
2.1.4 Avoid 0 in weights.
2.2 Check the model.
2.2.1 The resonaces mass should be valid, for example in the mass range (m1+m2, m0-m3), out of the threshold required special options.
3. NaN value when getting params error.
numpy.linalg.LinAlgError: Array must not contain infs or NaN.
3.1 Similar as sec 2.2.
3.2 Bad fit parameters: too wide width or two narrow width, reach the boundary and so on.
3.3 Bad gradients. No gradients or the gradients is not corret for fit paramters.
4. Singular Matrix when getting params error
numpy.linalg.LinAlgError: Singular matrix
4.1 Free paramters are not used in model.
4.2 Used numpy for calculation of variable. The calculation have to be done in get_amp with TensorFlow.
... def init_params(self): self.a = self.add_var("a") def get_amp(self, data, *args, **kwargs): # avoid use numpy for varible as a = np.sin(self.a()) # use tensorflow instead a = tf.sin(self.a())
5. Out of memory (OOM)
5.1 GPU
tensorflow.python.framework.errors_impl.ResourceExhaustedError: OOM when allocating tensor with shape ... device:GPU:0 by allocator GPU_0_bfc [Op:...]
5.1.1 Reduce batch size at config.fit(batch=65000)
and config.get_params_error(batch=13000)
in fit.py.
5.1.2 Use option for large data size, such as lazy call
# config.yml data: lazy_call: True
5.1.3 Try to use small data sample, or simple cases (less final particles).
5.1.4 Some speical model required large memory (such as interpolation model), try other model.
5.2 CPU
killed
5.2.1 Try to allocate more memory. There should be some options for job.
5.2.2 Similar as sec 5.1
6. Bad config.yml
6.1 yaml parse error
yaml.parser.ParserError: while parsing ..
Check the yaml file (see https://yaml.org): the indent, speical chars ,:}]
, unicode and so on.
6.2 Decay chain
AssertionError: not only one top particle
The decay chain should be complete. All the item in decay should decay from initial to finals.
6.3 Decay chain 2
RuntimeError: not decay chain aviable, check you config.yml
6.3.1 Similar as sec 6.2.
6.3.2 Check the information in remove decay chain, see the reson why those decays are not aviable.
ls not aviable means no possible LS combination allowed. Check the spin and parity. If allow parity voilate, add p_break: True
to decay.
For starters
Take the decay in config_sample.yml
for example, we will generate a toy, and then use it to conduct an analysis.
First, we use the class ConfigLoader
to load the configuration file, and thus building the amplitude expression.
from tf_pwa.config_loader import ConfigLoader
config = ConfigLoader("config_sample.yml")
amp = config.get_amplitude()
We can also use a json file to set the parameters in the amplitude formula config.set_params("parameters.json")
.
Otherwise, the parameters are set randomly.
Next, we can use functions in tf_pwa.applications
to directly generate data samples.
We need to provide the masses of A and B, C, D to generate the PhaseSpace MC, and then use it to generate the toy data.
from tf_pwa.applications import gen_mc, gen_data
PHSP = gen_mc(mother=4.6, daughters=[2.00698, 2.01028, 0.13957], number=100000, outfile="PHSP.dat")
data = gen_data(amp, Ndata=5000, mcfile="PHSP.dat", genfile="data.dat")
Now that we have updated data.dat
and PHSP.dat
, we’d better load the configuration file again,
and then fit the data.
config = ConfigLoader("config_sample.yml")
fit_result = config.fit()
Fitting is the major part of an analysis, and it could also be the most time-consuming part. For this example (the complexity of the amplitude expression matters a lot), the time for fitting is about xxx (running on xxxGPU). Then we can step further to complete the analysis, like calculating the fit fractions.
errors = config.get_params_error(fit_result)
fit_result.save_as("final_parameters.json")
fit_frac, err_frac = config.cal_fitfractions()
We can use error_print
in tf_pwa.utils
to print the fitting parameters as well as the fit fractions.
from tf_pwa.utils import error_print
print("########## fitting parameters:")
for key, value in config.get_params().items():
print(key, error_print(value, errors.get(key, None)))
print("########## fit fractions:")
for i in fit_frac:
print(i, " : " + error_print(fit_frac[i], err_frac.get(i, None)))
If the plotting options are also provided in the config_sample.yml
,
we can also plot the distributions of variables indicated in the configuration file.
config.plot_partial_wave(fit_result, prefix="figure/")
The figures will be saved under path figure
. Here are the three invariant mass pairs for example.
(three pictures here)
We can do a lot more using tf_pwa
. For more examples, please see path tutorials
.