-
Notifications
You must be signed in to change notification settings - Fork 429
Expand file tree
/
Copy pathHiggsJPC.py
More file actions
177 lines (157 loc) · 7.52 KB
/
HiggsJPC.py
File metadata and controls
177 lines (157 loc) · 7.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
from HiggsAnalysis.CombinedLimit.PhysicsModel import *
### This base class implements signal yields by production and decay mode
### Specific models can be obtained redefining getHiggsSignalYieldScale
class TwoHypotesisHiggs(PhysicsModel):
def __init__(self):
self.mHRange = []
self.muAsPOI = False
self.muFloating = False
self.fqqIncluded = False
self.fqqFloating = False
self.poiMap = []
self.pois = {}
self.verbose = False
self.altSignal = "ALT"
def setModelBuilder(self, modelBuilder):
PhysicsModel.setModelBuilder(self, modelBuilder)
self.modelBuilder.doModelBOnly = False
def getYieldScale(self, bin, process):
"Split in production and decay, and call getHiggsSignalYieldScale; return 1 for backgrounds"
if not self.DC.isSignal[process]:
return 1
isAlt = self.altSignal in process
if self.pois:
target = "%(bin)s/%(process)s" % locals()
scale = 1
for p, l in self.poiMap:
for el in l:
if re.match(el, target):
scale = p + self.sigNorms[isAlt]
print("Will scale ", target, " by ", scale)
return scale
elif self.fqqIncluded:
ret = self.sigNorms[isAlt]
if isAlt:
ret += self.sigNormsqqH["qqbarH" in process]
print("Process ", process, " will get scaled by ", ret)
return ret
else:
print("Process ", process, " will get norm ", self.sigNorms[isAlt])
return self.sigNorms[isAlt]
def setPhysicsOptions(self, physOptions):
for po in physOptions:
if po == "fqqIncluded":
print("Will consider fqq = fraction of qqH in Alt signal (signal strength will be left floating)")
# Here alsways setting muFloating if fqq in model, should this be kept optional?
self.fqqIncluded = True
self.muFloating = True
if po == "fqqFloating":
self.fqqIncluded = True
self.fqqFloating = True
self.fqqRange = "0.", "1."
self.muFloating = True
if po.startswith("fqqRange="):
self.fqqIncluded = True
self.fqqFloating = True
self.muFloating = True
self.fqqRange = po.replace("fqqRange=", "").split(",")
if len(self.fqqRange) != 2:
raise RuntimeError("fqq range definition requires two extrema")
elif float(self.fqqRange[0]) >= float(self.fqqRange[1]):
raise RuntimeError("Extrema for fqq range defined with inverterd order. Second must be larger than the first")
if po == "muAsPOI":
print("Will consider the signal strength as a parameter of interest")
self.muAsPOI = True
self.muFloating = True
if po == "muFloating":
print(
"Will consider the signal strength as a floating parameter (as a parameter of interest if --PO muAsPOI is specified, as a nuisance otherwise)"
)
self.muFloating = True
if po.startswith("altSignal="):
self.altSignal = po.split(",")[1]
if po.startswith("higgsMassRange="):
self.mHRange = po.replace("higgsMassRange=", "").split(",")
if len(self.mHRange) != 2:
raise RuntimeError("Higgs mass range definition requires two extrema")
elif float(self.mHRange[0]) >= float(self.mHRange[1]):
raise RuntimeError("Extrema for Higgs mass range defined with inverterd order. Second must be larger than the first")
if po.startswith("verbose"):
self.verbose = True
if po.startswith("map="):
self.muFloating = True
maplist, poi = po.replace("map=", "").split(":")
maps = maplist.split(",")
poiname = re.sub(r"\[.*", "", poi)
if poiname not in self.pois:
if self.verbose:
print("Will create a var ", poiname, " with factory ", poi)
self.pois[poiname] = poi
if self.verbose:
print("Mapping ", poiname, " to ", maps, " patterns")
self.poiMap.append((poiname, maps))
def doParametersOfInterest(self):
"""Create POI and other parameters, and define the POI set."""
self.modelBuilder.doVar("x[0,0,1]")
poi = "x"
if self.muFloating:
if self.pois:
for pn, pf in self.pois.items():
self.modelBuilder.doVar(pf)
if self.muAsPOI:
print("Treating %(pn)s as a POI" % locals())
poi += "," + pn
self.modelBuilder.factory_('expr::%(pn)s_times_not_x("@0*(1-@1)", %(pn)s, x)' % locals())
self.modelBuilder.factory_('expr::%(pn)s_times_x("@0*@1", %(pn)s, x)' % locals())
self.sigNorms = {True: "_times_x", False: "_times_not_x"}
else:
self.modelBuilder.doVar("r[1,0,4]")
if self.muAsPOI:
print("Treating r as a POI")
poi += ",r"
self.modelBuilder.factory_('expr::r_times_not_x("@0*(1-@1)", r, x)')
self.modelBuilder.factory_('expr::r_times_x("@0*@1", r, x)')
self.sigNorms = {True: "r_times_x", False: "r_times_not_x"}
if self.fqqIncluded:
if self.fqqFloating:
self.modelBuilder.doVar(f"fqq[0,{self.fqqRange[0]},{self.fqqRange[1]}]")
else:
self.modelBuilder.doVar("fqq[0]")
self.modelBuilder.factory_('expr::r_times_x_times_fqq("@0*@1", r_times_x, fqq)')
self.modelBuilder.factory_('expr::r_times_x_times_not_fqq("@0*(1-@1)", r_times_x, fqq)')
self.sigNormsqqH = {True: "_times_fqq", False: "_times_not_fqq"}
else:
self.modelBuilder.factory_('expr::not_x("(1-@0)", x)')
self.sigNorms = {True: "x", False: "not_x"}
if self.modelBuilder.out.var("MH"):
var = self.modelBuilder.out.var("MH")
if len(self.mHRange):
print(
"MH will be left floating within",
self.mHRange[0],
"and",
self.mHRange[1],
)
var.setRange(float(self.mHRange[0]), float(self.mHRange[1]))
var.setConstant(False)
poi += ",MH"
else:
print("MH will be assumed to be", self.options.mass)
var.removeMin()
var.removeMax()
var.setVal(self.options.mass)
else:
if len(self.mHRange):
print(
"MH will be left floating within",
self.mHRange[0],
"and",
self.mHRange[1],
)
self.modelBuilder.doVar(f"MH[{self.mHRange[0]},{self.mHRange[1]}]")
poi += ",MH"
else:
print("MH (not there before) will be assumed to be", self.options.mass)
self.modelBuilder.doVar("MH[%g]" % self.options.mass)
self.modelBuilder.doSet("POI", poi)
twoHypothesisHiggs = TwoHypotesisHiggs()