예제 #1
0
    def applyCuts(self,objects):
        """Apply cuts to our event-level quantities."""
        self.objects = objects # unique to each event

        # ----------------------- #
        # CONFIGURE EVENT OBJECTS #
        # ----------------------- #
        event_level_keys = self.cuts[self.lvl].keys()
        remake_met = [self.skip_met,self.redefine_met][('met' in self.objects.keys())]
        if any('ht' in ee for ee in event_level_keys):
            self.objects['ht'] = vlq.calcHT(self.objects)

            ## modify the objects dictionary to make keys for met,mtw,met+mtw,HT
            self.init_met()
        elif 'met' in self.objects.keys():
            self.init_met()
        elif 'mass_lb' in event_level_keys:    
            self.objects['mass_lb'] = (self.objects['lepton']+self.objects['bjets'][0]).M()
        elif 'A_mass' in event_level_keys:
            self.objects['A_mass'] = self.objects['TTbar']['A_mass']
        elif 'A_dr' in event_level_keys:
            self.objects['A_dr']   = self.objects['TTbar']['A_dr']
        elif 'A_distance' in event_level_keys:
            self.objects['A_distance'] = self.objects['TTbar']['asymmR']


        # -------------------------- #
        # LOOP OVER EVENT-LEVEL CUTS #
        # -------------------------- #
        #
        # There are three cases for types of event-level cuts:
        # 1. DeltaX cut -- requires 2 4-vectors inside parentheses
        # 2. min/max    -- no DeltaX cut, can contain anything inside
        # 3. Unique     -- [HT,nbtags,met+mtw]; no processing (grab from self.objects)
        for _k in event_level_keys:

            failed_cut     = False
            evt_results    = []
            self.cut_value = self.cuts[self.lvl][_k]['value'] # cut value
            self.cut_cond  = self.cuts[self.lvl][_k]['cond']  # cut condition (>,<,etc.)

            ##
            ## CASE 1 or 2
            ##
            if any(_k.startswith(i) for i in self.op_keys):

                ## -- CASE 1: DeltaX
                if any(i+'(' in _k for i in self.name2attr.keys()):
                    c_result = self.deltaX_cut(_k)
                    # {'result':False,'value':None}
                    # {'result':True,'value':evt_objects}
                    # evt_objects = {'names':[name0,name1],\
                    #                name0:  {'isVector':False,'index':None},\
                    #                name1:  {'isVector':False,'index':None},\
                    #                'minmax':min_max}

                    if not c_result['result']:
                        remake_met()
                        return {'result':False,'objects':self.objects}
                    # cut passed, now we need to either:
                    #    - save only the objects that passed the cut
                    #    - return all objects (min/max) [do nothing]
                    else:
                        c_result = c_result['value']
                        if not c_result['min_max']:
                            ## set new objects that survived!
                            good_objects        = [None,None]
                            obj0_name,obj1_name = c_result['names']

                            # -- Save object '0'
                            if not c_result[obj0_name]['isVector']:
                                good_objects[0] = self.objects[obj0_name]
                            else:
                                good_objects[0]  = []
                                selected_objects = [] # only save an object once
                                for ii in c_result[obj0_name]['index']:
                                    if ii not in selected_objects:
                                        selected_objects.append(ii)
                                        good_objects[0].append( self.objects[obj0_name][ii] )

                            self.objects[obj0_name] = good_objects[0]

                            # -- Save object '1'
                            if not c_result[obj1_name]['isVector']:
                                good_objects[1] = self.objects[obj1_name]
                            else:
                                good_objects[1]  = []
                                selected_objects = [] # only save an object once
                                for ii in c_result[obj1_name]['index']:
                                    if ii not in selected_objects:
                                        selected_objects.append(ii)
                                        good_objects[1].append( self.objects[obj1_name][ii] )

                            self.objects[obj1_name] = good_objects[1]
                            ## -- end saving -- ##

                ## -- CASE 2: min/max
                else:
                    c_result = self.minmax_cut(_k)

                    if not c_result['result']:
                        remake_met()
                        return {'result':False,'objects':self.objects}


            ##
            ## CASE 3
            ##
            else:
                c_result = self.ops[self.cut_cond]( self.objects[_k],self.cut_value )
                if not c_result:
                    remake_met()
                    return {'result':False,'objects':self.objects}


        ## -- Event Succeeded! -- ##
        remake_met()

        return {'result':True,'objects':self.objects}
