10: Scikit-HEP
The Scikit-HEP project is a well maintained collection of HEP packages in Python that are useful for analysis. It contains tools ranging from plotting helpers, PDG lookup, DecayLanguage converters over high-performance histogramming libraries and ROOT I/O up to likelihood fitting and statistics libraries.
This is a minimal overview over the packages that are available and have not yet been used in the other tutorials.
formulate - converting expressions
The package formulate converts between different style of expressions, notably between ROOT and numexpr. The former was used in the previous notebooks to apply cuts and create new variables with Pandas DataFrames query
and eval
methods.
The standard usage is with a from_style
and to_style
, but it allows for more as it parses the string such as the variables used can be extracted.
[1]:
import formulate
momentum = formulate.from_root('TMath::Sqrt(X_PX**2 + X_PY**2 + X_PZ**2)')
momentum
[1]:
Expression<SQRT>(Expression<ADD>(Expression<POW>(Variable(X_PX), UnnamedConstant(2)), Expression<POW>(Variable(X_PY), UnnamedConstant(2)), Expression<POW>(Variable(X_PZ), UnnamedConstant(2))))
[2]:
momentum.to_numexpr() # as used in Pandas eval/query
[2]:
'sqrt(((X_PX ** 2) + (X_PY ** 2) + (X_PZ ** 2)))'
[3]:
momentum.to_root() # as used in ROOT
[3]:
'TMath::Sqrt(((X_PX ** 2) + (X_PY ** 2) + (X_PZ ** 2)))'
Particle
particle provides an easy access to particle properties such as mass and decay width from PDG. One example is to get the actual particle in a Particle
object which holds all the relevant information.
[4]:
# Particle
from particle import Particle
piplus = Particle.from_pdgid(211)
Here we can access all the properties we wish to such as mass and decay width.
[5]:
piplus.mass
[5]:
139.57039
[6]:
piplus.charge
[6]:
1.0
[7]:
piplus.width
[7]:
2.5284e-14
[8]:
piplus.name
[8]:
'pi+'
It also serves as a data-base like structure and we can do searches. Let’s find all neutral beauty hadrons.
[9]:
Particle.findall(lambda p: p.pdgid.has_bottom and p.charge==0)
[9]:
[<Particle: name="B0", pdgid=511, mass=5279.66 ± 0.12 MeV>,
<Particle: name="B~0", pdgid=-511, mass=5279.66 ± 0.12 MeV>,
<Particle: name="B*0", pdgid=513, mass=5324.71 ± 0.21 MeV>,
<Particle: name="B*~0", pdgid=-513, mass=5324.71 ± 0.21 MeV>,
<Particle: name="B(2)*(5747)0", pdgid=515, mass=5739.5 ± 0.7 MeV>,
<Particle: name="B(2)*(5747)~0", pdgid=-515, mass=5739.5 ± 0.7 MeV>,
<Particle: name="B(s)0", pdgid=531, mass=5366.92 ± 0.10 MeV>,
<Particle: name="B(s)~0", pdgid=-531, mass=5366.92 ± 0.10 MeV>,
<Particle: name="B(s)*0", pdgid=533, mass=5415.4 + 1.8 - 1.5 MeV>,
<Particle: name="B(s)*~0", pdgid=-533, mass=5415.4 + 1.8 - 1.5 MeV>,
<Particle: name="B(s2)*(5840)0", pdgid=535, mass=5839.86 ± 0.12 MeV>,
<Particle: name="B(s2)*(5840)~0", pdgid=-535, mass=5839.86 ± 0.12 MeV>,
<Particle: name="eta(b)(1S)", pdgid=551, mass=9398.7 ± 2.0 MeV>,
<Particle: name="Upsilon(1S)", pdgid=553, mass=9460.40 ± 0.10 MeV>,
<Particle: name="chi(b2)(1P)", pdgid=555, mass=9912.2 ± 0.4 MeV>,
<Particle: name="Lambda(b)0", pdgid=5122, mass=5619.60 ± 0.17 MeV>,
<Particle: name="Lambda(b)~0", pdgid=-5122, mass=5619.60 ± 0.17 MeV>,
<Particle: name="Xi(b)0", pdgid=5232, mass=5791.9 ± 0.5 MeV>,
<Particle: name="Xi(b)~0", pdgid=-5232, mass=5791.9 ± 0.5 MeV>,
<Particle: name="chi(b0)(1P)", pdgid=10551, mass=9859.4 ± 0.5 MeV>,
<Particle: name="h(b)(1P)", pdgid=10553, mass=9899.3 ± 0.8 MeV>,
<Particle: name="chi(b1)(1P)", pdgid=20553, mass=9892.8 ± 0.4 MeV>,
<Particle: name="Upsilon(2)(1D)", pdgid=20555, mass=10163.7 ± 1.4 MeV>,
<Particle: name="Upsilon(2S)", pdgid=100553, mass=10023.4 ± 0.5 MeV>,
<Particle: name="chi(b2)(2P)", pdgid=100555, mass=10268.6 ± 0.5 MeV>,
<Particle: name="chi(b0)(2P)", pdgid=110551, mass=10232.5 ± 0.6 MeV>,
<Particle: name="h(b)(2P)", pdgid=110553, mass=10259.8 ± 1.2 MeV>,
<Particle: name="chi(b1)(2P)", pdgid=120553, mass=10255.5 ± 0.5 MeV>,
<Particle: name="Upsilon(3S)", pdgid=200553, mass=10355.1 ± 0.5 MeV>,
<Particle: name="chi(b2)(3P)", pdgid=200555, mass=10524.0 ± 0.8 MeV>,
<Particle: name="chi(b1)(3P)", pdgid=220553, mass=10513.4 ± 0.7 MeV>,
<Particle: name="Upsilon(4S)", pdgid=300553, mass=10579.4 ± 1.2 MeV>,
<Particle: name="Upsilon(10860)", pdgid=9000553, mass=10885.2 + 2.6 - 1.6 MeV>,
<Particle: name="Upsilon(11020)", pdgid=9010553, mass=11000 ± 4 MeV>]
hepunits
Ever hardcoded a physics constant? Or needed to manually convert units? That’s what the neat hepunits package is for.
It contains constants as well as units that all get converted into the standard units (e.g. MeV) which allows for calculations without the need to explicitly convert by just adding the unit; furthermore it greatly increases readability
[10]:
from hepunits.constants import c_light
c_light
[10]:
299.792458
[11]:
import hepunits as u # u for units
[12]:
150 * u.MeV + 1.1 * u.GeV # result in MeV
[12]:
1250.0
Vector
Manipulating and calculation vector quantities can be done using the vector library. It provides functionality to load, combine and work with vectors.
[13]:
import vector
[14]:
# NumPy-like arguments (literally passed through to NumPy)
vector.array([
(1.1, 2.1), (1.2, 2.2), (1.3, 2.3), (1.4, 2.4), (1.5, 2.5)
], dtype=[("x", float), ("y", float)])
# Pandas-like arguments (dict from names to column arrays)
vector.array({"x": [1.1, 1.2, 1.3, 1.4, 1.5], "y": [2.1, 2.2, 2.3, 2.4, 2.5]})
# As with objects, the coordinate system and dimension is taken from the names of the fields.
vec1 = vector.array({
"x": [1.1, 1.2, 1.3, 1.4, 1.5],
"y": [2.1, 2.2, 2.3, 2.4, 2.5],
"z": [3.1, 3.2, 3.3, 3.4, 3.5],
"t": [4.1, 4.2, 4.3, 4.4, 4.5],
})
vector.array({
"pt": [1.1, 1.2, 1.3, 1.4, 1.5],
"phi": [2.1, 2.2, 2.3, 2.4, 2.5],
"eta": [3.1, 3.2, 3.3, 3.4, 3.5],
"M": [4.1, 4.2, 4.3, 4.4, 4.5],
})
[14]:
MomentumNumpy4D([(1.1, 2.1, 3.1, 4.1), (1.2, 2.2, 3.2, 4.2), (1.3, 2.3, 3.3, 4.3),
(1.4, 2.4, 3.4, 4.4), (1.5, 2.5, 3.5, 4.5)],
dtype=[('rho', '<f8'), ('phi', '<f8'), ('eta', '<f8'), ('tau', '<f8')])
Vector properties
Vectors can have properties and provide quantities as attributes
[15]:
vector.obj(x=1, y=2, z=3).theta
vector.obj(x=1, y=2, z=3).eta
[15]:
1.1035868415601453
[16]:
vector.obj(x=3, y=4, z=-2, t=10) # Cartesian 4D vector
[16]:
VectorObject4D(x=3, y=4, z=-2, t=10)
[ ]: