sample.style = styles.fillStyle(sample.color) for sample in mc + signals: sample.scale = lumi_scale sample.read_variables = [ 'reweightBTagCSVv2_SF/F', 'reweightBTagDeepCSV_SF/F', 'reweightPU36fb/F', 'reweightTrigger_tight_4l/F', 'reweightLeptonTrackingSF_tight_4l/F', 'nTrueInt/F', 'reweightPU36fb/F', 'reweightLeptonSF_tight_4l/F' ] #, 'reweightLeptonSF_tight_4l/F'] if args.year == 2016: sample.weight = lambda event, sample: event.reweightBTagDeepCSV_SF * event.reweightTrigger_tight_4l * event.reweightLeptonTrackingSF_tight_4l * event.reweightPU36fb * event.reweightLeptonSF_tight_4l #*nTrueInt36fb_puRW(event.nTrueInt) else: sample.weight = lambda event, sample: event.reweightBTagDeepCSV_SF * event.reweightTrigger_tight_4l * event.reweightPU36fb * event.reweightLeptonSF_tight_4l #*event.reweightLeptonSF_tight_4l #*nTrueInt36fb_puRW(event.nTrueInt) tr = triggerSelector(args.year) sample.setSelectionString([ getFilterCut(isData=False, year=args.year), getLeptonSelection(mode), tr.getSelection("MC") ]) yt_TWZ_filter.scale = lumi_scale * 1.07314 if not args.noData: stack = Stack(mc, data_sample) else: stack = Stack(mc) stack.extend([[s] for s in signals])
# TZQ.color = ROOT.kRed - 9 dim6top_TTW.color = ROOT.kRed for sample in mc: sample.style = styles.fillStyle(sample.color) for sample in mc: sample.scale = lumi_scale #if args.WZpowheg and sample in [WZ_powheg]: # sample.scale = lumi_scale * 4.666/4.42965 # get same x-sec as amc@NLO #sample.read_variables = ['reweightTopPt/F','reweightDilepTriggerBackup/F','reweightLeptonSF/F','reweightBTag_SF/F','reweightPU36fb/F', 'nTrueInt/F', 'reweightLeptonTrackingSF/F'] #sample.weight = lambda event, sample: event.reweightTopPt*event.reweightBTag_SF*event.reweightLeptonSF*event.reweightDilepTriggerBackup*event.reweightPU36fb*event.reweightLeptonTrackingSF # dilep reweight? sample.read_variables = ['reweightBTagCSVv2_SF/F', 'reweightBTagDeepCSV_SF/F', 'reweightPU36fb/F', 'reweightLeptonSFSyst_tight_3l/F', 'reweightLeptonTrackingSF_tight_3l/F', 'reweightTrigger_tight_3l/F', "Z_pt/F"] sample.weight = lambda event, sample: event.reweightBTagDeepCSV_SF*event.reweightPU36fb*event.reweightLeptonSFSyst_tight_3l*event.reweightLeptonTrackingSF_tight_3l*event.reweightTrigger_tight_3l tr = triggerSelector(2016) sample.setSelectionString([getFilterCut(isData=False), getLeptonSelection(mode), tr.getSelection("MC")]) if not args.noData: stack = Stack(mc, data_sample) else: stack = Stack(mc) if args.small: for sample in stack.samples: sample.reduceFiles( to = 1 ) # Use some defaults Plot.setDefaults(stack = stack, weight = staticmethod(weight_), selectionString = cutInterpreter.cutString(args.selection), addOverFlowBin='upper') plots = []
def selection(self, dataMC, mllMin, metMin, zWindow1, zWindow2, zMassRange, nJets, nBTags, nElectrons=-1, nMuons=-1, hadronicSelection=False, isFastSim=False): '''Define full selection dataMC: 'Data' or 'MC' nElectrons, nMuons: Number of E and M. -1: all zWindow: offZ, onZ, or allZ hadronicSelection: whether to return only the hadronic selection isFastSim: adjust filter cut etc. for fastsim ''' nLeptons = self.nLeptons # Get the right channel and do sanity checks if nElectrons < 0 and nMuons < 0: # this should be the new "all" case. Just pass else: if nElectrons + nMuons != nLeptons: raise NotImplementedError("Electrons and Muons don't add up!") #Consistency checks if self.sys['selectionModifier']: assert self.sys[ 'selectionModifier'] in jmeVariations + metVariations + [ 'genMet' ], "Don't know about systematic variation %r, take one of %s" % ( self.sys['selectionModifier'], ",".join(jmeVariations + ['genMet'])) assert dataMC in ['Data', 'MC'], "dataMC = Data or MC, got %r." % dataMC #Postfix for variables (only for MC and if we have a jme variation) sysStr = "" metStr = "" if dataMC == "MC" and self.sys['selectionModifier'] in jmeVariations: sysStr = "_" + self.sys['selectionModifier'] if dataMC == "MC" and self.sys['selectionModifier'] in metVariations: metStr = "_" + self.sys['selectionModifier'] res = {'cuts': [], 'prefixes': []} if nJets and not (nJets[0] == 0 and nJets[1] < 0): assert nJets[0] >= 0 and ( nJets[1] >= nJets[0] or nJets[1] < 0), "Not a good nJets selection: %r" % nJets njetsstr = "nJetSelected" + sysStr + ">=" + str(nJets[0]) prefix = "nJets" + str(nJets[0]) if nJets[1] >= 0: njetsstr += "&&" + "nJetSelected" + sysStr + "<=" + str( nJets[1]) if nJets[1] != nJets[0]: prefix += str(nJets[1]) else: prefix += 'p' res['cuts'].append(njetsstr) res['prefixes'].append(prefix) if nBTags and not (nBTags[0] == 0 and nBTags[1] < 0): assert nBTags[0] >= 0 and ( nBTags[1] >= nBTags[0] or nBTags[1] < 0), "Not a good nBTags selection: %r" % nBTags nbtstr = "nBTag" + sysStr + ">=" + str(nBTags[0]) prefix = "nbtag" + str(nBTags[0]) if nBTags[1] >= 0: nbtstr += "&&nBTag" + sysStr + "<=" + str(nBTags[1]) if nBTags[1] != nBTags[0]: prefix += str(nBTags[1]) else: prefix += 'p' res['cuts'].append(nbtstr) res['prefixes'].append(prefix) if metMin and metMin > 0: res['cuts'].append('met_pt' + sysStr + metStr + '>=' + str(metMin)) res['prefixes'].append('met' + str(metMin)) if not hadronicSelection: if mllMin and mllMin > 0: res['cuts'].append('min_dl_mass>=' + str(mllMin)) res['prefixes'].append('mll' + str(mllMin)) if nMuons >= 0 and nElectrons >= 0: chStr = "(nMuons_%s==%i&&nElectrons_%s==%i)" % ( self.leptonId, nMuons, self.leptonId, nElectrons) else: # this is for the 'all' channel if not self.nonprompt: chStr = "nLeptons_%s==%i" % (self.leptonId, nLeptons) else: chStr = "nLeptons_%s>=%i" % (self.leptonId, nLeptons) #Z window # two different cases: Z_mass for 3l, Z1_mass_4l and Z2_mass_4l for 4l if nLeptons == 3: res['cuts'].append(getZCut(zWindow1, "Z_mass", zMassRange)) if not self.nonprompt: res['cuts'].append("Z_fromTight>0") elif nLeptons == 4: res['cuts'].append(getZCut(zWindow1, "Z1_mass_4l", zMassRange)) if zWindow2 == 'offZ': # if number of muons is even, go off-Z if nMuons % 2 == 0: logger.info("Z window 2 off Z, nMuons %s", nMuons) res['cuts'].append( getZCut("offZ", "Z2_mass_4l", zMassRange)) else: logger.info("Z window 2 all Z, nMuons %s", nMuons) res['cuts'].append( getZCut("allZ", "Z2_mass_4l", zMassRange)) else: logger.info("Z window 2 %s, nMuons %s", zWindow2, nMuons) res['cuts'].append( getZCut(zWindow2, "Z2_mass_4l", zMassRange)) # no Z-mass cut for 2l case res['cuts'].append(chStr) if not self.nonprompt: res['cuts'].append('nLeptons_%s==%i' % (self.leptonId, nLeptons)) else: res['cuts'].append('nLeptons_%s>=%i' % (self.leptonId, nLeptons)) if nLeptons == 1: lep_pt = "(lep_%s*(lep_pt - lep_ptCorr) + lep_ptCorr)" % self.tight_ID res['cuts'].append("Sum$(%s>40&&lep_%s>0)>0" % (lep_pt, self.leptonId)) res['cuts'].append("nlep==1") # loose lepton veto elif nLeptons == 2: raise NotImplementedError("Not yet thought about SS selection") elif nLeptons == 3: lep_pt = "(lep_%s*(lep_pt - lep_ptCorr) + lep_ptCorr)" % self.tight_ID leptonSelection = [\ "Sum$(%s>40&&lep_%s>0)>0"%(lep_pt, self.leptonId),\ "Sum$(%s>20&&lep_%s>0)>1"%(lep_pt, self.leptonId),\ "Sum$(%s>10&&lep_%s>0)>2"%(lep_pt, self.leptonId),\ ] res['cuts'].append("&&".join(leptonSelection)) res['cuts'].append( "!(nLeptons_tight_4l>=4)" ) # make sure to remove full overlap with 4l. This is enought, what is below shouldn't be necessary. if self.nonprompt: res['cuts'].append("nLeptons_tight_3l<3") #res['cuts'].append("min_dl_mass_FO_3l>12") #######################UPDATE ## need to veto 4l events to remove overlap #baseline4l = Setup(self.year, nLeptons=4) #baseline4l.parameters.update({'nJets':(2,-1), 'nBTags':(0,-1), 'zMassRange':20}) #for c in quadlepChannels: # res['cuts'].append("!(%s)"%baseline4l.preselection(dataMC, nElectrons=c.nE, nMuons=c.nM, short=True)['cut']) elif nLeptons == 4: res['cuts'].append( "Sum$(lep_pt>40&&lep_%s>0)>0 && Sum$(lep_pt>10&&lep_%s>0)>3" % (self.leptonId, self.leptonId)) #check if this is good enough res['cuts'].append("min_dl_mass>12&&totalLeptonCharge==0") else: raise NotImplementedError( "nLeptons has to be 1 or 2 or 3 or 4. That's already more than enough to think about." ) # Need a better solution for the Setups for different eras if self.year == 20167: self.year = 2016 #FIXME since we use 2016 MC for now if not self.short: res['cuts'].append( getFilterCut(isData=(dataMC == 'Data'), isFastSim=isFastSim, year=self.year)) # apply triggers in MC if not dataMC == 'Data': tr = triggerSelector(self.year) if not self.short: res['cuts'].append(tr.getSelection("MC")) res['cuts'].extend(self.externalCuts) return { 'cut': "&&".join(res['cuts']), 'prefix': '-'.join(res['prefixes']), 'weightStr': (self.weightString() if dataMC == 'MC' else 'weight') }