Beispiel #1
0
    def __init__( self, *args ):

        self.filenames = args

        # Hold the data
        self.histogram_titles = {}
        self.histogram_data   = {}

        # Let's keep all the header information
        self.headers = []

        # The first file defines the data structure. We want an error if we combine differently structured files.
        first_file = True

        # Read all files
        for filename in self.filenames:
            if os.path.exists( filename ): 
                self.filename = filename
            else:
                raise IOError( "File does not exist: %s" % filename )

            header = ""
            with open( filename ) as f:
                reading_header = True
                
                # read content of file
                for line in f.readlines():
                    if line.startswith( "# Histogram"):
                        reading_header = False
                        key, value = line.rstrip().lstrip("# Histogram").split(":")
                        self.histogram_titles[int(key)] = value.lstrip().rstrip()
                    elif line[0]!='#':
                        s_n, s_x0, s_y, s_y_err, s_hits = line.rstrip().rstrip('|').split('|')
                        n     = int(s_n)
                        x0    = float(s_x0)
                        y     = float(s_y)
                        y_err = float(s_y_err)
                        hits  = int(s_hits)

                        # protection: Take structure from first file. Any extra bin subsequent files will raise error
                        if first_file:
                            if not self.histogram_data.has_key(n):
                                self.histogram_data[n] = {}
                            if not self.histogram_data[n].has_key(x0):
                                self.histogram_data[n][x0] = u_float(0)

                        self.histogram_data[n][x0]+=u_float(y,y_err)
                         
                    else:
                        if reading_header: header+=line
            # Keep headers
            self.headers.append( header )

            first_file = False
            logger.info( "Read %i histograms from file %s", len(self.histogram_data.keys()), filename )

        # Make histograms. Don't make them again.
        self.__histos = { n: self.__make_histo__( n ) for n in self.histogram_data.keys() }
Beispiel #2
0
    def xsec(self, modified_couplings = None, overwrite=False, skip=False):

        key = self.getKey( modified_couplings )
        # Do we have the x-sec?
        if self.xsecDB.contains(key) and not overwrite:
            logger.debug( "Found x-sec %s for key %r. Do nothing.", self.xsecDB.get(key), key )
            return self.xsecDB.get(key)
        elif skip:
            return u_float(0)
        else:
            print "Trying to get xsec"
            self.__initialize( modified_couplings ) 
            logger.info( "Calculating x-sec" )
            # rerun MG to obtain the correct x-sec (with more events)
            with open( os.path.join( self.processTmpDir, 'Cards/run_card.dat'), 'a') as f:
                f.write(".false. =  gridpack\n")
            logger.info( "Calculate x-sec: Calling bin/generate_events" )
            output = subprocess.check_output([ os.path.join( self.processTmpDir, 'bin/generate_events') , '-f'])
            for i in range(10):
                try:
                    output = subprocess.check_output([ os.path.join( self.processTmpDir, 'bin/generate_events') , '-f'])
                    m = re.search("Cross-section :\s*(.*) \pb", output)
                    logger.info( "x-sec: {} pb".format(m.group(1)) )
                    break
                except ValueError:
                    logger.info("Encountered problem during the MG run. Restarting.")

            xsec_ = u_float.fromString(m.group(1)) 
            
            self.xsecDB.add(key, xsec_, overwrite=True)

            logger.info( "Done!" )

            return xsec_
Beispiel #3
0
def getEstimateFromCard(cardFile, estimateName, binName):
    res = u_float(0)
    binNumber = getBinNumber(cardFile, binName)
    uncName = 'Stat_' + binName + '_' + estimateName
    with open(cardFile) as f:
      binList = False
      estimateList = False
      for line in f:
        if len(line.split())==0: continue
        if line.split()[0] == "bin":
          if not binList: binList = True
          else:           binList = line.split()[1:]
        if line.split()[0] == "process":
          if not estimateList: estimateList = line.split()[1:]
        if line.split()[0] == "rate":
            for i in range(len(binList)):
              if binList[i] == binNumber and estimateList[i]==estimateName:
                try: res.val = float(line.split()[1:][i])
                except: res.val = 0
                #return float(line.split()[1:][i])
        if line.split()[0] != uncName: continue
        for i in range(len(binList)):
          if binList[i] == binNumber and estimateList[i]==estimateName:
            try:    res.sigma = (float(line.split()[2:][i])-1)*res.val
            except: res.sigma = 0.
    return res
Beispiel #4
0
    def _estimate(self, region, channel, setup):
        ''' Concrete implementation of abstract method 'estimate' as defined in Systematic
        '''

        logger.debug("MC prediction for %s channel %s" % (self.name, channel))

        if channel == 'all':
            # 'all' is the total of all contributions
            return sum(
                [self.cachedEstimate(region, c, setup) for c in channels])

        elif channel == 'SF':
            # 'all' is the total of all contributions
            return sum([
                self.cachedEstimate(region, c, setup) for c in ['MuMu', 'EE']
            ])

        else:
            preSelection = setup.preselection('MC',
                                              channel=channel,
                                              isFastSim=self.isFastSim)
            cut = "&&".join([
                region.cutString(setup.sys['selectionModifier']),
                preSelection['cut']
            ])
            weight = preSelection['weightStr']

            logger.debug("Using cut %s and weight %s" % (cut, weight))
            return setup.lumi[channel] / 1000. * u_float(
                **self.sample[channel].getYieldFromDraw(selectionString=cut,
                                                        weightString=weight))
Beispiel #5
0
    def _estimate(self, region, channel, setup):

        ''' Concrete implementation of abstract method 'estimate' as defined in Systematic
        '''

        logger.debug( "MC prediction for %s channel %s" %(self.name, channel.name) )

        if channel.name=='all':
            # 'all' is the total of all contributions
            if setup.nLeptons == 1: channels = singlelepChannels
            elif setup.nLeptons == 3: channels = trilepChannels
            elif setup.nLeptons == 4: channels = quadlepChannels
            else: raise NotImplementedError
            return sum([self.cachedEstimate(region, c, setup) for c in channels])

        #elif channel=='SF':
        #    # 'all' is the total of all contributions
        #    return sum([self.cachedEstimate(region, c, setup) for c in ['MuMu', 'EE']])

        else:
            preSelection = setup.preselection('MC', nElectrons=channel.nE, nMuons=channel.nM, isFastSim = self.isFastSim)
            cut = "&&".join([region.cutString(setup.sys['selectionModifier']), preSelection['cut']])
            weight = preSelection['weightStr']
            logger.debug( "Using cut %s and weight %s"%(cut, weight) )
            return setup.lumi/1000.*u_float(**self.sample.getYieldFromDraw(selectionString = cut, weightString = weight) )
Beispiel #6
0
 def yieldFromCache(self, setup, sample, c, selectionString, weightString):
     s = (sample, c, selectionString, weightString)
     if self.helperCache and self.helperCache.contains(s):
         return self.helperCache.get(s)
     else:
         yieldFromDraw = u_float(
             **setup.samples[sample][c].getYieldFromDraw(
                 selectionString, weightString))
         if self.helperCache: self.helperCache.add(s, yieldFromDraw)
         return yieldFromDraw
Beispiel #7
0
def getTotalPostFitUncertainty(cardFile, binName):
    binNumber = getBinNumber(cardFile, binName)
    with open(cardFile) as f:
      binList = False
      estimateList = False
      ind = []
      uncertainties = False
      uncDict = {}
      totalUnc = {}
      for line in f:
        if len(line.split())==0: continue
        if line.split()[0] == "bin":
          if not binList: binList = True
          else:
            binList = line.split()[1:]
            for i,b in enumerate(binList):
                if b == binName:
                    ind.append(i) 
          print ind
        if line.split()[0] == "process":
          if not estimateList:
            estimateList = line.split()[1:]
            estimateList = estimateList[ind[1]:ind[-1]+1]
        if line.split()[0] == "rate":
          estimates = line.split()[1:]
          estimates = [float(a) for a in estimates[ind[1]:ind[-1]+1]]
        if line.split()[0] == 'PU': uncertainties = True
        if uncertainties:
            uncDict[line.split()[0]] = [ 0 if a =='-' else float(a)-1 for a in line.split()[2:][ind[1]:ind[-1]+1] ]
    print estimateList
    print estimates
    nuisanceFile = cardFile.replace('.txt','_nuisances_full.txt')
    for unc in uncDict.keys():
        totalUnc[unc] = 0
        for i in range(len(estimates)):
            #totalUnc[unc] += uncDict[unc][i] * estimates[i] * ( 1 + getPull(nuisanceFile,unc)*uncDict[unc][i] ) #* getConstrain(nuisanceFile, unc)
            totalUnc[unc] += uncDict[unc][i] * estimates[i] * math.exp( getPull(nuisanceFile,unc)*uncDict[unc][i] )
            #totalUnc[unc] += (uncDict[unc][i] * estimates[i] * math.exp( getPull(nuisanceFile,unc)*uncDict[unc][i] ))**2
        if totalUnc[unc] > 0: print unc, totalUnc[unc]
        #totalUnc[unc] = math.sqrt(totalUnc[unc])
    total = 0
    for unc in totalUnc.keys():
        total += totalUnc[unc]**2
    estimatesPostFit = []
    for e in estimateList:
        res = getEstimateFromCard(cardFile, e, binName)
        res = applyAllNuisances(cardFile, e, res, binName)
        estimatesPostFit.append(res.val)
    estimatePostFit = sum(estimatesPostFit)
    return u_float(estimatePostFit,math.sqrt(total))
Beispiel #8
0
def getObservationFromCard(cardFile, binName):
    res = u_float(0)
    binNumber = getBinNumber(cardFile, binName)
    with open(cardFile) as f:
      binList = False
      estimateList = False
      for line in f:
        if len(line.split())==0: continue
        if line.split()[0] == "bin":
            binList = line.split()[1:]
        if line.split()[0] == "observation":
            for i in range(len(binList)):
              if binList[i] == binNumber:# and estimateList[i]==estimateName:
                try: res.val = float(line.split()[1:][i])
                except: res.val = 0
    return res
