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 (options, args) = parser.parse_args()
21 options.bin =
True; options.stat =
False
22 if len(args)
not in [1,3]:
28 refmasses = [ int(line)
for line
in open(options.ddir+
"/"+options.refmasses,
"r") ]
33 for m
in refmasses[1:]:
34 if abs(mass1 - mass) >
abs(m - mass)
or (
abs(mass1 - mass) ==
abs(m - mass)
and abs(mass1 - 164) <
abs(m - 164)):
40 if mass
in refmasses
and options.postfix ==
"":
raise RuntimeError,
"Will not overwrite the reference masses"
42 xsbr1 = {
'ggH':1.0,
'qqH':1.0 }
43 xsbr = {
'ggH':1.0,
'qqH':1.0 }
46 ret = {}; headers = []
49 if len(cols) < 2:
continue
51 headers = [i.strip()
for i
in cols[1:]]
53 fields = [ float(i)
for i
in cols ]
54 ret[fields[0]] =
dict(zip(headers,fields[1:]))
56 path = os.environ[
'CMSSW_BASE']+
"/src/HiggsAnalysis/CombinedLimit/data/";
63 ggXS[M] =
dict([ (key, 0.5*(ggXS[M+10][key] + ggXS[M-10][key]))
for key
in ggXS[M+10].iterkeys() ])
64 qqXS[M] =
dict([ (key, 0.5*(qqXS[M+10][key] + qqXS[M-10][key]))
for key
in qqXS[M+10].iterkeys() ])
65 br[M] =
dict([ (key, 0.5*(br[M+10][key] + br[M-10][key]))
for key
in br[M+10].iterkeys() ])
66 sm4[M] =
dict([ (key, 0.5*(sm4[M+10][key] + sm4[M-10][key]))
for key
in sm4[M+10].iterkeys() ])
67 xsbr1[
'ggH'] = ggXS[mass1][
'XS_pb'] * br[mass1][
'H_evmv'] * sm4[mass1][
'XS_over_SM'] * sm4[mass1][
'brWW_over_SM']
68 xsbr [
'ggH'] = ggXS[mass ][
'XS_pb'] * br[mass ][
'H_evmv'] * sm4[mass ][
'XS_over_SM'] * sm4[mass ][
'brWW_over_SM']
69 xsbr1[
'qqH'] = qqXS[mass1][
'XS_pb'] * br[mass1][
'H_evmv']
70 xsbr [
'qqH'] = qqXS[mass ][
'XS_pb'] * br[mass ][
'H_evmv']
72 print "Will interpolate %g from %d" % (mass, mass1)
74 for X
in [
'SM4_hwwof_0j_shape',
'SM4_hwwof_1j_shape',
'SM4_hwwsf_0j_shape',
'SM4_hwwsf_1j_shape',
'SM4_hww_2j_cut']:
75 print "Considering datacard ",X
77 XS = X.replace(
"_shape",
"")
78 os.system(
"cp %s/%d/%s.input.root %s/%g/%s%s.input.root" % (options.ddir,mass1,XS,options.ddir,mass,XS,options.postfix))
79 ofile = ROOT.TFile(
"%s/%g/%s%s.input.root" % (options.ddir,mass,XS,options.postfix) ,
"UPDATE" )
81 file1 = options.ddir+
"/%d/%s.txt" % (mass1, X)
82 options.fileName = file1; options.mass = mass1;
85 if len(DC1.bins) != 1:
raise RuntimeError,
"This does not work on multi-channel"
86 obsline = [str(x)
for x
in DC1.obs.values()]; obskeyline = DC1.bins; cmax = 5;
87 keyline = []; expline = []; systlines = {};
88 signals = []; backgrounds = []; shapeLines = [];
89 paramSysts = {}; flatParamNuisances = {}
90 for (name,nf,pdf,args,errline)
in DC1.systs:
91 systlines[name] = [ pdf, args, errline, nf ]
92 for b,p,sig
in DC1.keyline:
94 if p
in [
'ggH',
'qqH']:
97 if (rate != 0)
and (
"shape" in X):
98 histo = ofile.Get(
"histo_%s" % p);
99 histo.Scale(rate/histo.Integral())
100 ofile.WriteTObject(histo,
"histo_%s" % p,
"Overwrite");
101 keyline.append( (b, p, DC1.isSignal[p]) )
102 expline.append(
"%.4f" % rate )
103 shapeLines.append( (
"*", obskeyline[0], [
"%s%s.input.root" % (X,options.postfix),
"histo_$PROCESS" ]) )
104 shapeLines.append( (
"data_obs", obskeyline[0], [
"%s%s.input.root" % (X,options.postfix),
"histo_Data" ]) )
107 xfile = open(options.ddir+
"/%d/%s%s.txt" % (mass, X,options.postfix),
"w")
108 xfile.write(
" ".
join([
"imax %d number of bins" % len(DC1.bins)])+
"\n")
109 xfile.write(
" ".
join([
"jmax * number of processes minus 1"])+
"\n")
110 xfile.write(
" ".
join([
"kmax * number of nuisance parameters"])+
"\n")
111 xfile.write(
" ".
join([
"-" * 130])+
"\n")
113 chmax =
max([
max(len(p),len(c))
for p,c,x
in shapeLines]);
114 cfmt =
"%-"+str(chmax)+
"s ";
115 for (process,channel,stuff)
in shapeLines:
116 xfile.write(
" ".
join([
"shapes", cfmt % process, cfmt % channel,
' '.
join(stuff)])+
"\n")
117 xfile.write(
" ".
join([
"-" * 130])+
"\n")
120 cmax =
max([cmax]+[len(l)
for l
in obskeyline]+[len(x)
for x
in obsline])
121 cfmt =
"%-"+str(cmax)+
"s";
122 xfile.write(
" ".
join([
"bin ",
" ".
join([cfmt % x
for x
in obskeyline])])+
"\n")
123 xfile.write(
" ".
join([
"observation ",
" ".
join([cfmt % x
for x
in obsline])])+
"\n")
125 xfile.write(
" ".
join([
"-" * 150])+
"\n")
127 pidline = []; signals = []; backgrounds = []
128 for (b,p,s)
in keyline:
130 if p
not in signals: signals.append(p)
131 pidline.append(-len(DC1.signals)+signals.index(p)+1)
133 if p
not in backgrounds: backgrounds.append(p)
134 pidline.append(1+backgrounds.index(p))
135 cmax =
max([cmax]+[
max(len(p),len(b))
for p,b,s
in keyline]+[len(e)
for e
in expline])
136 hmax =
max([10] + [len(
"%-12s %s %s" % (l,p,a))
for l,(p,a,e,nf)
in systlines.items()])
137 cfmt =
"%-"+str(cmax)+
"s"; hfmt =
"%-"+str(hmax)+
"s ";
138 xfile.write(
" ".
join([hfmt %
"bin",
" ".
join([cfmt % p
for p,b,s
in keyline])])+
"\n")
139 xfile.write(
" ".
join([hfmt %
"process",
" ".
join([cfmt % b
for p,b,s
in keyline])])+
"\n")
140 xfile.write(
" ".
join([hfmt %
"process",
" ".
join([cfmt % x
for x
in pidline])])+
"\n")
141 xfile.write(
" ".
join([hfmt %
"rate",
" ".
join([cfmt % x
for x
in expline])])+
"\n")
142 xfile.write(
" ".
join([
"-" * 150])+
"\n")
143 sysnamesSorted = systlines.keys(); sysnamesSorted.sort()
144 for name
in sysnamesSorted:
145 (pdf,pdfargs,effect,nofloat) = systlines[name]
146 if nofloat: name +=
"[nofloat]"
148 for b,p,s
in keyline:
150 systline.append(effect[b][p]
if (effect[b][p] != 1.0
or pdf !=
'lnN')
else "-")
152 systline.append(
"-");
153 xfile.write(
" ".
join([hfmt % (
"%-28s %s %s" % (name, pdf,
" ".
join(pdfargs))),
" ".
join([cfmt % x
for x
in systline])])+
"\n")
154 for (pname, pargs)
in paramSysts.items():
155 xfile.write(
" ".
join([
"%-12s param %s" % (pname,
" ".
join(pargs))])+
"\n")
157 for pname
in flatParamNuisances.iterkeys():
158 xfile.write(
" ".
join([
"%-12s flatParam" % pname])+
"\n")
const T & max(const T &a, const T &b)
static std::string join(char **cmd)