CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_8_patch3/src/HiggsAnalysis/CombinedLimit/python/PhysicsModel.py

Go to the documentation of this file.
00001 
00002 ### Class that takes care of building a physics model by combining individual channels and processes together
00003 ### Things that it can do:
00004 ###   - define the parameters of interest (in the default implementation , "r")
00005 ###   - define other constant model parameters (e.g., "MH")
00006 ###   - yields a scaling factor for each pair of bin and process (by default, constant for background and linear in "r" for signal)
00007 ###   - possibly modifies the systematical uncertainties (does nothing by default)
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         # --- Signal Strength as only POI --- 
00022         self.modelBuilder.doVar("r[0,20]");
00023         self.modelBuilder.doSet("POI","r")
00024         # --- Higgs Mass as other parameter ----
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 # do nothing by default
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 ### This base class implements signal yields by production and decay mode
00040 ### Specific models can be obtained redefining getHiggsSignalYieldScale
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 # by default, decay comes from the datacard name or bin label
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' ## To ensure backward compatibility
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) # not using 'super(x,self).__init__' since I don't understand it
00080         self.mHRange = ['115','135'] # default
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         # --- Signal Strength as only POI --- 
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) # not using 'super(x,self).__init__' since I don't understand it
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         # --- Signal Strength as only POI --- 
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         # --- Higgs Mass as other parameter ----
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) # not using 'super(x,self).__init__' since I don't understand it
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         # --- Signal Strength as only POI --- 
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         # --- Higgs Mass as other parameter ----
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()