Beispiel #9
0
    def observation(self, region, channel, setup):

        if channel=='all':
            return sum([self.cachedEstimate(region, c, setup) for c in channels])

        if channel=='SF':
            return sum([self.cachedObservation(region, c, setup) for c in ['MuMu', 'EE']])

        else:
            preSelection = setup.preselection('Data', channel=channel)
            cut = "&&".join([region.cutString(setup.sys['selectionModifier']), preSelection['cut']])

            logger.debug( "Using cut %s"% cut )

            if hasattr(setup, 'blinding') and setup.blinding: weight = 'weight*' + setup.blinding
            else:                                             weight = 'weight'
            return u_float(**self.sample[channel].getYieldFromDraw(selectionString = cut, weightString = weight) )
Beispiel #10
0
def getValFrom1BinnedHistOrGraph(hist):
    """
        if input is AsymTGraph, the average of errors is given 
    """
    if type(hist) in [ROOT.TH1F, ROOT.TH1D]:
        v = hist.GetBinContent(1)
        e = hist.GetBinError(1)
    if type(hist) in [ROOT.TH2F, ROOT.TH2D]:
        v = hist.GetBinContent(1, 1)
        e = hist.GetBinError(1, 1)
    if type(hist) in [ROOT.TGraphAsymmErrors]:
        v = hist.GetY()[0]
        el = hist.GetEYlow()[0]
        eh = hist.GetEYhigh()[0]
        if el and eh:
            e = sum([abs(el), abs(eh)]) / 2.
        else:
            e = max(abs(el), abs(eh))
        #print hist , (v,el,eh)
        #return (v, el, eh )
    return u_float(v, e)
Beispiel #11
0
    def observation(self, region, channel, setup):
        if channel.name == 'all':
            if setup.nLeptons == 3: channels = trilepChannels
            elif setup.nLeptons == 4: channels = quadlepChannels
            else: raise NotImplementedError
            preSelection = setup.preselection('Data')
            cut = "&&".join([
                region.cutString(setup.sys['selectionModifier']),
                preSelection['cut']
            ])

            logger.info(
                "Getting Data observation for channel %s and region %s" %
                (channel.name, region.cutString()))
            logger.info("Using cut %s" % cut)

            weight = 'weight'
            #return u_float(**self.sample.getYieldFromDraw(selectionString = cut, weightString = weight) )
            return sum(
                [self.cachedEstimate(region, c, setup) for c in channels])

        #if channel=='SF':
        #    return sum([self.cachedObservation(region, c, setup) for c in ['MuMu', 'EE']])

        else:
            preSelection = setup.preselection('Data',
                                              nElectrons=channel.nE,
                                              nMuons=channel.nM)
            cut = "&&".join([
                region.cutString(setup.sys['selectionModifier']),
                preSelection['cut']
            ])

            logger.debug("Using cut %s" % cut)

            weight = 'weight'
            return u_float(**self.sample.getYieldFromDraw(selectionString=cut,
                                                          weightString=weight))
Beispiel #12
0
def getEstimate(sample, region, channel, overwrite=False):
    ''' to be extended '''
    res = resultsDB(results_directory + "resultsCache_v2.db", "TopEFT",
                    columns)
    key = {
        "process": sample.name,
        "channel": channel,
        "region": region.cutString(),
        "lumi": lumi,
        "presel": presel,
        "weightString": weightString
    }
    if res.contains(key) and not overwrite:
        print "Found estimate for %s in region %s" % (sample.name, region)
        return res.get(key)
    else:
        print "Adding estimate for %s in region %s" % (sample.name, region)
        y = u_float(
            sample.getYieldFromDraw("&&".join([presel,
                                               region.cutString()]),
                                    weightString))
        res.add(key, y, overwrite=True)
        return y
 def reweight_func(pt, cosThetaStar):
     return u_float(t.GetBinContent(t.FindBin(cosThetaStar, pt)),
                    t.GetBinError(t.FindBin(cosThetaStar, pt)))
