atlas-schema 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {atlas_schema-0.2.0 → atlas_schema-0.2.1}/.gitignore +1 -0
- {atlas_schema-0.2.0 → atlas_schema-0.2.1}/PKG-INFO +10 -4
- {atlas_schema-0.2.0 → atlas_schema-0.2.1}/README.md +1 -1
- {atlas_schema-0.2.0 → atlas_schema-0.2.1}/pyproject.toml +6 -2
- {atlas_schema-0.2.0 → atlas_schema-0.2.1}/src/atlas_schema/__init__.py +5 -1
- {atlas_schema-0.2.0 → atlas_schema-0.2.1}/src/atlas_schema/_version.py +2 -2
- atlas_schema-0.2.1/src/atlas_schema/enums.py +123 -0
- atlas_schema-0.2.1/src/atlas_schema/methods.py +241 -0
- atlas_schema-0.2.0/src/atlas_schema/enums.py +0 -116
- atlas_schema-0.2.0/src/atlas_schema/methods.py +0 -181
- {atlas_schema-0.2.0 → atlas_schema-0.2.1}/LICENSE +0 -0
- {atlas_schema-0.2.0 → atlas_schema-0.2.1}/src/atlas_schema/_version.pyi +0 -0
- {atlas_schema-0.2.0 → atlas_schema-0.2.1}/src/atlas_schema/py.typed +0 -0
- {atlas_schema-0.2.0 → atlas_schema-0.2.1}/src/atlas_schema/schema.py +0 -0
- {atlas_schema-0.2.0 → atlas_schema-0.2.1}/src/atlas_schema/typing_compat.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: atlas-schema
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.1
|
4
4
|
Summary: Helper python package for ATLAS Common NTuple Analysis work.
|
5
5
|
Project-URL: Homepage, https://github.com/scipp-atlas/atlas-schema
|
6
6
|
Project-URL: Bug Tracker, https://github.com/scipp-atlas/atlas-schema/issues
|
@@ -209,6 +209,7 @@ License:
|
|
209
209
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
210
210
|
See the License for the specific language governing permissions and
|
211
211
|
limitations under the License.
|
212
|
+
License-File: LICENSE
|
212
213
|
Classifier: Development Status :: 1 - Planning
|
213
214
|
Classifier: Intended Audience :: Developers
|
214
215
|
Classifier: Intended Audience :: Science/Research
|
@@ -225,14 +226,19 @@ Classifier: Topic :: Scientific/Engineering
|
|
225
226
|
Classifier: Typing :: Typed
|
226
227
|
Requires-Python: >=3.9
|
227
228
|
Requires-Dist: coffea[dask]>=2024.4.1
|
229
|
+
Requires-Dist: particle>=0.25.0
|
228
230
|
Provides-Extra: dev
|
229
231
|
Requires-Dist: pytest-cov>=3; extra == 'dev'
|
230
232
|
Requires-Dist: pytest>=6; extra == 'dev'
|
231
233
|
Provides-Extra: docs
|
232
234
|
Requires-Dist: furo>=2023.08.17; extra == 'docs'
|
235
|
+
Requires-Dist: intersphinx-registry>=0.2411.17; extra == 'docs'
|
236
|
+
Requires-Dist: ipywidgets; extra == 'docs'
|
233
237
|
Requires-Dist: myst-parser>=0.13; extra == 'docs'
|
234
238
|
Requires-Dist: sphinx-autodoc-typehints; extra == 'docs'
|
235
|
-
Requires-Dist: sphinx-
|
239
|
+
Requires-Dist: sphinx-click; extra == 'docs'
|
240
|
+
Requires-Dist: sphinx-copybutton!=0.5.1,>=0.3.2; extra == 'docs'
|
241
|
+
Requires-Dist: sphinx-issues; extra == 'docs'
|
236
242
|
Requires-Dist: sphinx>=7.0; extra == 'docs'
|
237
243
|
Provides-Extra: test
|
238
244
|
Requires-Dist: build; extra == 'test'
|
@@ -243,7 +249,7 @@ Requires-Dist: tbump>=6.7.0; extra == 'test'
|
|
243
249
|
Requires-Dist: twine; extra == 'test'
|
244
250
|
Description-Content-Type: text/markdown
|
245
251
|
|
246
|
-
# atlas-schema v0.2.
|
252
|
+
# atlas-schema v0.2.1
|
247
253
|
|
248
254
|
[![Actions Status][actions-badge]][actions-link]
|
249
255
|
[![Documentation Status][rtd-badge]][rtd-link]
|
@@ -28,7 +28,7 @@ classifiers = [
|
|
28
28
|
"Typing :: Typed",
|
29
29
|
]
|
30
30
|
dynamic = ["version"]
|
31
|
-
dependencies = ["coffea[dask] >= 2024.4.1"]
|
31
|
+
dependencies = ["coffea[dask] >= 2024.4.1", "particle >= 0.25.0"]
|
32
32
|
|
33
33
|
[project.optional-dependencies]
|
34
34
|
test = [
|
@@ -47,9 +47,13 @@ dev = [
|
|
47
47
|
docs = [
|
48
48
|
"sphinx>=7.0",
|
49
49
|
"myst_parser>=0.13",
|
50
|
-
"
|
50
|
+
"sphinx-copybutton>=0.3.2,!=0.5.1",
|
51
51
|
"sphinx_autodoc_typehints",
|
52
52
|
"furo>=2023.08.17",
|
53
|
+
"sphinx-click",
|
54
|
+
"ipywidgets",
|
55
|
+
"intersphinx_registry>=0.2411.17",
|
56
|
+
"sphinx-issues",
|
53
57
|
]
|
54
58
|
|
55
59
|
[project.urls]
|
@@ -6,7 +6,11 @@ atlas_schema: Collection of utilities and helper functions for HEP ATLAS analyse
|
|
6
6
|
|
7
7
|
from __future__ import annotations
|
8
8
|
|
9
|
+
import warnings
|
10
|
+
|
9
11
|
from atlas_schema._version import version as __version__
|
10
12
|
from atlas_schema.enums import ParticleOrigin, PhotonID
|
11
13
|
|
12
|
-
|
14
|
+
warnings.filterwarnings("ignore", module="coffea.*")
|
15
|
+
|
16
|
+
__all__ = ["ParticleOrigin", "PhotonID", "__version__"]
|
@@ -0,0 +1,123 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from enum import IntEnum
|
4
|
+
|
5
|
+
|
6
|
+
class ParticleType(IntEnum):
|
7
|
+
"""
|
8
|
+
Taken from `ATLAS Truth Utilities for ParticleType <https://gitlab.cern.ch/atlas/athena/-/blob/74f43ff0910edb2a2bd3778880ccbdad648dc037/Generators/TruthUtils/TruthUtils/TruthClasses.h#L8-49>`_.
|
9
|
+
"""
|
10
|
+
|
11
|
+
Unknown = 0
|
12
|
+
UnknownElectron = 1
|
13
|
+
IsoElectron = 2
|
14
|
+
NonIsoElectron = 3
|
15
|
+
BkgElectron = 4
|
16
|
+
UnknownMuon = 5
|
17
|
+
IsoMuon = 6
|
18
|
+
NonIsoMuon = 7
|
19
|
+
BkgMuon = 8
|
20
|
+
UnknownTau = 9
|
21
|
+
IsoTau = 10
|
22
|
+
NonIsoTau = 11
|
23
|
+
BkgTau = 12
|
24
|
+
UnknownPhoton = 13
|
25
|
+
IsoPhoton = 14
|
26
|
+
NonIsoPhoton = 15
|
27
|
+
BkgPhoton = 16
|
28
|
+
Hadron = 17
|
29
|
+
Neutrino = 18
|
30
|
+
NuclFrag = 19
|
31
|
+
NonPrimary = 20
|
32
|
+
GenParticle = 21
|
33
|
+
SUSYParticle = 22
|
34
|
+
OtherBSMParticle = 39
|
35
|
+
BBbarMesonPart = 23
|
36
|
+
BottomMesonPart = 24
|
37
|
+
CCbarMesonPart = 25
|
38
|
+
CharmedMesonPart = 26
|
39
|
+
BottomBaryonPart = 27
|
40
|
+
CharmedBaryonPart = 28
|
41
|
+
StrangeBaryonPart = 29
|
42
|
+
LightBaryonPart = 30
|
43
|
+
StrangeMesonPart = 31
|
44
|
+
LightMesonPart = 32
|
45
|
+
BJet = 33
|
46
|
+
CJet = 34
|
47
|
+
LJet = 35
|
48
|
+
GJet = 36
|
49
|
+
TauJet = 37
|
50
|
+
UnknownJet = 38
|
51
|
+
|
52
|
+
|
53
|
+
class ParticleOrigin(IntEnum):
|
54
|
+
"""
|
55
|
+
Taken from `ATLAS Truth Utilities for ParticleOrigin <https://gitlab.cern.ch/atlas/athena/-/blob/74f43ff0910edb2a2bd3778880ccbdad648dc037/Generators/TruthUtils/TruthUtils/TruthClasses.h#L51-103>`_.
|
56
|
+
"""
|
57
|
+
|
58
|
+
NonDefined = 0
|
59
|
+
SingleElec = 1
|
60
|
+
SingleMuon = 2
|
61
|
+
SinglePhot = 3
|
62
|
+
SingleTau = 4
|
63
|
+
PhotonConv = 5
|
64
|
+
DalitzDec = 6
|
65
|
+
ElMagProc = 7
|
66
|
+
Mu = 8
|
67
|
+
TauLep = 9
|
68
|
+
top = 10
|
69
|
+
QuarkWeakDec = 11
|
70
|
+
WBoson = 12
|
71
|
+
ZBoson = 13
|
72
|
+
Higgs = 14
|
73
|
+
HiggsMSSM = 15
|
74
|
+
HeavyBoson = 16
|
75
|
+
WBosonLRSM = 17
|
76
|
+
NuREle = 18
|
77
|
+
NuRMu = 19
|
78
|
+
NuRTau = 20
|
79
|
+
LQ = 21
|
80
|
+
SUSY = 22
|
81
|
+
OtherBSM = 46
|
82
|
+
LightMeson = 23
|
83
|
+
StrangeMeson = 24
|
84
|
+
CharmedMeson = 25
|
85
|
+
BottomMeson = 26
|
86
|
+
CCbarMeson = 27
|
87
|
+
JPsi = 28
|
88
|
+
BBbarMeson = 29
|
89
|
+
LightBaryon = 30
|
90
|
+
StrangeBaryon = 31
|
91
|
+
CharmedBaryon = 32
|
92
|
+
BottomBaryon = 33
|
93
|
+
PionDecay = 34
|
94
|
+
KaonDecay = 35
|
95
|
+
BremPhot = 36
|
96
|
+
PromptPhot = 37
|
97
|
+
UndrPhot = 38
|
98
|
+
ISRPhot = 39
|
99
|
+
FSRPhot = 40
|
100
|
+
NucReact = 41
|
101
|
+
PiZero = 42
|
102
|
+
DiBoson = 43
|
103
|
+
ZorHeavyBoson = 44
|
104
|
+
MultiBoson = 47
|
105
|
+
QCD = 45
|
106
|
+
|
107
|
+
|
108
|
+
class PhotonID(IntEnum):
|
109
|
+
"""
|
110
|
+
Taken from the `EGamma Identification CP group's twiki <https://twiki.cern.ch/twiki/bin/viewauth/AtlasProtected/EGammaIdentificationRun2#Photon_isEM_word>`_.
|
111
|
+
"""
|
112
|
+
|
113
|
+
Rhad = 10 # ClusterHadronicLeakage_Photon
|
114
|
+
E277 = 11 # ClusterMiddleEnergy_Photon
|
115
|
+
Reta = 12 # ClusterMiddleEratio37_Photon
|
116
|
+
Rphi = 13 # ClusterMiddleEratio33_Photon
|
117
|
+
Weta2 = 14 # ClusterMiddleWidth_Photon
|
118
|
+
f1 = 15 # ClusterStripsEratio_Photon
|
119
|
+
DeltaE = 17 # ClusterStripsDeltaE_Photon
|
120
|
+
Wstot = 18 # ClusterStripsWtot_Photon
|
121
|
+
fside = 19 # ClusterStripsFracm_Photon
|
122
|
+
Ws3 = 20 # ClusterStripsWeta1c_Photon
|
123
|
+
ERatio = 21 # ClusterStripsDEmaxs1_Photon
|
@@ -0,0 +1,241 @@
|
|
1
|
+
"""Mixins for the Ntuple schema"""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from functools import reduce
|
6
|
+
from operator import ior
|
7
|
+
|
8
|
+
import awkward
|
9
|
+
import particle
|
10
|
+
from coffea.nanoevents.methods import base, candidate, vector
|
11
|
+
from dask_awkward import dask_method
|
12
|
+
|
13
|
+
from atlas_schema.enums import PhotonID
|
14
|
+
from atlas_schema.typing_compat import Behavior
|
15
|
+
|
16
|
+
behavior: Behavior = {}
|
17
|
+
behavior.update(base.behavior)
|
18
|
+
# vector behavior is included in candidate behavior
|
19
|
+
behavior.update(candidate.behavior)
|
20
|
+
|
21
|
+
|
22
|
+
class NtupleEvents(behavior["NanoEvents"]): # type: ignore[misc, valid-type, name-defined]
|
23
|
+
def __repr__(self):
|
24
|
+
return f"<event {getattr(self, 'runNumber', '??')}:\
|
25
|
+
{getattr(self, 'eventNumber', '??')}:\
|
26
|
+
{getattr(self, 'mcChannelNumber', '??')}>"
|
27
|
+
|
28
|
+
|
29
|
+
behavior["NanoEvents"] = NtupleEvents
|
30
|
+
|
31
|
+
|
32
|
+
def _set_repr_name(classname):
|
33
|
+
def namefcn(_self):
|
34
|
+
return classname
|
35
|
+
|
36
|
+
behavior[("__typestr__", classname)] = classname[0].lower() + classname[1:]
|
37
|
+
behavior[classname].__repr__ = namefcn
|
38
|
+
|
39
|
+
|
40
|
+
@awkward.mixin_class(behavior)
|
41
|
+
class Weight(base.NanoCollection, base.Systematic): ...
|
42
|
+
|
43
|
+
|
44
|
+
_set_repr_name("Weight")
|
45
|
+
|
46
|
+
|
47
|
+
@awkward.mixin_class(behavior)
|
48
|
+
class Pass(base.NanoCollection, base.Systematic): ...
|
49
|
+
|
50
|
+
|
51
|
+
_set_repr_name("Pass")
|
52
|
+
|
53
|
+
behavior.update(
|
54
|
+
awkward._util.copy_behaviors("PtEtaPhiMLorentzVector", "Particle", behavior)
|
55
|
+
)
|
56
|
+
|
57
|
+
|
58
|
+
@awkward.mixin_class(behavior)
|
59
|
+
class Particle(vector.PtEtaPhiMLorentzVector):
|
60
|
+
"""Generic particle collection that has Lorentz vector properties
|
61
|
+
|
62
|
+
Also handles the following additional branches:
|
63
|
+
- '{obj}_select'
|
64
|
+
"""
|
65
|
+
|
66
|
+
@property
|
67
|
+
def mass(self):
|
68
|
+
r"""Invariant mass (+, -, -, -)
|
69
|
+
|
70
|
+
:math:`\sqrt{t^2-x^2-y^2-z^2}`
|
71
|
+
"""
|
72
|
+
return self["mass"] / 1.0e3
|
73
|
+
|
74
|
+
@dask_method
|
75
|
+
def passes(self, name):
|
76
|
+
return self[f"select_{name}"] == 1
|
77
|
+
|
78
|
+
@passes.dask
|
79
|
+
def passes(self, dask_array, name):
|
80
|
+
return dask_array[f"select_{name}"] == 1
|
81
|
+
|
82
|
+
# NB: fields with the name 'pt' take precedence over this
|
83
|
+
# @dask_property
|
84
|
+
# def pt(self):
|
85
|
+
# print('inside non-dask prop')
|
86
|
+
# return self["pt_NOSYS"]
|
87
|
+
|
88
|
+
# @pt.dask
|
89
|
+
# def pt(self, dask_array):
|
90
|
+
# branch = 'pt'
|
91
|
+
# print('inside dask prop')
|
92
|
+
# variation = dask_array._events().metadata.get("systematic", "NOSYS")
|
93
|
+
# with contextlib.suppress(Exception):
|
94
|
+
# return dask_array[f"{branch}_{variation}"]
|
95
|
+
|
96
|
+
# if variation != "NOSYS":
|
97
|
+
# with contextlib.suppress(Exception):
|
98
|
+
# return dask_array[f"{branch}_NOSYS"]
|
99
|
+
|
100
|
+
# return dask_array[branch]
|
101
|
+
|
102
|
+
|
103
|
+
_set_repr_name("Particle")
|
104
|
+
|
105
|
+
ParticleArray.ProjectionClass2D = vector.TwoVectorArray # noqa: F821
|
106
|
+
ParticleArray.ProjectionClass3D = vector.ThreeVectorArray # noqa: F821
|
107
|
+
ParticleArray.ProjectionClass4D = ParticleArray # noqa: F821
|
108
|
+
ParticleArray.MomentumClass = vector.LorentzVectorArray # noqa: F821
|
109
|
+
|
110
|
+
|
111
|
+
behavior.update(awkward._util.copy_behaviors("PolarTwoVector", "MissingET", behavior))
|
112
|
+
|
113
|
+
|
114
|
+
@awkward.mixin_class(behavior)
|
115
|
+
class MissingET(vector.PolarTwoVector, base.NanoCollection, base.Systematic):
|
116
|
+
@property
|
117
|
+
def r(self):
|
118
|
+
"""Distance from origin in XY plane"""
|
119
|
+
return self["met"]
|
120
|
+
|
121
|
+
|
122
|
+
_set_repr_name("MissingET")
|
123
|
+
|
124
|
+
MissingETArray.ProjectionClass2D = MissingETArray # noqa: F821
|
125
|
+
MissingETArray.ProjectionClass3D = vector.SphericalThreeVectorArray # noqa: F821
|
126
|
+
MissingETArray.ProjectionClass4D = vector.LorentzVectorArray # noqa: F821
|
127
|
+
MissingETArray.MomentumClass = MissingETArray # noqa: F821
|
128
|
+
|
129
|
+
behavior.update(awkward._util.copy_behaviors("Particle", "Photon", behavior))
|
130
|
+
|
131
|
+
|
132
|
+
@awkward.mixin_class(behavior)
|
133
|
+
class Photon(Particle, base.NanoCollection, base.Systematic):
|
134
|
+
@property
|
135
|
+
def mass(self):
|
136
|
+
"""Return zero mass for photon."""
|
137
|
+
return awkward.zeros_like(self.pt)
|
138
|
+
|
139
|
+
@property
|
140
|
+
def charge(self):
|
141
|
+
"""Return zero charge for photon."""
|
142
|
+
return awkward.zeros_like(self.pt)
|
143
|
+
|
144
|
+
@property
|
145
|
+
def isEM(self):
|
146
|
+
return self.isEM_syst.NOSYS == 0
|
147
|
+
|
148
|
+
def pass_isEM(self, words: list[PhotonID]):
|
149
|
+
# 0 is pass, 1 is fail
|
150
|
+
return (
|
151
|
+
self.isEM_syst.NOSYS & reduce(ior, (1 << word.value for word in words))
|
152
|
+
) == 0
|
153
|
+
|
154
|
+
|
155
|
+
_set_repr_name("Photon")
|
156
|
+
|
157
|
+
PhotonArray.ProjectionClass2D = vector.TwoVectorArray # noqa: F821
|
158
|
+
PhotonArray.ProjectionClass3D = vector.ThreeVectorArray # noqa: F821
|
159
|
+
PhotonArray.ProjectionClass4D = PhotonArray # noqa: F821
|
160
|
+
PhotonArray.MomentumClass = vector.LorentzVectorArray # noqa: F821
|
161
|
+
|
162
|
+
behavior.update(awkward._util.copy_behaviors("Particle", "Electron", behavior))
|
163
|
+
|
164
|
+
|
165
|
+
@awkward.mixin_class(behavior)
|
166
|
+
class Electron(Particle, base.NanoCollection, base.Systematic):
|
167
|
+
@property
|
168
|
+
def mass(self):
|
169
|
+
"""Electron mass in GeV"""
|
170
|
+
return particle.literals.e_minus.mass / 1.0e3
|
171
|
+
|
172
|
+
|
173
|
+
_set_repr_name("Electron")
|
174
|
+
|
175
|
+
ElectronArray.ProjectionClass2D = vector.TwoVectorArray # noqa: F821
|
176
|
+
ElectronArray.ProjectionClass3D = vector.ThreeVectorArray # noqa: F821
|
177
|
+
ElectronArray.ProjectionClass4D = ElectronArray # noqa: F821
|
178
|
+
ElectronArray.MomentumClass = vector.LorentzVectorArray # noqa: F821
|
179
|
+
|
180
|
+
behavior.update(awkward._util.copy_behaviors("Particle", "Muon", behavior))
|
181
|
+
|
182
|
+
|
183
|
+
@awkward.mixin_class(behavior)
|
184
|
+
class Muon(Particle, base.NanoCollection, base.Systematic):
|
185
|
+
@property
|
186
|
+
def mass(self):
|
187
|
+
"""Muon mass in GeV"""
|
188
|
+
return particle.literals.mu_minus.mass / 1.0e3
|
189
|
+
|
190
|
+
|
191
|
+
_set_repr_name("Muon")
|
192
|
+
|
193
|
+
MuonArray.ProjectionClass2D = vector.TwoVectorArray # noqa: F821
|
194
|
+
MuonArray.ProjectionClass3D = vector.ThreeVectorArray # noqa: F821
|
195
|
+
MuonArray.ProjectionClass4D = MuonArray # noqa: F821
|
196
|
+
MuonArray.MomentumClass = vector.LorentzVectorArray # noqa: F821
|
197
|
+
|
198
|
+
behavior.update(awkward._util.copy_behaviors("Particle", "Tau", behavior))
|
199
|
+
|
200
|
+
|
201
|
+
@awkward.mixin_class(behavior)
|
202
|
+
class Tau(Particle, base.NanoCollection, base.Systematic):
|
203
|
+
@property
|
204
|
+
def mass(self):
|
205
|
+
"""Tau mass in GeV"""
|
206
|
+
return particle.literals.tau_minus.mass / 1.0e3
|
207
|
+
|
208
|
+
|
209
|
+
_set_repr_name("Tau")
|
210
|
+
|
211
|
+
TauArray.ProjectionClass2D = vector.TwoVectorArray # noqa: F821
|
212
|
+
TauArray.ProjectionClass3D = vector.ThreeVectorArray # noqa: F821
|
213
|
+
TauArray.ProjectionClass4D = TauArray # noqa: F821
|
214
|
+
TauArray.MomentumClass = vector.LorentzVectorArray # noqa: F821
|
215
|
+
|
216
|
+
|
217
|
+
behavior.update(awkward._util.copy_behaviors("Particle", "Jet", behavior))
|
218
|
+
|
219
|
+
|
220
|
+
@awkward.mixin_class(behavior)
|
221
|
+
class Jet(Particle, base.NanoCollection, base.Systematic): ...
|
222
|
+
|
223
|
+
|
224
|
+
_set_repr_name("Jet")
|
225
|
+
|
226
|
+
JetArray.ProjectionClass2D = vector.TwoVectorArray # noqa: F821
|
227
|
+
JetArray.ProjectionClass3D = vector.ThreeVectorArray # noqa: F821
|
228
|
+
JetArray.ProjectionClass4D = JetArray # noqa: F821
|
229
|
+
JetArray.MomentumClass = vector.LorentzVectorArray # noqa: F821
|
230
|
+
|
231
|
+
__all__ = [
|
232
|
+
"Electron",
|
233
|
+
"Jet",
|
234
|
+
"MissingET",
|
235
|
+
"Muon",
|
236
|
+
"NtupleEvents",
|
237
|
+
"Particle",
|
238
|
+
"Pass",
|
239
|
+
"Photon",
|
240
|
+
"Weight",
|
241
|
+
]
|
@@ -1,116 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
from enum import IntEnum
|
4
|
-
|
5
|
-
from atlas_schema.typing_compat import Annotated
|
6
|
-
|
7
|
-
|
8
|
-
# https://gitlab.cern.ch/atlas/athena/-/blob/74f43ff0910edb2a2bd3778880ccbdad648dc037/Generators/TruthUtils/TruthUtils/TruthClasses.h#L51-103
|
9
|
-
class ParticleType(IntEnum):
|
10
|
-
Unknown: Annotated[int, "Unknown"] = 0
|
11
|
-
UnknownElectron: Annotated[int, "UnknownElectron"] = 1
|
12
|
-
IsoElectron: Annotated[int, "IsoElectron"] = 2
|
13
|
-
NonIsoElectron: Annotated[int, "NonIsoElectron"] = 3
|
14
|
-
BkgElectron: Annotated[int, "BkgElectron"] = 4
|
15
|
-
UnknownMuon: Annotated[int, "UnknownMuon"] = 5
|
16
|
-
IsoMuon: Annotated[int, "IsoMuon"] = 6
|
17
|
-
NonIsoMuon: Annotated[int, "NonIsoMuon"] = 7
|
18
|
-
BkgMuon: Annotated[int, "BkgMuon"] = 8
|
19
|
-
UnknownTau: Annotated[int, "UnknownTau"] = 9
|
20
|
-
IsoTau: Annotated[int, "IsoTau"] = 10
|
21
|
-
NonIsoTau: Annotated[int, "NonIsoTau"] = 11
|
22
|
-
BkgTau: Annotated[int, "BkgTau"] = 12
|
23
|
-
UnknownPhoton: Annotated[int, "UnknownPhoton"] = 13
|
24
|
-
IsoPhoton: Annotated[int, "IsoPhoton"] = 14
|
25
|
-
NonIsoPhoton: Annotated[int, "NonIsoPhoton"] = 15
|
26
|
-
BkgPhoton: Annotated[int, "BkgPhoton"] = 16
|
27
|
-
Hadron: Annotated[int, "Hadron"] = 17
|
28
|
-
Neutrino: Annotated[int, "Neutrino"] = 18
|
29
|
-
NuclFrag: Annotated[int, "NuclFrag"] = 19
|
30
|
-
NonPrimary: Annotated[int, "NonPrimary"] = 20
|
31
|
-
GenParticle: Annotated[int, "GenParticle"] = 21
|
32
|
-
SUSYParticle: Annotated[int, "SUSYParticle"] = 22
|
33
|
-
OtherBSMParticle: Annotated[int, "OtherBSMParticle"] = 39
|
34
|
-
BBbarMesonPart: Annotated[int, "BBbarMesonPart"] = 23
|
35
|
-
BottomMesonPart: Annotated[int, "BottomMesonPart"] = 24
|
36
|
-
CCbarMesonPart: Annotated[int, "CCbarMesonPart"] = 25
|
37
|
-
CharmedMesonPart: Annotated[int, "CharmedMesonPart"] = 26
|
38
|
-
BottomBaryonPart: Annotated[int, "BottomBaryonPart"] = 27
|
39
|
-
CharmedBaryonPart: Annotated[int, "CharmedBaryonPart"] = 28
|
40
|
-
StrangeBaryonPart: Annotated[int, "StrangeBaryonPart"] = 29
|
41
|
-
LightBaryonPart: Annotated[int, "LightBaryonPart"] = 30
|
42
|
-
StrangeMesonPart: Annotated[int, "StrangeMesonPart"] = 31
|
43
|
-
LightMesonPart: Annotated[int, "LightMesonPart"] = 32
|
44
|
-
BJet: Annotated[int, "BJet"] = 33
|
45
|
-
CJet: Annotated[int, "CJet"] = 34
|
46
|
-
LJet: Annotated[int, "LJet"] = 35
|
47
|
-
GJet: Annotated[int, "GJet"] = 36
|
48
|
-
TauJet: Annotated[int, "TauJet"] = 37
|
49
|
-
UnknownJet: Annotated[int, "UnknownJet"] = 38
|
50
|
-
|
51
|
-
|
52
|
-
# https://gitlab.cern.ch/atlas/athena/-/blob/74f43ff0910edb2a2bd3778880ccbdad648dc037/Generators/TruthUtils/TruthUtils/TruthClasses.h#L51-103
|
53
|
-
class ParticleOrigin(IntEnum):
|
54
|
-
NonDefined: Annotated[int, "NonDefined"] = 0
|
55
|
-
SingleElec: Annotated[int, "SingleElec"] = 1
|
56
|
-
SingleMuon: Annotated[int, "SingleMuon"] = 2
|
57
|
-
SinglePhot: Annotated[int, "SinglePhot"] = 3
|
58
|
-
SingleTau: Annotated[int, "SingleTau"] = 4
|
59
|
-
PhotonConv: Annotated[int, "PhotonConv"] = 5
|
60
|
-
DalitzDec: Annotated[int, "DalitzDec"] = 6
|
61
|
-
ElMagProc: Annotated[int, "ElMagProc"] = 7
|
62
|
-
Mu: Annotated[int, "Mu"] = 8
|
63
|
-
TauLep: Annotated[int, "TauLep"] = 9
|
64
|
-
top: Annotated[int, "top"] = 10
|
65
|
-
QuarkWeakDec: Annotated[int, "QuarkWeakDec"] = 11
|
66
|
-
WBoson: Annotated[int, "WBoson"] = 12
|
67
|
-
ZBoson: Annotated[int, "ZBoson"] = 13
|
68
|
-
Higgs: Annotated[int, "Higgs"] = 14
|
69
|
-
HiggsMSSM: Annotated[int, "HiggsMSSM"] = 15
|
70
|
-
HeavyBoson: Annotated[int, "HeavyBoson"] = 16
|
71
|
-
WBosonLRSM: Annotated[int, "WBosonLRSM"] = 17
|
72
|
-
NuREle: Annotated[int, "NuREle"] = 18
|
73
|
-
NuRMu: Annotated[int, "NuRMu"] = 19
|
74
|
-
NuRTau: Annotated[int, "NuRTau"] = 20
|
75
|
-
LQ: Annotated[int, "LQ"] = 21
|
76
|
-
SUSY: Annotated[int, "SUSY"] = 22
|
77
|
-
OtherBSM: Annotated[int, "OtherBSM"] = 46
|
78
|
-
LightMeson: Annotated[int, "LightMeson"] = 23
|
79
|
-
StrangeMeson: Annotated[int, "StrangeMeson"] = 24
|
80
|
-
CharmedMeson: Annotated[int, "CharmedMeson"] = 25
|
81
|
-
BottomMeson: Annotated[int, "BottomMeson"] = 26
|
82
|
-
CCbarMeson: Annotated[int, "CCbarMeson"] = 27
|
83
|
-
JPsi: Annotated[int, "JPsi"] = 28
|
84
|
-
BBbarMeson: Annotated[int, "BBbarMeson"] = 29
|
85
|
-
LightBaryon: Annotated[int, "LightBaryon"] = 30
|
86
|
-
StrangeBaryon: Annotated[int, "StrangeBaryon"] = 31
|
87
|
-
CharmedBaryon: Annotated[int, "CharmedBaryon"] = 32
|
88
|
-
BottomBaryon: Annotated[int, "BottomBaryon"] = 33
|
89
|
-
PionDecay: Annotated[int, "PionDecay"] = 34
|
90
|
-
KaonDecay: Annotated[int, "KaonDecay"] = 35
|
91
|
-
BremPhot: Annotated[int, "BremPhot"] = 36
|
92
|
-
PromptPhot: Annotated[int, "PromptPhot"] = 37
|
93
|
-
UndrPhot: Annotated[int, "UndrPhot"] = 38
|
94
|
-
ISRPhot: Annotated[int, "ISRPhot"] = 39
|
95
|
-
FSRPhot: Annotated[int, "FSRPhot"] = 40
|
96
|
-
NucReact: Annotated[int, "NucReact"] = 41
|
97
|
-
PiZero: Annotated[int, "PiZero"] = 42
|
98
|
-
DiBoson: Annotated[int, "DiBoson"] = 43
|
99
|
-
ZorHeavyBoson: Annotated[int, "ZorHeavyBoson"] = 44
|
100
|
-
MultiBoson: Annotated[int, "MultiBoson"] = 47
|
101
|
-
QCD: Annotated[int, "QCD"] = 45
|
102
|
-
|
103
|
-
|
104
|
-
# https://twiki.cern.ch/twiki/bin/viewauth/AtlasProtected/EGammaIdentificationRun2#Photon_isEM_word
|
105
|
-
class PhotonID(IntEnum):
|
106
|
-
Rhad: Annotated[int, "ClusterHadronicLeakage_Photon"] = 10
|
107
|
-
E277: Annotated[int, "ClusterMiddleEnergy_Photon"] = 11
|
108
|
-
Reta: Annotated[int, "ClusterMiddleEratio37_Photon"] = 12
|
109
|
-
Rphi: Annotated[int, "ClusterMiddleEratio33_Photon"] = 13
|
110
|
-
Weta2: Annotated[int, "ClusterMiddleWidth_Photon"] = 14
|
111
|
-
f1: Annotated[int, "ClusterStripsEratio_Photon"] = 15
|
112
|
-
DeltaE: Annotated[int, "ClusterStripsDeltaE_Photon"] = 17
|
113
|
-
Wstot: Annotated[int, "ClusterStripsWtot_Photon"] = 18
|
114
|
-
fside: Annotated[int, "ClusterStripsFracm_Photon"] = 19
|
115
|
-
Ws3: Annotated[int, "ClusterStripsWeta1c_Photon"] = 20
|
116
|
-
ERatio: Annotated[int, "ClusterStripsDEmaxs1_Photon"] = 21
|
@@ -1,181 +0,0 @@
|
|
1
|
-
"""Mixins for the Ntuple schema"""
|
2
|
-
|
3
|
-
from __future__ import annotations
|
4
|
-
|
5
|
-
from functools import reduce
|
6
|
-
from operator import ior
|
7
|
-
|
8
|
-
import awkward
|
9
|
-
from coffea.nanoevents.methods import base, candidate, vector
|
10
|
-
from dask_awkward import dask_method
|
11
|
-
|
12
|
-
from atlas_schema.enums import PhotonID
|
13
|
-
from atlas_schema.typing_compat import Behavior
|
14
|
-
|
15
|
-
behavior: Behavior = {}
|
16
|
-
behavior.update(base.behavior)
|
17
|
-
# vector behavior is included in candidate behavior
|
18
|
-
behavior.update(candidate.behavior)
|
19
|
-
|
20
|
-
|
21
|
-
class NtupleEvents(behavior["NanoEvents"]): # type: ignore[misc, valid-type, name-defined]
|
22
|
-
def __repr__(self):
|
23
|
-
return f"<event {getattr(self,'runNumber','??')}:\
|
24
|
-
{getattr(self,'eventNumber','??')}:\
|
25
|
-
{getattr(self,'mcChannelNumber','??')}>"
|
26
|
-
|
27
|
-
|
28
|
-
behavior["NanoEvents"] = NtupleEvents
|
29
|
-
|
30
|
-
|
31
|
-
def _set_repr_name(classname):
|
32
|
-
def namefcn(_self):
|
33
|
-
return classname
|
34
|
-
|
35
|
-
behavior[("__typestr__", classname)] = classname[0].lower() + classname[1:]
|
36
|
-
behavior[classname].__repr__ = namefcn
|
37
|
-
|
38
|
-
|
39
|
-
@awkward.mixin_class(behavior)
|
40
|
-
class Weight(base.NanoCollection, base.Systematic): ...
|
41
|
-
|
42
|
-
|
43
|
-
_set_repr_name("Weight")
|
44
|
-
|
45
|
-
|
46
|
-
@awkward.mixin_class(behavior)
|
47
|
-
class Pass(base.NanoCollection, base.Systematic): ...
|
48
|
-
|
49
|
-
|
50
|
-
_set_repr_name("Pass")
|
51
|
-
|
52
|
-
|
53
|
-
@awkward.mixin_class(behavior)
|
54
|
-
class Particle(vector.PtEtaPhiMLorentzVector):
|
55
|
-
"""Generic particle collection that has Lorentz vector properties
|
56
|
-
|
57
|
-
Also handles the following additional branches:
|
58
|
-
- '{obj}_select'
|
59
|
-
"""
|
60
|
-
|
61
|
-
@property
|
62
|
-
def mass(self):
|
63
|
-
r"""Invariant mass (+, -, -, -)
|
64
|
-
|
65
|
-
:math:`\sqrt{t^2-x^2-y^2-z^2}`
|
66
|
-
"""
|
67
|
-
return self["mass"] / 1.0e3
|
68
|
-
|
69
|
-
@dask_method
|
70
|
-
def passes(self, name):
|
71
|
-
return self[f"select_{name}"] == 1
|
72
|
-
|
73
|
-
@passes.dask
|
74
|
-
def passes(self, dask_array, name):
|
75
|
-
return dask_array[f"select_{name}"] == 1
|
76
|
-
|
77
|
-
# NB: fields with the name 'pt' take precedence over this
|
78
|
-
# @dask_property
|
79
|
-
# def pt(self):
|
80
|
-
# print('inside non-dask prop')
|
81
|
-
# return self["pt_NOSYS"]
|
82
|
-
|
83
|
-
# @pt.dask
|
84
|
-
# def pt(self, dask_array):
|
85
|
-
# branch = 'pt'
|
86
|
-
# print('inside dask prop')
|
87
|
-
# variation = dask_array._events().metadata.get("systematic", "NOSYS")
|
88
|
-
# with contextlib.suppress(Exception):
|
89
|
-
# return dask_array[f"{branch}_{variation}"]
|
90
|
-
|
91
|
-
# if variation != "NOSYS":
|
92
|
-
# with contextlib.suppress(Exception):
|
93
|
-
# return dask_array[f"{branch}_NOSYS"]
|
94
|
-
|
95
|
-
# return dask_array[branch]
|
96
|
-
|
97
|
-
|
98
|
-
_set_repr_name("Particle")
|
99
|
-
|
100
|
-
|
101
|
-
@awkward.mixin_class(behavior)
|
102
|
-
class MasslessParticle(Particle, base.NanoCollection):
|
103
|
-
@property
|
104
|
-
def mass(self):
|
105
|
-
r"""Invariant mass (+, -, -, -)
|
106
|
-
|
107
|
-
:math:`\sqrt{t^2-x^2-y^2-z^2}`
|
108
|
-
"""
|
109
|
-
return 0.0 * self.pt
|
110
|
-
|
111
|
-
|
112
|
-
_set_repr_name("MasslessParticle")
|
113
|
-
|
114
|
-
|
115
|
-
@awkward.mixin_class(behavior)
|
116
|
-
class MissingET(MasslessParticle, base.NanoCollection, base.Systematic):
|
117
|
-
@property
|
118
|
-
def pt(self):
|
119
|
-
"""Alias for `r`"""
|
120
|
-
return self["met"] / 1.0e3
|
121
|
-
|
122
|
-
@property
|
123
|
-
def eta(self):
|
124
|
-
r"""Pseudorapidity
|
125
|
-
|
126
|
-
:math:`-\ln\tan(\theta/2) = \text{arcsinh}(z/r)`
|
127
|
-
"""
|
128
|
-
return 0.0 * self.pt
|
129
|
-
|
130
|
-
|
131
|
-
_set_repr_name("MissingET")
|
132
|
-
|
133
|
-
|
134
|
-
@awkward.mixin_class(behavior)
|
135
|
-
class Photon(MasslessParticle, base.NanoCollection, base.Systematic):
|
136
|
-
@property
|
137
|
-
def isEM(self):
|
138
|
-
return self.isEM_syst.NOSYS == 0
|
139
|
-
|
140
|
-
def pass_isEM(self, words: list[PhotonID]):
|
141
|
-
# 0 is pass, 1 is fail
|
142
|
-
return (
|
143
|
-
self.isEM_syst.NOSYS & reduce(ior, (1 << word.value for word in words))
|
144
|
-
) == 0
|
145
|
-
|
146
|
-
|
147
|
-
_set_repr_name("Photon")
|
148
|
-
|
149
|
-
|
150
|
-
@awkward.mixin_class(behavior)
|
151
|
-
class Electron(MasslessParticle, base.NanoCollection, base.Systematic): ...
|
152
|
-
|
153
|
-
|
154
|
-
_set_repr_name("Electron")
|
155
|
-
|
156
|
-
|
157
|
-
@awkward.mixin_class(behavior)
|
158
|
-
class Muon(MasslessParticle, base.NanoCollection, base.Systematic): ...
|
159
|
-
|
160
|
-
|
161
|
-
_set_repr_name("Muon")
|
162
|
-
|
163
|
-
|
164
|
-
@awkward.mixin_class(behavior)
|
165
|
-
class Jet(Particle, base.NanoCollection, base.Systematic): ...
|
166
|
-
|
167
|
-
|
168
|
-
_set_repr_name("Jet")
|
169
|
-
|
170
|
-
|
171
|
-
__all__ = [
|
172
|
-
"NtupleEvents",
|
173
|
-
"Weight",
|
174
|
-
"Pass",
|
175
|
-
"MissingET",
|
176
|
-
"Particle",
|
177
|
-
"Photon",
|
178
|
-
"Electron",
|
179
|
-
"Muon",
|
180
|
-
"Jet",
|
181
|
-
]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|