diff --git a/Fitter/python/AnomalousCouplingEFTNegative.py b/Fitter/python/AnomalousCouplingEFTNegative.py index ede2f41..9bc086d 100644 --- a/Fitter/python/AnomalousCouplingEFTNegative.py +++ b/Fitter/python/AnomalousCouplingEFTNegative.py @@ -1,7 +1,7 @@ from HiggsAnalysis.CombinedLimit.PhysicsModel import * from HiggsAnalysis.CombinedLimit.SMHiggsBuilder import SMHiggsBuilder import ROOT, os -import json +import json # # See derivation and explanation, validation, tests in AN-20-204 @@ -12,7 +12,7 @@ class AnaliticAnomalousCouplingEFTNegative(PhysicsModel): "Float independently cross sections and branching ratios" def __init__(self): - PhysicsModel.__init__(self) + PhysicsModel.__init__(self) # not using 'super(x,self).__init__' since I don't understand it self.mHRange = [] self.poiNames = [] self.alternative = False @@ -45,140 +45,335 @@ def setPhysicsOptions(self,physOptions): """ Handle any physics options specified by the user.""" wcs_list_exists = False for po in physOptions: + 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 the first") + + if po.startswith("eftOperators="): + self.Operators = po.replace("eftOperators=","").split(",") + print(" Operators = ", self.Operators) + self.numOperators = len(self.Operators) + if po.startswith("eftAlternative"): self.alternative = True - raise RuntimeError("Alternative not yet implemented") + + # + # this is needed in the case the complete list of operators is not the one provided above, + # but for some reason, like a new model or a new basis, different or more operators are added. + # There could be also the possibility that one operator is removed from the complete list of operators, + # who knows why ... by it might happen, thus the method to remove it is given hereafter + # + if po.startswith("defineOperators="): + self.Operators = po.replace("defineOperators=","").split(",") + print(" Operators = ", self.Operators) + + if po.startswith("addToOperators="): + toAddOperators = po.replace("addToOperators=","").split(",") + self.Operators.extend ( toAddOperators ) + print(" Operators = ", self.Operators) + + if po.startswith("removeFromOperators="): + toRemoveOperators = po.replace("removeFromOperators=","").split(",") + newlist = [i for i in self.Operators if i not in toRemoveOperators] + self.Operators = newlist + print(" Operators = ", self.Operators) + if po.startswith("selectedWCs="): selected_wcs_fpath = po.replace("selectedWCs=","").strip() wcs_list_exists = True - if po.startswith("verbose"): - self.verbose = True - + assert wcs_list_exists, "selectedWCs.txt not provided. Provide the full path using the command line option `--PO selectedWCs=PATH_TO_DIR`." self.loadOperators(selected_wcs_fpath) +# +# standard, not touched (end) +# + + +# +# Define parameters of interest +# + def doParametersOfInterest(self): - """ Create POI and other parameters, and define the POI set.""" + """Create POI and other parameters, and define the POI set.""" self.modelBuilder.doVar("r[1,-10,10]") self.poiNames = "r" self.quadFactors = [] - for operator in self.alloperators: - self.modelBuilder.doVar(operator + "[0,-200,200]") - self.poiNames += "," + operator - # This is the pure SM contribution for sig in self.sgnl_known: - sgnl_ops = self.Operators[sig] - if self.numOperators[sig] != 1: - for op in sgnl_ops: - op_idx = sgnl_ops.index(op) - oplist = sgnl_ops[op_idx:] - terms = " ".join(['-@0*@%d'%(i+1) for i,x in enumerate(oplist[1:])]) - formula = "@0{}".format(terms) - expression = "expr::func_{sig}_sm_{op}(\"{formula}\", {oplist})".format( + for operator in range(0, self.numOperators[sig]): + self.modelBuilder.doVar(str(self.Operators[sig][operator]) + "[0,-200,200]") + self.poiNames += "," + str(self.Operators[sig][operator]) + + # + # model: SM + k*linear + k**2 * quadratic + # + # SM = Asm**2 + # linear = Asm*Absm + # quadratic = Absm**2 + # + # ... and extended to more operators + # + # + # model: SM + k*linear + k**2 * quadratic + # + # SM = Asm**2 + # linear_1 = Asm*Abs_1 + # linear_2 = Asm*Absm_2 + # linear_3 = Absm_1*Absm_2 + # quadratic_1 = Absm_1**2 + # quadratic_2 = Absm_2**2 + # + # + # Combine limitation/assumption: all histograms are defined positive + # See http://cms-analysis.github.io/HiggsAnalysis-CombinedLimit/part2/physicsmodels/#interference + # There will be some algebra here below to deal with it, but it will be transparent for the user + # as if it was ... + # + # + # e.g. expr::func_"+sig+"_sm("@0*(1-(@1+@2+@3-@1*@2-@1*@3-@2*@1-@2*@3-@3*@1-@3*@2))",r,cG,cGtil, cG,cH, cGtil,cG, cGtil,cH, cH,cG, cH,cGtil) + # + + # + # sm + # + # print " Test = " + + + # + # this is the coefficient of "SM" + # + + if not self.alternative : + #if self.numOperators != 1: + #print "expr::func_"+sig+"_sm(\"@0*(1-(" + \ + #"@" + "+@".join([str(i+1) for i in range(len(self.Operators[sig]))]) + \ + #"-@" + "-@".join([str(i+1)+"*@"+str(j+1) for i in range(len(self.Operators[sig])) for j in range(len(self.Operators[sig])) if i