Skip to content

Commit b12fb69

Browse files
authored
feat: add a playground for cccl studies (#3734)
1 parent e619aaa commit b12fb69

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

studies/cccl/playground.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
from __future__ import annotations
2+
3+
import awkward as ak
4+
import numpy as np
5+
6+
7+
# 3 events with different numbers of electrons and muons in each
8+
# (numerical values are made up and aren't physically meaningful)
9+
# ---
10+
# legend:
11+
# - 'pt': transverse momentum
12+
# - 'eta': pseudorapidity (collider detector angle, e.g. CMS detector)
13+
# - 'phi': azimuthal angle (collider detector angle, e.g. CMS detector)
14+
electrons = ak.Array(
15+
[
16+
# 2 electrons
17+
{"pt": [50.0, 60.0], "eta": [2.1, 2.2], "phi": [0.6, 0.7]},
18+
# 1 electron
19+
{"pt": [30.0], "eta": [-1.5], "phi": [0.3]},
20+
# 0 electrons
21+
{"pt": [], "eta": [], "phi": []},
22+
]
23+
)
24+
muons = ak.Array(
25+
[
26+
# 1 muon
27+
{"pt": [45.0], "eta": [2.5], "phi": [0.4]},
28+
# 2 muons
29+
{"pt": [25.0, 35.0], "eta": [-2.0, 1.0], "phi": [0.5, 0.6]},
30+
# 1 muon
31+
{"pt": [15.0], "eta": [0.0], "phi": [0.7]},
32+
]
33+
)
34+
35+
events = ak.zip({"electrons": electrons, "muons": muons}, depth_limit=1)
36+
37+
38+
def physics_analysis(events: ak.Array) -> ak.Array:
39+
"""
40+
A oversimplified physics analysis selecting events with exactly 2 leptons (electrons or muons)
41+
and computing their invariant mass.
42+
"""
43+
# select only electrons with pt > 40
44+
selected_electrons = events.electrons[events.electrons.pt > 40.0]
45+
# select only muons with pt > 20 and abs(eta) < 2.4
46+
selected_muons = events.muons[
47+
(events.muons.pt > 20.0) & (abs(events.muons.eta) < 2.4)
48+
]
49+
50+
# choose exactly 2 leptons (electrons or muons)
51+
two_electrons = selected_electrons[ak.num(selected_electrons.pt, axis=-1) == 2]
52+
two_muons = selected_muons[ak.num(selected_muons.pt, axis=-1) == 2]
53+
54+
return ak.zip(
55+
{
56+
"electron": invariant_mass(two_electrons),
57+
"muon": invariant_mass(two_muons),
58+
}
59+
)
60+
61+
62+
def invariant_mass(two_particles: ak.Array) -> ak.Array:
63+
"""Compute invariant mass of two particles given their pt, eta, phi."""
64+
pt1, eta1, phi1 = (
65+
two_particles[:, 0].pt,
66+
two_particles[:, 0].eta,
67+
two_particles[:, 0].phi,
68+
)
69+
pt2, eta2, phi2 = (
70+
two_particles[:, 1].pt,
71+
two_particles[:, 1].eta,
72+
two_particles[:, 1].phi,
73+
)
74+
75+
# https://en.wikipedia.org/wiki/Invariant_mass#Collider_experiments
76+
m2 = 2 * pt1 * pt2 * (np.cosh(eta1 - eta2) - np.cos(phi1 - phi2))
77+
return np.sqrt(m2)
78+
79+
80+
if __name__ == "__main__":
81+
# ipython -i studies/cccl/playground.py to play around with `events` and `physics_analysis`
82+
inv_mass = physics_analysis(events)
83+
84+
print("Electron invariant masses (in GeV):", inv_mass.electron)
85+
print("Muon invariant masses (in GeV):", inv_mass.muon)

0 commit comments

Comments
 (0)