예제 #2
0
    def event_loop(self,Entry):
        """Running the event selection for a single event."""
        self.entry = Entry

        logging.getLogger('share/{0}.log'.format(self.cfg_name))
        loggingLEVEL = logging.getLogger().getEffectiveLevel() # DEBUG, INFO, ERROR, etc.
        logging.info("")
        logging.critical(" -- In file 'SelectionBase.py'\n")
        logging.info("  ------------  ")

        self.t.GetEntry(self.entry)

        sampleID   = self.t.mcChannelNumber
        if sampleID > 0:
            self.isMC   = True
            evt_weights = self.Weights[self.energy][str(sampleID)]
            KFactor     = evt_weights['KFactor']
            XSection    = evt_weights['XSection']
            FilterEff   = evt_weights['FilterEff']
        else:
            self.isMC   = False
            KFactor     = 1.0
            XSection    = 1.0
            FilterEff   = 1.0


        if not self.entry%1000:
            print "  -> Entry {0}".format(self.entry) # So we can see it's actually running


        # Initialize these variables in case stuff fails 
        # Then, empty things are just passed around
        passedSelection     = False
        savedEventVariables = {'fatjets':   [],\
                               'rcjets':    [],\
                               'resjets':   [],\
                               'bjets':     [],\
                               'lepton':    None,\
                               'nu':        None,\
                               'jets':      [],\
                               'tjets':     [],\
                               'met':       -999.,\
                               'HT':        -999.,\
                               'MC':        {},\
                               'eventinfo': {}}

        # ---------------- #
        # Physics Objects  #
        # ---------------- #
        self.initializeObjects()

        # Protect against events with 3 jets but no boosted candidate
        if len(self.objects['jets']) <= 3 and not self.objects['fatjets']:
            logging.error(" Processing Pre-selection failed ")
            logging.error(" -- Entry {0} ".format(self.entry))
            logging.error(" -- Too few jets (3 small-r jets and not Boosted) ")
            logging.info(" jet assignments failed.") 
            return {'objects':savedEventVariables,'result':passedSelection}


        # ---------------- #
        # Cuts             #
        # ---------------- #
        ## -- cuts on objects
        c_objlevel = self.objectLevelCuts()  # function below
        if not c_objlevel['result']:
            return {'objects':savedEventVariables,'result':passedSelection}
        self.objects = c_objlevel['objects']  # update our dictionary of objects

        ## -- cuts on event-level quantities (HT, DeltaR(x,y), etc.)
        c_evtlevel = self.eventLevelCuts()   # function below
        if not c_evtlevel['result']:
            return {'objects':savedEventVariables,'result':passedSelection}
        self.objects = c_evtlevel['objects']

        ## -- record HT if it hasn't been saved or used
        if not self.objects.get('ht'):
            self.objects['ht'] = vlq.calcHT(self.objects)

        # ---------------- #
        # Hadronic W       #
        # ---------------- #
        logging.debug(' Hadronic W')
        self.resjets  = []

        ## Check for boosted W first
        if not self.objects['fatjets']:
            logging.debug(' Resolved Event')
            self.objects['resjets'] = [self.objects['jets'][0]+self.objects['jets'][1]]


        # ----------------- #
        # Truth Information #
        # ----------------- #
        all_sample_dsids = info.dsids()
        signal_dsids = all_sample_dsids['signal']['TTS'].keys()        # Just TTS
        ttbar_dsids  = all_sample_dsids['background']['ttbar'].keys()
        if self.isMC:
            if self.t.mcChannelNumber in signal_dsids:
                self.SetupTruth('vlq')
            elif self.t.mcChannelNumber in ttbar_dsids:
                if not self.init_prev_entry:
                    prev_truth_entry = 0
                else:
                    prev_truth_entry = int(open(self.ttbar_truth_file,'r').readlines()[0])
                self.SetupTruth('ttbar',prev_truth_entry)
            else:
                self.MC = {}
        else:
            self.MC = {}


        # ---------------- #
        # Event Info       #
        # ---------------- #
        boostedEvent       = (len(self.objects['fatjets'])>0) # converted to int in miniSL
        resolvedEvent      = (not boostedEvent)

        if self.isMC:
            trackjet_btag_weight_70 = self.t.weight_trackjet_bTagSF_70
            btag_weight_60     = self.t.weight_bTagSF_60
            btag_weight_70     = self.t.weight_bTagSF_70
            btag_weight_77     = self.t.weight_bTagSF_77
            btag_weight_85     = self.t.weight_bTagSF_85
            lept_eff           = self.t.weight_leptonSF
            self.weight_mc     = self.t.weight_mc
            self.weight_pileup = self.t.weight_pileup
        else:
            trackjet_btag_weight_70 = 1.0
            btag_weight_60     = 1.0
            btag_weight_70     = 1.0
            btag_weight_77     = 1.0
            btag_weight_85     = 1.0
            lept_eff           = 1.0
            self.weight_mc     = 1.0
            self.weight_pileup = 1.0



        eventInfo = {'mcWeight':        self.weight_mc,\
                     'pileupWeight':    self.weight_pileup,\
                     'eventNumber':     self.t.eventNumber,\
                     'runNumber':       self.t.runNumber,\
                     'mcChannelNumber': self.t.mcChannelNumber,\
                     'mu':              self.t.mu,\
                     'nAMI':            self.eventWeight[self.t.mcChannelNumber],\
                     'KFactor':         KFactor,\
                     'XSection':        XSection,\
                     'FilterEff':       FilterEff,\
                     'weight_btag_track_70': trackjet_btag_weight_70,\
                     'weight_btag_60':  btag_weight_60,\
                     'weight_btag_70':  btag_weight_70,\
                     'weight_btag_77':  btag_weight_77,\
                     'weight_btag_85':  btag_weight_85,\
                     'weight_lep_eff':  lept_eff,\
                     'isBoosted':       boostedEvent,\
                     'isResolved':      resolvedEvent,\
                     'mujets':          self.t.mujets,\
                     'ejets':           self.t.ejets,\
                     'nbtags':          self.objects['nbtags'],\
                     'vlq_tag':         self.objects['vlq_evtype']}



       # ------------------------------------------------------------- #
       # Log the results for inspection later                          #    
       # ------------------------------------------------------------- #
        if loggingLEVEL >= 20:
            self.logResults()

       # ------------------------------------------------------------- #
       # Return the results to miniSL.py                               #    
       # ------------------------------------------------------------- #
        passedSelection     = True
        savedEventVariables = {'fatjets':   self.objects['fatjets'],\
                               'rcjets':    self.objects['rcjets'],\
                               'resjets':   self.objects['resjets'],\
                               'lepton':    self.objects['lepton'],\
                               'nu':        self.objects['nu'],\
                               'jets':      self.objects['jets'],\
                               'tjets':     self.objects['tjets'],\
                               'met':       self.objects['met'],\
                               'HT':        self.objects['ht'],\
                               'MC':        self.MC,\
                               'eventinfo': eventInfo}
        ## Hard-coded analysis-specific objects...
        if self.objects.get('bjets'):
            savedEventVariables['bjets'] = self.objects['bjets']
        else:
            savedEventVariables['bjets'] = []


        return {'objects':savedEventVariables,'result':passedSelection}
