3 from sys
import argv, stdout, stderr, exit
4 from optparse
import OptionParser
10 ROOT.gROOT.SetBatch(
True)
12 parser = OptionParser(usage=
"usage: %prog [options] [refmass1] mass3 > datacard3.txt \nrun with --help to get list of options")
13 parser.add_option(
"--xsbr", dest=
"xsbr", action=
"store_true", default=
False, help=
"Use correct XS*BR for Higgs")
16 parser.add_option(
"--log", dest=
"log", action=
"store_true", default=
False, help=
"Use log-scale interpolation for yields (default is linear)")
17 parser.add_option(
"--ddir", dest=
"ddir", type=
"string", default=
".", help=
"Path to the datacards")
18 parser.add_option(
"--refmasses", dest=
"refmasses", type=
"string", default=
"hww.masses.txt", help=
"File containing the reference masses between which to interpolate (relative to --options.ddir)")
19 parser.add_option(
"--postfix", dest=
"postfix", type=
"string", default=
"", help=
"Postfix to add to datacard name")
20 parser.add_option(
"--extraThUncertainty", dest=
"etu", type=
"float", default=0.0, help=
"Add this amount linearly to gg->H cross section uncertainties")
21 (options, args) = parser.parse_args()
22 options.bin =
True; options.stat =
False
23 if len(args)
not in [1,3]:
29 refmasses = [ int(line)
for line
in open(options.ddir+
"/"+options.refmasses,
"r") ]
34 for m
in refmasses[1:]:
35 if abs(mass1 - mass) >
abs(m - mass)
or (
abs(mass1 - mass) ==
abs(m - mass)
and abs(mass1 - 164) <
abs(m - 164)):
41 xsbr1 = {
'ggH':1.0,
'qqH':1.0 }
42 xsbr = {
'ggH':1.0,
'qqH':1.0 }
44 ret = {}; headers = []
47 if len(cols) < 2:
continue
49 headers = [i.strip()
for i
in cols[1:]]
51 fields = [ float(i)
for i
in cols ]
52 ret[fields[0]] =
dict(zip(headers,fields[1:]))
54 path = os.environ[
'CMSSW_BASE']+
"/src/HiggsAnalysis/CombinedLimit/data/";
61 ggXS[M] =
dict([ (key, 0.5*(ggXS[M+10][key] + ggXS[M-10][key]))
for key
in ggXS[M+10].iterkeys() ])
62 qqXS[M] =
dict([ (key, 0.5*(qqXS[M+10][key] + qqXS[M-10][key]))
for key
in qqXS[M+10].iterkeys() ])
63 br[M] =
dict([ (key, 0.5*(br[M+10][key] + br[M-10][key]))
for key
in br[M+10].iterkeys() ])
64 sm4[M] =
dict([ (key, 0.5*(sm4[M+10][key] + sm4[M-10][key]))
for key
in sm4[M+10].iterkeys() ])
66 xsbr1[
'ggH'] = ggXS[mass1][
'XS_pb'] * br[mass1][
'H_evmv']
67 xsbr [
'ggH'] = ggXS[mass ][
'XS_pb'] * br[mass ][
'H_evmv'] * sm4[mass ][
'XS_over_SM'] * sm4[mass ][
'brWW_over_SM']
68 xsbr1[
'qqH'] = qqXS[mass1][
'XS_pb'] * br[mass1][
'H_evmv']
69 xsbr [
'qqH'] = qqXS[mass ][
'XS_pb'] * br[mass ][
'H_evmv'] * sm4[mass ][
'brWW_over_SM']
71 xsbr[
'ggH'] = sm4[mass1][
'XS_over_SM'] * sm4[mass1][
'brWW_over_SM']
72 xsbr[
'qqH'] = sm4[mass1][
'brWW_over_SM']
75 print "Will interpolate %g from %d" % (mass, mass1)
77 for X
in [
'hwwof_0j_shape',
'hwwof_1j_shape',
'hwwsf_0j_shape',
'hwwsf_1j_shape',
'hww_2j_cut']:
80 XS = X.replace(
"_shape",
"")
81 os.system(
"cp %s/%d/%s.input.root %s/%g/SM4_%s%s.input.root" % (options.ddir,mass1,XS,options.ddir,mass,XS,options.postfix))
82 ofile = ROOT.TFile(
"%s/%g/SM4_%s%s.input.root" % (options.ddir,mass,XS,options.postfix) ,
"UPDATE" )
84 file1 = options.ddir+
"/%d/%s.txt" % (mass1, X)
85 options.fileName = file1; options.mass = mass1;
88 if len(DC1.bins) != 1:
raise RuntimeError,
"This does not work on multi-channel"
89 obsline = [str(x)
for x
in DC1.obs.values()]; obskeyline = DC1.bins; cmax = 5;
90 keyline = []; expline = []; systlines = {};
91 signals = []; backgrounds = []; shapeLines = [];
92 paramSysts = {}; flatParamNuisances = {}
93 for (name,nf,pdf,args,errline)
in DC1.systs:
94 if options.etu != 0
and name
in [
"QCDscale_ggH",
"QCDscale_ggH1in",
"QCDscale_ggH2in" ]:
95 for b
in errline.iterkeys():
96 for p
in errline[b].iterkeys():
97 if errline[b][p] != 0
and errline[b][p] != 1:
98 inflated = errline[b][p]+options.etu
if errline[b][p] > 1
else errline[b][p]-options.etu
100 errline[b][p] = inflated
101 systlines[name] = [ pdf, args, errline, nf ]
102 for b,p,sig
in DC1.keyline:
104 if p
in [
'ggH',
'qqH']:
107 if (rate != 0)
and (
"shape" in X):
108 histo = ofile.Get(
"histo_%s" % p);
109 histo.Scale(rate/histo.Integral())
110 ofile.WriteTObject(histo,
"histo_%s" % p,
"Overwrite");
111 keyline.append( (b, p, DC1.isSignal[p]) )
112 expline.append(
"%.4f" % rate )
114 shapeLines.append( (
"*", obskeyline[0], [
"SM4_%s%s.input.root" % (XS,options.postfix),
"histo_$PROCESS" ]) )
115 shapeLines.append( (
"data_obs", obskeyline[0], [
"SM4_%s%s.input.root" % (XS,options.postfix),
"histo_Data" ]) )
118 xfile = open(options.ddir+
"/%d/SM4_%s%s.txt" % (mass, X,options.postfix),
"w")
119 xfile.write(
" ".
join([
"imax %d number of bins" % len(DC1.bins)])+
"\n")
120 xfile.write(
" ".
join([
"jmax * number of processes minus 1"])+
"\n")
121 xfile.write(
" ".
join([
"kmax * number of nuisance parameters"])+
"\n")
122 xfile.write(
" ".
join([
"-" * 130])+
"\n")
124 chmax =
max([
max(len(p),len(c))
for p,c,x
in shapeLines]);
125 cfmt =
"%-"+str(chmax)+
"s ";
126 for (process,channel,stuff)
in shapeLines:
127 xfile.write(
" ".
join([
"shapes", cfmt % process, cfmt % channel,
' '.
join(stuff)])+
"\n")
128 xfile.write(
" ".
join([
"-" * 130])+
"\n")
131 cmax =
max([cmax]+[len(l)
for l
in obskeyline]+[len(x)
for x
in obsline])
132 cfmt =
"%-"+str(cmax)+
"s";
133 xfile.write(
" ".
join([
"bin ",
" ".
join([cfmt % x
for x
in obskeyline])])+
"\n")
134 xfile.write(
" ".
join([
"observation ",
" ".
join([cfmt % x
for x
in obsline])])+
"\n")
136 xfile.write(
" ".
join([
"-" * 150])+
"\n")
138 pidline = []; signals = []; backgrounds = []
139 for (b,p,s)
in keyline:
141 if p
not in signals: signals.append(p)
142 pidline.append(-len(DC1.signals)+signals.index(p)+1)
144 if p
not in backgrounds: backgrounds.append(p)
145 pidline.append(1+backgrounds.index(p))
146 cmax =
max([cmax]+[
max(len(p),len(b))
for p,b,s
in keyline]+[len(e)
for e
in expline])
147 hmax =
max([10] + [len(
"%-12s %s %s" % (l,p,a))
for l,(p,a,e,nf)
in systlines.items()])
148 cfmt =
"%-"+str(cmax)+
"s"; hfmt =
"%-"+str(hmax)+
"s ";
149 xfile.write(
" ".
join([hfmt %
"bin",
" ".
join([cfmt % p
for p,b,s
in keyline])])+
"\n")
150 xfile.write(
" ".
join([hfmt %
"process",
" ".
join([cfmt % b
for p,b,s
in keyline])])+
"\n")
151 xfile.write(
" ".
join([hfmt %
"process",
" ".
join([cfmt % x
for x
in pidline])])+
"\n")
152 xfile.write(
" ".
join([hfmt %
"rate",
" ".
join([cfmt % x
for x
in expline])])+
"\n")
153 xfile.write(
" ".
join([
"-" * 150])+
"\n")
154 sysnamesSorted = systlines.keys(); sysnamesSorted.sort()
155 for name
in sysnamesSorted:
156 (pdf,pdfargs,effect,nofloat) = systlines[name]
157 if nofloat: name +=
"[nofloat]"
159 for b,p,s
in keyline:
161 systline.append(effect[b][p]
if (effect[b][p] != 1.0
or pdf !=
'lnN')
else "-")
163 systline.append(
"-");
164 xfile.write(
" ".
join([hfmt % (
"%-28s %s %s" % (name, pdf,
" ".
join(pdfargs))),
" ".
join([cfmt % x
for x
in systline])])+
"\n")
165 for (pname, pargs)
in paramSysts.items():
166 xfile.write(
" ".
join([
"%-12s param %s" % (pname,
" ".
join(pargs))])+
"\n")
168 for pname
in flatParamNuisances.iterkeys():
169 xfile.write(
" ".
join([
"%-12s flatParam" % pname])+
"\n")
const T & max(const T &a, const T &b)
static std::string join(char **cmd)