Beispiel #14
0
    def _estimate(self, region, channel, setup):
        if not setup.nonprompt:
            raise (NotImplementedError, "Need a nonprompt setup")
        ''' Concrete implementation of abstract method 'estimate' as defined in Systematic
        '''

        logger.info("Prediction for %s channel %s" % (self.name, channel))

        if channel.name == 'all':
            # estimate fake contribution from events with at least three loose leptons, and less than 3 tight leptons
            # take loose leptons with same pT requirements like analysis leptons

            tmpSample = self.sample

            variables = map(TreeVariable.fromString, [
                "run/I", "lumi/I", "evt/I", "Z_pt/F", "cosThetaStar/F",
                "weight/F", "met_pt/F", "Z_mass/F", "nJetSelected/I",
                "nBTag/I", 'Z_l1_index/I', 'Z_l2_index/I', 'nonZ_l1_index/I',
                'nonZ_l2_index/I', "nLeptons_FO_3l/I", "nLeptons_tight_3l/I",
                "nLeptons_tight_4l/I"
            ])
            if not self.sample.isData:
                logger.info("Adding weights to be read.")
                variables += map(
                    TreeVariable.fromString,
                    ['reweightPU36fb/F', 'reweightBTagDeepCSV_SF/F'])
            variables += [
                VectorTreeVariable.fromString(
                    'lep[pt/F,ptCorr/F,eta/F,phi/F,FO_3l/I,tight_3l/I,FO_SS/I,tight_SS/I,jetPtRatiov2/F,pdgId/I]'
                )
            ]

            tmpSample.setSelectionString([
                setup.preselection(self.dataMC,
                                   nElectrons=channel.nE,
                                   nMuons=channel.nM)['cut'],
                region.cutString()
            ])
            reader = tmpSample.treeReader(allBranchesActive=True,
                                          variables=variables)
            reader.start()
            fakeYield = u_float(0)

            nEvents = u_float(tmpSample.getYieldFromDraw())
            logger.info("Runing over %s events.", nEvents.val)

            while reader.run():
                nLep = len([l for l in reader.event.lep_pt if l > 0])
                lep = [
                    getObjDict(reader.event, "lep" + '_', [
                        "pt", "ptCorr", "eta", "phi", "FO_3l", "FO_SS",
                        "tight_3l", "tight_SS", "pdgId", "jetPtRatiov2"
                    ], i) for i in range(nLep)
                ]

                # get the relevant leptons
                lep = [l for l in lep if l[setup.leptonId]]

                # get tight and loose separately
                looseNotTight = [l for l in lep if not l[setup.tight_ID]]
                tight = [l for l in lep if l[setup.tight_ID]]
                nLooseNotTight = len(looseNotTight)
                nTight = len(tight)

                # Really get ALL possible combinations.
                allCombinations = itertools.combinations(
                    tight + looseNotTight, setup.nLeptons)
                for comb in allCombinations:
                    FR = 1.
                    nLooseNotTight = 0
                    for l in comb:
                        if l[setup.tight_ID]:
                            continue
                        else:
                            if abs(l['pdgId']) == 11: FRmap = self.elMap
                            elif abs(l['pdgId']) == 13: FRmap = self.muMap
                            else: raise NotImplementedError
                            # we run out of stats in data at higher pt, hence we cut at a lower value
                            ptCut = 45. if self.sample.isData else 99.
                            ptCorrected = l[
                                'ptCorr'] if l['ptCorr'] < ptCut else (ptCut -
                                                                       1)
                            FR_from_map = FRmap.GetBinContent(
                                FRmap.FindBin(ptCorrected, abs(l['eta'])))
                            if self.sample.isData:
                                FR *= FR_from_map / (1 - FR_from_map)
                            else:
                                FR *= FR_from_map
                            nLooseNotTight += 1

                    FR *= (-1)**(nLooseNotTight + 1)

                    allweights = [setup.sys['weight']] + setup.sys['reweight']

                    if self.sample.isData:
                        weight = 1
                    else:
                        weights = [
                            getattr(reader.event, w) for w in allweights
                        ]
                        weight = reduce(mul, weights, 1)

                    fakeYield += (weight * FR)
            # apply the statistical uncertainty to the result
            result = u_float(0.) if nEvents.val == 0 else u_float(
                fakeYield, (nEvents.sigma / nEvents.val) * fakeYield)
            return result if self.sample.isData else (result * setup.lumi /
                                                      1000.)