예제 #3
0
    def event_loop(self,Entry):
        """Running the event selection for a single event."""
        self.entry = Entry
        self.t.GetEntry(self.entry)

        if not self.entry%1000:
            print "  -> Entry {0}".format(self.entry)

        ## Initialize these in case stuff fails we can return empty values
        passedSelection     = False
        savedEventVariables = {'fatjets':   [],\
                               'rcjets':    [],\
                               'resjets':   [],\
                               'bjets':     [],\
                               'jets':      [],\
                               'lepton':    False,\
                               'nu':        False,\
                               'MET':       0,\
                               'HT':        0,\
                               'MC':        {},\
                               'eventinfo': {}}

        # ---------------- #
        # Physics Objects  #
        # ---------------- #
        self.initializeObjects()


        # ---------------- #
        # Cuts             #
        # ---------------- #
        ## Cutting on truth objects? DeltaR matching?
        if any('truth' in i for i in self.cuts):
            truth_objs = truthBase(self.t)
            for truth_obj in truth_objs.keys():
                self.objects[truth_obj] = truth_objs[truth_obj]

        ## -- cuts on objects
        c_objlevel = self.objectLevelCuts()  # function below
        if not c_objlevel['result']:
            return {'objects':savedEventVariables,'result':passedSelection}
        self.objects = c_objlevel['objects']  # update our dictionary of objects

        ## -- cuts on event-level quantities (HT, DeltaR(x,y), etc.)
        c_evtlevel = self.eventLevelCuts()   # function below
        if not c_evtlevel['result']:
            return {'objects':savedEventVariables,'result':passedSelection}
        self.objects = c_evtlevel['objects']

        ## -- record HT if it hasn't been saved or used
        if not self.objects.get('ht'):
            self.objects['ht'] = vlq.calcHT(self.objects)

        # ---------------- #
        # Event Info       #
        # ---------------- #
        signal_dsids = info.dsids()['signal']['TTS'].keys()
        ttbar_dsids  = info.dsids()['background']['ttbar'].keys()
        if self.t.mcChannelNumber in signal_dsids+ttbar_dsids:
            # setup the truth (after cuts and only for signal & ttbar)
            self.MC = truthBase(self.t)
        else:
            self.MC = {}

        boostedEvent   = (len(self.objects['fatjets'])>0)
        resolvedEvent  = (not boostedEvent)

        eventInfo = {'mcWeight':        self.t.weight_mc,\
                     'pileupWeight':    self.t.weight_pileup,\
                     'eventNumber':     self.t.eventNumber,\
                     'runNumber':       self.t.runNumber,\
                     'mcChannelNumber': self.t.mcChannelNumber,\
                     'mu':              self.t.mu,\
                     'weight_btag_track_70': self.t.weight_btag_track_70,\
                     'weight_btag_60':  self.t.weight_btag_60,\
                     'weight_btag_70':  self.t.weight_btag_70,\
                     'weight_btag_77':  self.t.weight_btag_77,\
                     'weight_btag_85':  self.t.weight_btag_85,\
                     'weight_lep_eff':  self.t.weight_lept_eff,\
                     'nAMI':            self.t.AMI,\
                     'isBoosted':       boostedEvent,\
                     'isResolved':      resolvedEvent,\
                     'mujets':          self.t.mujets,\
                     'ejets':           self.t.ejets,\
                     'nbtags':          self.t.btags_n,\
                     'KFactor':         self.t.KFactor,\
                     'XSection':        self.t.XSection,\
                     'vlq_tag':         self.t.vlq_evtype,\
                     'FilterEff':       self.t.FilterEff}

       # ------------------------------------------------------------- #
       # Log the results for inspection later                          #    
       # ------------------------------------------------------------- #
        if self.loggingLEVEL >= 20:
            self.logResults()

       # ------------------------------------------------------------- #
       # Return the results to miniSL.py                               #    
       # ------------------------------------------------------------- #
        passedSelection     = True
        savedEventVariables = {'fatjets':   self.objects['fatjets'],\
                               'rcjets':    self.objects['rcjets'],\
                               'resjets':   self.objects['resjets'],\
                               'lepton':    self.objects['lepton'],\
                               'nu':        self.objects['nu'],\
                               'jets':      self.objects['jets'],\
                               'tjets':     self.objects['tjets'],\
                               'met':       self.objects['met'],\
                               'HT':        self.objects['ht'],\
                               'MC':        self.MC,\
                               'eventinfo': eventInfo}

        ## Analysis-specific custom object :: need to remove this hard-coding...
        if self.objects.get('TTbar'):
            savedEventVariables['TTbar'] = self.objects['TTbar']
        else:
            savedEventVariables['TTbar'] = []


        return {'objects':savedEventVariables,'result':passedSelection}
