JHUGen MELA  v2.4.1
Matrix element calculations as used in JHUGen. MELA is an important tool that was used for the Higgs boson discovery and for precise measurements of its structure and interactions. Please see the website https://spin.pha.jhu.edu/ and papers cited there for more details, and kindly cite those papers when using this code.
lhefile.py
Go to the documentation of this file.
1 import abc
2 import collections
3 import re
4 
5 if __name__ == "__main__":
6  import argparse, itertools, sys, unittest
7  from mela import TVar
8  parser = argparse.ArgumentParser()
9  parser.add_argument('--lhefile-hwithdecay')
10  parser.add_argument('--lhefile-jhugenvbfvh')
11  parser.add_argument('--lhefile-jhugentth')
12  parser.add_argument('unittest_args', nargs='*')
13  args = parser.parse_args()
14 
15 import ROOT
16 
17 from mela import Mela, SimpleParticle_t, SimpleParticleCollection_t
18 
19 InputEvent = collections.namedtuple("InputEvent", "daughters associated mothers isgen")
20 
21 class LHEEvent(object):
22  __metaclass__ = abc.ABCMeta
23  def __init__(self, event, isgen):
24  lines = event.split("\n")
25 
26  self.weights = {}
27  for line in lines:
28  if "<wgt" not in line: continue
29  match = re.match("<wgt id='(.*)'>([0-9+Ee.-]*)</wgt>", line)
30  if match: self.weights[match.group(1)] = float(match.group(2))
31 
32  lines = [line for line in lines if not ("<" in line or ">" in line or not line.split("#")[0].strip())]
33  nparticles, _, weight, _, _, _ = lines[0].split()
34 
35  nparticles = int(nparticles)
36  self.weight = float(weight)
37  if nparticles != len(lines)-1:
38  raise ValueError("Wrong number of particles! Should be {}, have {}".format(nparticles, len(lines)-1))
39 
40  daughters, associated, mothers = (SimpleParticleCollection_t(_) for _ in self.extracteventparticles(lines[1:], isgen))
41  if not list(mothers): mothers = None
42  self.daughters, self.associated, self.mothers, self.isgen = self.inputevent = InputEvent(daughters, associated, mothers, isgen)
43 
44  @abc.abstractmethod
45  def extracteventparticles(cls, lines, isgen): "has to be a classmethod that returns daughters, associated, mothers"
46 
47  def __iter__(self):
48  return iter(self.inputevent)
49 
51  @classmethod
52  def extracteventparticles(cls, lines, isgen):
53  daughters, mothers, associated = [], [], []
54  ids = [None]
55  mother1s = [None]
56  mother2s = [None]
57  for line in lines:
58  id, status, mother1, mother2 = (int(_) for _ in line.split()[0:4])
59  ids.append(id)
60  if (1 <= abs(id) <= 6 or abs(id) == 21) and not isgen:
61  line = line.replace(str(id), "0", 1) #replace the first instance of the jet id with 0, which means unknown jet
62  mother1s.append(mother1)
63  mother2s.append(mother2)
64  if status == -1:
65  mothers.append(line)
66  elif status == 1 and (1 <= abs(id) <= 6 or 11 <= abs(id) <= 16 or abs(id) in (21, 22)):
67  while True:
68  if mother1 != mother2 or mother1 is None:
69  associated.append(line)
70  break
71  if ids[mother1] in (25, 39):
72  daughters.append(line)
73  break
74  mother2 = mother2s[mother1]
75  mother1 = mother1s[mother1]
76 
77  if not isgen: mothers = None
78  return daughters, associated, mothers
79 
81  @classmethod
82  def extracteventparticles(cls, lines, isgen):
83  daughters, mothers, associated = [], [], []
84  for line in lines:
85  id, status, mother1, mother2 = (int(_) for _ in line.split()[0:4])
86  if (1 <= abs(id) <= 6 or abs(id) == 21) and not isgen:
87  line = line.replace(str(id), "0", 1) #replace the first instance of the jet id with 0, which means unknown jet
88  if status == -1:
89  mothers.append(line)
90  if id == 25:
91  if status != 1:
92  raise ValueError("Higgs has status {}, expected it to be 1\n\n".format(status) + "\n".join(lines))
93  daughters.append(line)
94  if abs(id) in (0, 1, 2, 3, 4, 5, 11, 12, 13, 14, 15, 16, 21) and status == 1:
95  associated.append(line)
96 
97  if len(daughters) != 1:
98  raise ValueError("More than one H in the event??\n\n"+"\n".join(lines))
99  if cls.nassociatedparticles is not None and len(associated) != cls.nassociatedparticles:
100  raise ValueError("Wrong number of associated particles (expected {}, found {})\n\n".format(cls.nassociatedparticles, len(associated))+"\n".join(lines))
101  if len(mothers) != 2:
102  raise ValueError("{} mothers in the event??\n\n".format(len(mothers))+"\n".join(lines))
103 
104  if not isgen: mothers = None
105  return daughters, associated, mothers
106 
107  nassociatedparticles = None
108 
110  nassociatedparticles = 2
111 
113  nassociatedparticles = 6
114 
116  @classmethod
117  def extracteventparticles(cls, lines, isgen):
118  daughters, mothers, associated = [], [], []
119  for line in lines:
120  id, status, mother1, mother2 = (int(_) for _ in line.split()[0:4])
121  if (1 <= abs(id) <= 6 or abs(id) == 21) and not isgen:
122  line = line.replace(str(id), "0", 1) #replace the first instance of the jet id with 0, which means unknown jet
123  if status == -1:
124  mothers.append(line)
125  if abs(id) in (11, 12, 13, 14, 15, 16) and status == 1:
126  daughters.append(line)
127  if abs(id) in (0, 1, 2, 3, 4, 5, 21) and status == 1:
128  associated.append(line)
129 
130  if len(daughters) != 4:
131  raise ValueError("Wrong number of daughters (expected {}, found {})\n\n".format(4, len(daughters))+"\n".join(lines))
132  if cls.nassociatedparticles is not None and len(associated) != cls.nassociatedparticles:
133  raise ValueError("Wrong number of associated particles (expected {}, found {})\n\n".format(cls.nassociatedparticles, len(associated))+"\n".join(lines))
134  if len(mothers) != 2:
135  raise ValueError("{} mothers in the event??\n\n".format(len(mothers))+"\n".join(lines))
136 
137  if not isgen: mothers = None
138  return daughters, associated, mothers
139 
140  nassociatedparticles = None
141 
142 class LHEFileBase(object):
143  """
144  Simple class to iterate through an LHE file and calculate probabilities for each event
145  Example usage:
146  h1 = ROOT.TH1F("costheta1", "costheta1", 100, -1, 1)
147  h2 = ROOT.TH1F("D_0minus", "D_0minus", 100, 0, 1)
148  with LHEFile("filename.lhe") as f:
149  for event in f: #event becomes the mela object
150  h1.Fill(event.computeDecayAngles().costheta1)
151  event.ghz1 = 1
152  p0plus = event.computeP()
153  event.ghz4 = 1
154  p0minus = event.computeP()
155  h2.Fill(p0plus / (p0plus + p0minus))
156  """
157  __metaclass__ = abc.ABCMeta
158 
159  __melas = {}
160 
161  def __init__(self, filename, *melaargs, **kwargs):
162  self.isgen = kwargs.pop("isgen", True)
163  reusemela = kwargs.pop("reusemela", False)
164  gzip = kwargs.pop("gzip", False)
165  if kwargs: raise ValueError("Unknown kwargs: " + ", ".join(kwargs))
166  self.filename = filename
167  if reusemela and melaargs in self.__melas:
168  self.mela = self.__melas[melaargs]
169  else:
170  self.__melas[melaargs] = self.mela = Mela(*melaargs)
171 
172  openfunction = open
173  if gzip: from gzip import GzipFile as openfunction
174  self.f = openfunction(self.filename)
175  def __enter__(self, *args, **kwargs):
176  self.f.__enter__(*args, **kwargs)
177  return self
178  def __exit__(self, *args, **kwargs):
179  return self.f.__exit__(*args, **kwargs)
180 
181  def __iter__(self):
182  event = ""
183  for linenumber, line in enumerate(self.f, start=1):
184  if "<event>" not in line and not event:
185  continue
186  event += line
187  if "</event>" in line:
188  try:
189  self._setInputEvent(event)
190  yield self
191  event = ""
192  except GeneratorExit:
193  raise
194  except:
195  print("On line", linenumber)
196  raise
197  finally:
198  try:
199  self.mela.resetInputEvent()
200  except:
201  pass
202 
203  def _setInputEvent(self, event):
204  lheevent = self.lheeventclass(event, self.isgen)
205  self.daughters = lheevent.daughters
206  self.associated = lheevent.associated
207  self.mothers = lheevent.mothers
208  self.weight = lheevent.weight
209  self.weights = lheevent.weights
210  self.setInputEvent(*lheevent)
211 
212  @classmethod
214  return "filename", "f", "mela", "isgen", "daughters", "mothers", "associated", "weight", "weights"
215 
216  def __getattr__(self, attr):
217  if attr == "mela": raise RuntimeError("Something is wrong, trying to access mela before it's created")
218  return getattr(self.mela, attr)
219  def __setattr__(self, attr, value):
220  if attr in self._LHEclassattributes():
221  super(LHEFileBase, self).__setattr__(attr, value)
222  else:
223  setattr(self.mela, attr, value)
224 
226  lheeventclass = LHEEvent_Hwithdecay
228  lheeventclass = LHEEvent_StableHiggs
230  lheeventclass = LHEEvent_JHUGenVBFVH
232  lheeventclass = LHEEvent_JHUGenttH
234  lheeventclass = LHEEvent_Offshell4l
235 
236 if __name__ == '__main__':
237  class TestLHEFiles(unittest.TestCase):
238  @unittest.skipUnless(args.lhefile_hwithdecay, "needs --lhefile-hwithdecay argument")
239  def testHwithDecay(self):
240  with LHEFile_Hwithdecay(args.lhefile_hwithdecay) as f:
241  for event, i in itertools.izip(f, range(10)):
242  event.ghz1 = 1
243  event.setProcess(TVar.SelfDefine_spin0, TVar.JHUGen, TVar.ZZINDEPENDENT)
244  prob = event.computeP()
245  self.assertNotEqual(prob, 0)
246  print(prob, event.computeDecayAngles())
247 
248  @unittest.skipUnless(args.lhefile_jhugenvbfvh, "needs --lhefile-jhugenvbfvh argument")
249  def testJHUGenVBFVH(self):
250  with LHEFile_JHUGenVBFVH(args.lhefile_jhugenvbfvh, isgen=False) as f:
251  for event, i in itertools.izip(f, range(10)):
252  event.ghz1 = 1
253  if any(11 <= abs(p.first) <= 16 for p in event.associated):
254  if sum(p.first for p in event.associated) == 0:
255  VHprocess = TVar.Lep_ZH
256  event.setProcess(TVar.SelfDefine_spin0, TVar.JHUGen, TVar.Lep_ZH)
257  else:
258  VHprocess = TVar.Lep_WH
259  event.setProcess(TVar.SelfDefine_spin0, TVar.JHUGen, TVar.Lep_WH)
260  else:
261  VHprocess = TVar.Had_ZH
262  event.setProcess(TVar.SelfDefine_spin0, TVar.JHUGen, TVar.JJVBF)
263  prob = event.computeProdP()
264  self.assertNotEqual(prob, 0)
265  print(prob, event.computeVBFAngles(), event.computeVHAngles(VHprocess))
266 
267  @unittest.skipUnless(args.lhefile_jhugentth, "needs --lhefile-jhugentth argument")
268  def testJHUGenttH(self):
269  with LHEFile_JHUGenttH(args.lhefile_jhugentth) as f:
270  for event, i in itertools.izip(f, range(10)):
271  pass
272 
273  unittest.main(argv=[sys.argv[0]]+args.unittest_args)
lhefile.LHEEvent.weights
weights
Definition: lhefile.py:26
lhefile.LHEEvent_Offshell4l.extracteventparticles
def extracteventparticles(cls, lines, isgen)
Definition: lhefile.py:117
lhefile.LHEFileBase.isgen
isgen
Definition: lhefile.py:162
lhefile.LHEFileBase._setInputEvent
def _setInputEvent(self, event)
Definition: lhefile.py:203
lhefile.LHEEvent_StableHiggs.extracteventparticles
def extracteventparticles(cls, lines, isgen)
Definition: lhefile.py:82
lhefile.LHEFileBase.__exit__
def __exit__(self, *args, **kwargs)
Definition: lhefile.py:178
lhefile.LHEFile_JHUGenVBFVH
Definition: lhefile.py:229
lhefile.LHEEvent_Hwithdecay.extracteventparticles
def extracteventparticles(cls, lines, isgen)
Definition: lhefile.py:52
lhefile.LHEEvent_Offshell4l
Definition: lhefile.py:115
lhefile.LHEFileBase.weights
weights
Definition: lhefile.py:209
lhefile.InputEvent
InputEvent
Definition: lhefile.py:19
lhefile.LHEFile_Hwithdecay
Definition: lhefile.py:225
lhefile.TestLHEFiles.testJHUGenttH
def testJHUGenttH(self)
Definition: lhefile.py:268
lhefile.LHEFileBase
Definition: lhefile.py:142
lhefile.LHEEvent.extracteventparticles
def extracteventparticles(cls, lines, isgen)
Definition: lhefile.py:45
lhefile.LHEEvent_Hwithdecay
Definition: lhefile.py:50
lhefile.LHEFileBase.__iter__
def __iter__(self)
Definition: lhefile.py:181
lhefile.LHEFileBase.associated
associated
Definition: lhefile.py:206
lhefile.LHEEvent.isgen
isgen
Definition: lhefile.py:42
lhefile.LHEEvent
Definition: lhefile.py:21
lhefile.LHEEvent.weight
weight
Definition: lhefile.py:36
lhefile.LHEFileBase.filename
filename
Definition: lhefile.py:166
lhefile.LHEFileBase._LHEclassattributes
def _LHEclassattributes(cls)
Definition: lhefile.py:213
lhefile.LHEFileBase.__setattr__
def __setattr__(self, attr, value)
Definition: lhefile.py:219
mela.Mela
Definition: mela.py:49
lhefile.LHEEvent_StableHiggs.nassociatedparticles
nassociatedparticles
Definition: lhefile.py:107
lhefile.LHEEvent_JHUGenVBFVH
Definition: lhefile.py:109
lhefile.LHEEvent_Offshell4l.nassociatedparticles
nassociatedparticles
Definition: lhefile.py:140
testME_all.int
int
Definition: testME_all.py:13
lhefile.LHEFileBase.f
f
Definition: lhefile.py:174
lhefile.LHEFileBase.__init__
def __init__(self, filename, *melaargs, **kwargs)
Definition: lhefile.py:161
lhefile.LHEFileBase.mela
mela
Definition: lhefile.py:168
lhefile.LHEEvent_JHUGenttH
Definition: lhefile.py:112
lhefile.LHEEvent.__init__
def __init__(self, event, isgen)
Definition: lhefile.py:23
lhefile.TestLHEFiles.testHwithDecay
def testHwithDecay(self)
Definition: lhefile.py:239
lhefile.LHEFile_StableHiggs
Definition: lhefile.py:227
lhefile.LHEFile_JHUGenttH
Definition: lhefile.py:231
lhefile.LHEFileBase.weight
weight
Definition: lhefile.py:208
lhefile.LHEEvent.__iter__
def __iter__(self)
Definition: lhefile.py:47
lhefile.LHEFileBase.__melas
dictionary __melas
Definition: lhefile.py:159
lhefile.LHEFileBase.__getattr__
def __getattr__(self, attr)
Definition: lhefile.py:216
lhefile.TestLHEFiles.testJHUGenVBFVH
def testJHUGenVBFVH(self)
Definition: lhefile.py:249
lhefile.LHEFileBase.__enter__
def __enter__(self, *args, **kwargs)
Definition: lhefile.py:175
lhefile.LHEFileBase.mothers
mothers
Definition: lhefile.py:207
lhefile.LHEEvent_StableHiggs
Definition: lhefile.py:80
SimpleParticleCollection_t
std::vector< SimpleParticle_t > SimpleParticleCollection_t
Definition: TVar.hh:25
lhefile.LHEEvent.inputevent
inputevent
Definition: lhefile.py:42
lhefile.LHEFileBase.daughters
daughters
Definition: lhefile.py:205
lhefile.TestLHEFiles
Definition: lhefile.py:237
lhefile.LHEFile_Offshell4l
Definition: lhefile.py:233