Beispiel #15
0
                        p = Process(process=proc, nEvents=50000, config=config)
                        if p.hasXSec(modified_couplings=modified_couplings):
                            logger.debug(
                                "Couplings:    %s", ", ".join([
                                    "%s=%5.4f" % c
                                    for c in modified_couplings.items()
                                ]))
                            xsec_val = p.xsec(
                                modified_couplings=modified_couplings)
                            ratio = xsec_val / SM_xsec[proc]
                            x_list.append(x)
                            y_list.append(y)
                            z_list.append(ratio.val)
                        else:
                            ratio = u_float(-1.)

                        config.cleanup()
                if interpolate:
                    a = toGraph2D(nameStr, nameStr, len(x_list), x_list,
                                  y_list, z_list)
                    xmin = min(x_list)
                    xmax = max(x_list)
                    ymin = min(y_list)
                    ymax = max(y_list)
                    bin_size_x = (abs(xmax) +
                                  abs(xmin)) / (3 * len(points[comb[0]]))
                    bin_size_y = (abs(ymax) +
                                  abs(ymin)) / (3 * len(points[comb[1]]))
                    nxbins = max(
                        1,
Beispiel #16
0
years = [2016,2017] if options.combine else [options.year]

for i, r in enumerate(regions):
    #i = i+15
    totalYield          = 0.
    backgroundYield     = 0.
    totalUncertainty    = 0.
    backgroundUncertainty = 0.

    if options.postFit:
        suffix = '_bestfit' if options.bestFit else '_r1'
        postFitResults = getPrePostFitFromMLF(cardFile.replace('.txt','_FD%s.root'%suffix)) #r1

    for p,tex in processes:

        pYield = u_float(0,0)
        preYield = u_float(0,0)
        pError = 0
        
        for year in years:

            postfix  = '_%s'%year
            prefix   = 'dc_%s_'%year if options.combine else ''
            binName  = prefix+'Bin%s'%i
            logger.info("Working on bin %s, process %s, year %s.", binName, p, year)
            proc = "%s_%s"%(p,year) if p in ["WZ","ZZ","TTX","rare","XG"] else p
            res      = getEstimateFromCard(cardFile, proc, binName, postfix=postfix)

            if options.postFit:
                tmpYield    = u_float(0,0)
                # postfit: all uncertainties already taken care of
Beispiel #17
0
 def mult(self, l):
     if len(l) > 0:
         res = l[0]
         for i in l[1:]: res = res*i
     else: res = u_float(1)
     return res
Beispiel #18
0
 def getPartialSF(self, effMap, pt, eta):
     sf  = effMap.GetBinContent(effMap.GetXaxis().FindBin(pt), effMap.GetYaxis().FindBin(eta))
     err = effMap.GetBinError(  effMap.GetXaxis().FindBin(pt), effMap.GetYaxis().FindBin(eta))
     return u_float(sf, err)
def wrapper(s):
    
    logger.info("Now working on %s", s.name)
    xSecScale = 1
    c = cardFileWriter.cardFileWriter()
    c.releaseLocation = combineReleaseLocation

    for coup in nonZeroCouplings:
        try:
            modification_dict[coup] = getCouplingFromName(s.name, coup)
            logger.info("The following coupling is set to non-zero value: %s: %s", coup, modification_dict[coup])
        except ValueError:
            logger.info("The following coupling is kept at zero: %s: %s", coup, modification_dict[coup])
            continue
    try:
        p = Process(process = "ttZ_ll", nEvents = 5000, config = config, xsec_cache=xsecDB)
        xsec = p.xsecDB.get(modification_dict)
    except IndexError:
        logger.info("Looking into backup DB for x-sec")
        p = Process(process = "ttZ_ll", nEvents = 5000, config = config, xsec_cache=xsecDB_Backup)
        xsec = p.xsecDB.get(modification_dict)
    if not xsec:
        try:
            p = Process(process = "ttZ_ll", nEvents = 5000, config = config, xsec_cache=xsecDB_Backup)
            xsec = p.xsecDB.get(modification_dict)
        except IndexError:
            logger.info("No x-sec found.")
    logger.info("Found modified x-sec of %s", xsec)
    
    cardFileName = os.path.join(limitDir, s.name+'.txt')
    if not os.path.exists(cardFileName) or overWrite:
        counter=0
        c.reset()
        c.setPrecision(3)
        postfix = '_%s'%args.year
        c.addUncertainty('PU',                  'lnN') # correlated
        c.addUncertainty('JEC'+postfix,         'lnN') # uncorrelated, for now!
        c.addUncertainty('btag_heavy'+postfix,  'lnN') # uncorrelated, wait for offical recommendation
        c.addUncertainty('btag_light'+postfix,  'lnN') # uncorrelated, wait for offical recommendation
        c.addUncertainty('trigger'+postfix,     'lnN') # uncorrelated, statistics dominated
        c.addUncertainty('leptonSF',            'lnN') # correlated
        c.addUncertainty('scale',               'lnN') # correlated.
        c.addUncertainty('scale_sig',           'lnN') # correlated.
        c.addUncertainty('PDF',                 'lnN') # correlated.
        c.addUncertainty('PartonShower',        'lnN') # correlated.
        c.addUncertainty('nonprompt',           'lnN') # correlated?!
        c.addUncertainty('WZ_xsec',             'lnN') # correlated.
        c.addUncertainty('WZ_bb',               'lnN') # correlated
        c.addUncertainty('WZ_powheg',           'lnN') # correlated
        c.addUncertainty('ZZ_xsec',             'lnN') # correlated.
        c.addUncertainty('ZG_xsec',             'lnN') # correlated.
        c.addUncertainty('rare',                'lnN') # correlated.
        c.addUncertainty('ttX',                 'lnN') # correlated.
        c.addUncertainty('Lumi'+postfix, 'lnN')

        uncList = ['PU', 'JEC', 'btag_heavy', 'btag_light', 'leptonSF', 'trigger']
        for unc in uncList:
            uncertainties[unc] = []
        
        ## use rate parameters??
        #c.addRateParameter('WZ', 1, '[0,2]')
        #c.addRateParameter('ZZ', 1, '[0,2]')

        for setupPair in setups:
            
            # extract the nominal and nonprompt setup from the pair
            setup, setupNP = setupPair
            
            signal      = MCBasedEstimate(name="TTZ", sample=setup.samples["TTZ"], cacheDir=setup.defaultCacheDir())
            #nonprompt   = FakeEstimate(name="nonPromptDD", sample=setup.samples["Data"], setup=setupNP, cacheDir=setup.defaultCacheDir())
            if args.unblind or (setup == setup3l_CR) or (setup == setup4l_CR):
                observation = DataObservation(name="Data", sample=setup.samples["Data"], cacheDir=setup.defaultCacheDir())
                logger.info("Using data!")
            else:
                observation = MCBasedEstimate(name="observation", sample=setup.samples["pseudoData"], cacheDir=setup.defaultCacheDir())
                logger.info("Using pseudo-data!")
            for e in setup.estimators: e.initCache(setup.defaultCacheDir())

            for r in setup.regions:
                totalBackground = u_float(0)
                for channel in setup.channels:
                    niceName = ' '.join([channel.name, r.__str__()])
                    binname = 'Bin'+str(counter)
                    logger.info("Working on %s", binname)
                    counter += 1
                    c.addBin(binname, [e.name.split('-')[0] for e in setup.estimators]+["nonPromptDD"], niceName)
                    #c.addBin(binname, 'nonPromptDD', niceName)

                    for e in setup.estimators:
                        name = e.name.split('-')[0]
                        if name.count('WZ'):
                            logger.info("Using reweighting to powheg for WZ sample")
                            wzReweighting = WZReweighting( cacheDir = reweightCacheWZ )
                            f = wzReweighting.cachedReweightingFunc( setup.WZselection )
                            powhegExpected = e.reweight1D(r, channel, setup, f)
                            expected = e.cachedEstimate(r, channel, setup)
                            print expected
                            WZ_powheg_unc = (powhegExpected-expected)/expected
                        else:
                            expected = e.cachedEstimate(r, channel, setup)
                        logger.info("Adding expectation %s for process %s", expected.val, name)
                        c.specifyExpectation(binname, name, expected.val if expected.val > 0.01 else 0.01)

                        totalBackground += expected

                        if not args.statOnly:
                            # uncertainties
                            pu          = 1 + e.PUSystematic( r, channel, setup).val            if expected.val>0.01 else 1.1
                            jec         = 1 + e.JECSystematic( r, channel, setup).val           if expected.val>0.01 else 1.1
                            btag_heavy  = 1 + e.btaggingSFbSystematic(r, channel, setup).val    if expected.val>0.01 else 1.1
                            btag_light  = 1 + e.btaggingSFlSystematic(r, channel, setup).val    if expected.val>0.01 else 1.1
                            trigger     = 1 + e.triggerSystematic(r, channel, setup).val        if expected.val>0.01 else 1.1
                            leptonSF    = 1 + e.leptonSFSystematic(r, channel, setup).val       if expected.val>0.01 else 1.1
                            if name.count('WZ'):
                                WZ_powheg   = 1 + WZ_powheg_unc.val                                 if expected.val>0.01 else 1.1

                            c.specifyUncertainty('PU',          binname, name, 1 + e.PUSystematic( r, channel, setup).val)
                            if not name.count('nonprompt'):
                                c.specifyUncertainty('JEC'+postfix,         binname, name, jec)
                                c.specifyUncertainty('btag_heavy'+postfix,  binname, name, btag_heavy)
                                c.specifyUncertainty('btag_light'+postfix,  binname, name, btag_light)
                                c.specifyUncertainty('trigger'+postfix,     binname, name, trigger)
                                c.specifyUncertainty('leptonSF',    binname, name, leptonSF)
                                c.specifyUncertainty('scale',       binname, name, 1.01) 
                                c.specifyUncertainty('PDF',         binname, name, 1.01)
                                c.specifyUncertainty('Lumi'+postfix, binname, name, 1.025 )

                            if name.count('ZZ'):    c.specifyUncertainty('ZZ_xsec',     binname, name, 1.10)
                            if name.count('ZG'):    c.specifyUncertainty('ZG_xsec',     binname, name, 1.20)
                            if name.count('WZ'):
                                c.specifyUncertainty('WZ_xsec',     binname, name, 1.10)
                                if setup == setup3l:
                                    c.specifyUncertainty('WZ_bb',     binname, name, 1.08)
                                c.specifyUncertainty('WZ_powheg',     binname, name, WZ_powheg)
                            
                            if name.count('nonprompt'):    c.specifyUncertainty('nonprompt',   binname, name, 1.30)
                            if name.count('rare'):    c.specifyUncertainty('rare',        binname, name, 1.50)
                            if name.count('TTX'):     c.specifyUncertainty('ttX',         binname, name, 1.11)


                        #MC bkg stat (some condition to neglect the smaller ones?)
                        uname = 'Stat_'+binname+'_'+name+postfix
                        c.addUncertainty(uname, 'lnN')
                        if expected.val > 0:
                            c.specifyUncertainty(uname, binname, name, 1 + expected.sigma/expected.val )
                        else:
                            c.specifyUncertainty(uname, binname, name, 1.01 )
                    
                    uname = 'Stat_'+binname+'_nonprompt'+postfix
                    c.addUncertainty(uname, 'lnN')
                    
                    if setup.nLeptons == 3 and setupNP:
                        nonprompt   = FakeEstimate(name="nonPromptDD", sample=setup.samples["Data"], setup=setupNP, cacheDir=setup.defaultCacheDir())
                        np = nonprompt.cachedEstimate(r, channel, setupNP)
                        if np.val < 0.01:
                            np = u_float(0.01,0.)
                        c.specifyExpectation(binname, 'nonPromptDD', np.val ) 
                        c.specifyUncertainty(uname,   binname, "nonPromptDD", 1 + np.sigma/np.val )
                        c.specifyUncertainty('nonprompt',   binname, "nonPromptDD", 1.30)
                    else:
                        np = u_float(0)
                        c.specifyExpectation(binname, 'nonPromptDD', np.val)
                    
                    if args.expected:
                        sig = signal.cachedEstimate(r, channel, setup)
                        obs = totalBackground + sig + np
                    elif args.unblind or (setup == setup3l_CR) or (setup == setup4l_CR):
                        obs = observation.cachedObservation(r, channel, setup)
                    else:
                        obs = observation.cachedEstimate(r, channel, setup)
                    c.specifyObservation(binname, int(round(obs.val,0)) )


                    if args.useShape:
                        logger.info("Using 2D reweighting method for shapes")
                        if args.model == "dim6top_LO":
                            source_gen = dim6top_central
                        elif args.model == "ewkDM":
                            source_gen = ewkDM_central

                        signalReweighting = SignalReweighting( source_sample = source_gen, target_sample = s, cacheDir = reweightCache)
                        f = signalReweighting.cachedReweightingFunc( setup.genSelection )
                        sig = signal.reweight2D(r, channel, setup, f)
                    else:
                        sig = signal.cachedEstimate(r, channel, setup)

                    xSecMod = 1
                    if args.useXSec:
                        xSecMod = xsec.val/xsec_central.val
                    
                    logger.info("x-sec is multiplied by %s",xSecMod)
                    
                    c.specifyExpectation(binname, 'signal', sig.val * xSecScale * xSecMod )
                    logger.info('Adding signal %s'%(sig.val * xSecScale * xSecMod))
                    
                    if sig.val>0:
                        c.specifyUncertainty('Lumi'+postfix, binname, 'signal', 1.025 )
                        if not args.statOnly:
                            # uncertainties
                            pu          = 1 + e.PUSystematic( r, channel, setup).val
                            jec         = 1 + e.JECSystematic( r, channel, setup).val
                            btag_heavy  = 1 + e.btaggingSFbSystematic(r, channel, setup).val
                            btag_light  = 1 + e.btaggingSFlSystematic(r, channel, setup).val
                            trigger     = 1 + e.triggerSystematic(r, channel, setup).val
                            leptonSF    = 1 + e.leptonSFSystematic(r, channel, setup).val

                            if sig.sigma/sig.val < 0.05:
                                uncertainties['PU']         += [pu]
                                uncertainties['JEC']        += [jec]
                                uncertainties['btag_heavy'] += [btag_heavy]
                                uncertainties['btag_light'] += [btag_light]
                                uncertainties['trigger']    += [trigger]
                                uncertainties['leptonSF']   += [leptonSF]

                            c.specifyUncertainty('PU',                  binname, "signal", pu)
                            c.specifyUncertainty('JEC'+postfix,         binname, "signal", jec)
                            c.specifyUncertainty('btag_heavy'+postfix,  binname, "signal", btag_heavy)
                            c.specifyUncertainty('btag_light'+postfix,  binname, "signal", btag_light)
                            c.specifyUncertainty('trigger'+postfix,     binname, "signal", trigger)
                            c.specifyUncertainty('leptonSF',            binname, "signal", leptonSF)
                            # This doesn't get the right uncertainty in CRs. However, signal doesn't matter there anyway.
                            if setup in [setup3l, setup4l]:
                                c.specifyUncertainty('scale_sig',   binname, "signal", 1 + scale_cache.get({"region":r, "channel":channel.name, "PDFset":"scale"}).val)
                                c.specifyUncertainty('PDF',         binname, "signal", 1 + PDF_cache.get({"region":r, "channel":channel.name, "PDFset":PDFset}).val)
                                c.specifyUncertainty('PartonShower',binname, "signal", PS_cache.get({"region":r, "channel":channel.name, "PDFset":"PSscale"}).val) #something wrong here?
                            #c.specifyUncertainty('scale_sig',   binname, "signal", 1.05) #1.30
                            #c.specifyUncertainty('PDF',         binname, "signal", 1.04) #1.15

                        uname = 'Stat_'+binname+'_signal'+postfix
                        c.addUncertainty(uname, 'lnN')
                        c.specifyUncertainty(uname, binname, 'signal', 1 + sig.sigma/sig.val )
                    else:
                        uname = 'Stat_'+binname+'_signal'+postfix
                        c.addUncertainty(uname, 'lnN')
                        c.specifyUncertainty(uname, binname, 'signal', 1 )

                    
        #c.addUncertainty('Lumi'+postfix, 'lnN')
        #c.specifyFlatUncertainty('Lumi'+postfix, 1.026)
        cardFileName = c.writeToFile(cardFileName)
    else:
        logger.info("File %s found. Reusing.",cardFileName)
    
    res = {}
    
    if not os.path.isdir(limitDir):
        os.makedirs(limitDir)
    resDB = resultsDB(limitDir+'/results.sq', "results", setup.resultsColumns)
    res = {"signal":s.name}
    if not overWrite and res.DB.contains(key):
        res = resDB.getDicts(key)[0]
        logger.info("Found result for %s, reusing", s.name)
    else:
        # We don't calculate limits here, but just in case we find a way how to do it, put placeholders here
        res.update({"exp":0, "obs":0, "exp1up":0, "exp2up":0, "exp1down":0, "exp2down":0})
        # Don't extract all the nuisances by default
        signalRegions = range(15,30) ## shouldn't be hardcoded
        masks = ['mask_ch1_Bin'+str(i)+'=1' for i in signalRegions]
        masks = ','.join(masks)

        if args.calcNuisances:
            c.calcNuisances(cardFileName, masks=masks)
        # extract the NLL
        #nll = c.calcNLL(cardFileName, options="")
        nll = c.physicsModel(cardFileName, options="", normList=["WZ_norm","ZZ_norm"], masks=masks) # fastScan turns of profiling
        if nll["nll0"] > 0:
            res.update({"dNLL_postfit_r1":nll["nll"], "dNLL_bestfit":nll["bestfit"], "NLL_prefit":nll["nll0"]})
        else:
            res.update({"dNLL_postfit_r1":-999, "dNLL_bestfit":-999, "NLL_prefit":-999})
            logger.info("Fits failed, adding values -999 as results")
        logger.info("Adding results to database")
        resDB.add(res, nll['nll_abs'], overwrite=True)

    print
    print "NLL results:"
    print "{:>15}{:>15}{:>15}".format("Pre-fit", "Post-fit r=1", "Best fit")
    print "{:15.2f}{:15.2f}{:15.2f}".format(float(res["NLL_prefit"]), float(res["NLL_prefit"])+float(res["dNLL_postfit_r1"]), float(res["NLL_prefit"])+float(res["dNLL_bestfit"]))
    
    print 'PU', min(uncertainties['PU']), max(uncertainties['PU'])
    print 'JEC', min(uncertainties['JEC']), max(uncertainties['JEC'])
    print 'btag_heavy', min(uncertainties['btag_heavy']), max(uncertainties['btag_heavy'])
    print 'btag_light', min(uncertainties['btag_light']), max(uncertainties['btag_light'])
    print 'trigger', min(uncertainties['trigger']), max(uncertainties['trigger'])
    print 'leptonSF', min(uncertainties['leptonSF']), max(uncertainties['leptonSF'])
Beispiel #20
0
}

