def hist2D(self, var1, nBins1, a1, b1, var2, nBins2, a2, b2, **kwargs): name = kwargs.get( 'name', makeHistName(self.label + "_merged", "%s_vs_%s" % (var1, var2))) title = kwargs.get('title', self.label) blind = kwargs.get('blind', self.blind) kwargs['scale'] = self.scale * kwargs.get('scale', 1.0) # pass scale down verbosity = kwargs.get('verbosity', 0) printVerbose( ">>>\n>>> Samples - %s, %s vs. %s: %s" % (color(name, color="grey"), var1, var2, self.filenameshort), verbosity) printVerbose(">>> scale: %.4f" % (kwargs['scale']), verbosity) hist2D = TH2D(name, title, nBins2, a2, b2, nBins1, a1, b1) for sample in self.samples: if 'name' in kwargs: # prevent memory leaks kwargs['name'] = makeHistName( sample.label, name.replace(self.label + '_', '')) hist2D.Add( sample.hist2D(var1, nBins1, a1, b1, var2, nBins2, a2, b2, **kwargs)) return hist2D
def normalizeSignal(self,S_exp,**kwargs): """Calculates normalization for a given expected signal yield.""" verbosity = kwargs.get('verbosity',0) cuts = [ ("%s && %s" % (baseline, category1)), ("%s && %s" % (baseline, category2)), ] cuts = kwargs.get('cuts',cuts) weight = kwargs.get('weight',"") (aa,bb) = kwargs.get('signalregion',(0,40)) N = 0; MC = 0 scale = 1 for i,cut in enumerate(cuts): cut = combineCuts("m_sv>0", cut) name = "m_sv_for_signal_renormalization_%d" % i hist = self.hist("m_sv",100,aa,bb,name=name,cuts=cut,weight=weight) N += hist.GetSumOfWeights() MC += hist.GetEntries() gDirectory.Delete(name) if N: scale = S_exp / N * self.scale printVerbose(">>> normalizeSignal: S_exp=%.4f, N=%.4f, MC=%.1f, old scale=%.4f, scale=%.4f" % (S_exp, N, MC, self.scale, scale), verbosity) printVerbose(">>> normalizeSignal: signalregion=(%.1f,%.1f)" % (aa,bb),verbosity) else: print warning("Could not find normalization for signal: no MC events in given signal region after cuts (%s)!" % cuts) self.setAllScales(scale) return scale
def normalizeSignal(self, S_exp, **kwargs): """Calculates normalization for a given expected signal yield.""" if not self.isSignal: print warning("normalizeSignal: Not a signal sample!") verbosity = kwargs.get('verbosity', 0) var = kwargs.get('var', "m_sv") cuts = [ ("%s && %s" % (baseline, category1)), ("%s && %s" % (baseline, category2)), ] cuts = kwargs.get('cuts', cuts) if not isinstance(cuts, list) and not isinstance(cuts, tuple): cuts = [cuts] (aa, bb) = kwargs.get('signalregion', (0, 40)) weight = kwargs.get('weight', "") channel = kwargs.get('channel', "mutau") #treeName = kwargs.get('treeName',"tree_%s"%channel) setScale = kwargs.get('setScale', True) N = 0 MC = 0 scale = 1 for i, cut in enumerate(cuts): #cut = combineCuts("%s<%s && %s<%s"%(aa,var,var,bb), cut) # remove over and underflow name = "m_sv_for_signal_renormalization_%d" % i hist = self.hist("m_sv", 100, aa, bb, name=name, cuts=cut, weight=weight, verbosity=verbosity) N += hist.GetSumOfWeights() MC += hist.GetEntries() gDirectory.Delete(name) printVerbose(">>> normalizeSignal: N=%s, MC=%s" % (N, MC), verbosity) if N: scale = S_exp / N * self.scale printVerbose( ">>> normalizeSignal: S_exp=%.4f, N=%.4f, MC=%.1f, old scale=%.4f, scale=%.4f" % (S_exp, N, MC, self.scale, scale), verbosity) #printVerbose(">>> normalizeSignal: signalregion=(%.1f,%.1f)" % (aa,bb),verbosity) else: print warning( "Could not find normalization for signal: no MC events (N=%s,MC=%s) in given signal region after cuts (%s)!" % (N, MC, cuts)) if setScale: self.setAllScales(scale) return scale
def hist2D(self, var1, nBins1, a1, b1, var2, nBins2, a2, b2, **kwargs): """Make a 2D histogram with a tree.""" scale = kwargs.get('scale', 1.0) * self.scale tree = self.file.Get(self.treeName) name = kwargs.get('name', makeHistName(self.label, "%s_vs_%s" % (var1,var2))) title = kwargs.get('title', self.label) verbosity = kwargs.get('verbosity', 0) blindcuts = "" if var1 in self.blind: blindcuts += self.blind[var1] if var2 in self.blind: blindcuts += self.blind[var2] weight = combineWeights(self.weight, kwargs.get('weight', "")) cuts = combineCuts(self.cuts, kwargs.get('cuts', ""), blindcuts, weight=weight) printVerbose(">>>>\n>>> Sample - %s, %s vs. %s: %s" % (color(name,color="grey"), var1, var2, self.filenameshort),verbosity) printVerbose(">>> scale: %.4f" % (scale),verbosity) printVerbose(">>> weight: %s" % (weight),verbosity) printVerbose(">>> %s" % (cuts),verbosity) hist2D = TH2F(name, title, nBins2, a2, b2, nBins1, a1, b1) out = tree.Draw("%s:%s >> %s" % (var1,var2,name), cuts, "gOff") if out < 0: print error("Drawing histogram for %s sample failed!" % (title)) #if scale is not 1.0: hist.Scale(scale) #if scale is 0.0: print warning("Scale of %s is 0!" % self.label) return hist2D
def calculateLumiAcceptance(self,cuts,**kwargs): """Calculates scale for a given expected signal yield, to divide out the luminosity and acceptance. This method only returns the scale, it does not rescale the signal.""" verbosity = kwargs.get('verbosity',0) weight = kwargs.get('weight',"") (a,b) = kwargs.get('range',(0,500)) scale = 1 N_tot = self.N name = "m_sv_for_LumiAcceptance" hist = self.hist("m_sv",100,a,b,name=name,cuts=cuts,weight=weight) (N,MC) = (hist.GetSumOfWeights(),hist.GetEntries()) gDirectory.Delete(name) if N_tot and N and lumi: scale = N_tot/(N*lumi) printVerbose(">>> normalizeSignal: N_tot=%.4f, N=%.4f, MC=%.1f, lumi=%s, current scale=%.4f, scale=%.4f" % (N_tot, N, MC, lumi, self.scale, scale), verbosity) printVerbose(">>> normalizeSignal: range=(%.1f,%.1f)" % (a,b),verbosity) else: print warning("Could not find normalization for signal: N_tot=%s, N=%s, lumi=%s!" % (N_tot,N,lumi)) return scale
def hist(self, var, nBins, a, b, **kwargs): name = kwargs.get('name', makeHistName(self.label + "_merged", var)) name += kwargs.get('append_name', "") title = kwargs.get('title', self.label) blind = kwargs.get('blind', self.blind) kwargs['scale'] = self.scale * kwargs.get('scale', 1.0) # pass scale down verbosity = kwargs.get('verbosity', 0) printVerbose( ">>>\n>>> Samples - %s, %s: %s" % (color(name, color="grey"), var, self.filenameshort), verbosity) printVerbose(">>> scale: %.4f" % (kwargs['scale']), verbosity) hist = TH1D(name, title, nBins, a, b) hist.Sumw2() for sample in self.samples: if 'name' in kwargs: # prevent memory leaks kwargs['name'] = makeHistName( sample.label, name.replace(self.label + '_', '')) hist_new = sample.hist(var, nBins, a, b, **kwargs) hist.Add(hist_new) printVerbose( ">>> sample %s added with %.1f events (%d entries)" % (sample.label, hist_new.Integral(), hist_new.GetEntries()), verbosity, level=2) if verbosity > 2: printBinError(hist) return hist
def calculateLumiAcceptance(self, cuts, **kwargs): """Calculates scale for a given expected signal yield, to divide out the luminosity and acceptance. This method only returns the scale, it does not rescale the signal.""" verbosity = kwargs.get('verbosity', 0) var = kwargs.get('var', "m_sv") weight = kwargs.get('weight', "") (a, b) = kwargs.get('signalregion', (0, 500)) scale = 1 N_tot = self.N name = "%s_for_LA" % var hist = self.hist(var, 100, a, b, name=name, cuts=cuts, weight=weight) (N, MC) = (hist.GetSumOfWeights(), hist.GetEntries()) gDirectory.Delete(name) #cuts = combineCuts("%s<%s && %s<%s"%(a,var,var,b), cuts) printVerbose(">>> calculateLA:", verbosity) printVerbose(">>> cuts=%s" % (cuts), verbosity) if N_tot and N and lumi: scale = N_tot / (N * lumi * 1000) printVerbose( ">>> N_tot=%.4f, N=%.4f, MC=%.1f, lumi=%s, current scale=%.4f, scale=%.4f" % (N_tot, N, MC, lumi, self.scale, scale), verbosity) #printVerbose(">>> signalregion=(%.1f,%.1f)" % (a,b),verbosity) else: print warning( "Could not find normalization for signal: N_tot=%s, N=%s, lumi=%s!" % (N_tot, N, lumi)) return scale
def histAndColor(self, var, nBins, a, b, **kwargs): '''Return a list of tuples containing a histogram and a color. Return multiple ntuples if a sample need to be split.''' split = kwargs.get('split', False) and len(self.split) verbosity = kwargs.get('verbosity', 0) if split: printVerbose(">>> histAndColor: splitting %s" % (self.label), verbosity) histsAndColors = [] cuts0 = kwargs.get('cuts', "") for key, (splitlabel, splitcut, splitcolor) in self.split.iteritems(): kwargs['cuts'] = combineCuts(cuts0, splitcut) kwargs['title'] = splitlabel kwargs['append_name'] = "_%s" % (key) hist = self.hist(var, nBins, a, b, **kwargs) histsAndColors.append((hist, splitcolor)) return histsAndColors else: printVerbose(">>> histAndColor: not splitting", verbosity, level=2) hist = self.hist(var, nBins, a, b, **kwargs) return [(hist, self.color)]
def renormalizeWJ(samples, **kwargs): """Helpfunction to renormalize W + Jets.""" #print ">>>\n>>> renormalizing WJ" var = kwargs.get('var', "pfmt_1") QCD = kwargs.get('QCD', True) channel = kwargs.get('channel', "mutau") label = kwargs.get('label', "baseline") cuts = kwargs.get('cuts', baseline) reset = kwargs.get('reset', True) shift_QCD = kwargs.get('shift_QCD', 0) # e.g. 0.30 prepend = kwargs.get('prepend', "") verbosity = kwargs.get('verbosity', 0) ratio_WJ_QCD_SS = kwargs.get('ratio_WJ_QCD_SS', True) #samples = kwargs.get('samples',[ ]) name = "%s/%s%s/%s_tail_%s_noWJrenormalization.png" % (PLOTS_DIR, channel, mylabel, var, label) title = "%s: %s" % (channel.replace("tau", "#tau").replace("mu", "#mu"), label) printVerbose(">>> WJ renormalization with:\n>>> %s: %s\n>>> %s: %s" % ("QCD", QCD, "ratio_WJ_QCD_SS", ratio_WJ_QCD_SS), verbosity, level=2) plot = Plot(samples, var, 200, 80, 200, cuts=cuts, QCD=QCD, ratio_WJ_QCD_SS=ratio_WJ_QCD_SS, reset=True, shift_QCD=shift_QCD, verbosity=verbosity) #plot.plot(stack=True, title=title, staterror=True, ratio=True) scale = plot.renormalizeWJ(prepend=prepend, verbosity=verbosity) plot.close()
def hist(self, var, nBins, a, b, **kwargs): """Make a histogram with a tree.""" scale = kwargs.get('scale', 1.0) * self.scale tree = self.file.Get(self.treeName) name = kwargs.get('name', makeHistName(self.label, var)) title = kwargs.get('title', self.label) shift = kwargs.get('shift', 0) smear = kwargs.get('smear', 0) verbosity = kwargs.get('verbosity', 0) if self.isSignal and self.scale is not self.scaleBU and self.scaleBU: title += " (#times%d)" % (self.scale/self.scaleBU) blindcuts = "" if var in self.blind: blindcuts = self.blind[var] weight = combineWeights(self.weight, kwargs.get('weight', "")) cuts = combineCuts(self.cuts, kwargs.get('cuts', ""), blindcuts, weight=weight) hist = TH1F(name, title, nBins, a, b) out = tree.Draw("%s >> %s" % (var,name), cuts, "gOff") if shift or smear: mean0 = hist.GetMean() #smear = min(1,smear) #smear = sqrt(smear*smear-1) #*sigma #tree.SetAlias("rng","sin(2*pi*rndm)*sqrt(-2*log(rndm))") var2 = "%s*%s + %s + %s*%s" % (var,smear,shift,(1-smear),mean0) tree.Draw("%s >> %s" % (var2,name), cuts, "gOff") if out < 0: print error("Drawing histogram for %s sample failed!" % (title)) if scale is not 1.0: hist.Scale(scale) if scale is 0.0: print warning("Scale of %s is 0!" % self.label) #print hist.GetEntries() #gDirectory.Delete(label) printVerbose(">>>\n>>> Sample - %s, %s: %s" % (color(name,color="grey"), var, self.filenameshort),verbosity) printVerbose(">>> scale: %.4f (%.4f)" % (scale,self.scale),verbosity) printVerbose(">>> weight: %s" % (("\n>>>%s*("%(' '*18)).join(weight.rsplit('*(',max(0,weight.count("*(")-1)))),verbosity) printVerbose(">>> %s" % (cuts.replace("*(","\n>>>%s*("%(' '*18))),verbosity) return hist
def mergeSamples(sample_list, names, **kwargs): """Merge samples""" verbosity = kwargs.get('verbosity', 2) if not isinstance(names, list): names = [names] name0 = kwargs.get('name', names[0]) #+ " merged" signal = kwargs.get('signal', False) background = kwargs.get('background', True) and not signal labels = kwargs.get('labels', []) # extra search term labels.append(kwargs.get('label', "")) color0 = kwargs.get('color', colors_dict.get(name0.replace("_merged", ''), kBlack)) samples = Samples(name0, background=background, signal=signal, color=color0) printVerbose(">>>", verbosity, level=2) printVerbose(">>> merging %s" % (name0), verbosity, level=1) # get samples containing names and label merge_list = [] for name in names: merge_list += [s for s in sample_list if s.isPartOf(name, *labels)] # check if sample list of contains to-be-stitched-sample if len(merge_list) < 2: print warning("Could not stitch %s: less than two %s samples" % (name0, name0)) #return sample_list fill = max([len(s.label) for s in merge_list]) # add samples with name0 and label for sample in merge_list: printVerbose(">>> merging %s to %s: %s" % (sample.label.ljust(fill), name0, sample.filenameshort), verbosity, level=2) samples.add(sample) # remove merged samples from sample_list if samples.samples: sample_list.append(samples) #print "samples.samples.label = %s\n" % [s.label for s in samples.samples] #print "sample_list.label = %s\n" % [s.label for s in sample_list] for sample in samples.samples: #print "sample.name =", sample.label sample_list.remove(sample)
def hist(self, var, nBins, a, b, **kwargs): """Make a histogram with a tree.""" scale = kwargs.get('scale', 1.0) * self.scale treeName = kwargs.get('treeName', self.treeName) name = kwargs.get('name', makeHistName(self.label, var)) name += kwargs.get('append_name', "") title = kwargs.get('title', self.label) shift = kwargs.get('shift', 0) smear = kwargs.get('smear', 0) blind = kwargs.get('blind', self.blind) verbosity = kwargs.get('verbosity', 0) if self.isSignal and self.scale is not self.scaleBU and self.scaleBU: title += " (#times%d)" % (self.scale / self.scaleBU) blindcuts = "" if var in blind and "SS" not in name: blindcuts = blind[ var] # TODO: blind by removing bins from hist or rounding? FindBin(a), SetBinContent weight = combineWeights(self.weight, kwargs.get('weight', "")) cuts = combineCuts(self.cuts, kwargs.get('cuts', ""), blindcuts, weight=weight) tree = self.file.Get(treeName) if not tree or not isinstance(tree, TTree): print error("Could not find tree \"%s\" for %s! Check %s" % (treeName, self.label, self.filenameshort)) hist = TH1D(name, title, nBins, a, b) hist.Sumw2() out = tree.Draw("%s >> %s" % (var, name), cuts, "gOff") if shift or (smear and smear != 1): mean0 = hist.GetMean() #smear = min(1,smear) #smear = sqrt(smear*smear-1) #*sigma #tree.SetAlias("rng","sin(2*pi*rndm)*sqrt(-2*log(rndm))") var2 = "%s*%s + %s + %s*%s" % (var, smear, shift, (1 - smear), mean0) tree.Draw("%s >> %s" % (var2, name), cuts, "gOff") if out < 0: print error("Drawing histogram for %s sample failed!" % (title)) if scale is not 1.0: hist.Scale(scale) if scale is 0.0: print warning("Scale of %s is 0!" % self.label) if verbosity > 2: printBinError(hist) #print hist.GetEntries() #gDirectory.Delete(label) printVerbose( ">>>\n>>> Sample - %s, %s: %s (%s)" % (color( name, color="grey"), var, self.filenameshort, self.treeName), verbosity) printVerbose(">>> scale: %.4f (%.4f)" % (scale, self.scale), verbosity) printVerbose( ">>> weight: %s" % (("\n>>>%s*(" % (' ' * 18)).join( weight.rsplit('*(', max(0, weight.count("*(") - 1)))), verbosity) printVerbose( ">>> entries: %d (%.2f integral)" % (hist.GetEntries(), hist.Integral()), verbosity) printVerbose( ">>> %s" % (cuts.replace("*(", "\n>>>%s*(" % (' ' * 18))), verbosity) return hist
def stitchSamples(sample_list, name0, **kwargs): """Stitching samples: merge samples and reweight inclusive sample and rescale jet-binned samples""" verbosity = kwargs.get('verbosity', 2) printVerbose(">>>", verbosity, level=2) printVerbose(">>> stiching %s: rescale, reweight and merge samples" % (name0), verbosity, level=1) # see /shome/ytakahas/work/TauTau/SFrameAnalysis/TauTauResonances/plot/config.py # DY cross sections 5765.4 [ 4954.0, 1012.5, 332.8, 101.8, 54.8 ] # WJ cross sections 61526.7 [ 50380.0, 9644.5, 3144.5, 954.8, 485.6 ] sigmasLO = { "DY": { "M-50": 4954.0, "M-10to50": 18610.0 }, "WJ": { "": 50380.0 } } sigmasNLO = { "DY": { "M-50": 5765.4, "M-10to50": 21658.0 }, "WJ": { "": 61526.7 } } #name0 = "DY" #"WJ" label_incl = kwargs.get('label_incl', "Jets") name_incl = kwargs.get('name_incl', name0 + label_incl) labels = kwargs.get('labels', []) # extra search term labels.append(kwargs.get('label', "")) sigmaLO = sigmasLO[name0][labels[0]] kfactor = sigmasNLO[name0][labels[0]] / sigmaLO N_incl = 0 weights = [] stitch_list = [s for s in sample_list if s.isPartOf(name0, *labels)] printVerbose(">>> %s k-factor = %.2f" % (name0, kfactor), verbosity, level=2) # check if sample list of contains to-be-stitched-sample if len(stitch_list) < 2: print warning("Could not stitch %s: less than two %s samples" % (name0, name0)) for s in stitch_list: print ">>> %s" % s.label return sample_list fill = max([len(s.label) for s in stitch_list]) name = kwargs.get('name', stitch_list[0].label) # set renormalization scales with effective luminosity for sample in stitch_list: N_tot = sample.N sigma = sample.sigma N = N_tot if name_incl in sample.filename: N_incl = N_tot elif not N_incl: print warning("Could not stitch %s: N_incl == 0!" % name0) return sample_list else: N = N_tot + N_incl * sigma / sigmaLO # effective luminosity scale = lumi * kfactor * sigma * 1000 / N weights.append("(NUP==%i ? %s : 1)" % (len(weights), scale)) printVerbose( ">>> stitching %s with scale %5.2f and cross section %7.2f pb" % (sample.label.ljust(fill), scale, sigma), verbosity, level=2) #print ">>> weight.append(%s)" % weights[-1] if name_incl in sample.filename: sample.scale = 1.0 # apply renormalization scale with weights else: sample.scale = scale # apply renormalization scale # set weight of inclusive sample for sample in stitch_list: if sample.isPartOf(name_incl, *labels): sample.scale = 1.0 sample.addWeight("*".join(weights)) # merge mergeSamples(sample_list, name0, labels=labels, name=name, verbosity=verbosity)