예제 #4
0
    def BuildObjects(self):
        """
        Build 4-vectors of objects in event:
        lepton,met,nu,jets,tjets,bjets,fatjets,rcjets,resjets
        """
        objects = self.p_objects.split(',')
        # make 'resjets' be the last thing built (need the jets first)
        if objects[-1]!='resjets' and 'resjets' in objects:
            objects.remove('resjets')
            objects.append('resjets')

        ## possible objects linked to their functions
        import_keys = {'lepton':  lepBase,\
                       'met':     metBase,\
                       'nu':      nuBase,\
                       'jets':    jetBase,\
                       'bjets':   bjetBase,\
                       'tjets':   tjetBase,\
                       'fatjets': fjBase,\
                       'rcjets':  rcBase,\
                       'resjets': resBase}

        self.event_objects = {'vlq_evtype':self.ttree.vlq_evtype}

        ## special treatment for truth information because of how it is saved in truthSelection
        if any(ob.startswith('truth') for ob in objects) or self.p_plot1d=='efficiency':
            objs = truthBase(self.ttree)
            for key in objs.keys():
                self.event_objects[key] = objs[key]
            objects.remove('truth') # just set it up, done with truth information

        for event_object in objects:
            if event_object == 'bjets+jets' or event_object == 'jets+bjets':
                jets  = jetBase(self.ttree)
                bjets = bjetBase(self.ttree)
                jets  = jets+bjets           # merge the objects into one list
                jets.sort(   key=lambda x: x.Pt(), reverse=True) # [0] has the highest pT
                self.event_objects['jets'] = jets
            elif event_object == 'resjets':
                obj = import_keys[event_object](self.event_objects['jets'])
                self.event_objects[event_object] = obj
                obj.sort(   key=lambda x: x.Pt(), reverse=True) # [0] has the highest pT
            else:
                obj = import_keys[event_object](self.ttree)
                self.event_objects[event_object] = obj
                try:
                    obj.sort(   key=lambda x: x.Pt(), reverse=True) # [0] has the highest pT
                except AttributeError:
                    continue

        if 'jets' in objects or 'bjets' in objects or 'bjets+jets' in objects:
            self.event_objects['nbtags'] = len( [q for q in self.event_objects['jets'] if q.mv2c20>self.p_btag_wkpt] )

        if 'bjets' not in objects:
            self.event_objects['bjets'] = []
        self.event_objects['resjets'] = []

        if 'ht' in self.p_variables:
            self.event_objects['ht'] = vlq.calcHT(self.event_objects)

        return