00001
00002
00003
00004
00005
00006
00007
00008 class PhysicsModel:
00009 def __init__(self):
00010 pass
00011 def setModelBuilder(self, modelBuilder):
00012 "Connect to the ModelBuilder to get workspace, datacard and options. Should not be overloaded."
00013 self.modelBuilder = modelBuilder
00014 self.DC = modelBuilder.DC
00015 self.options = modelBuilder.options
00016 def setPhysicsOptions(self,physOptions):
00017 "Receive a list of strings with the physics options from command line"
00018 pass
00019 def doParametersOfInterest(self):
00020 """Create POI and other parameters, and define the POI set."""
00021
00022 self.modelBuilder.doVar("r[0,20]");
00023 self.modelBuilder.doSet("POI","r")
00024
00025 if self.options.mass != 0:
00026 if self.modelBuilder.out.var("MH"):
00027 self.modelBuilder.out.var("MH").removeRange()
00028 self.modelBuilder.out.var("MH").setVal(self.options.mass)
00029 else:
00030 self.modelBuilder.doVar("MH[%g]" % self.options.mass);
00031 def preProcessNuisances(self,nuisances):
00032 "receive the usual list of (name,nofloat,pdf,args,errline) to be edited"
00033 pass
00034 def getYieldScale(self,bin,process):
00035 "Return the name of a RooAbsReal to scale this yield by or the two special values 1 and 0 (don't scale, and set to zero)"
00036 return "r" if self.DC.isSignal[process] else 1;
00037
00038
00039
00040
00041 class SMLikeHiggsModel(PhysicsModel):
00042 def getHiggsSignalYieldScale(self, production, decay, energy):
00043 raise RuntimeError, "Not implemented"
00044 def getYieldScale(self,bin,process):
00045 "Split in production and decay, and call getHiggsSignalYieldScale; return 1 for backgrounds "
00046 if not self.DC.isSignal[process]: return 1
00047 processSource = process
00048 decaySource = self.options.fileName+":"+bin
00049 if "_" in process: (processSource, decaySource) = process.split("_")
00050 if processSource not in ["ggH", "qqH", "VH", "WH", "ZH", "ttH"]:
00051 raise RuntimeError, "Validation Error: signal process %s not among the allowed ones." % processSource
00052
00053 foundDecay = None
00054 for D in [ "hww", "hzz", "hgg", "htt", "hbb" ]:
00055 if D in decaySource:
00056 if foundDecay: raise RuntimeError, "Validation Error: decay string %s contains multiple known decay names" % decaySource
00057 foundDecay = D
00058 if not foundDecay: raise RuntimeError, "Validation Error: decay string %s does not contain any known decay name" % decaySource
00059
00060 foundEnergy = None
00061 for D in [ '7TeV', '8TeV', '14TeV' ]:
00062 if D in decaySource:
00063 if foundEnergy: raise RuntimeError, "Validation Error: decay string %s contains multiple known energies" % decaySource
00064 foundEnergy = D
00065 if not foundEnergy:
00066 foundEnergy = '7TeV'
00067 print "Warning: decay string %s does not contain any known energy, assuming %s" % (decaySource, foundEnergy)
00068
00069 return self.getHiggsSignalYieldScale(processSource, foundDecay, foundEnergy)
00070
00071 class StrictSMLikeHiggsModel(SMLikeHiggsModel):
00072 "Doesn't do anything more, but validates that the signal process names are correct"
00073 def getHiggsSignalYieldScale(self,production,decay, energy):
00074 return "r"
00075
00076 class FloatingHiggsMass(SMLikeHiggsModel):
00077 "assume the SM coupling but let the Higgs mass to float"
00078 def __init__(self):
00079 SMLikeHiggsModel.__init__(self)
00080 self.mHRange = ['115','135']
00081 def setPhysicsOptions(self,physOptions):
00082 for po in physOptions:
00083 if po.startswith("higgsMassRange="):
00084 self.mHRange = po.replace("higgsMassRange=","").split(",")
00085 print 'The Higgs mass range:', self.mHRange
00086 if len(self.mHRange) != 2:
00087 raise RuntimeError, "Higgs mass range definition requires two extrema"
00088 elif float(self.mHRange[0]) >= float(self.mHRange[1]):
00089 raise RuntimeError, "Extrama for Higgs mass range defined with inverterd order. Second must be larger the first"
00090 def doParametersOfInterest(self):
00091 """Create POI out of signal strength and MH"""
00092
00093 self.modelBuilder.doVar("r[1,0,20]")
00094 if self.modelBuilder.out.var("MH"):
00095 self.modelBuilder.out.var("MH").setRange(float(self.mHRange[0]),float(self.mHRange[1]))
00096 self.modelBuilder.out.var("MH").setConstant(False)
00097 else:
00098 self.modelBuilder.doVar("MH[%s,%s]" % (self.mHRange[0],self.mHRange[1]))
00099 self.modelBuilder.doSet("POI",'r,MH')
00100 def getHiggsSignalYieldScale(self,production,decay, energy):
00101 return "r"
00102
00103
00104 class FloatingXSHiggs(SMLikeHiggsModel):
00105 "Float independently ggH and qqH cross sections"
00106 def __init__(self):
00107 SMLikeHiggsModel.__init__(self)
00108 self.modes = [ "ggH", "qqH", "VH", "ttH" ]
00109 self.mHRange = []
00110 def setPhysicsOptions(self,physOptions):
00111 for po in physOptions:
00112 if po.startswith("modes="): self.modes = po.replace("modes=","").split(",")
00113 if po.startswith("higgsMassRange="):
00114 self.mHRange = po.replace("higgsMassRange=","").split(",")
00115 if len(self.mHRange) != 2:
00116 raise RuntimeError, "Higgs mass range definition requires two extrema"
00117 elif float(self.mHRange[0]) >= float(self.mHRange[1]):
00118 raise RuntimeError, "Extrema for Higgs mass range defined with inverterd order. Second must be larger the first"
00119 def doParametersOfInterest(self):
00120 """Create POI and other parameters, and define the POI set."""
00121
00122 if "ggH" in self.modes: self.modelBuilder.doVar("r_ggH[1,0,5]");
00123 if "qqH" in self.modes: self.modelBuilder.doVar("r_qqH[1,0,20]");
00124 if "VH" in self.modes: self.modelBuilder.doVar("r_VH[1,0,20]");
00125 if "ttH" in self.modes: self.modelBuilder.doVar("r_ttH[1,0,20]");
00126 poi = ",".join(["r_"+m for m in self.modes])
00127
00128 if self.modelBuilder.out.var("MH"):
00129 if len(self.mHRange):
00130 print 'MH will be left floating within', self.mHRange[0], 'and', self.mHRange[1]
00131 self.modelBuilder.out.var("MH").setRange(float(self.mHRange[0]),float(self.mHRange[1]))
00132 self.modelBuilder.out.var("MH").setConstant(False)
00133 poi+=',MH'
00134 else:
00135 print 'MH will be assumed to be', self.options.mass
00136 self.modelBuilder.out.var("MH").removeRange()
00137 self.modelBuilder.out.var("MH").setVal(self.options.mass)
00138 else:
00139 if len(self.mHRange):
00140 print 'MH will be left floating within', self.mHRange[0], 'and', self.mHRange[1]
00141 self.modelBuilder.doVar("MH[%s,%s]" % (self.mHRange[0],self.mHRange[1]))
00142 poi+=',MH'
00143 else:
00144 print 'MH (not there before) will be assumed to be', self.options.mass
00145 self.modelBuilder.doVar("MH[%g]" % self.options.mass)
00146 self.modelBuilder.doSet("POI",poi)
00147 def getHiggsSignalYieldScale(self,production,decay, energy):
00148 if production == "ggH": return ("r_ggH" if "ggH" in self.modes else 1)
00149 if production == "qqH": return ("r_qqH" if "qqH" in self.modes else 1)
00150 if production == "ttH": return ("r_ttH" if "ttH" in self.modes else 1)
00151 if production in [ "WH", "ZH", "VH" ]: return ("r_VH" if "VH" in self.modes else 1)
00152 raise RuntimeError, "Unknown production mode '%s'" % production
00153
00154 class FloatingBRHiggs(SMLikeHiggsModel):
00155 "Float independently ggH and qqH cross sections"
00156 def __init__(self):
00157 SMLikeHiggsModel.__init__(self)
00158 self.modes = [ "hbb", "htt", "hgg", "hww", "hzz" ]
00159 self.mHRange = []
00160 def setPhysicsOptions(self,physOptions):
00161 for po in physOptions:
00162 if po.startswith("modes="): self.modes = po.replace("modes=","").split(",")
00163 if po.startswith("higgsMassRange="):
00164 self.mHRange = po.replace("higgsMassRange=","").split(",")
00165 if len(self.mHRange) != 2:
00166 raise RuntimeError, "Higgs mass range definition requires two extrema"
00167 elif float(self.mHRange[0]) >= float(self.mHRange[1]):
00168 raise RuntimeError, "Extrema for Higgs mass range defined with inverterd order. Second must be larger the first"
00169 def doParametersOfInterest(self):
00170 """Create POI and other parameters, and define the POI set."""
00171
00172 for m in self.modes:
00173 self.modelBuilder.doVar("r_%s[1,0,10]" % m);
00174 poi = ",".join(["r_"+m for m in self.modes])
00175
00176 if self.modelBuilder.out.var("MH"):
00177 if len(self.mHRange):
00178 print 'MH will be left floating within', self.mHRange[0], 'and', self.mHRange[1]
00179 self.modelBuilder.out.var("MH").setRange(float(self.mHRange[0]),float(self.mHRange[1]))
00180 self.modelBuilder.out.var("MH").setConstant(False)
00181 poi+=',MH'
00182 else:
00183 print 'MH will be assumed to be', self.options.mass
00184 self.modelBuilder.out.var("MH").removeRange()
00185 self.modelBuilder.out.var("MH").setVal(self.options.mass)
00186 else:
00187 if len(self.mHRange):
00188 print 'MH will be left floating within', self.mHRange[0], 'and', self.mHRange[1]
00189 self.modelBuilder.doVar("MH[%s,%s]" % (self.mHRange[0],self.mHRange[1]))
00190 poi+=',MH'
00191 else:
00192 print 'MH (not there before) will be assumed to be', self.options.mass
00193 self.modelBuilder.doVar("MH[%g]" % self.options.mass)
00194 self.modelBuilder.doSet("POI",poi)
00195 def getHiggsSignalYieldScale(self,production,decay, energy):
00196 if decay in self.modes:
00197 return "r_"+decay
00198 elif decay not in [ "hbb", "htt", "hgg", "hww", "hzz" ]:
00199 raise RuntimeError, "Unknown decay mode '%s'" % decay
00200
00201 defaultModel = PhysicsModel()
00202 strictSMLikeHiggs = StrictSMLikeHiggsModel()
00203 floatingXSHiggs = FloatingXSHiggs()
00204 floatingBRHiggs = FloatingBRHiggs()
00205 floatingHiggsMass = FloatingHiggsMass()