processes = ["ttZ", "ttH", "ttW"]

SM_xsec = {}

modified_couplings = {args.coupling: 0.0}

for proc in processes:
    logger.info("Checking SM x-sec:")
    config = Configuration(model_name=model_name,
                           modified_couplings=modified_couplings)
    p = Process(process=proc, nEvents=50000, config=config)
    SM_xsec[proc] = p.xsec()
    logger.info("SM x-sec for %s is %s", proc, SM_xsec[proc])
    if SM_xsec[proc].val == 0.: SM_xsec[proc] = u_float(1)

del config

hists = []
fits = []
m = 0

if args.scale:
    scale = lambdaSqInv[args.coupling]
else:
    scale = 1

for proc in processes:
    #hists.append(ROOT.TGraph(len(couplingValues)))
    #hists.append(ROOT.TH1F(p.process,"",len(couplingValues),min(couplingValues),max([abs(min(couplingValues)),max(couplingValues)])))
Beispiel #21
0
#triggers = {"singleLep_addDiLep_addTriLep": "(%s)"%"||".join(singleMuTTZ+singleEleTTZ+diMuTriggers+diEleTriggers+EMuTriggers+trilepTriggers)}
#triggers = {"stopDilepMix": "((HLT_mumuIso||HLT_mumuNoiso)||(HLT_ee_DZ||HLT_ee_33||HLT_ee_33_MW)||(HLT_mue||HLT_mu30e30)||HLT_SingleMu_noniso||HLT_SingleEle_noniso)"}
#triggers = {"ttHMix": "(%s)"%"||".join(singleMuTriggers+singleEleTriggers+diMuTriggers+diEleTriggers+EMuTriggers+trilepTriggers)}
#triggers = {"ttHMix_no3l": "(%s)"%"||".join(singleMuTriggers+singleEleTriggers+diMuTriggers+diEleTriggers+EMuTriggers)}

for trigger in triggers:
    for c in channels:
        print c

        h_total = ROOT.TH1F("total", "", nReg, 0, nReg)
        h_trigg = ROOT.TH1F("trigger", "", nReg, 0, nReg)
        h_ratio = ROOT.TH1F("eff", "", nReg, 0, nReg)
        h_ratio.Sumw2()

        for j, r in enumerate(regions):
            num = u_float(0)
            denom = u_float(0)
            for i, sample in enumerate(signal + bkg):
                print sample.name
                val = sample.getYieldFromDraw(
                    '&&'.join([presel, channels[c], r]), "weight*35.9")
                trig = sample.getYieldFromDraw(
                    '&&'.join([presel, channels[c], r, triggers[trigger]]),
                    "weight*35.9")
                print j, val, trig
                num += u_float(val)
                denom += u_float(trig)

            h_total.SetBinContent(j + 1, num.val)
            h_total.SetBinError(j + 1, num.sigma)
            h_trigg.SetBinContent(j + 1, denom.val)