Exemplo n.º 1
0
def test_read_nanomc(suffix):
    path = os.path.abspath(f'tests/samples/nano_dy.{suffix}')
    factory = getattr(NanoEventsFactory, f'from_{suffix}')(path)
    events = factory.events()

    # test after views first
    genroundtrips(events.GenPart.mask[events.GenPart.eta > 0])
    genroundtrips(events.mask[ak.any(events.Electron.pt > 50, axis=1)].GenPart)
    genroundtrips(events.GenPart)

    genroundtrips(events.GenPart[events.GenPart.eta > 0])
    genroundtrips(events[ak.any(events.Electron.pt > 50, axis=1)].GenPart)

    # sane gen matching (note for electrons gen match may be photon(22))
    assert ak.all((abs(events.Electron.matched_gen.pdgId) == 11) | (events.Electron.matched_gen.pdgId == 22))
    assert ak.all(abs(events.Muon.matched_gen.pdgId) == 13)

    genroundtrips(events.Electron.matched_gen)

    crossref(events[ak.num(events.Jet) > 2])
    crossref(events)

    if suffix == 'root':
        assert ak.any(events.Photon.isTight, axis=1).tolist()[:9] == [False, True, True, True, False, False, False, False, False]
    if suffix == 'parquet':
        assert ak.any(events.Photon.isTight, axis=1).tolist()[:9] == [False, True, False, True, False, False, False, False, True]
Exemplo n.º 2
0
def match(first, second, **kwargs):
    if 'dR_cutoff' not in kwargs:
        raise Exception("Please specify dR cutoff for matching!")
    dR_cutoff = kwargs.pop('dR_cutoff', 0.3)
    return_match_properties = kwargs.pop('return_match_properties', False)
    etas = ak.cartesian({
        'first': first.eta,
        'second': second.eta
    },
                        axis=1,
                        nested=True)
    phis = ak.cartesian({
        'first': first.phi,
        'second': second.phi
    },
                        axis=1,
                        nested=True)
    dR, deta, dphi = delta_r(etas['first'], etas['second'], phis['first'],
                             phis['second'])
    min_idx = ak.argmin(dR, axis=2)
    match_properties = {
        'pt': second.pt[min_idx],
        'eta': second.eta[min_idx],
        'phi': second.phi[min_idx],
    }
    if return_match_properties:
        return ak.any(dR < dR_cutoff, axis=2), match_properties
    else:
        return ak.any(dR < dR_cutoff, axis=2)
Exemplo n.º 3
0
def test_any_all():
    array = ak.Array(
        [
            [
                [
                    np.datetime64("2022"),
                    np.datetime64("2023"),
                    np.datetime64("2025")
                ],
                [],
                [np.datetime64("2027"),
                 np.datetime64("2011")],
                [np.datetime64("2013")],
            ],
            [],
            [[np.datetime64("2017"),
              np.datetime64("2019")], [np.datetime64("2023")]],
        ],
        check_valid=True,
    )

    assert ak.to_list(ak.any(array, axis=-1)) == [
        [True, False, True, True],
        [],
        [True, True],
    ]
    assert ak.to_list(ak.any(array, axis=-2)) == [[True, True, True], [],
                                                  [True, True]]
Exemplo n.º 4
0
def test_read_nanomc(suffix):
    path = os.path.abspath(f"tests/samples/nano_dy.{suffix}")
    # parquet files were converted from even older nanoaod
    nanoversion = NanoAODSchema.v6 if suffix == "root" else NanoAODSchema.v5
    factory = getattr(NanoEventsFactory, f"from_{suffix}")(
        path, schemaclass=nanoversion
    )
    events = factory.events()

    # test after views first
    genroundtrips(events.GenPart.mask[events.GenPart.eta > 0])
    genroundtrips(events.mask[ak.any(events.Electron.pt > 50, axis=1)].GenPart)
    genroundtrips(events.GenPart)

    genroundtrips(events.GenPart[events.GenPart.eta > 0])
    genroundtrips(events[ak.any(events.Electron.pt > 50, axis=1)].GenPart)

    # sane gen matching (note for electrons gen match may be photon(22))
    assert ak.all(
        (abs(events.Electron.matched_gen.pdgId) == 11)
        | (events.Electron.matched_gen.pdgId == 22)
    )
    assert ak.all(abs(events.Muon.matched_gen.pdgId) == 13)

    genroundtrips(events.Electron.matched_gen)

    crossref(events[ak.num(events.Jet) > 2])
    crossref(events)

    # test issue 409
    assert ak.to_list(events[[]].Photon.mass) == []

    if suffix == "root":
        assert ak.any(events.Photon.isTight, axis=1).tolist()[:9] == [
            False,
            True,
            True,
            True,
            False,
            False,
            False,
            False,
            False,
        ]
    if suffix == "parquet":
        assert ak.any(events.Photon.isTight, axis=1).tolist()[:9] == [
            False,
            True,
            False,
            True,
            False,
            False,
            False,
            False,
            True,
        ]
Exemplo n.º 5
0
def genroundtrips(genpart):
    # check genpart roundtrip
    assert ak.all(genpart.children.parent.pdgId == genpart.pdgId)
    assert ak.all(ak.any(genpart.parent.children.pdgId == genpart.pdgId, axis=-1, mask_identity=True))
    # distinctParent should be distinct and it should have a relevant child
    assert ak.all(genpart.distinctParent.pdgId != genpart.pdgId)
    assert ak.all(ak.any(genpart.distinctParent.children.pdgId == genpart.pdgId, axis=-1, mask_identity=True))
    # exercise hasFlags
    genpart.hasFlags(['isHardProcess'])
    genpart.hasFlags(['isHardProcess', 'isDecayedLeptonHadron'])
Exemplo n.º 6
0
def get_lepton_sf(year: str, lepton: str, corrections, pt, eta):
    sf_dict = corrections[lepton]
    eta_ranges = sf_dict["eta_ranges"]
    reco_cen = np.ones(len(pt))
    reco_err = np.ones(len(pt))
    trig_cen = np.ones(len(pt))
    trig_err = np.ones(len(pt))

    for idx, eta_range in enumerate(eta_ranges):
        mask = (eta >= eta_range[0]) & (eta < eta_range[1]) # find inds that are within given eta range
        if not ak.any(mask): continue # no values fall within eta range
        recoSF_cen = sf_dict["Reco_ID"]["Central"]["eta_bin%i" % idx]
        recoSF_err = sf_dict["Reco_ID"]["Error"]["eta_bin%i" % idx]
        trigSF_cen = sf_dict["Trig"]["Central"]["eta_bin%i" % idx]
        trigSF_err = sf_dict["Trig"]["Error"]["eta_bin%i" % idx]
        reco_cen[mask] = recoSF_cen(pt[mask])
        reco_err[mask] = recoSF_err(pt[mask])
        trig_cen[mask] = trigSF_cen(pt[mask])
        trig_err[mask] = trigSF_err(pt[mask])

    output_SFs = {
        "RECO_CEN" : reco_cen,
        "RECO_ERR" : reco_err,
        "TRIG_CEN" : trig_cen,
        "TRIG_ERR" : trig_err,
    }

    return output_SFs
def get_triggers(HLT, leptype, year, noIso=False, accumulator=None):
    ## event triggers to be used found here: https://twiki.cern.ch/twiki/bin/view/CMS/TopTriggerYear2016 or 2017, 2018...

    allowed_leptypes = ['Muon', 'Electron']
    if leptype not in allowed_leptypes:
        raise ValueError(f"Select 'leptype' from {allowed_leptypes}")

    iso_cat = 'noIso' if noIso else 'Iso'
    pass_triggers = ak.any((HLT[i] for i in single_mu_trigger_paths[year][iso_cat] if i in HLT.fields), axis=0) if leptype == 'Muon'\
            else ak.any((HLT[i] for i in single_el_trigger_paths[year][iso_cat] if i in HLT.fields), axis=0)

    if accumulator:
        accumulator['cutflow']['nEvts pass %s pass_triggers' % leptype] += ak.sum(pass_triggers)
        return pass_triggers, accumulator
    else:
        return pass_triggers
def test_reducers():
    # axis=None reducers are implemented in NumPy.
    assert ak.sum(ak.from_iter([[1 + 1j, 2 + 2j], [], [3 + 3j]])) == 6 + 6j
    assert ak.prod(ak.from_iter([[1 + 1j, 2 + 2j], [], [3 + 3j]])) == -12 + 12j

    # axis != None reducers are implemented in libawkward; this should be ReducerSum.
    assert ak.sum(ak.from_iter([[1 + 1j, 2 + 2j], [], [3 + 3j]]),
                  axis=1).tolist() == [
                      3 + 3j,
                      0 + 0j,
                      3 + 3j,
                  ]
    # And this is in ReducerProd.
    assert ak.prod(ak.from_iter([[1 + 1j, 2 + 2j], [], [3 + 3j]]),
                   axis=1).tolist() == [
                       0 + 4j,
                       1 + 0j,
                       3 + 3j,
                   ]

    # ReducerCount, ReducerCountNonzero, ReducerAny, and ReducerAll work.
    assert ak.count(ak.from_iter([[1 + 1j, 2 + 2j], [], [3 + 3j]]),
                    axis=1).tolist() == [2, 0, 1]
    assert ak.count_nonzero(ak.from_iter([[1 + 1j, 2 + 2j], [], [3 + 3j]]),
                            axis=1).tolist() == [2, 0, 1]
    assert ak.any(ak.from_iter([[1 + 1j, 2 + 2j], [], [3 + 3j]]),
                  axis=1).tolist() == [
                      True,
                      False,
                      True,
                  ]
    assert ak.all(ak.from_iter([[1 + 1j, 2 + 2j], [], [3 + 3j]]),
                  axis=1).tolist() == [
                      True,
                      True,
                      True,
                  ]
    assert ak.any(ak.from_iter([[1 + 1j, 2 + 2j, 0 + 0j], [], [3 + 3j]]),
                  axis=1).tolist() == [True, False, True]
    assert ak.all(ak.from_iter([[1 + 1j, 2 + 2j, 0 + 0j], [], [3 + 3j]]),
                  axis=1).tolist() == [False, True, True]
Exemplo n.º 9
0
def SS_selection(lep1, lep2):
    selection = PackedSelection()

    is_dilep   = ((ak.num(lep1) + ak.num(lep2))==2)
    pos_charge = ((ak.sum(lep1.pdgId, axis=1) + ak.sum(lep2.pdgId, axis=1))<0)
    neg_charge = ((ak.sum(lep1.pdgId, axis=1) + ak.sum(lep2.pdgId, axis=1))>0)

    dilep2    = choose(lep2, 2)
    dilep1   = choose(lep1, 2)
    dilep   = cross(lep2, lep1)

    is_SS = ( ak.any((dilep2['0'].charge * dilep2['1'].charge)>0, axis=1) | \
              ak.any((dilep1['0'].charge * dilep1['1'].charge)>0, axis=1) | \
              ak.any((dilep['0'].charge * dilep['1'].charge)>0, axis=1) )

    selection.add('SS', is_SS)
    ss_reqs = ['SS']

    ss_reqs_d = {sel: True for sel in ss_reqs}
    ss_selection = selection.require(**ss_reqs_d)
    return ss_selection
Exemplo n.º 10
0
def in_sensitive_volume(events, sensitive_volumes):
    """
    Function which identifies which events are inside sensitive volumes.

    Further, tests if sensitive volumes overlap. Assigns volume id, and
    xenon density to interactions.

    Args:
        events (ak.records): Awkward record of the interactions.
        sensitive_volumes (dict): Dictionary of the different volumes
            defined via the SensitiveVolume class.

    Returns:
        ak.array: Awkward array containing the event ids.
    """
    if len(events) == 0:
        res_det_dtype = [('xe_density', 'float64'),
                         ('vol_id', 'int64'),
                         ('create_S2', 'bool'),
                         ]
        return ak.from_numpy(np.empty(0, dtype=res_det_dtype))

    for ind, vol in enumerate(sensitive_volumes):
        res = ak.ArrayBuilder()
        res = _inside_sens_vol(events['x'],
                               events['y'],
                               events['z'],
                               vol.roi,
                               vol.volume_id,
                               vol.xe_density,
                               vol.create_S2,
                               res)
        if ind:
            # Now we add the other results, but first test if 
            # volumes overlap. Only possible if we explicitly loop
            # over everything. This reduces performance but adds layer of
            # safety.
            m = (result['vol_id'] > 0) & (res['vol_id'] == vol.volume_id)
            if ak.any(m):
                overlapping_id = result[m][0]
                # Get volume name:
                name = [vol.name for vol in sensitive_volumes if vol.volume_id == overlapping_id][0]
                raise ValueError(f'The volume {vol.name} is overlapping with'
                                 f' volume {name}!')
            new_results = res.snapshot()
            for field in result.fields:
                # Workaround since we cannot sum up records-arrays anymore
                result[field] = result[field] + new_results[field]
        else:
            # First result initiates the array
            result = res.snapshot()
    return result
 def process(self, events):
     mupair = ak.combinations(events.Muon, 2)
     with np.errstate(invalid="ignore"):
         pairmass = (mupair.slot0 + mupair.slot1).mass
     goodevent = ak.any(
         (pairmass > 60)
         & (pairmass < 120)
         & (mupair.slot0.charge == -mupair.slot1.charge),
         axis=1,
     )
     return (hist.Hist.new.Reg(100,
                               0,
                               200,
                               name="met",
                               label="$E_{T}^{miss}$ [GeV]").Double().fill(
                                   events[goodevent].MET.pt))
Exemplo n.º 12
0
    def process(self, events):
        output = pd.DataFrame()

        events = events[ak.any(events.Muon.pt > 20, axis=-1)]

        output['run'] = ak.to_numpy(events.run)
        output['event'] = ak.to_numpy(events.event)
        output['dataset'] = events.metadata['dataset']

        output['mu1_pt'] = -999.0
        output['mu2_pt'] = -999.0

        muons = events.Muon[events.Muon.pt > 20]

        counts = ak.num(muons)
        one_muon = ak.to_numpy(counts > 0)
        two_muons = ak.to_numpy(counts > 1)

        output.loc[one_muon, 'mu1_pt'] = ak.to_numpy(muons[one_muon][:, 0].pt)
        output.loc[two_muons, 'mu2_pt'] = ak.to_numpy(muons[two_muons][:,
                                                                       1].pt)
        return output
Exemplo n.º 13
0
def studyAcc(ifile, title, acceptances_dict, mass):
    dq_events = getData(ifile, "Truth")
    # choosing the nevts for denominator (because all files have 10000 evts)
    den = len(dq_events)

    # choosing 500 evts for denominator
    den500 = False
    if den500:
        dq_events = dq_events[:500]
        den = 500

    dq_showers = dq_events["Showers"]
    dq_electrons = dq_events["Electrons"]

    dq_sh_z = ak.fill_none(ak.pad_none(dq_showers.sz, 2, axis=1), 0)
    dq_sh_e = ak.fill_none(ak.pad_none(dq_showers.sedep_ecal, 2, axis=1), -1)
    dq_e_ge = ak.fill_none(ak.pad_none(dq_electrons.ge, 2, axis=1), -1)

    shower_zero_mask = ak.any(dq_sh_e == 0, axis=1)
    shower_zero_index = np.where(shower_zero_mask)

    eshower_mask = ak.all(dq_sh_e > 0.1 * dq_e_ge, axis=1)
    eshower_index = np.where(eshower_mask)

    masks = {'shower_zero': shower_zero_index, 'eshower': eshower_index}

    dq_evts = dq_events[ak.all(dq_e_ge > -1, axis=1)]
    # print(acceptances_dict)
    # we can print the mass, the number of events with gen e-, the number of events in the sample, and the denominator
    print(mass, len(dq_evts), len(dq_events), den)
    for maskstr, m in masks.items():
        if maskstr in acceptances_dict:
            acceptances_dict[maskstr].append(len(m[0]) / den)
        else:
            acceptances_dict[maskstr] = [len(m[0]) / den]
        #print(maskstr+':', len(m[0])/den)

    return acceptances_dict
Exemplo n.º 14
0
def match2(first, second, deltaRCut=0.4):
    drCut2 = deltaRCut**2
    combs = ak.cartesian([first, second], nested=True)
    return ak.any((combs['0'].delta_r2(combs['1']) < drCut2), axis=2)
Exemplo n.º 15
0
    def process(self, events):
        # Dataset parameters
        dataset = events.metadata['dataset']
        year   = self._samples[dataset]['year']
        xsec   = self._samples[dataset]['xsec']
        sow    = self._samples[dataset]['nSumOfWeights' ]
        isData = self._samples[dataset]['isData']
        datasets = ['SingleMuon', 'SingleElectron', 'EGamma', 'MuonEG', 'DoubleMuon', 'DoubleElectron']
        for d in datasets: 
          if d in dataset: dataset = dataset.split('_')[0] 

        # Inittialize objects
        met = events.GenMET
        e = events.GenPart[abs(events.GenPart.pdgId)==11]
        mu = events.GenPart[abs(events.GenPart.pdgId)==13]
        tau = events.GenPart[abs(events.GenPart.pdgId)==15]
        j = events.GenJet

        leading_mu = mu[ak.argmax(mu.pt,axis=-1,keepdims=True)]

        leading_e = e[ak.argmax(e.pt,axis=-1,keepdims=True)]

        nElec = ak.num(e)
        nMuon = ak.num(mu)
        nTau  = ak.num(tau)

        twoLeps   = (nElec+nMuon) == 2
        threeLeps = (nElec+nMuon) == 3
        twoElec   = (nElec == 2)
        twoMuon   = (nMuon == 2)
        e0 = e[ak.argmax(e.pt,axis=-1,keepdims=True)]
        m0 = mu[ak.argmax(mu.pt,axis=-1,keepdims=True)]
        elecs = e[ak.argsort(e.pt, ascending=False)]
        muons = mu[ak.argsort(mu.pt, ascending=False)]
        e1 = elecs
        e2 = elecs
        m1 = muons
        m2 = muons

        # Jet selection

        jetptname = 'pt_nom' if hasattr(j, 'pt_nom') else 'pt'
        njets = ak.num(j)
        ht = ak.sum(j.pt,axis=-1)
        jets = j[ak.argsort(j.pt, ascending=False)]
        j0 = j[ak.argmax(j.pt,axis=-1,keepdims=True)]
        j1 = jets
        j2 = jets
        j3 = jets
        nbtags = ak.num(j[abs(j.hadronFlavour)==5])

        ##################################################################
        ### 2 same-sign leptons
        ##################################################################

        # emu
        singe = e [(nElec==1)&(nMuon==1)&(e .pt>-1)]
        singm = mu[(nElec==1)&(nMuon==1)&(mu.pt>-1)]
        em = ak.cartesian({"e":singe,"m":singm})
        emSSmask = (em.e.pdgId*em.m.pdgId>0)
        emSS = em[emSSmask]
        nemSS = len(ak.flatten(emSS))

        year = 2018
        lepSF_emSS = GetLeptonSF(mu.pt, mu.eta, 'm', e.pt, e.eta, 'e', year=year)

        # ee and mumu
        # pt>-1 to preserve jagged dimensions
        ee = e [(nElec==2)&(nMuon==0)&(e.pt>-1)]
        mm = mu[(nElec==0)&(nMuon==2)&(mu.pt>-1)]

        eepairs = ak.combinations(ee, 2, fields=["e0","e1"])
        eeSSmask = (eepairs.e0.pdgId*eepairs.e1.pdgId>0)
        eeonZmask  = (np.abs((eepairs.e0+eepairs.e1).mass-91.2)<10)
        eeoffZmask = (eeonZmask==0)

        mmpairs = ak.combinations(mm, 2, fields=["m0","m1"])
        mmSSmask = (mmpairs.m0.pdgId*mmpairs.m1.pdgId>0)
        mmonZmask = (np.abs((mmpairs.m0+mmpairs.m1).mass-91.2)<10)
        mmoffZmask = (mmonZmask==0)

        eeSSonZ  = eepairs[eeSSmask &  eeonZmask]
        eeSSoffZ = eepairs[eeSSmask & eeoffZmask]
        mmSSonZ  = mmpairs[mmSSmask &  mmonZmask]
        mmSSoffZ = mmpairs[mmSSmask & mmoffZmask]
        neeSS = len(ak.flatten(eeSSonZ)) + len(ak.flatten(eeSSoffZ))
        nmmSS = len(ak.flatten(mmSSonZ)) + len(ak.flatten(mmSSoffZ))

        lepSF_eeSS = GetLeptonSF(eepairs.e0.pt, eepairs.e0.eta, 'e', eepairs.e1.pt, eepairs.e1.eta, 'e', year=year)
        lepSF_mumuSS = GetLeptonSF(mmpairs.m0.pt, mmpairs.m0.eta, 'm', mmpairs.m1.pt, mmpairs.m1.eta, 'm', year=year)

        print('Same-sign events [ee, emu, mumu] = [%i, %i, %i]'%(neeSS, nemSS, nmmSS))

        # Cuts
        eeSSmask   = (ak.num(eeSSmask[eeSSmask])>0)
        mmSSmask   = (ak.num(mmSSmask[mmSSmask])>0)
        eeonZmask  = (ak.num(eeonZmask[eeonZmask])>0)
        eeoffZmask = (ak.num(eeoffZmask[eeoffZmask])>0)
        mmonZmask  = (ak.num(mmonZmask[mmonZmask])>0)
        mmoffZmask = (ak.num(mmoffZmask[mmoffZmask])>0)
        emSSmask   = (ak.num(emSSmask[emSSmask])>0)


        ##################################################################
        ### 3 leptons
        ##################################################################

        # eem
        muon_eem = mu[(nElec==2)&(nMuon==1)&(mu.pt>-1)]
        elec_eem =  e[(nElec==2)&(nMuon==1)&( e.pt>-1)]
        ee_eem = ak.combinations(elec_eem, 2, fields=["e0", "e1"])

        ee_eemZmask     = (ee_eem.e0.pdgId*ee_eem.e1.pdgId<1)&(np.abs((ee_eem.e0+ee_eem.e1).mass-91.2)<10)
        ee_eemOffZmask  = (ee_eem.e0.pdgId*ee_eem.e1.pdgId<1)&(np.abs((ee_eem.e0+ee_eem.e1).mass-91.2)>10)
        ee_eemZmask     = (ak.num(ee_eemZmask[ee_eemZmask])>0)
        ee_eemOffZmask  = (ak.num(ee_eemOffZmask[ee_eemOffZmask])>0)

        eepair_eem  = (ee_eem.e0+ee_eem.e1)
        trilep_eem = eepair_eem+muon_eem #ak.cartesian({"e0":ee_eem.e0,"e1":ee_eem.e1, "m":muon_eem})

        lepSF_eem = GetLeptonSF(ee_eem.e0.pt, ee_eem.e0.eta, 'e', ee_eem.e1.pt, ee_eem.e1.eta, 'e', mu.pt, mu.eta, 'm', year)

        # mme
        muon_mme = mu[(nElec==1)&(nMuon==2)&(mu.pt>-1)]
        elec_mme =  e[(nElec==1)&(nMuon==2)&( e.pt>-1)]

        mm_mme = ak.combinations(muon_mme, 2, fields=["m0", "m1"])
        mm_mmeZmask     = (mm_mme.m0.pdgId*mm_mme.m1.pdgId<1)&(np.abs((mm_mme.m0+mm_mme.m1).mass-91.2)<10)
        mm_mmeOffZmask  = (mm_mme.m0.pdgId*mm_mme.m1.pdgId<1)&(np.abs((mm_mme.m0+mm_mme.m1).mass-91.2)>10)
        mm_mmeZmask     = (ak.num(mm_mmeZmask[mm_mmeZmask])>0)
        mm_mmeOffZmask  = (ak.num(mm_mmeOffZmask[mm_mmeOffZmask])>0)

        mmpair_mme     = (mm_mme.m0+mm_mme.m1)
        trilep_mme     = mmpair_mme+elec_mme

        mZ_mme  = mmpair_mme.mass
        mZ_eem  = eepair_eem.mass
        m3l_eem = trilep_eem.mass
        m3l_mme = trilep_mme.mass

        lepSF_mme = GetLeptonSF(mm_mme.m0.pt, mm_mme.m0.eta, 'm', mm_mme.m1.pt, mm_mme.m1.eta, 'm', e.pt, e.eta, 'e', year)

        # eee and mmm
        eee =   e[(nElec==3)&(nMuon==0)&( e.pt>-1)] 
        mmm =  mu[(nElec==0)&(nMuon==3)&(mu.pt>-1)] 

        eee_leps = ak.combinations(eee, 3, fields=["e0", "e1", "e2"])
        mmm_leps = ak.combinations(mmm, 3, fields=["m0", "m1", "m2"])
        ee_pairs = ak.combinations(eee, 2, fields=["e0", "e1"])
        mm_pairs = ak.combinations(mmm, 2, fields=["m0", "m1"])
        ee_pairs_index = ak.argcombinations(eee, 2, fields=["e0", "e1"])
        mm_pairs_index = ak.argcombinations(mmm, 2, fields=["m0", "m1"])

        lepSF_eee = GetLeptonSF(eee_leps.e0.pt, eee_leps.e0.eta, 'e', eee_leps.e1.pt, eee_leps.e1.eta, 'e', eee_leps.e2.pt, eee_leps.e2.eta, 'e', year)
        lepSF_mmm = GetLeptonSF(mmm_leps.m0.pt, mmm_leps.m0.eta, 'm', mmm_leps.m1.pt, mmm_leps.m1.eta, 'm', mmm_leps.m2.pt, mmm_leps.m2.eta, 'm', year)

        mmSFOS_pairs = mm_pairs[(np.abs(mm_pairs.m0.pdgId) == np.abs(mm_pairs.m1.pdgId)) & (mm_pairs.m0.pdgId != mm_pairs.m1.pdgId)]
        offZmask_mm = ak.all(np.abs((mmSFOS_pairs.m0 + mmSFOS_pairs.m1).mass - 91.2)>10., axis=1, keepdims=True) & (ak.num(mmSFOS_pairs)>0)
        onZmask_mm  = ak.any(np.abs((mmSFOS_pairs.m0 + mmSFOS_pairs.m1).mass - 91.2)<10., axis=1, keepdims=True)
      
        eeSFOS_pairs = ee_pairs[(np.abs(ee_pairs.e0.pdgId) == np.abs(ee_pairs.e1.pdgId)) & (ee_pairs.e0.pdgId != ee_pairs.e1.pdgId)]
        offZmask_ee = ak.all(np.abs((eeSFOS_pairs.e0 + eeSFOS_pairs.e1).mass - 91.2)>10, axis=1, keepdims=True) & (ak.num(eeSFOS_pairs)>0)
        onZmask_ee  = ak.any(np.abs((eeSFOS_pairs.e0 + eeSFOS_pairs.e1).mass - 91.2)<10, axis=1, keepdims=True)

        # Create masks **for event selection**
        eeeOnZmask  = (ak.num(onZmask_ee[onZmask_ee])>0)
        eeeOffZmask = (ak.num(offZmask_ee[offZmask_ee])>0)
        mmmOnZmask  = (ak.num(onZmask_mm[onZmask_mm])>0)
        mmmOffZmask = (ak.num(offZmask_mm[offZmask_mm])>0)

        # Now we need to create masks for the leptons in order to select leptons from the Z boson candidate (in onZ categories)
        ZeeMask = ak.argmin(np.abs((eeSFOS_pairs.e0 + eeSFOS_pairs.e1).mass - 91.2),axis=1,keepdims=True)
        ZmmMask = ak.argmin(np.abs((mmSFOS_pairs.m0 + mmSFOS_pairs.m1).mass - 91.2),axis=1,keepdims=True)
  
        Zee = eeSFOS_pairs[ZeeMask]
        Zmm = mmSFOS_pairs[ZmmMask]
        eZ0= Zee.e0[ak.num(eeSFOS_pairs)>0]
        eZ1= Zee.e1[ak.num(eeSFOS_pairs)>0]
        eZ = eZ0+eZ1
        mZ0= Zmm.m0[ak.num(mmSFOS_pairs)>0]
        mZ1= Zmm.m1[ak.num(mmSFOS_pairs)>0]
        mZ = mZ0+mZ1
        mZ_eee  = eZ.mass
        mZ_mmm  = mZ.mass

        # And for the W boson
        ZmmIndices = mm_pairs_index[ZmmMask]
        ZeeIndices = ee_pairs_index[ZeeMask]
        eW = eee[~ZeeIndices.e0 | ~ZeeIndices.e1]
        mW = mmm[~ZmmIndices.m0 | ~ZmmIndices.m1]

        triElec = eee_leps.e0+eee_leps.e1+eee_leps.e2
        triMuon = mmm_leps.m0+mmm_leps.m1+mmm_leps.m2
        m3l_eee = triElec.mass
        m3l_mmm = triMuon.mass
    
        # Triggers
        trig_eeSS = passTrigger(events,'ee',isData,dataset)
        trig_mmSS = passTrigger(events,'mm',isData,dataset)
        trig_emSS = passTrigger(events,'em',isData,dataset)
        trig_eee  = passTrigger(events,'eee',isData,dataset)
        trig_mmm  = passTrigger(events,'mmm',isData,dataset)
        trig_eem  = passTrigger(events,'eem',isData,dataset)
        trig_mme  = passTrigger(events,'mme',isData,dataset)

        # MET filters

        # Weights
        genw = np.ones_like(events['MET_pt']) if isData else events['genWeight']

        ### We need weights for: normalization, lepSF, triggerSF, pileup, btagSF...
        weights = {}
        for r in ['all', 'ee', 'mm', 'em', 'eee', 'mmm', 'eem', 'mme']:
          weights[r] = coffea.analysis_tools.Weights(len(events))
          weights[r].add('norm',genw if isData else (xsec/sow)*genw)

        weights['ee'].add('lepSF_eeSS', lepSF_eeSS)
        weights['em'].add('lepSF_emSS', lepSF_emSS)
        weights['mm'].add('lepSF_mmSS', lepSF_mumuSS)
        weights['eee'].add('lepSF_eee', lepSF_eee)
        weights['mmm'].add('lepSF_mmm', lepSF_mmm)
        weights['mme'].add('lepSF_mme', lepSF_mme)
        weights['eem'].add('lepSF_eem', lepSF_eem)

        # Extract the EFT quadratic coefficients and optionally use them to calculate the coefficients on the w**2 quartic function
        # eft_coeffs is never Jagged so convert immediately to numpy for ease of use.
        eft_coeffs = ak.to_numpy(events['EFTfitCoefficients']) if hasattr(events, "EFTfitCoefficients") else None
        eft_w2_coeffs = efth.calc_w2_coeffs(eft_coeffs,self._dtype) if (self._do_errors and eft_coeffs is not None) else None

        # Selections and cuts
        selections = PackedSelection()
        channels2LSS = ['eeSSonZ', 'eeSSoffZ', 'mmSSonZ', 'mmSSoffZ', 'emSS']
        selections.add('eeSSonZ',  (eeonZmask)&(eeSSmask)&(trig_eeSS))
        selections.add('eeSSoffZ', (eeoffZmask)&(eeSSmask)&(trig_eeSS))
        selections.add('mmSSonZ',  (mmonZmask)&(mmSSmask)&(trig_mmSS))
        selections.add('mmSSoffZ', (mmoffZmask)&(mmSSmask)&(trig_mmSS))
        selections.add('emSS',     (emSSmask)&(trig_emSS))

        channels3L = ['eemSSonZ', 'eemSSoffZ', 'mmeSSonZ', 'mmeSSoffZ']
        selections.add('eemSSonZ',   (ee_eemZmask)&(trig_eem))
        selections.add('eemSSoffZ',  (ee_eemOffZmask)&(trig_eem))
        selections.add('mmeSSonZ',   (mm_mmeZmask)&(trig_mme))
        selections.add('mmeSSoffZ',  (mm_mmeOffZmask)&(trig_mme))

        channels3L += ['eeeSSonZ', 'eeeSSoffZ', 'mmmSSonZ', 'mmmSSoffZ']
        selections.add('eeeSSonZ',   (eeeOnZmask)&(trig_eee))
        selections.add('eeeSSoffZ',  (eeeOffZmask)&(trig_eee))
        selections.add('mmmSSonZ',   (mmmOnZmask)&(trig_mmm))
        selections.add('mmmSSoffZ',  (mmmOffZmask)&(trig_mmm))

        levels = ['base', '2jets', '4jets', '4j1b', '4j2b']
        selections.add('base', (nElec+nMuon>=2))
        selections.add('2jets',(njets>=2))
        selections.add('4jets',(njets>=4))
        selections.add('4j1b',(njets>=4)&(nbtags>=1))
        selections.add('4j2b',(njets>=4)&(nbtags>=2))

        # Variables
        invMass_eeSSonZ  = ( eeSSonZ.e0+ eeSSonZ.e1).mass
        invMass_eeSSoffZ = (eeSSoffZ.e0+eeSSoffZ.e1).mass
        invMass_mmSSonZ  = ( mmSSonZ.m0+ mmSSonZ.m1).mass
        invMass_mmSSoffZ = (mmSSoffZ.m0+mmSSoffZ.m1).mass
        invMass_emSS     = (emSS.e+emSS.m).mass

        varnames = {}
        varnames['met'] = met.pt
        varnames['ht'] = ht
        varnames['njets'] = njets
        varnames['nbtags'] = nbtags
        varnames['invmass'] = {
          'eeSSonZ'   : invMass_eeSSonZ,
          'eeSSoffZ'  : invMass_eeSSoffZ,
          'mmSSonZ'   : invMass_mmSSonZ,
          'mmSSoffZ'  : invMass_mmSSoffZ,
          'emSS'      : invMass_emSS,
          'eemSSonZ'  : mZ_eem,
          'eemSSoffZ' : mZ_eem,
          'mmeSSonZ'  : mZ_mme,
          'mmeSSoffZ' : mZ_mme,
          'eeeSSonZ'  : mZ_eee,
          'eeeSSoffZ' : mZ_eee,
          'mmmSSonZ'  : mZ_mmm,
          'mmmSSoffZ' : mZ_mmm,
        }
        varnames['m3l'] = {
          'eemSSonZ'  : m3l_eem,
          'eemSSoffZ' : m3l_eem,
          'mmeSSonZ'  : m3l_mme,
          'mmeSSoffZ' : m3l_mme,
          'eeeSSonZ'  : m3l_eee,
          'eeeSSoffZ' : m3l_eee,
          'mmmSSonZ'  : m3l_mmm,
          'mmmSSoffZ' : m3l_mmm,
        }
        varnames['e0pt' ] = e0.pt
        varnames['e0eta'] = e0.eta
        varnames['m0pt' ] = m0.pt
        varnames['m0eta'] = m0.eta
        varnames['e1pt' ] = e1
        varnames['e1eta'] = e1
        varnames['e2pt' ] = e2
        varnames['e2eta'] = e2
        varnames['m1pt' ] = m1
        varnames['m1eta'] = m1
        varnames['m2pt' ] = m2
        varnames['m2eta'] = m2
        varnames['j0pt' ] = j0.pt
        varnames['j0eta'] = j0.eta
        varnames['j1pt']  = j1
        varnames['j1eta'] = j1
        varnames['j2pt']  = j2
        varnames['j2eta'] = j2
        varnames['j3pt']  = j3
        varnames['j3eta'] = j3
        varnames['counts'] = np.ones_like(events.GenMET.pt)

        # fill Histos
        hout = self.accumulator.identity()
        normweights = weights['all'].weight().flatten() # Why does it not complain about .flatten() here?
        hout['SumOfEFTweights'].fill(sample=dataset, SumOfEFTweights=varnames['counts'], weight=normweights, eft_coeff=eft_coeffs, eft_err_coeff=eft_w2_coeffs)

        for var, v in varnames.items():
         for ch in channels2LSS+channels3L:
          for lev in levels:
            weight = weights[ ch[:3] if (ch.startswith('eee') or ch.startswith('mmm') or ch.startswith('eem') or ch.startswith('mme')) else ch[:2]].weight()
            cuts = [ch] + [lev]
            cut = selections.all(*cuts)
            weights_flat = weight[cut].flatten() # Why does it not complain about .flatten() here?
            weights_ones = np.ones_like(weights_flat, dtype=np.int)
            eft_coeffs_cut = eft_coeffs[cut] if eft_coeffs is not None else None
            eft_w2_coeffs_cut = eft_w2_coeffs[cut] if eft_w2_coeffs is not None else None
            if var == 'invmass':
              if   ch in ['eeeSSoffZ', 'mmmSSoffZ']: continue
              elif ch in ['eeeSSonZ' , 'mmmSSonZ' ]: continue #values = v[ch]
              else                                 : values = ak.flatten(v[ch][cut])
              hout['invmass'].fill(eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut, sample=dataset, channel=ch, cut=lev, invmass=values, weight=weights_flat)
            elif var == 'm3l': 
              if ch in ['eeSSonZ','eeSSoffZ', 'mmSSonZ', 'mmSSoffZ','emSS', 'eeeSSoffZ', 'mmmSSoffZ', 'eeeSSonZ' , 'mmmSSonZ']: continue
              values = ak.flatten(v[ch][cut])
              hout['m3l'].fill(sample=dataset, channel=ch, cut=lev, m3l=values, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
            else:
              values = v[cut]
              if   var == 'ht'    : hout[var].fill(ht=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'met'   : hout[var].fill(met=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'njets' : hout[var].fill(njets=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'nbtags': hout[var].fill(nbtags=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'counts': hout[var].fill(counts=values, sample=dataset, channel=ch, cut=lev, weight=weights_ones)
              elif var == 'j0eta' : 
                if lev == 'base': continue
                values = ak.flatten(values)
                #values=np.asarray(values)
                hout[var].fill(j0eta=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'e0pt'  : 
                if ch in ['mmSSonZ', 'mmSSoffZ', 'mmmSSoffZ', 'mmmSSonZ']: continue
                values = ak.flatten(values)
                #values=np.asarray(values)
                hout[var].fill(e0pt=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut) 
              elif var == 'm0pt'  : 
                if ch in ['eeSSonZ', 'eeSSoffZ', 'eeeSSoffZ', 'eeeSSonZ']: continue
                values = ak.flatten(values)
                #values=np.asarray(values)
                hout[var].fill(m0pt=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'e0eta' : 
                if ch in ['mmSSonZ', 'mmSSoffZ', 'mmmSSoffZ', 'mmmSSonZ']: continue
                values = ak.flatten(values)
                #values=np.asarray(values)
                hout[var].fill(e0eta=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'm0eta':
                if ch in ['eeSSonZ', 'eeSSoffZ', 'eeeSSoffZ', 'eeeSSonZ']: continue
                values = ak.flatten(values)
                #values=np.asarray(values)
                hout[var].fill(m0eta=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'j0pt'  : 
                if lev == 'base': continue
                values = ak.flatten(values)
                #values=np.asarray(values)
                hout[var].fill(j0pt=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'j1pt':
                if lev == "base": continue
                values = values.pt[:,1]
                #values = ak.flatten(values)
                hout[var].fill(j1pt=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var =='j1eta':
                if lev == 'base': continue
                values = values.eta[:,1]
                hout[var].fill(j1eta=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'j2pt':
                if lev in ['base', "2jets"]: continue
                values = values.pt[:,2]
                hout[var].fill(j2pt=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'j2eta':
                if lev in ['base', "2jets"]: continue
                values = values.eta[:,2]
                hout[var].fill(j2eta=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'j3pt':
                if lev in ['base', "2jets"]: continue
                values = values.pt[:,3]
                hout[var].fill(j3pt=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'j3eta':
                if lev in ['base', "2jets"]: continue
                values = values.eta[:,3]
                hout[var].fill(j3eta=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'e1pt':
                if ch in ['mmSSonZ', 'mmSSoffZ', 'mmmSSoffZ', 'mmmSSonZ', 'mmeSSonZ', 'mmeSSoffZ', 'emSS']: continue
                values = values.pt[:,1]
                hout[var].fill(e1pt=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'e1eta':
                if ch in ['mmSSonZ', 'mmSSoffZ', 'mmmSSoffZ', 'mmmSSonZ', 'mmeSSonZ', 'mmeSSoffZ', 'emSS']: continue
                values = values.eta[:,1]
                hout[var].fill(e1eta=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'e2pt':
                if ch in ['eeeSSonZ', 'eeeSSoffZ']:
                  values = values.pt[:,2]
                  hout[var].fill(e2pt=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'e2eta':
                if ch in ['eeeSSonZ', 'eeeSSoffZ']:
                  values = values.eta[:,2]
                  hout[var].fill(e2eta=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'm1pt':
                if ch in ['eeSSonZ', 'eeSSoffZ', 'eeeSSoffZ', 'eeeSSonZ', 'eemSSonZ', 'eemSSoffZ', 'emSS']: continue
                values = values.pt[:,1]
                hout[var].fill(m1pt=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'm1eta':
                if ch in ['eeSSonZ', 'eeSSoffZ', 'eeeSSoffZ', 'eeeSSonZ', 'eemSSonZ', 'eemSSoffZ', 'emSS']: continue
                values = values.eta[:,1]
                hout[var].fill(m1eta=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'm2pt':
                if ch in ['mmmSSonZ', 'mmmSSoffZ']:
                  values = values.pt[:,2]
                  hout[var].fill(m2pt=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
              elif var == 'm2eta':
                if ch in ['mmmSSonZ', 'mmmSSoffZ']:
                  values = values.eta[:,2]
                  hout[var].fill(m2eta=values, sample=dataset, channel=ch, cut=lev, weight=weights_flat, eft_coeff=eft_coeffs_cut, eft_err_coeff=eft_w2_coeffs_cut)
        return hout
Exemplo n.º 16
0
def bosonFlavor(bosons):
    childid = abs(bosons.children.pdgId)
    genflavor = ak.any(childid == 5, axis=-1) * 3 + ak.any(
        childid == 4, axis=-1) * 2 + ak.all(childid < 4, axis=-1) * 1
    return ak.fill_none(genflavor, 0)
    def process(self, events):

        output = self.accumulator.identity()

        dataset = events.metadata['dataset']

        output['sumw'][dataset] += ak.sum(np.sign(events.Generator.weight))
        output['nevents'][dataset] += len(events)

        output = self.accumulator.identity()

        dataset = events.metadata['dataset']

        if dataset not in ['singleelectron','singlemuon','egamma']:
            output['sumw'][dataset] += ak.sum(np.sign(events.Generator.weight))
        output['nevents'][dataset] += len(events)

        if dataset in ['singleelectron','singlemuon','egamma']:
            events = events[lumimask(events.run,events.luminosityBlock)]

        events = events[(events.PuppiMET.pt > 30) | (events.PuppiMET.ptJERUp > 30) | (events.PuppiMET.ptJESUp > 30)]    

        if year == "2016":
            if dataset == 'singlemuon':
                events = events[events.HLT.IsoTkMu24 | events.HLT.IsoMu24]
            elif dataset == 'singleelectron':
                events = events[vents.HLT.IsoTkMu24 | events.HLT.IsoMu24 | events.HLT.Ele27_WPTight_Gsf]
            else:    
                events = events[events.HLT.IsoTkMu24 | events.HLT.IsoMu24 | events.HLT.Ele27_WPTight_Gsf]
        elif year == "2017":
            if dataset == 'singlemuon':
                events = events[events.HLT.IsoMu27]
            elif dataset == 'singleelectron':
                events = events[events.HLT.Ele32_WPTight_Gsf_L1DoubleEG]    
            else:
                events = events[events.HLT.IsoMu27 | events.HLT.Ele32_WPTight_Gsf_L1DoubleEG]        
        elif year == "2018":
            if dataset == 'singlemuon':
                events = events[events.HLT.IsoMu24]
            elif dataset == 'egamma':    
                events = events[events.HLT.Ele32_WPTight_Gsf]
            else:
                events = events[events.HLT.IsoMu24 |events.HLT.Ele32_WPTight_Gsf]

        events = events[(ak.num(events.Jet) > 3) | ((ak.num(events.Jet) > 1) & (ak.num(events.FatJet) > 0))]

        events = events[(ak.num(events.Electron) > 0) | (ak.num(events.Muon) > 0)]

        tight_muons = events.Muon[events.Muon.tightId & (events.Muon.pfRelIso04_all < 0.15) & (events.Muon.pt > 26) & (abs(events.Muon.eta) < 2.4)]

        loose_not_tight_muons = events.Muon[events.Muon.tightId & (events.Muon.pfRelIso04_all < 0.4) & (events.Muon.pfRelIso04_all > 0.15) & (events.Muon.pt > 20) & (abs(events.Muon.eta) < 2.4)]

        tight_electrons = events.Electron[(events.Electron.pt > 30) & (events.Electron.cutBased >= 3) & (events.Electron.eta + events.Electron.deltaEtaSC < 2.5) & ((abs(events.Electron.dz) < 0.1) & (abs(events.Electron.dxy) < 0.05) & (events.Electron.eta + events.Electron.deltaEtaSC < 1.479)) | ((abs(events.Electron.dz) < 0.2) & (abs(events.Electron.dxy) < 0.1) & (events.Electron.eta + events.Electron.deltaEtaSC > 1.479))]

        name_map = jec_stack.blank_name_map
        name_map['JetPt'] = 'pt'
        name_map['JetMass'] = 'mass'
        name_map['JetEta'] = 'eta'
        name_map['JetA'] = 'area'

        jets = events.Jet
        
        jets['pt_raw'] = (1 - jets['rawFactor']) * jets['pt']
        jets['mass_raw'] = (1 - jets['rawFactor']) * jets['mass']
        jets['pt_gen'] = ak.values_astype(ak.fill_none(jets.matched_gen.pt, 0), np.float32)
        jets['rho'] = ak.broadcast_arrays(events.fixedGridRhoFastjetAll, jets.pt)[0]
        name_map['ptGenJet'] = 'pt_gen'
        name_map['ptRaw'] = 'pt_raw'
        name_map['massRaw'] = 'mass_raw'
        name_map['Rho'] = 'rho'

        events_cache = events.caches[0]

        jet_factory = CorrectedJetsFactory(name_map, jec_stack)
        corrected_jets = jet_factory.build(jets, lazy_cache=events_cache)    

        jet_pt = corrected_jets.pt
        jet_pt_jesup = corrected_jets.JES_jes.up.pt
        jet_pt_jerup = corrected_jets.JER.up.pt

        corrected_jets = ak.zip({
            "pt": corrected_jets.pt,
            "eta": corrected_jets.eta,
            "phi": corrected_jets.phi,
            "mass": corrected_jets.mass,
            "charge": np.ones(len(corrected_jets.pt)),
            "btagDeepB": corrected_jets.btagDeepB
        }, with_name="PtEtaPhiMCandidate")    

        fatjets = events.FatJet[(events.FatJet.pt > 250) & (abs(events.FatJet.eta) < 2.5) & (events.FatJet.msoftdrop > 50) & (events.FatJet.msoftdrop < 150)]    
        b_jets = corrected_jets[(events.Jet.cleanmask == 1) & (jet_pt > 30) & (abs(events.Jet.eta) < 2.5) & (events.Jet.btagDeepB > 0.8953)]
        vbf_jets = corrected_jets[(events.Jet.cleanmask == 1) & (jet_pt > 30) & (abs(events.Jet.eta) < 4.7) & (events.Jet.btagDeepB < 0.2217)]
        nextrajets = ak.num(events.Jet[(events.Jet.cleanmask == 1) & (jet_pt > 30) & (abs(events.Jet.eta) < 4.7)]) - 4
        nextrabjets = ak.num(events.Jet[(events.Jet.cleanmask == 1) & (jet_pt > 30) & (abs(events.Jet.eta) < 4.7) & (events.Jet.btagDeepB > 0.2217)]) - 2

        basecut_merged = (ak.num(fatjets) > 0) & (ak.num(vbf_jets) > 1) & (ak.num(tight_muons) + ak.num(tight_electrons) == 1) & (ak.num(loose_not_tight_muons) == 0) & (events.PuppiMET.pt > 30)
        events_merged = events[basecut_merged]
        fatjets_merged = fatjets[basecut_merged]
        vbf_jets_merged = vbf_jets[basecut_merged]
        tight_muons_merged = tight_muons[basecut_merged]
        tight_electrons_merged = tight_electrons[basecut_merged]
        nextrajets_merged = nextrajets[basecut_merged]
        nextrabjets_merged = nextrabjets[basecut_merged]

        basecut = (ak.num(b_jets) > 1) & (ak.num(vbf_jets) > 1) & (ak.num(tight_muons) + ak.num(tight_electrons) == 1) & (ak.num(loose_not_tight_muons) == 0) & (events.PuppiMET.pt > 30)
        events = events[basecut]
        b_jets = b_jets[basecut]
        vbf_jets = vbf_jets[basecut]
        tight_muons = tight_muons[basecut]
        tight_electrons = tight_electrons[basecut]
        nextrajets = nextrajets[basecut]
        nextrabjets = nextrabjets[basecut]

        if dataset in ['singleelectron','singlemuon','egamma']:
            dataset = 'data'

        if ak.any(basecut_merged):
            cut7 = (fatjets_merged[:,0].mass > 50) & (fatjets_merged[:,0].mass < 150) & ((vbf_jets_merged[:,0]+vbf_jets_merged[:,1]).mass > 500) & (abs(vbf_jets_merged[:,0].eta - vbf_jets_merged[:,1].eta) > 2.5) & (ak.num(tight_muons_merged) > 0)
            cut8 = (fatjets_merged[:,0].mass > 50) & (fatjets_merged[:,0].mass < 150) & ((vbf_jets_merged[:,0]+vbf_jets_merged[:,1]).mass > 500) & (abs(vbf_jets_merged[:,0].eta - vbf_jets_merged[:,1].eta) > 2.5) & (ak.num(tight_electrons_merged) > 0)
#            cut9 = cut7 | cut8

        cut1 = ((b_jets[:,0] + b_jets[:,1]).mass > 50) & ((b_jets[:,0] + b_jets[:,1]).mass < 150) & ((vbf_jets[:,0] + vbf_jets[:,1]).mass > 500) & (abs(vbf_jets[:,0].eta - vbf_jets[:,1].eta) > 2.5) & (ak.num(tight_muons) > 0)
        cut2 = ((b_jets[:,0] + b_jets[:,1]).mass > 50) & ((b_jets[:,0] + b_jets[:,1]).mass < 150) & ((vbf_jets[:,0] + vbf_jets[:,1]).mass > 500) & (abs(vbf_jets[:,0].eta - vbf_jets[:,1].eta) > 2.5) & (ak.num(tight_electrons) > 0)
#            cut3 = cut1 | cut2

        if ak.any(basecut_merged) and ak.any(cut7):

            sel7_events = events_merged[cut7]
            sel7_fatjets = fatjets_merged[cut7]
            sel7_vbf_jets = vbf_jets_merged[cut7]
            sel7_muons = tight_muons_merged[cut7][:,0]
            sel7_nextrajets = nextrajets_merged[cut7]
            sel7_nextrabjets = nextrabjets_merged[cut7]

            output["weights_merged"][dataset] += processor.column_accumulator(np.sign(ak.to_numpy(sel7_events.Generator.weight).data))

            output['variables_merged'][dataset] += processor.column_accumulator(np.transpose(np.vstack((
                ak.to_numpy(sel7_fatjets[:,0].pt),
                ak.to_numpy(sel7_fatjets[:,0].eta),
                ak.to_numpy(sel7_fatjets[:,0].phi),
                ak.to_numpy(sel7_fatjets[:,0].btagDeepB),
                ak.to_numpy(sel7_fatjets[:,0].btagHbb),
                ak.to_numpy(sel7_fatjets[:,0].msoftdrop),
                ak.to_numpy(sel7_nextrajets),
                ak.to_numpy(sel7_nextrabjets),
                np.zeros(len(sel7_events)),
                np.sign(ak.to_numpy(sel7_muons.charge)+1),
                ak.to_numpy(sel7_muons.pt),
                ak.to_numpy(sel7_muons.eta),
                ak.to_numpy(sel7_muons.phi),
                ak.to_numpy(sel7_events.PuppiMET.pt),
                ak.to_numpy(sel7_events.PuppiMET.phi),
                ak.to_numpy(sel7_vbf_jets[:,0].pt),
                ak.to_numpy(sel7_vbf_jets[:,1].pt),
                ak.to_numpy(sel7_vbf_jets[:,0].eta),
                ak.to_numpy(sel7_vbf_jets[:,1].eta),
                ak.to_numpy(sel7_vbf_jets[:,0].phi),
                ak.to_numpy(sel7_vbf_jets[:,1].phi),
                ak.to_numpy(sel7_vbf_jets[:,0].btagDeepB),
                ak.to_numpy(sel7_vbf_jets[:,1].btagDeepB),
                ak.to_numpy((sel7_vbf_jets[:,0]+sel7_vbf_jets[:,1]).mass),
                ak.to_numpy(sel7_vbf_jets[:,0].eta - sel7_vbf_jets[:,1].eta),
                ak.to_numpy(np.sqrt(2*(sel7_muons+sel7_vbf_jets[:,0]).pt*sel7_events.PuppiMET.pt*(1 - np.cos(sel7_events.PuppiMET.phi - (sel7_muons+sel7_vbf_jets[:,0]).phi)))),
                ak.to_numpy(np.sqrt(2*(sel7_muons+sel7_vbf_jets[:,1]).pt*sel7_events.PuppiMET.pt*(1 - np.cos(sel7_events.PuppiMET.phi - (sel7_muons+sel7_vbf_jets[:,1]).phi))))))))

            sel7_muonidsf = evaluator['muonidsf'](abs(sel7_muons.eta), sel7_muons.pt)
            sel7_muonisosf = evaluator['muonisosf'](abs(sel7_muons.eta), sel7_muons.pt)
            sel7_muonhltsf = evaluator['muonhltsf'](abs(sel7_muons.eta), sel7_muons.pt)
            sel7_weight = np.sign(sel7_events.Generator.weight)*sel7_events.L1PreFiringWeight.Nom*sel7_muonidsf*sel7_muonisosf*sel7_muonhltsf

        if ak.any(basecut_merged) and ak.any(cut8):

            sel8_events = events_merged[cut8]
            sel8_fatjets = fatjets_merged[cut8]
            sel8_vbf_jets = vbf_jets_merged[cut8]
            sel8_electrons = tight_electrons_merged[cut8][:,0]
            sel8_nextrajets = nextrajets_merged[cut8]
            sel8_nextrabjets = nextrabjets_merged[cut8]

            output["weights_merged"][dataset] += processor.column_accumulator(np.sign(ak.to_numpy(sel8_events.Generator.weight).data))

            output['variables_merged'][dataset] += processor.column_accumulator(np.transpose(np.vstack((
                ak.to_numpy(sel8_fatjets[:,0].pt),
                ak.to_numpy(sel8_fatjets[:,0].eta),
                ak.to_numpy(sel8_fatjets[:,0].phi),
                ak.to_numpy(sel8_fatjets[:,0].btagDeepB),
                ak.to_numpy(sel8_fatjets[:,0].btagHbb),
                ak.to_numpy(sel8_fatjets[:,0].msoftdrop),
                ak.to_numpy(sel8_nextrajets),
                ak.to_numpy(sel8_nextrabjets),
                np.ones(len(sel8_events)),
                np.sign(ak.to_numpy(sel8_electrons.charge)+1),
                ak.to_numpy(sel8_electrons.pt),
                ak.to_numpy(sel8_electrons.eta),
                ak.to_numpy(sel8_electrons.phi),
                ak.to_numpy(sel8_events.PuppiMET.pt),
                ak.to_numpy(sel8_events.PuppiMET.phi),
                ak.to_numpy(sel8_vbf_jets[:,0].pt),
                ak.to_numpy(sel8_vbf_jets[:,1].pt),
                ak.to_numpy(sel8_vbf_jets[:,0].eta),
                ak.to_numpy(sel8_vbf_jets[:,1].eta),
                ak.to_numpy(sel8_vbf_jets[:,0].phi),
                ak.to_numpy(sel8_vbf_jets[:,1].phi),
                ak.to_numpy(sel8_vbf_jets[:,0].btagDeepB),
                ak.to_numpy(sel8_vbf_jets[:,1].btagDeepB),
                ak.to_numpy((sel8_vbf_jets[:,0]+sel8_vbf_jets[:,1]).mass),
                ak.to_numpy(sel8_vbf_jets[:,0].eta - sel8_vbf_jets[:,1].eta),
                ak.to_numpy(np.sqrt(2*(sel8_electrons+sel8_vbf_jets[:,0]).pt*sel8_events.PuppiMET.pt*(1 - np.cos(sel8_events.PuppiMET.phi - (sel8_electrons+sel8_vbf_jets[:,0]).phi)))),
                ak.to_numpy(np.sqrt(2*(sel8_electrons+sel8_vbf_jets[:,1]).pt*sel8_events.PuppiMET.pt*(1 - np.cos(sel8_events.PuppiMET.phi - (sel8_electrons+sel8_vbf_jets[:,1]).phi))))))))

            sel8_electronidsf = evaluator['electronidsf'](sel8_electrons.eta, sel8_electrons.pt)
            sel8_electronrecosf = evaluator['electronrecosf'](sel8_electrons.eta, sel8_electrons.pt)
            sel8_weight = np.sign(sel8_events.Generator.weight)*sel8_events.L1PreFiringWeight.Nom*sel8_electronidsf*sel8_electronrecosf

        if ak.any(basecut) and ak.any(cut1):

            sel1_events = events[cut1]
            
            sel1_b_jets = b_jets[cut1]

            sel1_vbf_jets = vbf_jets[cut1]

            sel1_muons = tight_muons[cut1][:,0]

            sel1_nextrajets = nextrajets[cut1]

            sel1_nextrabjets = nextrabjets[cut1]

            output["weights"][dataset] += processor.column_accumulator(np.sign(ak.to_numpy(sel1_events.Generator.weight).data))

            output['variables'][dataset] += processor.column_accumulator(np.transpose(np.vstack((
                ak.to_numpy(sel1_nextrajets),
                ak.to_numpy(sel1_nextrabjets),
                np.zeros(len(sel1_events)),
                np.sign(ak.to_numpy(sel1_muons.charge)+1),
                ak.to_numpy(sel1_muons.pt),
                ak.to_numpy(sel1_muons.eta),
                ak.to_numpy(sel1_muons.phi),
                ak.to_numpy(sel1_events.PuppiMET.pt),
                ak.to_numpy(sel1_events.PuppiMET.phi),
                ak.to_numpy(sel1_b_jets[:,0].pt),
                ak.to_numpy(sel1_b_jets[:,1].pt),
                ak.to_numpy(sel1_vbf_jets[:,0].pt),
                ak.to_numpy(sel1_vbf_jets[:,1].pt),
                ak.to_numpy(sel1_b_jets[:,0].eta),
                ak.to_numpy(sel1_b_jets[:,1].eta),
                ak.to_numpy(sel1_vbf_jets[:,0].eta),
                ak.to_numpy(sel1_vbf_jets[:,1].eta),
                ak.to_numpy(sel1_b_jets[:,0].phi),
                ak.to_numpy(sel1_b_jets[:,1].phi),
                ak.to_numpy(sel1_vbf_jets[:,0].phi),
                ak.to_numpy(sel1_vbf_jets[:,1].phi),
                ak.to_numpy(sel1_b_jets[:,0].btagDeepB),
                ak.to_numpy(sel1_b_jets[:,1].btagDeepB),
                ak.to_numpy(sel1_vbf_jets[:,0].btagDeepB),
                ak.to_numpy(sel1_vbf_jets[:,1].btagDeepB),
                ak.to_numpy((sel1_b_jets[:,0]+sel1_b_jets[:,1]).mass),
                ak.to_numpy((sel1_vbf_jets[:,0]+sel1_vbf_jets[:,1]).mass),
                ak.to_numpy(sel1_vbf_jets[:,0].eta - sel1_vbf_jets[:,1].eta),
                ak.to_numpy(np.sqrt(2*(sel1_muons+sel1_b_jets[:,0]).pt*sel1_events.PuppiMET.pt*(1 - np.cos(sel1_events.PuppiMET.phi - (sel1_muons+sel1_b_jets[:,0]).phi)))),ak.to_numpy(np.sqrt(2*(sel1_muons+sel1_b_jets[:,1]).pt*sel1_events.PuppiMET.pt*(1 - np.cos(sel1_events.PuppiMET.phi - (sel1_muons+sel1_b_jets[:,1]).phi))))))))

            sel1_pu_weight = evaluator['pileup'](sel1_events.Pileup.nTrueInt)
            sel1_muonidsf = evaluator['muonidsf'](abs(sel1_muons.eta), sel1_muons.pt)
            sel1_muonisosf = evaluator['muonisosf'](abs(sel1_muons.eta), sel1_muons.pt)
            sel1_muonhltsf = evaluator['muonhltsf'](abs(sel1_muons.eta), sel1_muons.pt)
            sel1_weight = np.sign(sel1_events.Generator.weight)*sel1_pu_weight*sel1_events.L1PreFiringWeight.Nom*sel1_muonidsf*sel1_muonisosf*sel1_muonhltsf

        if ak.any(basecut) and ak.any(cut2):
       
            sel2_events = events[cut2]
            sel2_b_jets = b_jets[cut2]
            sel2_vbf_jets = vbf_jets[cut2]
            sel2_electrons = tight_electrons[cut2][:,0]
            sel2_nextrajets = nextrajets[cut2]
            sel2_nextrabjets = nextrabjets[cut2]
         
            output["weights"][dataset] += processor.column_accumulator(np.sign(ak.to_numpy(sel2_events.Generator.weight).data))

            output['variables'][dataset] += processor.column_accumulator(np.transpose(np.vstack((
                ak.to_numpy(sel2_nextrajets),
                ak.to_numpy(sel2_nextrabjets),
                np.ones(len(sel2_events)),
                np.sign(ak.to_numpy(sel2_electrons.charge)+1),
                ak.to_numpy(sel2_electrons.pt),
                ak.to_numpy(sel2_electrons.eta),
                ak.to_numpy(sel2_electrons.phi),
                ak.to_numpy(sel2_events.PuppiMET.pt),
                ak.to_numpy(sel2_events.PuppiMET.phi),
                ak.to_numpy(sel2_b_jets[:,0].pt),
                ak.to_numpy(sel2_b_jets[:,1].pt),
                ak.to_numpy(sel2_vbf_jets[:,0].pt),
                ak.to_numpy(sel2_vbf_jets[:,1].pt),
                ak.to_numpy(sel2_b_jets[:,0].eta),
                ak.to_numpy(sel2_b_jets[:,1].eta),
                ak.to_numpy(sel2_vbf_jets[:,0].eta),
                ak.to_numpy(sel2_vbf_jets[:,1].eta),
                ak.to_numpy(sel2_b_jets[:,0].phi),
                ak.to_numpy(sel2_b_jets[:,1].phi),
                ak.to_numpy(sel2_vbf_jets[:,0].phi),
                ak.to_numpy(sel2_vbf_jets[:,1].phi),
                ak.to_numpy(sel2_b_jets[:,0].btagDeepB),
                ak.to_numpy(sel2_b_jets[:,1].btagDeepB),
                ak.to_numpy(sel2_vbf_jets[:,0].btagDeepB),
                ak.to_numpy(sel2_vbf_jets[:,1].btagDeepB),
                ak.to_numpy((sel2_b_jets[:,0]+sel2_b_jets[:,1]).mass),
                ak.to_numpy((sel2_vbf_jets[:,0]+sel2_vbf_jets[:,1]).mass),
                ak.to_numpy(sel2_vbf_jets[:,0].eta - sel2_vbf_jets[:,1].eta),
                ak.to_numpy(np.sqrt(2*(sel2_electrons+sel2_b_jets[:,0]).pt*sel2_events.PuppiMET.pt*(1 - np.cos(sel2_events.PuppiMET.phi - (sel2_electrons+sel2_b_jets[:,0]).phi)))),ak.to_numpy(np.sqrt(2*(sel2_electrons+sel2_b_jets[:,1]).pt*sel2_events.PuppiMET.pt*(1 - np.cos(sel2_events.PuppiMET.phi - (sel2_electrons+sel2_b_jets[:,1]).phi))))))))

            sel2_pu_weight = evaluator['pileup'](sel2_events.Pileup.nTrueInt)

            sel2_electronidsf = evaluator['electronidsf'](sel2_electrons.eta, sel2_electrons.pt)
            sel2_electronrecosf = evaluator['electronrecosf'](sel2_electrons.eta, sel2_electrons.pt)

            sel2_weight = np.sign(sel2_events.Generator.weight)*sel2_pu_weight*sel2_events.L1PreFiringWeight.Nom*sel2_electronidsf*sel2_electronrecosf

        return output
Exemplo n.º 18
0
    def process(self, events):
        output = self.accumulator.identity()

        self.sample_name = events.metadata["dataset"]

        ## make event weights
        # data or MC distinction made internally
        evt_weights = MCWeights.get_event_weights(events,
                                                  year=args.year,
                                                  corrections=self.corrections)

        all_gen_tops = events["GenPart"][events["GenPart"].pdgId == 6]
        all_gen_tbars = events["GenPart"][events["GenPart"].pdgId == -6]

        # find all stages of decay/hadronization process of tops (and tbars) for which there are only at most 1 top passing per event (but not all events are empty)
        tops_dict = {
            flag: all_gen_tops[all_gen_tops.hasFlags([flag])]
            for flag in self.FLAGS if
            (ak.all(ak.num(all_gen_tops[all_gen_tops.hasFlags([flag])]) < 2)
             & ak.any(ak.num(all_gen_tops[all_gen_tops.hasFlags([flag])]) > 0))
        }
        tbars_dict = {
            flag: all_gen_tbars[all_gen_tbars.hasFlags([flag])]
            for flag in self.FLAGS
            if (ak.all(
                ak.num(all_gen_tbars[all_gen_tbars.hasFlags([flag])]) < 2)
                & ak.any(
                    ak.num(all_gen_tbars[all_gen_tbars.hasFlags([flag])]) > 0))
        }

        for flag in tops_dict.keys():
            if not ak.all(ak.num(tops_dict[flag]) == ak.num(tbars_dict[flag])):
                print(
                    f"Gen tops and tbars don't have same number of entries for {flag}"
                )
                continue

            evt_mask = ak.num(tops_dict[flag]) > 0
            wts = evt_weights.weight()[evt_mask]

            gen_tops = tops_dict[flag][evt_mask]
            gen_tbars = tbars_dict[flag][evt_mask]
            gen_ttbars = gen_tops + gen_tbars

            #set_trace()
            top_ctstar, tbar_ctstar = make_vars.ctstar(gen_tops, gen_tbars)
            if "Int" in self.sample_name:
                pos_evts = np.where(wts > 0)
                # tops
                output = self.fill_genp_hists(accumulator=output,
                                              dname="%s_pos" %
                                              self.sample_name,
                                              genp_type="Top",
                                              flag=flag,
                                              obj=gen_tops[pos_evts],
                                              evt_weights=wts[pos_evts])
                # tbars
                output = self.fill_genp_hists(accumulator=output,
                                              dname="%s_pos" %
                                              self.sample_name,
                                              genp_type="Tbar",
                                              flag=flag,
                                              obj=gen_tbars[pos_evts],
                                              evt_weights=wts[pos_evts])
                # ttbars
                output = self.fill_genp_hists(accumulator=output,
                                              dname="%s_pos" %
                                              self.sample_name,
                                              genp_type="TTbar",
                                              flag=flag,
                                              obj=gen_ttbars[pos_evts],
                                              evt_weights=wts[pos_evts])

                neg_evts = np.where(wts < 0)
                # tops
                output = self.fill_genp_hists(accumulator=output,
                                              dname="%s_neg" %
                                              self.sample_name,
                                              genp_type="Top",
                                              flag=flag,
                                              obj=gen_tops[neg_evts],
                                              evt_weights=wts[neg_evts])
                # tbars
                output = self.fill_genp_hists(accumulator=output,
                                              dname="%s_neg" %
                                              self.sample_name,
                                              genp_type="Tbar",
                                              flag=flag,
                                              obj=gen_tbars[neg_evts],
                                              evt_weights=wts[neg_evts])
                # ttbars
                output = self.fill_genp_hists(accumulator=output,
                                              dname="%s_neg" %
                                              self.sample_name,
                                              genp_type="TTbar",
                                              flag=flag,
                                              obj=gen_ttbars[neg_evts],
                                              evt_weights=wts[neg_evts])

                # fill ctstar hists
                output["ctstar"].fill(dataset="%s_pos" % self.sample_name,
                                      objtype="Top",
                                      flag=flag,
                                      ctstar=ak.flatten(top_ctstar[pos_evts],
                                                        axis=None),
                                      weight=wts[pos_evts])
                output["ctstar"].fill(dataset="%s_pos" % self.sample_name,
                                      objtype="Tbar",
                                      flag=flag,
                                      ctstar=ak.flatten(tbar_ctstar[pos_evts],
                                                        axis=None),
                                      weight=wts[pos_evts])
                output["ctstar"].fill(dataset="%s_neg" % self.sample_name,
                                      objtype="Top",
                                      flag=flag,
                                      ctstar=ak.flatten(top_ctstar[neg_evts],
                                                        axis=None),
                                      weight=wts[neg_evts])
                output["ctstar"].fill(dataset="%s_neg" % self.sample_name,
                                      objtype="Tbar",
                                      flag=flag,
                                      ctstar=ak.flatten(tbar_ctstar[neg_evts],
                                                        axis=None),
                                      weight=wts[neg_evts])
                output["ctstar_abs"].fill(dataset="%s_pos" % self.sample_name,
                                          objtype="Top",
                                          flag=flag,
                                          ctstar_abs=np.abs(
                                              ak.flatten(top_ctstar[pos_evts],
                                                         axis=None)),
                                          weight=wts[pos_evts])
                output["ctstar_abs"].fill(dataset="%s_pos" % self.sample_name,
                                          objtype="Tbar",
                                          flag=flag,
                                          ctstar_abs=np.abs(
                                              ak.flatten(tbar_ctstar[pos_evts],
                                                         axis=None)),
                                          weight=wts[pos_evts])
                output["ctstar_abs"].fill(dataset="%s_neg" % self.sample_name,
                                          objtype="Top",
                                          flag=flag,
                                          ctstar_abs=np.abs(
                                              ak.flatten(top_ctstar[neg_evts],
                                                         axis=None)),
                                          weight=wts[neg_evts])
                output["ctstar_abs"].fill(dataset="%s_neg" % self.sample_name,
                                          objtype="Tbar",
                                          flag=flag,
                                          ctstar_abs=np.abs(
                                              ak.flatten(tbar_ctstar[neg_evts],
                                                         axis=None)),
                                          weight=wts[neg_evts])
            else:
                # tops
                output = self.fill_genp_hists(accumulator=output,
                                              dname=self.sample_name,
                                              genp_type="Top",
                                              flag=flag,
                                              obj=gen_tops,
                                              evt_weights=wts)
                # tbars
                output = self.fill_genp_hists(accumulator=output,
                                              dname=self.sample_name,
                                              genp_type="Tbar",
                                              flag=flag,
                                              obj=gen_tbars,
                                              evt_weights=wts)
                # ttbars
                output = self.fill_genp_hists(accumulator=output,
                                              dname=self.sample_name,
                                              genp_type="TTbar",
                                              flag=flag,
                                              obj=gen_ttbars,
                                              evt_weights=wts)

                # fill ctstar hists
                output["ctstar"].fill(dataset=self.sample_name,
                                      objtype="Top",
                                      flag=flag,
                                      ctstar=ak.flatten(top_ctstar, axis=None),
                                      weight=wts)
                output["ctstar"].fill(dataset=self.sample_name,
                                      objtype="Tbar",
                                      flag=flag,
                                      ctstar=ak.flatten(tbar_ctstar,
                                                        axis=None),
                                      weight=wts)
                output["ctstar_abs"].fill(dataset=self.sample_name,
                                          objtype="Top",
                                          flag=flag,
                                          ctstar_abs=np.abs(
                                              ak.flatten(top_ctstar,
                                                         axis=None)),
                                          weight=wts)
                output["ctstar_abs"].fill(dataset=self.sample_name,
                                          objtype="Tbar",
                                          flag=flag,
                                          ctstar_abs=np.abs(
                                              ak.flatten(tbar_ctstar,
                                                         axis=None)),
                                          weight=wts)

        return output
Exemplo n.º 19
0
def select_normal(genparts, w_decay_momid):

    columns = ["pt", "eta", "phi", "mass", "pdgId", "charge", "decaytype"]

    # get tops, defined as last copy
    gen_tops = genparts[(genparts.hasFlags(['isLastCopy']))
                        & (genparts.pdgId == 6)]
    gen_tops['charge'] = ak.ones_like(gen_tops.pt) * (2. / 3.)
    gen_tbars = genparts[(genparts.hasFlags(['isLastCopy']))
                         & (genparts.pdgId == -6)]
    gen_tbars['charge'] = ak.ones_like(gen_tbars.pt) * (-2. / 3.)

    # get direct top decay products (children are "isHardProcess" and "isFirstCopy")
    gen_bs = ak.flatten(gen_tops.children[(gen_tops.children.pdgId == 5)],
                        axis=2)
    gen_bs['charge'] = ak.ones_like(gen_bs.pt) * (-1. / 3.)
    gen_bbars = ak.flatten(
        gen_tbars.children[(gen_tbars.children.pdgId == -5)], axis=2)
    gen_bbars['charge'] = ak.ones_like(gen_bbars.pt) * (1. / 3.)
    gen_wplus = ak.flatten(
        gen_tops.children[(gen_tops.children.pdgId == w_decay_momid)], axis=2)
    gen_wplus['charge'] = ak.ones_like(gen_wplus.pt)
    gen_wminus = ak.flatten(
        gen_tbars.children[(gen_tbars.children.pdgId == -1 * w_decay_momid)],
        axis=2)
    gen_wminus['charge'] = ak.ones_like(gen_wminus.pt) * (-1.)

    # get w decay products
    # get last copy of W bosons
    last_gen_wplus = ak.flatten(gen_tops.distinctChildren[
        (gen_tops.distinctChildren.pdgId == w_decay_momid)
        & (gen_tops.distinctChildren.hasFlags(['isLastCopy']))],
                                axis=2)
    last_gen_wminus = ak.flatten(gen_tbars.distinctChildren[
        (gen_tbars.distinctChildren.pdgId == -1 * w_decay_momid)
        & (gen_tbars.distinctChildren.hasFlags(['isLastCopy']))],
                                 axis=2)

    gen_wplus_decaytype = np.zeros(len(gen_wplus))
    gen_wminus_decaytype = np.zeros(len(gen_wminus))
    # up/down partons from last W+
    gen_wpartons_up_fromWplus = ak.flatten(
        last_gen_wplus.children[(np.mod(last_gen_wplus.children.pdgId, 2) == 0)
                                & (np.abs(last_gen_wplus.children.pdgId) < 6)],
        axis=2)
    gen_wpartons_up_fromWplus['charge'] = np.sign(
        gen_wpartons_up_fromWplus.pdgId) * (2. / 3.)
    gen_wplus_decaytype[ak.num(gen_wpartons_up_fromWplus) > 0] = np.ones(
        ak.sum(ak.num(gen_wpartons_up_fromWplus) > 0)) * 2
    gen_wpartons_dw_fromWplus = ak.flatten(
        last_gen_wplus.children[(np.mod(last_gen_wplus.children.pdgId, 2) == 1)
                                & (np.abs(last_gen_wplus.children.pdgId) < 6)],
        axis=2)
    gen_wpartons_dw_fromWplus['charge'] = np.sign(
        gen_wpartons_up_fromWplus.pdgId) * (-1. / 3.)
    # up/down partons from last W-
    gen_wpartons_up_fromWminus = ak.flatten(last_gen_wminus.children[
        (np.mod(last_gen_wminus.children.pdgId, 2) == 0)
        & (np.abs(last_gen_wminus.children.pdgId) < 6)],
                                            axis=2)
    gen_wpartons_up_fromWminus['charge'] = np.sign(
        gen_wpartons_up_fromWminus.pdgId) * (2. / 3.)
    gen_wminus_decaytype[ak.num(gen_wpartons_up_fromWminus) > 0] = np.ones(
        ak.sum(ak.num(gen_wpartons_up_fromWminus) > 0)) * 2
    gen_wpartons_dw_fromWminus = ak.flatten(last_gen_wminus.children[
        (np.mod(last_gen_wminus.children.pdgId, 2) == 1)
        & (np.abs(last_gen_wminus.children.pdgId) < 6)],
                                            axis=2)
    gen_wpartons_dw_fromWminus['charge'] = np.sign(
        gen_wpartons_up_fromWminus.pdgId) * (-1. / 3.)

    # charged leps from last W+
    gen_charged_leps_fromWplus = ak.flatten(
        last_gen_wplus.children[(np.abs(last_gen_wplus.children.pdgId) == 11) |
                                (np.abs(last_gen_wplus.children.pdgId) == 13) |
                                (np.abs(last_gen_wplus.children.pdgId) == 15)],
        axis=2)
    gen_charged_leps_fromWplus['charge'] = ak.ones_like(
        gen_charged_leps_fromWplus.pdgId)
    gen_wplus_decaytype[ak.num(gen_charged_leps_fromWplus) > 0] = np.ones(
        ak.sum(ak.num(gen_charged_leps_fromWplus) > 0))
    # add decaytype (0 is INVALID, 1 is LEPTONIC, 2 is HADRONIC)
    gen_wplus['decaytype'] = ak.unflatten(gen_wplus_decaytype,
                                          ak.num(gen_wplus))
    gen_tops['decaytype'] = gen_wplus['decaytype']  # set decaytype for tops
    gen_bs['decaytype'] = gen_wplus['decaytype']  # set decaytype for bs
    # neutral leps from last W+
    gen_neutral_leps_fromWplus = ak.flatten(
        last_gen_wplus.children[(np.abs(last_gen_wplus.children.pdgId) == 12) |
                                (np.abs(last_gen_wplus.children.pdgId) == 14) |
                                (np.abs(last_gen_wplus.children.pdgId) == 16)],
        axis=2)
    gen_neutral_leps_fromWplus['charge'] = ak.zeros_like(
        gen_neutral_leps_fromWplus.pt)

    # charged leps from last W-
    gen_charged_leps_fromWminus = ak.flatten(last_gen_wminus.children[
        (np.abs(last_gen_wminus.children.pdgId) == 11) |
        (np.abs(last_gen_wminus.children.pdgId) == 13) |
        (np.abs(last_gen_wminus.children.pdgId) == 15)],
                                             axis=2)
    gen_charged_leps_fromWminus['charge'] = ak.ones_like(
        gen_charged_leps_fromWminus.pdgId) * (-1.)
    gen_wminus_decaytype[ak.num(gen_charged_leps_fromWminus) > 0] = np.ones(
        ak.sum(ak.num(gen_charged_leps_fromWminus) > 0))
    # add decaytype (0 is INVALID, 1 is LEPTONIC, 2 is HADRONIC)
    gen_wminus['decaytype'] = ak.unflatten(gen_wminus_decaytype,
                                           ak.num(gen_wminus))
    gen_tbars['decaytype'] = gen_wminus['decaytype']  # set decaytype for tbars
    gen_bbars['decaytype'] = gen_wminus['decaytype']  # set decaytype for bbars
    # neutral leps from last W-
    gen_neutral_leps_fromWminus = ak.flatten(last_gen_wminus.children[
        (np.abs(last_gen_wminus.children.pdgId) == 12) |
        (np.abs(last_gen_wminus.children.pdgId) == 14) |
        (np.abs(last_gen_wminus.children.pdgId) == 16)],
                                             axis=2)
    gen_neutral_leps_fromWminus['charge'] = ak.zeros_like(
        gen_neutral_leps_fromWminus.pt)

    gen_wpartons_up = ak.Array({}, with_name="PtEtaPhiMLorentzVector")
    gen_wpartons_dw = ak.Array({}, with_name="PtEtaPhiMLorentzVector")
    gen_charged_leps = ak.Array({}, with_name="PtEtaPhiMLorentzVector")
    gen_neutral_leps = ak.Array({}, with_name="PtEtaPhiMLorentzVector")
    for column in columns:
        if column == 'decaytype': continue
        gen_wpartons_up[column] = ak.flatten(
            ak.concatenate([
                gen_wpartons_up_fromWplus[column],
                gen_wpartons_up_fromWminus[column]
            ],
                           axis=1))  # (up-type partons from W+, W-)
        gen_wpartons_dw[column] = ak.flatten(
            ak.concatenate([
                gen_wpartons_dw_fromWplus[column],
                gen_wpartons_dw_fromWminus[column]
            ],
                           axis=1))  # (dw-type partons from W+, W-)
        gen_charged_leps[column] = ak.flatten(
            ak.concatenate([
                gen_charged_leps_fromWplus[column],
                gen_charged_leps_fromWminus[column]
            ],
                           axis=1))  # (charged leps from W+, W-)
        gen_neutral_leps[column] = ak.flatten(
            ak.concatenate([
                gen_neutral_leps_fromWplus[column],
                gen_neutral_leps_fromWminus[column]
            ],
                           axis=1))  # (neutral leps from W+, W-)

    gen_wpartons_up = ak.unflatten(
        gen_wpartons_up,
        ak.num(gen_wpartons_up_fromWplus) + ak.num(gen_wpartons_up_fromWminus))
    gen_wpartons_dw = ak.unflatten(
        gen_wpartons_dw,
        ak.num(gen_wpartons_dw_fromWplus) + ak.num(gen_wpartons_dw_fromWminus))
    gen_charged_leps = ak.unflatten(
        gen_charged_leps,
        ak.num(gen_charged_leps_fromWplus) +
        ak.num(gen_charged_leps_fromWminus))
    gen_neutral_leps = ak.unflatten(
        gen_neutral_leps,
        ak.num(gen_neutral_leps_fromWplus) +
        ak.num(gen_neutral_leps_fromWminus))
    gen_taus = gen_charged_leps[np.abs(gen_charged_leps.pdgId) == 15]
    gen_nu_taus = gen_neutral_leps[np.abs(gen_neutral_leps.pdgId) == 16]

    # fully hadronic evts
    had_evts = (ak.num(gen_charged_leps) == 0) & (
        ak.num(gen_neutral_leps)
        == 0) & (ak.num(gen_wpartons_up) == 2) & (ak.num(gen_wpartons_dw) == 2)

    #set_trace()
    # get direct tau decay products from hard processes (subset of gen_taus events above)
    tau_decay_prods = genparts[genparts.hasFlags(
        ['isDirectHardProcessTauDecayProduct'])]

    # only need decays to leptons (e/mu, tau nu) for event classification
    tau_TO_tau_nu = tau_decay_prods[np.abs(tau_decay_prods.pdgId) == 16]
    tau_TO_charged_lep = tau_decay_prods[(np.abs(tau_decay_prods.pdgId) == 11)
                                         |
                                         (np.abs(tau_decay_prods.pdgId) == 13)]
    tau_TO_neutral_lep = tau_decay_prods[(np.abs(tau_decay_prods.pdgId) == 12)
                                         |
                                         (np.abs(tau_decay_prods.pdgId) == 14)]

    # set decaytype for gen taus
    charged_lep_decaytype_array = ak.to_numpy(
        ak.flatten(ak.zeros_like(gen_charged_leps['pt'])))

    # semilep evts
    semilep_evts = (ak.num(gen_charged_leps) == 1) & (
        ak.num(gen_neutral_leps)
        == 1) & (ak.num(gen_wpartons_up) == 1) & (ak.num(gen_wpartons_dw) == 1)
    tau_jets_evts = semilep_evts & (ak.num(gen_taus) == 1)
    sl_evts_mask = np.repeat(ak.to_numpy(semilep_evts),
                             ak.to_numpy(ak.num(gen_charged_leps)))
    semilep_decaytype_array = np.zeros(ak.to_numpy(semilep_evts).sum(),
                                       dtype=int)
    # tau -> l
    semilep_tau_leptonic_decay = (tau_jets_evts) & (
        ak.num(tau_TO_charged_lep) == 1) & (
            ak.num(tau_TO_neutral_lep) == 1) & (ak.num(tau_TO_tau_nu) == 1)
    semilep_tau_hadronic_decay = (tau_jets_evts) & (
        ~semilep_tau_leptonic_decay)
    semilep_decaytype_array[
        semilep_tau_leptonic_decay[semilep_evts]] = np.ones(
            ak.to_numpy(semilep_tau_leptonic_decay).sum(), dtype=int)
    semilep_decaytype_array[
        semilep_tau_hadronic_decay[semilep_evts]] = np.ones(
            ak.to_numpy(semilep_tau_hadronic_decay).sum(), dtype=int) * 2

    # set charged_lep_decatype_array for semileptonic events
    charged_lep_decaytype_array[sl_evts_mask] = semilep_decaytype_array

    # dilep evts
    dilep_evts = (ak.num(gen_charged_leps) == 2) & (
        ak.num(gen_neutral_leps)
        == 2) & (ak.num(gen_wpartons_up) == 0) & (ak.num(gen_wpartons_dw) == 0)
    lep_lep_evts = dilep_evts & (ak.num(gen_taus) == 0)
    lep_tau_evts = dilep_evts & (ak.num(gen_taus) == 1)
    tau_tau_evts = dilep_evts & (ak.num(gen_taus) == 2)
    dl_evts_mask = np.repeat(ak.to_numpy(dilep_evts),
                             ak.to_numpy(ak.num(gen_charged_leps)))
    dilep_decaytype_array = np.zeros((ak.to_numpy(dilep_evts).sum(), 2),
                                     dtype=int)
    # tau + tau
    # tau + tau -> ll
    dilep_TauTau_ll_decay = (tau_tau_evts) & (
        ak.num(tau_TO_charged_lep) == 2) & (
            ak.num(tau_TO_neutral_lep) == 2) & (ak.num(tau_TO_tau_nu) == 2)
    dilep_decaytype_array[dilep_TauTau_ll_decay[dilep_evts]] = np.ones(
        (ak.to_numpy(dilep_TauTau_ll_decay).sum(), 2), dtype=int)
    # tau + tau -> hh
    dilep_TauTau_hh_decay = (tau_tau_evts) & (
        (ak.num(tau_TO_charged_lep) + ak.num(tau_TO_neutral_lep))
        == 0) & (ak.num(tau_TO_tau_nu) == 2)
    dilep_decaytype_array[dilep_TauTau_hh_decay[dilep_evts]] = np.ones(
        (ak.to_numpy(dilep_TauTau_hh_decay).sum(), 2), dtype=int) * 2
    # tau + tau -> lh
    dilep_TauTau_lh_decay = (
        tau_tau_evts) & ~(dilep_TauTau_ll_decay | dilep_TauTau_hh_decay)
    # set index corresponding to leptonically decaying tau to 1, default array is set to 2
    dl_TauTau_to_lh_decaytype_array = np.ones(
        ak.to_numpy(dilep_TauTau_lh_decay).sum() * 2, dtype=int) * 2
    lep_tau_mask = (np.repeat(
        ak.to_numpy(
            ak.flatten(
                tau_TO_charged_lep[dilep_TauTau_lh_decay].parent.pdgId)),
        2) == ak.flatten(gen_charged_leps[dilep_TauTau_lh_decay].pdgId))
    dl_TauTau_to_lh_decaytype_array[lep_tau_mask] = np.ones(lep_tau_mask.sum(),
                                                            dtype=int)
    dilep_decaytype_array[dilep_TauTau_lh_decay[
        dilep_evts]] = dl_TauTau_to_lh_decaytype_array.reshape(
            ak.to_numpy(dilep_TauTau_lh_decay).sum(), 2)

    # lep + tau
    # tau -> l
    dilep_LepTau_l_decay = (lep_tau_evts) & (
        ak.num(tau_TO_charged_lep) == 1) & (
            ak.num(tau_TO_neutral_lep) == 1) & (ak.num(tau_TO_tau_nu) == 1)
    # set index corresponding to tau to 1
    dl_LepTau_to_Lep_decaytype_array = np.zeros(
        ak.to_numpy(dilep_LepTau_l_decay).sum() * 2, dtype=int)
    dl_LepTau_to_Lep_decaytype_array[ak.flatten(
        np.abs(gen_charged_leps[dilep_LepTau_l_decay].pdgId) == 15)] = np.ones(
            ak.sum(dilep_LepTau_l_decay), dtype=int)
    dilep_decaytype_array[dilep_LepTau_l_decay[
        dilep_evts]] = dl_LepTau_to_Lep_decaytype_array.reshape(
            ak.sum(dilep_LepTau_l_decay), 2)
    # tau -> h
    dilep_LepTau_h_decay = (lep_tau_evts) & ~(dilep_LepTau_l_decay)
    # set index corresponding to tau to 2
    dl_LepTau_to_Had_decaytype_array = np.zeros(ak.sum(dilep_LepTau_h_decay) *
                                                2,
                                                dtype=int)
    dl_LepTau_to_Had_decaytype_array[ak.flatten(
        np.abs(gen_charged_leps[dilep_LepTau_h_decay].pdgId) == 15)] = np.ones(
            ak.sum(dilep_LepTau_h_decay), dtype=int) * 2
    dilep_decaytype_array[dilep_LepTau_h_decay[
        dilep_evts]] = dl_LepTau_to_Had_decaytype_array.reshape(
            ak.sum(dilep_LepTau_h_decay), 2)

    # set charged_lep_decatype_array for dileptonic events
    charged_lep_decaytype_array[dl_evts_mask] = dilep_decaytype_array.flatten()

    #  set charged lepton decaytype (defined for taus only, e/mu are 0) (1 is LEPTONIC, 2 is HADRONIC)
    gen_charged_leps['decaytype'] = ak.unflatten(charged_lep_decaytype_array,
                                                 ak.num(gen_charged_leps))

    # make awkward arrays of (top decay prods, tbar decay prods)
    Gen_Top_Pairs = ak.Array({}, with_name="PtEtaPhiMLorentzVector")
    Gen_B_Pairs = ak.Array({}, with_name="PtEtaPhiMLorentzVector")
    Gen_W_Pairs = ak.Array({}, with_name="PtEtaPhiMLorentzVector")
    Gen_Wparton_Pairs = ak.Array({}, with_name="PtEtaPhiMLorentzVector")
    for column in columns:
        Gen_Top_Pairs[column] = ak.flatten(
            ak.concatenate([gen_tops[column], gen_tbars[column]],
                           axis=1))  # (top, tbar)
        Gen_B_Pairs[column] = ak.flatten(
            ak.concatenate([gen_bs[column], gen_bbars[column]],
                           axis=1))  # (b, bbar)
        Gen_W_Pairs[column] = ak.flatten(
            ak.concatenate([gen_wplus[column], gen_wminus[column]],
                           axis=1))  # (W+, W-)
        if column is not "decaytype":
            Gen_Wparton_Pairs[column] = ak.flatten(
                ak.concatenate(
                    [
                        ak.pad_none(gen_wpartons_up[column], 1, axis=1),
                        ak.pad_none(gen_wpartons_dw[column], 1, axis=1)
                    ],
                    axis=1))  # (up-type wpartons, down-type wpartons)

    Gen_Top_Pairs = ak.unflatten(Gen_Top_Pairs,
                                 ak.num(gen_tops) + ak.num(gen_tbars))
    Gen_B_Pairs = ak.unflatten(Gen_B_Pairs, ak.num(gen_bs) + ak.num(gen_bbars))
    Gen_W_Pairs = ak.unflatten(Gen_W_Pairs,
                               ak.num(gen_wplus) + ak.num(gen_wminus))
    Gen_Wparton_Pairs = ak.unflatten(
        Gen_Wparton_Pairs,
        ak.num(ak.pad_none(gen_wpartons_up, 1, axis=1)) +
        ak.num(ak.pad_none(gen_wpartons_dw, 1, axis=1)))
    Gen_Wparton_Pairs = Gen_Wparton_Pairs[ak.argsort(
        Gen_Wparton_Pairs["pt"], ascending=False)]  # sort by pt

    Gen_TTbar = ak.Array(
        {
            "pt": (gen_tops + gen_tbars).pt,
            "eta": (gen_tops + gen_tbars).eta,
            "phi": (gen_tops + gen_tbars).phi,
            "mass": (gen_tops + gen_tbars).mass,
            "decaytype": gen_tops["decaytype"] + gen_tbars[
                "decaytype"],  # 0 is for INVALID, 2 for DILEP, 3 for SEMILEP, 4 for HADRONIC
        },
        with_name="PtEtaPhiMLorentzVector")

    ## make "table" of gen objects for certain decays
    ## DILEP
    DILEP_evts = ak.zip({
        "TTbar":
        Gen_TTbar[dilep_evts] if ak.any(dilep_evts) else ak.unflatten(
            Gen_TTbar[dilep_evts], ak.values_astype(dilep_evts, int)),
        "Top":
        Gen_Top_Pairs[np.sign(Gen_Top_Pairs.charge) == 1][dilep_evts]
        if ak.any(dilep_evts) else ak.unflatten(
            Gen_Top_Pairs[np.sign(Gen_Top_Pairs.charge) == 1][dilep_evts],
            ak.values_astype(dilep_evts, int)),
        "Tbar":
        Gen_Top_Pairs[np.sign(Gen_Top_Pairs.charge) == -1][dilep_evts]
        if ak.any(dilep_evts) else ak.unflatten(
            Gen_Top_Pairs[np.sign(Gen_Top_Pairs.charge) == -1][dilep_evts],
            ak.values_astype(dilep_evts, int)),
        "B":
        Gen_B_Pairs[np.sign(Gen_B_Pairs.charge) == -1][dilep_evts]
        if ak.any(dilep_evts) else ak.unflatten(
            Gen_B_Pairs[np.sign(Gen_B_Pairs.charge) == -1][dilep_evts],
            ak.values_astype(dilep_evts, int)),
        "Bbar":
        Gen_B_Pairs[np.sign(Gen_B_Pairs.charge) == 1][dilep_evts]
        if ak.any(dilep_evts) else ak.unflatten(
            Gen_B_Pairs[np.sign(Gen_B_Pairs.charge) == 1][dilep_evts],
            ak.values_astype(dilep_evts, int)),
        "Wplus":
        Gen_W_Pairs[Gen_W_Pairs.charge == 1][dilep_evts] if ak.any(dilep_evts)
        else ak.unflatten(Gen_W_Pairs[Gen_W_Pairs.charge == 1][dilep_evts],
                          ak.values_astype(dilep_evts, int)),
        "Wminus":
        Gen_W_Pairs[Gen_W_Pairs.charge == -1][dilep_evts] if ak.any(dilep_evts)
        else ak.unflatten(Gen_W_Pairs[Gen_W_Pairs.charge == -1][dilep_evts],
                          ak.values_astype(dilep_evts, int)),
        "First_plus":
        gen_charged_leps[gen_charged_leps.charge > 0][dilep_evts]
        if ak.any(dilep_evts) else ak.unflatten(
            gen_charged_leps[gen_charged_leps.charge > 0][dilep_evts],
            ak.values_astype(dilep_evts,
                             int)),  # charged lepton always made leading
        "Second_plus":
        gen_neutral_leps[gen_charged_leps.charge > 0][dilep_evts]
        if ak.any(dilep_evts) else ak.unflatten(
            gen_neutral_leps[gen_charged_leps.charge > 0][dilep_evts],
            ak.values_astype(dilep_evts,
                             int)),  # neutral lepton always made subleading
        "First_minus":
        gen_charged_leps[gen_charged_leps.charge < 0][dilep_evts]
        if ak.any(dilep_evts) else ak.unflatten(
            gen_charged_leps[gen_charged_leps.charge < 0][dilep_evts],
            ak.values_astype(dilep_evts,
                             int)),  # charged lepton always made leading
        "Second_minus":
        gen_neutral_leps[gen_charged_leps.charge < 0][dilep_evts]
        if ak.any(dilep_evts) else ak.unflatten(
            gen_neutral_leps[gen_charged_leps.charge < 0][dilep_evts],
            ak.values_astype(dilep_evts,
                             int)),  # neutral lepton always made subleading
        "Up_plus":
        gen_neutral_leps[gen_charged_leps.charge > 0][dilep_evts]
        if ak.any(dilep_evts) else ak.unflatten(
            gen_neutral_leps[gen_charged_leps.charge > 0][dilep_evts],
            ak.values_astype(dilep_evts, int)),  # same as second plus
        "Down_plus":
        gen_charged_leps[gen_charged_leps.charge > 0][dilep_evts]
        if ak.any(dilep_evts) else ak.unflatten(
            gen_charged_leps[gen_charged_leps.charge > 0][dilep_evts],
            ak.values_astype(dilep_evts, int)),  # same as first plus
        "Up_minus":
        gen_neutral_leps[gen_charged_leps.charge < 0][dilep_evts]
        if ak.any(dilep_evts) else ak.unflatten(
            gen_neutral_leps[gen_charged_leps.charge < 0][dilep_evts],
            ak.values_astype(dilep_evts, int)),  # same as second minus
        "Down_minus":
        gen_charged_leps[gen_charged_leps.charge < 0][dilep_evts]
        if ak.any(dilep_evts) else ak.unflatten(
            gen_charged_leps[gen_charged_leps.charge < 0][dilep_evts],
            ak.values_astype(dilep_evts, int)),  # same as first minus
    })

    ## HAD
    HAD_evts = ak.zip({
        "TTbar":
        Gen_TTbar[had_evts] if ak.any(had_evts) else ak.unflatten(
            Gen_TTbar[had_evts], ak.values_astype(had_evts, int)),
        "Top":
        Gen_Top_Pairs[np.sign(Gen_Top_Pairs.charge) == 1][had_evts]
        if ak.any(had_evts) else ak.unflatten(
            Gen_Top_Pairs[np.sign(Gen_Top_Pairs.charge) == 1][had_evts],
            ak.values_astype(had_evts, int)),
        "Tbar":
        Gen_Top_Pairs[np.sign(Gen_Top_Pairs.charge) == -1][had_evts]
        if ak.any(had_evts) else ak.unflatten(
            Gen_Top_Pairs[np.sign(Gen_Top_Pairs.charge) == -1][had_evts],
            ak.values_astype(had_evts, int)),
        "B":
        Gen_B_Pairs[np.sign(Gen_B_Pairs.charge) == -1][had_evts]
        if ak.any(had_evts) else ak.unflatten(
            Gen_B_Pairs[np.sign(Gen_B_Pairs.charge) == -1][had_evts],
            ak.values_astype(had_evts, int)),
        "Bbar":
        Gen_B_Pairs[np.sign(Gen_B_Pairs.charge) == 1][had_evts]
        if ak.any(had_evts) else ak.unflatten(
            Gen_B_Pairs[np.sign(Gen_B_Pairs.charge) == 1][had_evts],
            ak.values_astype(had_evts, int)),
        "Wplus":
        Gen_W_Pairs[Gen_W_Pairs.charge == 1][had_evts] if ak.any(had_evts) else
        ak.unflatten(Gen_W_Pairs[Gen_W_Pairs.charge == 1][had_evts],
                     ak.values_astype(had_evts, int)),
        "Wminus":
        Gen_W_Pairs[Gen_W_Pairs.charge == -1][had_evts] if ak.any(had_evts)
        else ak.unflatten(Gen_W_Pairs[Gen_W_Pairs.charge == -1][had_evts],
                          ak.values_astype(had_evts, int)),
        "First_plus":
        Gen_Wparton_Pairs[had_evts][Gen_Wparton_Pairs[had_evts].charge > 0][:,
                                                                            0]
        if ak.any(had_evts) else ak.unflatten(
            Gen_Wparton_Pairs[had_evts][Gen_Wparton_Pairs[had_evts].charge > 0]
            [:, 0], ak.values_astype(
                had_evts, int)),  # leading positively-charged parton
        "Second_plus":
        Gen_Wparton_Pairs[had_evts][Gen_Wparton_Pairs[had_evts].charge > 0][:,
                                                                            1]
        if ak.any(had_evts) else ak.unflatten(
            Gen_Wparton_Pairs[had_evts][Gen_Wparton_Pairs[had_evts].charge > 0]
            [:, 1], ak.values_astype(
                had_evts, int)),  # subleading positively-charged parton
        "First_minus":
        Gen_Wparton_Pairs[had_evts][Gen_Wparton_Pairs[had_evts].charge < 0][:,
                                                                            0]
        if ak.any(had_evts) else ak.unflatten(
            Gen_Wparton_Pairs[had_evts][Gen_Wparton_Pairs[had_evts].charge < 0]
            [:, 0], ak.values_astype(
                had_evts, int)),  # leading negatively-charged parton
        "Second_minus":
        Gen_Wparton_Pairs[had_evts][Gen_Wparton_Pairs[had_evts].charge < 0][:,
                                                                            1]
        if ak.any(had_evts) else ak.unflatten(
            Gen_Wparton_Pairs[had_evts][Gen_Wparton_Pairs[had_evts].charge < 0]
            [:, 1], ak.values_astype(
                had_evts, int)),  # subleading negatively-charged parton
        "Up_plus":
        gen_wpartons_up[gen_wpartons_up.charge > 0][had_evts]
        if ak.any(had_evts) else ak.unflatten(
            gen_wpartons_up[gen_wpartons_up.charge > 0][had_evts],
            ak.values_astype(had_evts,
                             int)),  # positively-charged up-type parton
        "Down_plus":
        gen_wpartons_dw[gen_wpartons_dw.charge > 0][had_evts]
        if ak.any(had_evts) else ak.unflatten(
            gen_wpartons_dw[gen_wpartons_dw.charge > 0][had_evts],
            ak.values_astype(had_evts,
                             int)),  # positively-charged down-type parton
        "Up_minus":
        gen_wpartons_up[gen_wpartons_up.charge < 0][had_evts]
        if ak.any(had_evts) else ak.unflatten(
            gen_wpartons_up[gen_wpartons_up.charge < 0][had_evts],
            ak.values_astype(had_evts,
                             int)),  # negatively-charged up-type parton
        "Down_minus":
        gen_wpartons_dw[gen_wpartons_dw.charge < 0][had_evts]
        if ak.any(had_evts) else ak.unflatten(
            gen_wpartons_dw[gen_wpartons_dw.charge < 0][had_evts],
            ak.values_astype(had_evts,
                             int)),  # negatively-charged down-type parton
    })

    ## SEMILEP
    SEMILEP_evts = ak.zip({
        "TTbar":
        Gen_TTbar[semilep_evts] if ak.any(semilep_evts) else ak.unflatten(
            Gen_TTbar[semilep_evts], ak.values_astype(semilep_evts, int)),
        "THad":
        Gen_Top_Pairs[Gen_Top_Pairs.decaytype == 2][semilep_evts]
        if ak.any(semilep_evts) else ak.unflatten(
            Gen_Top_Pairs[Gen_Top_Pairs.decaytype == 2][semilep_evts],
            ak.values_astype(semilep_evts, int)),
        "TLep":
        Gen_Top_Pairs[Gen_Top_Pairs.decaytype == 1][semilep_evts]
        if ak.any(semilep_evts) else ak.unflatten(
            Gen_Top_Pairs[Gen_Top_Pairs.decaytype == 1][semilep_evts],
            ak.values_astype(semilep_evts, int)),
        "BHad":
        Gen_B_Pairs[Gen_B_Pairs.decaytype == 2][semilep_evts]
        if ak.any(semilep_evts) else ak.unflatten(
            Gen_B_Pairs[Gen_B_Pairs.decaytype == 2][semilep_evts],
            ak.values_astype(semilep_evts, int)),
        "BLep":
        Gen_B_Pairs[Gen_B_Pairs.decaytype == 1][semilep_evts]
        if ak.any(semilep_evts) else ak.unflatten(
            Gen_B_Pairs[Gen_B_Pairs.decaytype == 1][semilep_evts],
            ak.values_astype(semilep_evts, int)),
        "WHad":
        Gen_W_Pairs[Gen_W_Pairs.decaytype == 2][semilep_evts]
        if ak.any(semilep_evts) else ak.unflatten(
            Gen_W_Pairs[Gen_W_Pairs.decaytype == 2][semilep_evts],
            ak.values_astype(semilep_evts, int)),
        "WLep":
        Gen_W_Pairs[Gen_W_Pairs.decaytype == 1][semilep_evts]
        if ak.any(semilep_evts) else ak.unflatten(
            Gen_W_Pairs[Gen_W_Pairs.decaytype == 1][semilep_evts],
            ak.values_astype(semilep_evts, int)),
        "Lepton":
        gen_charged_leps[semilep_evts] if ak.any(semilep_evts) else
        ak.unflatten(gen_charged_leps[semilep_evts],
                     ak.values_astype(semilep_evts, int)),
        "Nu":
        gen_neutral_leps[semilep_evts] if ak.any(semilep_evts) else
        ak.unflatten(gen_neutral_leps[semilep_evts],
                     ak.values_astype(semilep_evts, int)),
        "WJa":
        Gen_Wparton_Pairs[:, 0][semilep_evts] if ak.any(semilep_evts) else
        ak.unflatten(Gen_Wparton_Pairs[:, 0][semilep_evts],
                     ak.values_astype(semilep_evts, int)),
        "WJb":
        Gen_Wparton_Pairs[:, 1][semilep_evts] if ak.any(semilep_evts) else
        ak.unflatten(Gen_Wparton_Pairs[:, 1][semilep_evts],
                     ak.values_astype(semilep_evts, int)),
        "Up_Had":
        gen_wpartons_up[semilep_evts] if ak.any(semilep_evts) else
        ak.unflatten(gen_wpartons_up[semilep_evts],
                     ak.values_astype(semilep_evts, int)),
        "Down_Had":
        gen_wpartons_dw[semilep_evts] if ak.any(semilep_evts) else
        ak.unflatten(gen_wpartons_dw[semilep_evts],
                     ak.values_astype(semilep_evts, int)),
    })

    # make dictionary to return
    GenObjects = dict({
        "SL": SEMILEP_evts,
        "DL": DILEP_evts,
        "Had": HAD_evts,
    })

    return GenObjects
def test_highlevel():
    array = ak.Array(
        [[[2, 3, 5], [], [7, 11], [13]], [], [[17, 19], [23]]], check_valid=True
    )

    assert ak.count(array) == 9
    assert ak.to_list(ak.count(array, axis=-1)) == [[3, 0, 2, 1], [], [2, 1]]
    assert ak.to_list(ak.count(array, axis=2)) == [[3, 0, 2, 1], [], [2, 1]]
    assert ak.to_list(ak.count(array, axis=-1, keepdims=True)) == [
        [[3], [0], [2], [1]],
        [],
        [[2], [1]],
    ]
    assert ak.to_list(ak.count(array, axis=-2)) == [[3, 2, 1], [], [2, 1]]
    assert ak.to_list(ak.count(array, axis=1)) == [[3, 2, 1], [], [2, 1]]
    assert ak.to_list(ak.count(array, axis=-2, keepdims=True)) == [
        [[3, 2, 1]],
        [[]],
        [[2, 1]],
    ]

    assert ak.count_nonzero(array) == 9
    assert ak.to_list(ak.count_nonzero(array, axis=-1)) == [[3, 0, 2, 1], [], [2, 1]]
    assert ak.to_list(ak.count_nonzero(array, axis=-2)) == [[3, 2, 1], [], [2, 1]]

    assert ak.sum(array) == 2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23
    assert ak.to_list(ak.sum(array, axis=-1)) == [
        [2 + 3 + 5, 0, 7 + 11, 13],
        [],
        [17 + 19, 23],
    ]
    assert ak.to_list(ak.sum(array, axis=-2)) == [
        [2 + 7 + 13, 3 + 11, 5],
        [],
        [17 + 23, 19],
    ]

    assert ak.prod(array) == 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23
    assert ak.to_list(ak.prod(array, axis=-1)) == [
        [2 * 3 * 5, 1, 7 * 11, 13],
        [],
        [17 * 19, 23],
    ]
    assert ak.to_list(ak.prod(array, axis=-2)) == [
        [2 * 7 * 13, 3 * 11, 5],
        [],
        [17 * 23, 19],
    ]

    assert ak.min(array) == 2
    assert ak.to_list(ak.min(array, axis=-1)) == [[2, None, 7, 13], [], [17, 23]]
    assert ak.to_list(ak.min(array, axis=-2)) == [[2, 3, 5], [], [17, 19]]

    assert ak.max(array) == 23
    assert ak.to_list(ak.max(array, axis=-1)) == [[5, None, 11, 13], [], [19, 23]]
    assert ak.to_list(ak.max(array, axis=-2)) == [[13, 11, 5], [], [23, 19]]

    array = ak.Array(
        [
            [[True, False, True], [], [False, False], [True]],
            [],
            [[False, True], [True]],
        ],
        check_valid=True,
    )

    assert ak.any(array) == True
    assert ak.to_list(ak.any(array, axis=-1)) == [
        [True, False, False, True],
        [],
        [True, True],
    ]
    assert ak.to_list(ak.any(array, axis=-2)) == [[True, False, True], [], [True, True]]

    assert ak.all(array) == False
    assert ak.to_list(ak.all(array, axis=-1)) == [
        [False, True, False, True],
        [],
        [False, True],
    ]
    assert ak.to_list(ak.all(array, axis=-2)) == [
        [False, False, True],
        [],
        [False, True],
    ]
Exemplo n.º 21
0
    def trilep_baseline(self, omit=[], cutflow=None, tight=False):
        '''
        give it a cutflow object if you want it to be filed.
        cuts in the omit list will not be applied
        '''
        self.selection = PackedSelection()

        is_trilep  = ((ak.num(self.ele) + ak.num(self.mu))==3)
        los_trilep = ((ak.num(self.ele) + ak.num(self.mu))>=2)
        pos_charge = ((ak.sum(self.ele.pdgId, axis=1) + ak.sum(self.mu.pdgId, axis=1))<0)
        neg_charge = ((ak.sum(self.ele.pdgId, axis=1) + ak.sum(self.mu.pdgId, axis=1))>0)
        lep0pt     = ((ak.num(self.ele[(self.ele.pt>25)]) + ak.num(self.mu[(self.mu.pt>25)]))>0)
        lep1pt     = ((ak.num(self.ele[(self.ele.pt>20)]) + ak.num(self.mu[(self.mu.pt>20)]))>1)
        lepveto    = ((ak.num(self.ele_veto) + ak.num(self.mu_veto))==3)

        dimu    = choose(self.mu, 2)
        diele   = choose(self.ele, 2)
        dimu_veto = choose(self.mu_veto,2)
        diele_veto = choose(self.ele_veto,2)
        #dilep   = cross(self.mu, self.ele)

        OS_dimu = dimu[(dimu['0'].charge*dimu['1'].charge < 0)]
        OS_diele = diele[(diele['0'].charge*diele['1'].charge < 0)]
        OS_dimu_veto = dimu_veto[(dimu_veto['0'].charge*dimu_veto['1'].charge < 0)]
        OS_diele_veto = diele_veto[(diele_veto['0'].charge*diele_veto['1'].charge < 0)]
        
        SFOS = ak.concatenate([OS_diele_veto, OS_dimu_veto], axis=1)

        offZ = (ak.all(abs(OS_dimu.mass-91.2)>10, axis=1) & ak.all(abs(OS_diele.mass-91.2)>10, axis=1))
        offZ_veto = (ak.all(abs(OS_dimu_veto.mass-91.2)>10, axis=1) & ak.all(abs(OS_diele_veto.mass-91.2)>10, axis=1))

        lepton = ak.concatenate([self.ele, self.mu], axis=1)
        lepton_pdgId_pt_ordered = ak.fill_none(ak.pad_none(lepton[ak.argsort(lepton.pt, ascending=False)].pdgId, 2, clip=True), 0)
        dilep = choose(lepton,2)
        SS_dilep = (dilep['0'].charge*dilep['1'].charge > 0)
        los_trilep_SS = (ak.any(SS_dilep, axis=1))

        vetolepton   = ak.concatenate([self.ele_veto, self.mu_veto], axis=1)    
        vetotrilep = choose3(vetolepton, 3)
        pos_trilep = ak.any((vetotrilep['0'].charge+vetotrilep['1'].charge+vetotrilep['2'].charge > 0),axis=1)
        neg_trilep = ak.any((vetotrilep['0'].charge+vetotrilep['1'].charge+vetotrilep['2'].charge < 0),axis=1)
        
        triggers  = getTriggers(self.events,
            ak.flatten(lepton_pdgId_pt_ordered[:,0:1]),
            ak.flatten(lepton_pdgId_pt_ordered[:,1:2]), year=self.year, dataset=self.dataset)

        ht = ak.sum(self.jet_all.pt, axis=1)
        st = self.met.pt + ht + ak.sum(self.mu.pt, axis=1) + ak.sum(self.ele.pt, axis=1)
        st_veto = self.met.pt + ht + ak.sum(self.mu_veto.pt, axis=1) + ak.sum(self.ele_veto.pt, axis=1)

        lep0pt_veto     = ((ak.num(self.ele_veto[(self.ele_veto.pt>25)]) + ak.num(self.mu_veto[(self.mu_veto.pt>25)]))>0)
        lep1pt_veto     = ((ak.num(self.ele_veto[(self.ele_veto.pt>20)]) + ak.num(self.mu_veto[(self.mu_veto.pt>20)]))>1)

        self.selection.add('lepveto',       lepveto)
        self.selection.add('trilep',        los_trilep_SS)
        self.selection.add('filter',        self.filters)
        self.selection.add('trigger',       triggers)
        self.selection.add('p_T(lep0)>25',  lep0pt_veto)
        self.selection.add('p_T(lep1)>20',  lep1pt_veto)
        self.selection.add('N_jet>2',       (ak.num(self.jet_all)>2) )
        self.selection.add('N_jet>3',       (ak.num(self.jet_all)>3) )
        self.selection.add('N_central>1',   (ak.num(self.jet_central)>1) )
        self.selection.add('N_central>2',   (ak.num(self.jet_central)>2) )
        self.selection.add('N_btag>0',      (ak.num(self.jet_btag)>0 ))
        self.selection.add('N_fwd>0',       (ak.num(self.jet_fwd)>0) )
        self.selection.add('MET>50',        (self.met.pt>50) )
        self.selection.add('ST>600',        (st_veto>600) )
        self.selection.add('offZ',          offZ_veto )
        #self.selection.add('SFOS>=1',          ak.num(SFOS)==0)
        #self.selection.add('charge_sum',          neg_trilep)
        
        reqs = [
            'filter',
            'lepveto',
            'trilep',
            'p_T(lep0)>25',
            'p_T(lep1)>20',
            'trigger',
            'offZ',
            'MET>50',
            'N_jet>2',
            'N_central>1',
            'N_btag>0',
            'N_fwd>0',
            #'SFOS>=1',
            #'charge_sum'
        ]
        
        if tight:
            reqs += [
                'N_jet>3',
                'N_central>2',
                'ST>600',
                #'MET>50',
                #'delta_eta',
            ]

        reqs_d = { sel: True for sel in reqs if not sel in omit }
        selection = self.selection.require(**reqs_d)

        self.reqs = [ sel for sel in reqs if not sel in omit ]

        if cutflow:
            #
            cutflow_reqs_d = {}
            for req in reqs:
                cutflow_reqs_d.update({req: True})
                cutflow.addRow( req, self.selection.require(**cutflow_reqs_d) )

        return selection
    def process(self, events):

        output = self.accumulator.identity()

        output['total']['all'] += len(events)
        # use a very loose preselection to filter the events
        presel = ak.num(events.Jet) > 2

        ev = events[presel]
        dataset = ev.metadata['dataset']

        # load the config - probably not needed anymore
        cfg = loadConfig()

        ## Muons
        muon = Collections(ev, "Muon", "vetoTTH").get()
        tightmuon = Collections(ev, "Muon", "tightTTH").get()
        dimuon = choose(muon, 2)
        SSmuon = ak.any((dimuon['0'].charge * dimuon['1'].charge) > 0, axis=1)
        leading_muon_idx = ak.singletons(ak.argmax(muon.pt, axis=1))
        leading_muon = muon[leading_muon_idx]

        ## Electrons
        electron = Collections(ev, "Electron", "vetoTTH").get()
        tightelectron = Collections(ev, "Electron", "tightTTH").get()
        dielectron = choose(electron, 2)
        SSelectron = ak.any(
            (dielectron['0'].charge * dielectron['1'].charge) > 0, axis=1)
        leading_electron_idx = ak.singletons(ak.argmax(electron.pt, axis=1))
        leading_electron = electron[leading_electron_idx]

        ## Merge electrons and muons - this should work better now in ak1
        dilepton = cross(muon, electron)
        SSlepton = ak.any((dilepton['0'].charge * dilepton['1'].charge) > 0,
                          axis=1)

        lepton = ak.concatenate([muon, electron], axis=1)
        leading_lepton_idx = ak.singletons(ak.argmax(lepton.pt, axis=1))
        leading_lepton = lepton[leading_lepton_idx]
        trailing_lepton_idx = ak.singletons(ak.argmin(lepton.pt, axis=1))
        trailing_lepton = lepton[trailing_lepton_idx]

        dilepton_mass = (leading_lepton + trailing_lepton).mass
        dilepton_pt = (leading_lepton + trailing_lepton).pt
        dilepton_dR = delta_r(leading_lepton, trailing_lepton)

        mt_lep_met = mt(lepton.pt, lepton.phi, ev.MET.pt, ev.MET.phi)
        min_mt_lep_met = ak.min(mt_lep_met, axis=1)

        ## Jets
        jet = getJets(ev, minPt=25, maxEta=4.7, pt_var='pt_nom')
        jet = jet[ak.argsort(
            jet.pt_nom, ascending=False
        )]  # need to sort wrt smeared and recorrected jet pt
        jet = jet[~match(jet, muon,
                         deltaRCut=0.4)]  # remove jets that overlap with muons
        jet = jet[~match(
            jet, electron,
            deltaRCut=0.4)]  # remove jets that overlap with electrons

        central = jet[(abs(jet.eta) < 2.4)]
        btag = getBTagsDeepFlavB(
            jet, year=self.year)  # should study working point for DeepJet
        light = getBTagsDeepFlavB(jet, year=self.year, invert=True)
        fwd = getFwdJet(light)
        fwd_noPU = getFwdJet(light, puId=False)

        tau = getTaus(ev)
        track = getIsoTracks(ev)
        ## forward jets
        j_fwd = fwd[ak.singletons(ak.argmax(
            fwd.p, axis=1))]  # highest momentum spectator

        high_score_btag = central[ak.argsort(central.btagDeepFlavB)][:, :2]

        bl = cross(lepton, high_score_btag)
        bl_dR = delta_r(bl['0'], bl['1'])
        min_bl_dR = ak.min(bl_dR, axis=1)

        jf = cross(j_fwd, jet)
        mjf = (jf['0'] + jf['1']).mass
        j_fwd2 = jf[ak.singletons(
            ak.argmax(mjf, axis=1)
        )]['1']  # this is the jet that forms the largest invariant mass with j_fwd
        delta_eta = ak.fill_none(
            ak.pad_none(abs(j_fwd2.eta - j_fwd.eta), 1, clip=True), 0)

        ## MET -> can switch to puppi MET
        met_pt = ev.MET.pt
        met_phi = ev.MET.phi

        ## other variables
        ht = ak.sum(jet.pt, axis=1)
        st = met_pt + ht + ak.sum(muon.pt, axis=1) + ak.sum(electron.pt,
                                                            axis=1)

        ## event selectors
        filters = getFilters(ev, year=self.year, dataset=dataset)

        dilep = ((ak.num(tightelectron) + ak.num(tightmuon)) == 2)
        lep0pt = ((ak.num(electron[(electron.pt > 25)]) +
                   ak.num(muon[(muon.pt > 25)])) > 0)
        lep1pt = ((ak.num(electron[(electron.pt > 20)]) +
                   ak.num(muon[(muon.pt > 20)])) > 1)
        lepveto = ((ak.num(electron) + ak.num(muon)) == 2)

        selection = PackedSelection()
        selection.add('lepveto', lepveto)
        selection.add('dilep', dilep)
        selection.add('filter', (filters))
        selection.add('p_T(lep0)>25', lep0pt)
        selection.add('p_T(lep1)>20', lep1pt)
        selection.add('SS', (SSlepton | SSelectron | SSmuon))
        selection.add('N_jet>3', (ak.num(jet) >= 4))
        selection.add('N_central>2', (ak.num(central) >= 3))
        selection.add('N_btag>0', (ak.num(btag) >= 1))
        selection.add('N_fwd>0', (ak.num(fwd) >= 1))

        #ss_reqs = ['lepveto', 'dilep', 'filter', 'p_T(lep0)>25', 'p_T(lep1)>20', 'SS']
        ss_reqs = [
            'lepveto', 'dilep', 'filter', 'p_T(lep0)>25', 'p_T(lep1)>20', 'SS'
        ]
        #bl_reqs = ss_reqs + ['N_jet>3', 'N_central>2', 'N_btag>0', 'N_fwd>0']
        bl_reqs = ss_reqs + ['N_jet>3', 'N_central>2', 'N_btag>0']

        ss_reqs_d = {sel: True for sel in ss_reqs}
        ss_selection = selection.require(**ss_reqs_d)
        bl_reqs_d = {sel: True for sel in bl_reqs}
        BL = selection.require(**bl_reqs_d)

        weight = Weights(len(ev))

        if not dataset == 'MuonEG':
            # lumi weight
            weight.add("weight", ev.weight)

            # PU weight - not in the babies...
            weight.add("PU",
                       ev.puWeight,
                       weightUp=ev.puWeightUp,
                       weightDown=ev.puWeightDown,
                       shift=False)

            # b-tag SFs
            weight.add("btag", self.btagSF.Method1a(btag, light))

            # lepton SFs
            weight.add("lepton", self.leptonSF.get(electron, muon))

        #cutflow     = Cutflow(output, ev, weight=weight)
        #cutflow_reqs_d = {}
        #for req in bl_reqs:
        #    cutflow_reqs_d.update({req: True})
        #    cutflow.addRow( req, selection.require(**cutflow_reqs_d) )

        labels = {
            'topW_v3': 0,
            'TTW': 1,
            'TTZ': 2,
            'TTH': 3,
            'ttbar': 4,
            'ttbar1l_MG': 4
        }
        if dataset in labels:
            label_mult = labels[dataset]
        else:
            label_mult = 5
        label = np.ones(len(ev[BL])) * label_mult

        output["n_lep"] += processor.column_accumulator(
            ak.to_numpy((ak.num(electron) + ak.num(muon))[BL]))
        output["n_lep_tight"] += processor.column_accumulator(
            ak.to_numpy((ak.num(tightelectron) + ak.num(tightmuon))[BL]))

        output["lead_lep_pt"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(leading_lepton[BL].pt, axis=1)))
        output["lead_lep_eta"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(leading_lepton[BL].eta, axis=1)))
        output["lead_lep_phi"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(leading_lepton[BL].phi, axis=1)))
        output["lead_lep_charge"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(leading_lepton[BL].charge, axis=1)))

        output["sublead_lep_pt"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(trailing_lepton[BL].pt, axis=1)))
        output["sublead_lep_eta"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(trailing_lepton[BL].eta, axis=1)))
        output["sublead_lep_phi"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(trailing_lepton[BL].phi, axis=1)))
        output["sublead_lep_charge"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(trailing_lepton[BL].charge, axis=1)))

        output["lead_jet_pt"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(jet[:, 0:1][BL].pt, axis=1)))
        output["lead_jet_eta"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(jet[:, 0:1][BL].eta, axis=1)))
        output["lead_jet_phi"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(jet[:, 0:1][BL].phi, axis=1)))

        output["sublead_jet_pt"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(jet[:, 1:2][BL].pt, axis=1)))
        output["sublead_jet_eta"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(jet[:, 1:2][BL].eta, axis=1)))
        output["sublead_jet_phi"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(jet[:, 1:2][BL].phi, axis=1)))

        output["lead_btag_pt"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(high_score_btag[:, 0:1][BL].pt, axis=1)))
        output["lead_btag_eta"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(high_score_btag[:, 0:1][BL].eta, axis=1)))
        output["lead_btag_phi"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(high_score_btag[:, 0:1][BL].phi, axis=1)))

        output["sublead_btag_pt"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(high_score_btag[:, 1:2][BL].pt, axis=1)))
        output["sublead_btag_eta"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(high_score_btag[:, 1:2][BL].eta, axis=1)))
        output["sublead_btag_phi"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(high_score_btag[:, 1:2][BL].phi, axis=1)))

        output["fwd_jet_p"] += processor.column_accumulator(
            ak.to_numpy(
                ak.flatten(ak.fill_none(ak.pad_none(j_fwd[BL].p, 1, clip=True),
                                        0),
                           axis=1)))
        output["fwd_jet_pt"] += processor.column_accumulator(
            ak.to_numpy(
                ak.flatten(ak.fill_none(
                    ak.pad_none(j_fwd[BL].pt, 1, clip=True), 0),
                           axis=1)))
        output["fwd_jet_eta"] += processor.column_accumulator(
            ak.to_numpy(
                ak.flatten(ak.fill_none(
                    ak.pad_none(j_fwd[BL].eta, 1, clip=True), 0),
                           axis=1)))
        output["fwd_jet_phi"] += processor.column_accumulator(
            ak.to_numpy(
                ak.flatten(ak.fill_none(
                    ak.pad_none(j_fwd[BL].phi, 1, clip=True), 0),
                           axis=1)))

        output["mjj_max"] += processor.column_accumulator(
            ak.to_numpy(ak.fill_none(ak.max(mjf[BL], axis=1), 0)))
        output["delta_eta_jj"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(delta_eta[BL], axis=1)))

        output["met"] += processor.column_accumulator(ak.to_numpy(met_pt[BL]))
        output["ht"] += processor.column_accumulator(ak.to_numpy(ht[BL]))
        output["st"] += processor.column_accumulator(ak.to_numpy(st[BL]))
        output["n_jet"] += processor.column_accumulator(
            ak.to_numpy(ak.num(jet[BL])))
        output["n_btag"] += processor.column_accumulator(
            ak.to_numpy(ak.num(btag[BL])))
        output["n_fwd"] += processor.column_accumulator(
            ak.to_numpy(ak.num(fwd[BL])))
        output["n_central"] += processor.column_accumulator(
            ak.to_numpy(ak.num(central[BL])))
        output["n_tau"] += processor.column_accumulator(
            ak.to_numpy(ak.num(tau[BL])))
        output["n_track"] += processor.column_accumulator(
            ak.to_numpy(ak.num(track[BL])))

        output["dilepton_pt"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(dilepton_pt[BL], axis=1)))
        output["dilepton_mass"] += processor.column_accumulator(
            ak.to_numpy(ak.flatten(dilepton_mass[BL], axis=1)))
        output["min_bl_dR"] += processor.column_accumulator(
            ak.to_numpy(min_bl_dR[BL]))
        output["min_mt_lep_met"] += processor.column_accumulator(
            ak.to_numpy(min_mt_lep_met[BL]))

        output["label"] += processor.column_accumulator(label)
        output["weight"] += processor.column_accumulator(weight.weight()[BL])

        output["presel"]["all"] += len(ev[ss_selection])
        output["sel"]["all"] += len(ev[BL])

        return output
Exemplo n.º 23
0
    def process(self, events):
        # Dataset parameters
        dataset = events.metadata['dataset']
        histAxisName = self._samples[dataset]['histAxisName']
        year = self._samples[dataset]['year']
        xsec = self._samples[dataset]['xsec']
        sow = self._samples[dataset]['nSumOfWeights']
        isData = self._samples[dataset]['isData']
        datasets = [
            'SingleMuon', 'SingleElectron', 'EGamma', 'MuonEG', 'DoubleMuon',
            'DoubleElectron'
        ]
        for d in datasets:
            if d in dataset: dataset = dataset.split('_')[0]

        # Initialize objects
        met = events.MET
        e = events.Electron
        mu = events.Muon
        tau = events.Tau
        j = events.Jet

        # Muon selection

        mu['isPres'] = isPresMuon(mu.dxy, mu.dz, mu.sip3d, mu.looseId)
        mu['isTight'] = isTightMuon(mu.pt,
                                    mu.eta,
                                    mu.dxy,
                                    mu.dz,
                                    mu.pfRelIso03_all,
                                    mu.sip3d,
                                    mu.mvaTTH,
                                    mu.mediumPromptId,
                                    mu.tightCharge,
                                    mu.looseId,
                                    minpt=10)
        mu['isGood'] = mu['isPres'] & mu['isTight']

        leading_mu = mu[ak.argmax(mu.pt, axis=-1, keepdims=True)]
        leading_mu = leading_mu[leading_mu.isGood]

        mu = mu[mu.isGood]
        mu_pres = mu[mu.isPres]

        # Electron selection
        e['isPres'] = isPresElec(e.pt,
                                 e.eta,
                                 e.dxy,
                                 e.dz,
                                 e.miniPFRelIso_all,
                                 e.sip3d,
                                 e.lostHits,
                                 minpt=15)
        e['isTight'] = isTightElec(e.pt,
                                   e.eta,
                                   e.dxy,
                                   e.dz,
                                   e.miniPFRelIso_all,
                                   e.sip3d,
                                   e.mvaTTH,
                                   e.mvaFall17V2Iso,
                                   e.lostHits,
                                   e.convVeto,
                                   e.tightCharge,
                                   e.sieie,
                                   e.hoe,
                                   e.eInvMinusPInv,
                                   minpt=15)
        e['isClean'] = isClean(e, mu, drmin=0.05)
        e['isGood'] = e['isPres'] & e['isTight'] & e['isClean']

        leading_e = e[ak.argmax(e.pt, axis=-1, keepdims=True)]
        leading_e = leading_e[leading_e.isGood]

        e = e[e.isGood]
        e_pres = e[e.isPres & e.isClean]

        # Tau selection
        tau['isPres'] = isPresTau(tau.pt,
                                  tau.eta,
                                  tau.dxy,
                                  tau.dz,
                                  tau.leadTkPtOverTauPt,
                                  tau.idAntiMu,
                                  tau.idAntiEle,
                                  tau.rawIso,
                                  tau.idDecayModeNewDMs,
                                  minpt=20)
        tau['isClean'] = isClean(tau, e_pres, drmin=0.4) & isClean(
            tau, mu_pres, drmin=0.4)
        tau['isGood'] = tau['isPres']  # & tau['isClean'], for the moment
        tau = tau[tau.isGood]

        nElec = ak.num(e)
        nMuon = ak.num(mu)
        nTau = ak.num(tau)

        twoLeps = (nElec + nMuon) == 2
        threeLeps = (nElec + nMuon) == 3
        twoElec = (nElec == 2)
        twoMuon = (nMuon == 2)
        e0 = e[ak.argmax(e.pt, axis=-1, keepdims=True)]
        m0 = mu[ak.argmax(mu.pt, axis=-1, keepdims=True)]

        # Attach the lepton SFs to the electron and muons collections
        AttachElectronSF(e, year=year)
        AttachMuonSF(mu, year=year)

        # Create a lepton (muon+electron) collection and calculate a per event lepton SF
        leps = ak.concatenate([e, mu], axis=-1)
        events['lepSF_nom'] = ak.prod(leps.sf_nom, axis=-1)
        events['lepSF_hi'] = ak.prod(leps.sf_hi, axis=-1)
        events['lepSF_lo'] = ak.prod(leps.sf_lo, axis=-1)

        # Jet selection
        jetptname = 'pt_nom' if hasattr(j, 'pt_nom') else 'pt'

        ### Jet energy corrections
        if not isData:
            j["pt_raw"] = (1 - j.rawFactor) * j.pt
            j["mass_raw"] = (1 - j.rawFactor) * j.mass
            j["pt_gen"] = ak.values_astype(ak.fill_none(j.matched_gen.pt, 0),
                                           np.float32)
            j["rho"] = ak.broadcast_arrays(events.fixedGridRhoFastjetAll,
                                           j.pt)[0]
            events_cache = events.caches[0]
            corrected_jets = jet_factory.build(j, lazy_cache=events_cache)
            #print('jet pt: ',j.pt)
            #print('cor pt: ',corrected_jets.pt)
            #print('jes up: ',corrected_jets.JES_jes.up.pt)
            #print('jes down: ',corrected_jets.JES_jes.down.pt)
            #print(ak.fields(corrected_jets))
            '''
          # SYSTEMATICS
          jets = corrected_jets
          if(self.jetSyst == 'JERUp'):
            jets = corrected_jets.JER.up
          elif(self.jetSyst == 'JERDown'):
            jets = corrected_jets.JER.down
          elif(self.jetSyst == 'JESUp'):
            jets = corrected_jets.JES_jes.up
          elif(self.jetSyst == 'JESDown'):
            jets = corrected_jets.JES_jes.down
          '''
        j['isGood'] = isTightJet(getattr(j,
                                         jetptname), j.eta, j.jetId, j.neHEF,
                                 j.neEmEF, j.chHEF, j.chEmEF, j.nConstituents)
        #j['isgood']  = isGoodJet(j.pt, j.eta, j.jetId)
        #j['isclean'] = isClean(j, e, mu)
        j['isClean'] = isClean(j, e, drmin=0.4) & isClean(
            j, mu, drmin=0.4)  # & isClean(j, tau, drmin=0.4)
        goodJets = j[(j.isClean) & (j.isGood)]
        njets = ak.num(goodJets)
        ht = ak.sum(goodJets.pt, axis=-1)
        j0 = goodJets[ak.argmax(goodJets.pt, axis=-1, keepdims=True)]
        #nbtags = ak.num(goodJets[goodJets.btagDeepFlavB > 0.2770])
        # Loose DeepJet WP
        if year == 2017: btagwpl = 0.0532  #WP loose
        else: btagwpl = 0.0490  #WP loose
        isBtagJetsLoose = (goodJets.btagDeepB > btagwpl)
        isNotBtagJetsLoose = np.invert(isBtagJetsLoose)
        nbtagsl = ak.num(goodJets[isBtagJetsLoose])
        # Medium DeepJet WP
        if year == 2017: btagwpm = 0.3040  #WP medium
        else: btagwpm = 0.2783  #WP medium
        isBtagJetsMedium = (goodJets.btagDeepB > btagwpm)
        isNotBtagJetsMedium = np.invert(isBtagJetsMedium)
        nbtagsm = ak.num(goodJets[isBtagJetsMedium])

        # Btag SF following 1a) in https://twiki.cern.ch/twiki/bin/viewauth/CMS/BTagSFMethods
        btagSF = np.ones_like(ht)
        btagSFUp = np.ones_like(ht)
        btagSFDo = np.ones_like(ht)
        if not isData:
            pt = goodJets.pt
            abseta = np.abs(goodJets.eta)
            flav = goodJets.hadronFlavour
            bJetSF = GetBTagSF(abseta, pt, flav)
            bJetSFUp = GetBTagSF(abseta, pt, flav, sys=1)
            bJetSFDo = GetBTagSF(abseta, pt, flav, sys=-1)
            bJetEff = GetBtagEff(abseta, pt, flav, year)
            bJetEff_data = bJetEff * bJetSF
            bJetEff_dataUp = bJetEff * bJetSFUp
            bJetEff_dataDo = bJetEff * bJetSFDo

            pMC = ak.prod(bJetEff[isBtagJetsMedium], axis=-1) * ak.prod(
                (1 - bJetEff[isNotBtagJetsMedium]), axis=-1)
            pData = ak.prod(bJetEff_data[isBtagJetsMedium], axis=-1) * ak.prod(
                (1 - bJetEff_data[isNotBtagJetsMedium]), axis=-1)
            pDataUp = ak.prod(
                bJetEff_dataUp[isBtagJetsMedium], axis=-1) * ak.prod(
                    (1 - bJetEff_dataUp[isNotBtagJetsMedium]), axis=-1)
            pDataDo = ak.prod(
                bJetEff_dataDo[isBtagJetsMedium], axis=-1) * ak.prod(
                    (1 - bJetEff_dataDo[isNotBtagJetsMedium]), axis=-1)

            pMC = ak.where(pMC == 0, 1,
                           pMC)  # removeing zeroes from denominator...
            btagSF = pData / pMC
            btagSFUp = pDataUp / pMC
            btagSFDo = pDataUp / pMC

        ##################################################################
        ### 2 same-sign leptons
        ##################################################################

        # emu
        singe = e[(nElec == 1) & (nMuon == 1) & (e.pt > -1)]
        singm = mu[(nElec == 1) & (nMuon == 1) & (mu.pt > -1)]
        em = ak.cartesian({"e": singe, "m": singm})
        emSSmask = (em.e.charge * em.m.charge > 0)
        emSS = em[emSSmask]
        nemSS = len(ak.flatten(emSS))

        # ee and mumu
        # pt>-1 to preserve jagged dimensions
        ee = e[(nElec == 2) & (nMuon == 0) & (e.pt > -1)]
        mm = mu[(nElec == 0) & (nMuon == 2) & (mu.pt > -1)]

        sumcharge = ak.sum(e.charge, axis=-1) + ak.sum(mu.charge, axis=-1)

        eepairs = ak.combinations(ee, 2, fields=["e0", "e1"])
        eeSSmask = (eepairs.e0.charge * eepairs.e1.charge > 0)
        eeonZmask = (np.abs((eepairs.e0 + eepairs.e1).mass - 91.2) < 10)
        eeoffZmask = (eeonZmask == 0)

        mmpairs = ak.combinations(mm, 2, fields=["m0", "m1"])
        mmSSmask = (mmpairs.m0.charge * mmpairs.m1.charge > 0)
        mmonZmask = (np.abs((mmpairs.m0 + mmpairs.m1).mass - 91.2) < 10)
        mmoffZmask = (mmonZmask == 0)

        eeSSonZ = eepairs[eeSSmask & eeonZmask]
        eeSSoffZ = eepairs[eeSSmask & eeoffZmask]
        mmSSonZ = mmpairs[mmSSmask & mmonZmask]
        mmSSoffZ = mmpairs[mmSSmask & mmoffZmask]
        neeSS = len(ak.flatten(eeSSonZ)) + len(ak.flatten(eeSSoffZ))
        nmmSS = len(ak.flatten(mmSSonZ)) + len(ak.flatten(mmSSoffZ))

        print('Same-sign events [ee, emu, mumu] = [%i, %i, %i]' %
              (neeSS, nemSS, nmmSS))

        # Cuts
        eeSSmask = (ak.num(eeSSmask[eeSSmask]) > 0)
        mmSSmask = (ak.num(mmSSmask[mmSSmask]) > 0)
        eeonZmask = (ak.num(eeonZmask[eeonZmask]) > 0)
        eeoffZmask = (ak.num(eeoffZmask[eeoffZmask]) > 0)
        mmonZmask = (ak.num(mmonZmask[mmonZmask]) > 0)
        mmoffZmask = (ak.num(mmoffZmask[mmoffZmask]) > 0)
        emSSmask = (ak.num(emSSmask[emSSmask]) > 0)

        ##################################################################
        ### 3 leptons
        ##################################################################

        # eem
        muon_eem = mu[(nElec == 2) & (nMuon == 1) & (mu.pt > -1)]
        elec_eem = e[(nElec == 2) & (nMuon == 1) & (e.pt > -1)]

        ee_eem = ak.combinations(elec_eem, 2, fields=["e0", "e1"])
        ee_eemZmask = (ee_eem.e0.charge * ee_eem.e1.charge < 1) & (np.abs(
            (ee_eem.e0 + ee_eem.e1).mass - 91.2) < 10)
        ee_eemOffZmask = (ee_eem.e0.charge * ee_eem.e1.charge < 1) & (np.abs(
            (ee_eem.e0 + ee_eem.e1).mass - 91.2) > 10)
        ee_eemZmask = (ak.num(ee_eemZmask[ee_eemZmask]) > 0)
        ee_eemOffZmask = (ak.num(ee_eemOffZmask[ee_eemOffZmask]) > 0)

        eepair_eem = (ee_eem.e0 + ee_eem.e1)
        trilep_eem = eepair_eem + muon_eem  #ak.cartesian({"e0":ee_eem.e0,"e1":ee_eem.e1, "m":muon_eem})

        # mme
        muon_mme = mu[(nElec == 1) & (nMuon == 2) & (mu.pt > -1)]
        elec_mme = e[(nElec == 1) & (nMuon == 2) & (e.pt > -1)]

        mm_mme = ak.combinations(muon_mme, 2, fields=["m0", "m1"])
        mm_mmeZmask = (mm_mme.m0.charge * mm_mme.m1.charge < 1) & (np.abs(
            (mm_mme.m0 + mm_mme.m1).mass - 91.2) < 10)
        mm_mmeOffZmask = (mm_mme.m0.charge * mm_mme.m1.charge < 1) & (np.abs(
            (mm_mme.m0 + mm_mme.m1).mass - 91.2) > 10)
        mm_mmeZmask = (ak.num(mm_mmeZmask[mm_mmeZmask]) > 0)
        mm_mmeOffZmask = (ak.num(mm_mmeOffZmask[mm_mmeOffZmask]) > 0)

        mmpair_mme = (mm_mme.m0 + mm_mme.m1)
        trilep_mme = mmpair_mme + elec_mme

        mZ_mme = mmpair_mme.mass
        mZ_eem = eepair_eem.mass
        m3l_eem = trilep_eem.mass
        m3l_mme = trilep_mme.mass

        # eee and mmm
        eee = e[(nElec == 3) & (nMuon == 0) & (e.pt > -1)]
        mmm = mu[(nElec == 0) & (nMuon == 3) & (mu.pt > -1)]

        eee_leps = ak.combinations(eee, 3, fields=["e0", "e1", "e2"])
        mmm_leps = ak.combinations(mmm, 3, fields=["m0", "m1", "m2"])

        ee_pairs = ak.combinations(eee, 2, fields=["e0", "e1"])
        mm_pairs = ak.combinations(mmm, 2, fields=["m0", "m1"])
        ee_pairs_index = ak.argcombinations(eee, 2, fields=["e0", "e1"])
        mm_pairs_index = ak.argcombinations(mmm, 2, fields=["m0", "m1"])

        mmSFOS_pairs = mm_pairs[
            (np.abs(mm_pairs.m0.pdgId) == np.abs(mm_pairs.m1.pdgId))
            & (mm_pairs.m0.charge != mm_pairs.m1.charge)]
        offZmask_mm = ak.all(
            np.abs((mmSFOS_pairs.m0 + mmSFOS_pairs.m1).mass - 91.2) > 10.,
            axis=1,
            keepdims=True) & (ak.num(mmSFOS_pairs) > 0)
        onZmask_mm = ak.any(
            np.abs((mmSFOS_pairs.m0 + mmSFOS_pairs.m1).mass - 91.2) < 10.,
            axis=1,
            keepdims=True)

        eeSFOS_pairs = ee_pairs[
            (np.abs(ee_pairs.e0.pdgId) == np.abs(ee_pairs.e1.pdgId))
            & (ee_pairs.e0.charge != ee_pairs.e1.charge)]
        offZmask_ee = ak.all(
            np.abs((eeSFOS_pairs.e0 + eeSFOS_pairs.e1).mass - 91.2) > 10,
            axis=1,
            keepdims=True) & (ak.num(eeSFOS_pairs) > 0)
        onZmask_ee = ak.any(
            np.abs((eeSFOS_pairs.e0 + eeSFOS_pairs.e1).mass - 91.2) < 10,
            axis=1,
            keepdims=True)

        # Create masks **for event selection**
        eeeOnZmask = (ak.num(onZmask_ee[onZmask_ee]) > 0)
        eeeOffZmask = (ak.num(offZmask_ee[offZmask_ee]) > 0)
        mmmOnZmask = (ak.num(onZmask_mm[onZmask_mm]) > 0)
        mmmOffZmask = (ak.num(offZmask_mm[offZmask_mm]) > 0)

        # Now we need to create masks for the leptons in order to select leptons from the Z boson candidate (in onZ categories)
        ZeeMask = ak.argmin(np.abs((eeSFOS_pairs.e0 + eeSFOS_pairs.e1).mass -
                                   91.2),
                            axis=1,
                            keepdims=True)
        ZmmMask = ak.argmin(np.abs((mmSFOS_pairs.m0 + mmSFOS_pairs.m1).mass -
                                   91.2),
                            axis=1,
                            keepdims=True)

        Zee = eeSFOS_pairs[ZeeMask]
        Zmm = mmSFOS_pairs[ZmmMask]
        eZ0 = Zee.e0[ak.num(eeSFOS_pairs) > 0]
        eZ1 = Zee.e1[ak.num(eeSFOS_pairs) > 0]
        eZ = eZ0 + eZ1
        mZ0 = Zmm.m0[ak.num(mmSFOS_pairs) > 0]
        mZ1 = Zmm.m1[ak.num(mmSFOS_pairs) > 0]
        mZ = mZ0 + mZ1
        mZ_eee = eZ.mass
        mZ_mmm = mZ.mass

        # And for the W boson
        ZmmIndices = mm_pairs_index[ZmmMask]
        ZeeIndices = ee_pairs_index[ZeeMask]
        eW = eee[~ZeeIndices.e0 | ~ZeeIndices.e1]
        mW = mmm[~ZmmIndices.m0 | ~ZmmIndices.m1]

        triElec = eee_leps.e0 + eee_leps.e1 + eee_leps.e2
        triMuon = mmm_leps.m0 + mmm_leps.m1 + mmm_leps.m2
        m3l_eee = triElec.mass
        m3l_mmm = triMuon.mass

        ##################################################################
        ### >=4 leptons
        ##################################################################

        # 4lep cat
        is4lmask = ((nElec + nMuon) >= 4)
        muon_4l = mu[(is4lmask) & (mu.pt > -1)]
        elec_4l = e[(is4lmask) & (e.pt > -1)]

        # selecting 4 leading leptons
        leptons = ak.concatenate([e, mu], axis=-1)
        leptons_sorted = leptons[ak.argsort(leptons.pt,
                                            axis=-1,
                                            ascending=False)]
        lep4l = leptons_sorted[:, 0:4]
        e4l = lep4l[abs(lep4l.pdgId) == 11]
        mu4l = lep4l[abs(lep4l.pdgId) == 13]
        nElec4l = ak.num(e4l)
        nMuon4l = ak.num(mu4l)

        # Triggers
        trig_eeSS = passTrigger(events, 'ee', isData, dataset)
        trig_mmSS = passTrigger(events, 'mm', isData, dataset)
        trig_emSS = passTrigger(events, 'em', isData, dataset)
        trig_eee = passTrigger(events, 'eee', isData, dataset)
        trig_mmm = passTrigger(events, 'mmm', isData, dataset)
        trig_eem = passTrigger(events, 'eem', isData, dataset)
        trig_mme = passTrigger(events, 'mme', isData, dataset)
        trig_4l = triggerFor4l(events, nMuon, nElec, isData, dataset)

        # MET filters

        # Weights
        genw = np.ones_like(events['event']) if (
            isData or len(self._wc_names_lst) > 0) else events['genWeight']

        ### We need weights for: normalization, lepSF, triggerSF, pileup, btagSF...
        weights = {}
        for r in [
                'all', 'ee', 'mm', 'em', 'eee', 'mmm', 'eem', 'mme', 'eeee',
                'eeem', 'eemm', 'mmme', 'mmmm'
        ]:
            # weights[r] = coffea.analysis_tools.Weights(len(events))
            weights[r] = coffea.analysis_tools.Weights(len(events),
                                                       storeIndividual=True)
            if len(self._wc_names_lst) > 0:
                sow = np.ones_like(
                    sow
                )  # Not valid in nanoAOD for EFT samples, MUST use SumOfEFTweights at analysis level
            weights[r].add('norm', genw if isData else (xsec / sow) * genw)
            weights[r].add('btagSF', btagSF, btagSFUp, btagSFDo)
            weights[r].add('lepSF', events.lepSF_nom, events.lepSF_hi,
                           events.lepSF_lo)

        # Extract the EFT quadratic coefficients and optionally use them to calculate the coefficients on the w**2 quartic function
        # eft_coeffs is never Jagged so convert immediately to numpy for ease of use.
        eft_coeffs = ak.to_numpy(events['EFTfitCoefficients']) if hasattr(
            events, "EFTfitCoefficients") else None
        if eft_coeffs is not None:
            # Check to see if the ordering of WCs for this sample matches what want
            if self._samples[dataset]['WCnames'] != self._wc_names_lst:
                eft_coeffs = efth.remap_coeffs(
                    self._samples[dataset]['WCnames'], self._wc_names_lst,
                    eft_coeffs)
        eft_w2_coeffs = efth.calc_w2_coeffs(eft_coeffs, self._dtype) if (
            self._do_errors and eft_coeffs is not None) else None

        # Selections and cuts
        selections = PackedSelection()  #(dtype='uint64')
        channels2LSS = ['eeSSonZ', 'eeSSoffZ', 'mmSSonZ', 'mmSSoffZ', 'emSS']
        selections.add('eeSSonZ', (eeonZmask) & (eeSSmask) & (trig_eeSS))
        selections.add('eeSSoffZ', (eeoffZmask) & (eeSSmask) & (trig_eeSS))
        selections.add('mmSSonZ', (mmonZmask) & (mmSSmask) & (trig_mmSS))
        selections.add('mmSSoffZ', (mmoffZmask) & (mmSSmask) & (trig_mmSS))
        selections.add('emSS', (emSSmask) & (trig_emSS))

        channels3L = ['eemSSonZ', 'eemSSoffZ', 'mmeSSonZ', 'mmeSSoffZ']
        selections.add('eemSSonZ', (ee_eemZmask) & (trig_eem))
        selections.add('eemSSoffZ', (ee_eemOffZmask) & (trig_eem))
        selections.add('mmeSSonZ', (mm_mmeZmask) & (trig_mme))
        selections.add('mmeSSoffZ', (mm_mmeOffZmask) & (trig_mme))

        channels3L += ['eeeSSonZ', 'eeeSSoffZ', 'mmmSSonZ', 'mmmSSoffZ']
        selections.add('eeeSSonZ', (eeeOnZmask) & (trig_eee))
        selections.add('eeeSSoffZ', (eeeOffZmask) & (trig_eee))
        selections.add('mmmSSonZ', (mmmOnZmask) & (trig_mmm))
        selections.add('mmmSSoffZ', (mmmOffZmask) & (trig_mmm))

        channels4L = ['eeee', 'eeem', 'eemm', 'mmme', 'mmmm']
        selections.add('eeee', ((nElec4l == 4) & (nMuon4l == 0)) & (trig_4l))
        selections.add('eeem', ((nElec4l == 3) & (nMuon4l == 1)) & (trig_4l))
        selections.add('eemm', ((nElec4l == 2) & (nMuon4l == 2)) & (trig_4l))
        selections.add('mmme', ((nElec4l == 1) & (nMuon4l == 3)) & (trig_4l))
        selections.add('mmmm', ((nElec4l == 0) & (nMuon4l == 4)) & (trig_4l))

        selections.add('ch+', (sumcharge > 0))
        selections.add('ch-', (sumcharge < 0))
        selections.add('ch0', (sumcharge == 0))

        levels = ['base', '1+bm2+bl', '1bm', '2+bm']
        selections.add('base', (nElec + nMuon >= 2))
        selections.add('1+bm2+bl', (nElec + nMuon >= 2) & ((nbtagsm >= 1) &
                                                           (nbtagsl >= 2)))
        selections.add('1bm', (nElec + nMuon >= 2) & (nbtagsm == 1))
        selections.add('2+bm', (nElec + nMuon >= 2) & (nbtagsm >= 2))

        # Variables
        invMass_eeSSonZ = (eeSSonZ.e0 + eeSSonZ.e1).mass
        invMass_eeSSoffZ = (eeSSoffZ.e0 + eeSSoffZ.e1).mass
        invMass_mmSSonZ = (mmSSonZ.m0 + mmSSonZ.m1).mass
        invMass_mmSSoffZ = (mmSSoffZ.m0 + mmSSoffZ.m1).mass
        invMass_emSS = (emSS.e + emSS.m).mass

        varnames = {}
        varnames['met'] = met.pt
        varnames['ht'] = ht
        varnames['njets'] = njets
        varnames['invmass'] = {
            'eeSSonZ': invMass_eeSSonZ,
            'eeSSoffZ': invMass_eeSSoffZ,
            'mmSSonZ': invMass_mmSSonZ,
            'mmSSoffZ': invMass_mmSSoffZ,
            'emSS': invMass_emSS,
            'eemSSonZ': mZ_eem,
            'eemSSoffZ': mZ_eem,
            'mmeSSonZ': mZ_mme,
            'mmeSSoffZ': mZ_mme,
            'eeeSSonZ': mZ_eee,
            'eeeSSoffZ': mZ_eee,
            'mmmSSonZ': mZ_mmm,
            'mmmSSoffZ': mZ_mmm,
        }
        varnames['m3l'] = {
            'eemSSonZ': m3l_eem,
            'eemSSoffZ': m3l_eem,
            'mmeSSonZ': m3l_mme,
            'mmeSSoffZ': m3l_mme,
            'eeeSSonZ': m3l_eee,
            'eeeSSoffZ': m3l_eee,
            'mmmSSonZ': m3l_mmm,
            'mmmSSoffZ': m3l_mmm,
        }
        varnames['e0pt'] = e0.pt
        varnames['e0eta'] = e0.eta
        varnames['m0pt'] = m0.pt
        varnames['m0eta'] = m0.eta
        varnames['j0pt'] = j0.pt
        varnames['j0eta'] = j0.eta
        varnames['counts'] = np.ones_like(events['event'])

        # systematics
        systList = []
        if isData == False:
            systList = ['nominal']
            if self._do_systematics:
                systList = systList + [
                    'lepSFUp', 'lepSFDown', 'btagSFUp', 'btagSFDown'
                ]
        else:
            systList = ['noweight']
        # fill Histos
        hout = self.accumulator.identity()
        normweights = weights['all'].weight().flatten(
        )  # Why does it not complain about .flatten() here?
        sowweights = np.ones_like(normweights) if len(
            self._wc_names_lst) > 0 else normweights
        hout['SumOfEFTweights'].fill(sample=histAxisName,
                                     SumOfEFTweights=varnames['counts'],
                                     weight=sowweights,
                                     eft_coeff=eft_coeffs,
                                     eft_err_coeff=eft_w2_coeffs)

        for syst in systList:
            for var, v in varnames.items():
                for ch in channels2LSS + channels3L + channels4L:
                    for sumcharge in ['ch+', 'ch-', 'ch0']:
                        for lev in levels:
                            #find the event weight to be used when filling the histograms
                            weightSyst = syst
                            #in the case of 'nominal', or the jet energy systematics, no weight systematic variation is used (weightSyst=None)
                            if syst in [
                                    'nominal', 'JERUp', 'JERDown', 'JESUp',
                                    'JESDown'
                            ]:
                                weightSyst = None  # no weight systematic for these variations
                            if syst == 'noweight':
                                weight = np.ones(len(events))  # for data
                            else:
                                # call weights.weight() with the name of the systematic to be varied
                                if ch in channels3L: ch_w = ch[:3]
                                elif ch in channels2LSS: ch_w = ch[:2]
                                else: ch_w = ch
                                weight = weights['all'].weight(
                                    weightSyst
                                ) if isData else weights[ch_w].weight(
                                    weightSyst)
                            cuts = [ch] + [lev] + [sumcharge]
                            cut = selections.all(*cuts)
                            weights_flat = weight[cut].flatten(
                            )  # Why does it not complain about .flatten() here?
                            weights_ones = np.ones_like(weights_flat,
                                                        dtype=np.int)
                            eft_coeffs_cut = eft_coeffs[
                                cut] if eft_coeffs is not None else None
                            eft_w2_coeffs_cut = eft_w2_coeffs[
                                cut] if eft_w2_coeffs is not None else None

                            # filling histos
                            if var == 'invmass':
                                if ((ch in [
                                        'eeeSSoffZ', 'mmmSSoffZ', 'eeeSSonZ',
                                        'mmmSSonZ'
                                ]) or (ch in channels4L)):
                                    continue
                                else:
                                    values = ak.flatten(v[ch][cut])
                                hout['invmass'].fill(
                                    eft_coeff=eft_coeffs_cut,
                                    eft_err_coeff=eft_w2_coeffs_cut,
                                    sample=histAxisName,
                                    channel=ch,
                                    cut=lev,
                                    sumcharge=sumcharge,
                                    invmass=values,
                                    weight=weights_flat,
                                    systematic=syst)
                            elif var == 'm3l':
                                if ((ch in channels2LSS) or (ch in [
                                        'eeeSSoffZ', 'mmmSSoffZ', 'eeeSSonZ',
                                        'mmmSSonZ'
                                ]) or (ch in channels4L)):
                                    continue
                                values = ak.flatten(v[ch][cut])
                                hout['m3l'].fill(
                                    eft_coeff=eft_coeffs_cut,
                                    eft_err_coeff=eft_w2_coeffs_cut,
                                    sample=histAxisName,
                                    channel=ch,
                                    cut=lev,
                                    sumcharge=sumcharge,
                                    m3l=values,
                                    weight=weights_flat,
                                    systematic=syst)
                            else:
                                values = v[cut]
                                # These all look identical, do we need if/else here?
                                if var == 'ht':
                                    hout[var].fill(
                                        eft_coeff=eft_coeffs_cut,
                                        eft_err_coeff=eft_w2_coeffs_cut,
                                        ht=values,
                                        sample=histAxisName,
                                        channel=ch,
                                        cut=lev,
                                        sumcharge=sumcharge,
                                        weight=weights_flat,
                                        systematic=syst)
                                elif var == 'met':
                                    hout[var].fill(
                                        eft_coeff=eft_coeffs_cut,
                                        eft_err_coeff=eft_w2_coeffs_cut,
                                        met=values,
                                        sample=histAxisName,
                                        channel=ch,
                                        cut=lev,
                                        sumcharge=sumcharge,
                                        weight=weights_flat,
                                        systematic=syst)
                                elif var == 'njets':
                                    hout[var].fill(
                                        eft_coeff=eft_coeffs_cut,
                                        eft_err_coeff=eft_w2_coeffs_cut,
                                        njets=values,
                                        sample=histAxisName,
                                        channel=ch,
                                        cut=lev,
                                        sumcharge=sumcharge,
                                        weight=weights_flat,
                                        systematic=syst)
                                elif var == 'nbtags':
                                    hout[var].fill(
                                        eft_coeff=eft_coeffs_cut,
                                        eft_err_coeff=eft_w2_coeffs_cut,
                                        nbtags=values,
                                        sample=histAxisName,
                                        channel=ch,
                                        cut=lev,
                                        sumcharge=sumcharge,
                                        weight=weights_flat,
                                        systematic=syst)
                                elif var == 'counts':
                                    hout[var].fill(counts=values,
                                                   sample=histAxisName,
                                                   channel=ch,
                                                   cut=lev,
                                                   sumcharge=sumcharge,
                                                   weight=weights_ones,
                                                   systematic=syst)
                                elif var == 'j0eta':
                                    if lev == 'base': continue
                                    values = ak.flatten(values)
                                    #values=np.asarray(values)
                                    hout[var].fill(
                                        eft_coeff=eft_coeffs_cut,
                                        eft_err_coeff=eft_w2_coeffs_cut,
                                        j0eta=values,
                                        sample=histAxisName,
                                        channel=ch,
                                        cut=lev,
                                        sumcharge=sumcharge,
                                        weight=weights_flat,
                                        systematic=syst)
                                elif var == 'e0pt':
                                    if ch in [
                                            'mmSSonZ', 'mmSSoffZ', 'mmmSSoffZ',
                                            'mmmSSonZ', 'mmmm'
                                    ]:
                                        continue
                                    values = ak.flatten(values)
                                    #values=np.asarray(values)
                                    hout[var].fill(
                                        eft_coeff=eft_coeffs_cut,
                                        eft_err_coeff=eft_w2_coeffs_cut,
                                        e0pt=values,
                                        sample=histAxisName,
                                        channel=ch,
                                        cut=lev,
                                        sumcharge=sumcharge,
                                        weight=weights_flat,
                                        systematic=syst
                                    )  # Crashing here, not sure why. Related to values?
                                elif var == 'm0pt':
                                    if ch in [
                                            'eeSSonZ', 'eeSSoffZ', 'eeeSSoffZ',
                                            'eeeSSonZ', 'eeee'
                                    ]:
                                        continue
                                    values = ak.flatten(values)
                                    #values=np.asarray(values)
                                    hout[var].fill(
                                        eft_coeff=eft_coeffs_cut,
                                        eft_err_coeff=eft_w2_coeffs_cut,
                                        m0pt=values,
                                        sample=histAxisName,
                                        channel=ch,
                                        cut=lev,
                                        sumcharge=sumcharge,
                                        weight=weights_flat,
                                        systematic=syst)
                                elif var == 'e0eta':
                                    if ch in [
                                            'mmSSonZ', 'mmSSoffZ', 'mmmSSoffZ',
                                            'mmmSSonZ', 'mmmm'
                                    ]:
                                        continue
                                    values = ak.flatten(values)
                                    #values=np.asarray(values)
                                    hout[var].fill(
                                        eft_coeff=eft_coeffs_cut,
                                        eft_err_coeff=eft_w2_coeffs_cut,
                                        e0eta=values,
                                        sample=histAxisName,
                                        channel=ch,
                                        cut=lev,
                                        sumcharge=sumcharge,
                                        weight=weights_flat,
                                        systematic=syst)
                                elif var == 'm0eta':
                                    if ch in [
                                            'eeSSonZ', 'eeSSoffZ', 'eeeSSoffZ',
                                            'eeeSSonZ', 'eeee'
                                    ]:
                                        continue
                                    values = ak.flatten(values)
                                    #values=np.asarray(values)
                                    hout[var].fill(
                                        eft_coeff=eft_coeffs_cut,
                                        eft_err_coeff=eft_w2_coeffs_cut,
                                        m0eta=values,
                                        sample=histAxisName,
                                        channel=ch,
                                        cut=lev,
                                        sumcharge=sumcharge,
                                        weight=weights_flat,
                                        systematic=syst)
                                elif var == 'j0pt':
                                    if lev == 'base': continue
                                    values = ak.flatten(values)
                                    #values=np.asarray(values)
                                    hout[var].fill(
                                        eft_coeff=eft_coeffs_cut,
                                        eft_err_coeff=eft_w2_coeffs_cut,
                                        j0pt=values,
                                        sample=histAxisName,
                                        channel=ch,
                                        cut=lev,
                                        sumcharge=sumcharge,
                                        weight=weights_flat,
                                        systematic=syst)
        return hout
Exemplo n.º 24
0
    def process(self, events):
        # Dataset parameters
        dataset = events.metadata['dataset']
        year = self._samples[dataset]['year']
        xsec = self._samples[dataset]['xsec']
        sow = self._samples[dataset]['nSumOfWeights']
        isData = self._samples[dataset]['isData']
        datasets = [
            'SingleMuon', 'SingleElectron', 'EGamma', 'MuonEG', 'DoubleMuon',
            'DoubleElectron'
        ]
        for d in datasets:
            if d in dataset: dataset = dataset.split('_')[0]

        # Initialize objects
        met = events.MET
        e = events.Electron
        mu = events.Muon
        tau = events.Tau
        j = events.Jet

        # Muon selection

        #mu['isGood'] = isMuonMVA(mu.pt, mu.eta, mu.dxy, mu.dz, mu.miniPFRelIso_all, mu.sip3d, mu.mvaTTH, mu.mediumPromptId, mu.tightCharge, minpt=10)
        mu['isPres'] = isPresMuon(mu.dxy, mu.dz, mu.sip3d, mu.looseId)
        mu['isTight'] = isTightMuon(mu.pt,
                                    mu.eta,
                                    mu.dxy,
                                    mu.dz,
                                    mu.pfRelIso03_all,
                                    mu.sip3d,
                                    mu.mvaTTH,
                                    mu.mediumPromptId,
                                    mu.tightCharge,
                                    mu.looseId,
                                    minpt=10)
        mu['isGood'] = mu['isPres'] & mu['isTight']

        leading_mu = mu[ak.argmax(mu.pt, axis=-1, keepdims=True)]
        leading_mu = leading_mu[leading_mu.isGood]

        mu = mu[mu.isGood]
        mu_pres = mu[mu.isPres]

        # Electron selection
        #e['isGood'] = isElecMVA(e.pt, e.eta, e.dxy, e.dz, e.miniPFRelIso_all, e.sip3d, e.mvaTTH, e.mvaFall17V2Iso, e.lostHits, e.convVeto, e.tightCharge, minpt=10)
        e['isPres'] = isPresElec(e.pt,
                                 e.eta,
                                 e.dxy,
                                 e.dz,
                                 e.miniPFRelIso_all,
                                 e.sip3d,
                                 e.lostHits,
                                 minpt=15)
        e['isTight'] = isTightElec(e.pt,
                                   e.eta,
                                   e.dxy,
                                   e.dz,
                                   e.miniPFRelIso_all,
                                   e.sip3d,
                                   e.mvaTTH,
                                   e.mvaFall17V2Iso,
                                   e.lostHits,
                                   e.convVeto,
                                   e.tightCharge,
                                   e.sieie,
                                   e.hoe,
                                   e.eInvMinusPInv,
                                   minpt=15)
        e['isClean'] = isClean(e, mu, drmin=0.05)
        e['isGood'] = e['isPres'] & e['isTight'] & e['isClean']

        leading_e = e[ak.argmax(e.pt, axis=-1, keepdims=True)]
        leading_e = leading_e[leading_e.isGood]

        e = e[e.isGood]
        e_pres = e[e.isPres & e.isClean]

        # Tau selection
        tau['isPres'] = isPresTau(tau.pt,
                                  tau.eta,
                                  tau.dxy,
                                  tau.dz,
                                  tau.leadTkPtOverTauPt,
                                  tau.idAntiMu,
                                  tau.idAntiEle,
                                  tau.rawIso,
                                  tau.idDecayModeNewDMs,
                                  minpt=20)
        tau['isClean'] = isClean(tau, e_pres, drmin=0.4) & isClean(
            tau, mu_pres, drmin=0.4)
        tau['isGood'] = tau['isPres']  # & tau['isClean'], for the moment
        tau = tau[tau.isGood]

        nElec = ak.num(e)
        nMuon = ak.num(mu)
        nTau = ak.num(tau)

        twoLeps = (nElec + nMuon) == 2
        threeLeps = (nElec + nMuon) == 3
        twoElec = (nElec == 2)
        twoMuon = (nMuon == 2)
        e0 = e[ak.argmax(e.pt, axis=-1, keepdims=True)]
        m0 = mu[ak.argmax(mu.pt, axis=-1, keepdims=True)]

        # Jet selection

        jetptname = 'pt_nom' if hasattr(j, 'pt_nom') else 'pt'
        j['isGood'] = isTightJet(getattr(j,
                                         jetptname), j.eta, j.jetId, j.neHEF,
                                 j.neEmEF, j.chHEF, j.chEmEF, j.nConstituents)
        #j['isgood']  = isGoodJet(j.pt, j.eta, j.jetId)
        #j['isclean'] = isClean(j, e, mu)
        j['isClean'] = isClean(j, e, drmin=0.4) & isClean(
            j, mu, drmin=0.4)  # & isClean(j, tau, drmin=0.4)
        goodJets = j[(j.isClean) & (j.isGood)]
        njets = ak.num(goodJets)
        ht = ak.sum(goodJets.pt, axis=-1)
        j0 = goodJets[ak.argmax(goodJets.pt, axis=-1, keepdims=True)]
        #nbtags = ak.num(goodJets[goodJets.btagDeepFlavB > 0.2770])
        nbtags = ak.num(goodJets[goodJets.btagDeepB > 0.4941])

        ##################################################################
        ### 2 same-sign leptons
        ##################################################################

        # emu
        singe = e[(nElec == 1) & (nMuon == 1) & (e.pt > -1)]
        singm = mu[(nElec == 1) & (nMuon == 1) & (mu.pt > -1)]
        em = ak.cartesian({"e": singe, "m": singm})
        emSSmask = (em.e.charge * em.m.charge > 0)
        emSS = em[emSSmask]
        nemSS = len(ak.flatten(emSS))

        # ee and mumu
        # pt>-1 to preserve jagged dimensions
        ee = e[(nElec == 2) & (nMuon == 0) & (e.pt > -1)]
        mm = mu[(nElec == 0) & (nMuon == 2) & (mu.pt > -1)]

        eepairs = ak.combinations(ee, 2, fields=["e0", "e1"])
        eeSSmask = (eepairs.e0.charge * eepairs.e1.charge > 0)
        eeonZmask = (np.abs((eepairs.e0 + eepairs.e1).mass - 91.2) < 10)
        eeoffZmask = (eeonZmask == 0)

        mmpairs = ak.combinations(mm, 2, fields=["m0", "m1"])
        mmSSmask = (mmpairs.m0.charge * mmpairs.m1.charge > 0)
        mmonZmask = (np.abs((mmpairs.m0 + mmpairs.m1).mass - 91.2) < 10)
        mmoffZmask = (mmonZmask == 0)

        eeSSonZ = eepairs[eeSSmask & eeonZmask]
        eeSSoffZ = eepairs[eeSSmask & eeoffZmask]
        mmSSonZ = mmpairs[mmSSmask & mmonZmask]
        mmSSoffZ = mmpairs[mmSSmask & mmoffZmask]
        neeSS = len(ak.flatten(eeSSonZ)) + len(ak.flatten(eeSSoffZ))
        nmmSS = len(ak.flatten(mmSSonZ)) + len(ak.flatten(mmSSoffZ))

        print('Same-sign events [ee, emu, mumu] = [%i, %i, %i]' %
              (neeSS, nemSS, nmmSS))

        # Cuts
        eeSSmask = (ak.num(eeSSmask[eeSSmask]) > 0)
        mmSSmask = (ak.num(mmSSmask[mmSSmask]) > 0)
        eeonZmask = (ak.num(eeonZmask[eeonZmask]) > 0)
        eeoffZmask = (ak.num(eeoffZmask[eeoffZmask]) > 0)
        mmonZmask = (ak.num(mmonZmask[mmonZmask]) > 0)
        mmoffZmask = (ak.num(mmoffZmask[mmoffZmask]) > 0)
        emSSmask = (ak.num(emSSmask[emSSmask]) > 0)

        ##################################################################
        ### 3 leptons
        ##################################################################

        # eem
        muon_eem = mu[(nElec == 2) & (nMuon == 1) & (mu.pt > -1)]
        elec_eem = e[(nElec == 2) & (nMuon == 1) & (e.pt > -1)]
        ee_eem = ak.combinations(elec_eem, 2, fields=["e0", "e1"])

        ee_eemZmask = (ee_eem.e0.charge * ee_eem.e1.charge < 1) & (np.abs(
            (ee_eem.e0 + ee_eem.e1).mass - 91.2) < 10)
        ee_eemOffZmask = (ee_eem.e0.charge * ee_eem.e1.charge < 1) & (np.abs(
            (ee_eem.e0 + ee_eem.e1).mass - 91.2) > 10)
        ee_eemZmask = (ak.num(ee_eemZmask[ee_eemZmask]) > 0)
        ee_eemOffZmask = (ak.num(ee_eemOffZmask[ee_eemOffZmask]) > 0)

        eepair_eem = (ee_eem.e0 + ee_eem.e1)
        trilep_eem = eepair_eem + muon_eem  #ak.cartesian({"e0":ee_eem.e0,"e1":ee_eem.e1, "m":muon_eem})

        # mme
        muon_mme = mu[(nElec == 1) & (nMuon == 2) & (mu.pt > -1)]
        elec_mme = e[(nElec == 1) & (nMuon == 2) & (e.pt > -1)]

        mm_mme = ak.combinations(muon_mme, 2, fields=["m0", "m1"])
        mm_mmeZmask = (mm_mme.m0.charge * mm_mme.m1.charge < 1) & (np.abs(
            (mm_mme.m0 + mm_mme.m1).mass - 91.2) < 10)
        mm_mmeOffZmask = (mm_mme.m0.charge * mm_mme.m1.charge < 1) & (np.abs(
            (mm_mme.m0 + mm_mme.m1).mass - 91.2) > 10)
        mm_mmeZmask = (ak.num(mm_mmeZmask[mm_mmeZmask]) > 0)
        mm_mmeOffZmask = (ak.num(mm_mmeOffZmask[mm_mmeOffZmask]) > 0)

        mmpair_mme = (mm_mme.m0 + mm_mme.m1)
        trilep_mme = mmpair_mme + elec_mme

        mZ_mme = mmpair_mme.mass
        mZ_eem = eepair_eem.mass
        m3l_eem = trilep_eem.mass
        m3l_mme = trilep_mme.mass

        # eee and mmm
        eee = e[(nElec == 3) & (nMuon == 0) & (e.pt > -1)]
        mmm = mu[(nElec == 0) & (nMuon == 3) & (mu.pt > -1)]

        eee_leps = ak.combinations(eee, 3, fields=["e0", "e1", "e2"])
        mmm_leps = ak.combinations(mmm, 3, fields=["m0", "m1", "m2"])
        ee_pairs = ak.combinations(eee, 2, fields=["e0", "e1"])
        mm_pairs = ak.combinations(mmm, 2, fields=["m0", "m1"])
        ee_pairs_index = ak.argcombinations(eee, 2, fields=["e0", "e1"])
        mm_pairs_index = ak.argcombinations(mmm, 2, fields=["m0", "m1"])

        mmSFOS_pairs = mm_pairs[
            (np.abs(mm_pairs.m0.pdgId) == np.abs(mm_pairs.m1.pdgId))
            & (mm_pairs.m0.charge != mm_pairs.m1.charge)]
        offZmask_mm = ak.all(
            np.abs((mmSFOS_pairs.m0 + mmSFOS_pairs.m1).mass - 91.2) > 10.,
            axis=1,
            keepdims=True) & (ak.num(mmSFOS_pairs) > 0)
        onZmask_mm = ak.any(
            np.abs((mmSFOS_pairs.m0 + mmSFOS_pairs.m1).mass - 91.2) < 10.,
            axis=1,
            keepdims=True)

        eeSFOS_pairs = ee_pairs[
            (np.abs(ee_pairs.e0.pdgId) == np.abs(ee_pairs.e1.pdgId))
            & (ee_pairs.e0.charge != ee_pairs.e1.charge)]
        offZmask_ee = ak.all(
            np.abs((eeSFOS_pairs.e0 + eeSFOS_pairs.e1).mass - 91.2) > 10,
            axis=1,
            keepdims=True) & (ak.num(eeSFOS_pairs) > 0)
        onZmask_ee = ak.any(
            np.abs((eeSFOS_pairs.e0 + eeSFOS_pairs.e1).mass - 91.2) < 10,
            axis=1,
            keepdims=True)

        # Create masks **for event selection**
        eeeOnZmask = (ak.num(onZmask_ee[onZmask_ee]) > 0)
        eeeOffZmask = (ak.num(offZmask_ee[offZmask_ee]) > 0)
        mmmOnZmask = (ak.num(onZmask_mm[onZmask_mm]) > 0)
        mmmOffZmask = (ak.num(offZmask_mm[offZmask_mm]) > 0)

        # Now we need to create masks for the leptons in order to select leptons from the Z boson candidate (in onZ categories)
        ZeeMask = ak.argmin(np.abs((eeSFOS_pairs.e0 + eeSFOS_pairs.e1).mass -
                                   91.2),
                            axis=1,
                            keepdims=True)
        ZmmMask = ak.argmin(np.abs((mmSFOS_pairs.m0 + mmSFOS_pairs.m1).mass -
                                   91.2),
                            axis=1,
                            keepdims=True)

        Zee = eeSFOS_pairs[ZeeMask]
        Zmm = mmSFOS_pairs[ZmmMask]
        eZ0 = Zee.e0[ak.num(eeSFOS_pairs) > 0]
        eZ1 = Zee.e1[ak.num(eeSFOS_pairs) > 0]
        eZ = eZ0 + eZ1
        mZ0 = Zmm.m0[ak.num(mmSFOS_pairs) > 0]
        mZ1 = Zmm.m1[ak.num(mmSFOS_pairs) > 0]
        mZ = mZ0 + mZ1
        mZ_eee = eZ.mass
        mZ_mmm = mZ.mass

        # And for the W boson
        ZmmIndices = mm_pairs_index[ZmmMask]
        ZeeIndices = ee_pairs_index[ZeeMask]
        eW = eee[~ZeeIndices.e0 | ~ZeeIndices.e1]
        mW = mmm[~ZmmIndices.m0 | ~ZmmIndices.m1]

        triElec = eee_leps.e0 + eee_leps.e1 + eee_leps.e2
        triMuon = mmm_leps.m0 + mmm_leps.m1 + mmm_leps.m2
        m3l_eee = triElec.mass
        m3l_mmm = triMuon.mass

        # Triggers
        trig_eeSS = passTrigger(events, 'ee', isData, dataset)
        trig_mmSS = passTrigger(events, 'mm', isData, dataset)
        trig_emSS = passTrigger(events, 'em', isData, dataset)
        trig_eee = passTrigger(events, 'eee', isData, dataset)
        trig_mmm = passTrigger(events, 'mmm', isData, dataset)
        trig_eem = passTrigger(events, 'eem', isData, dataset)
        trig_mme = passTrigger(events, 'mme', isData, dataset)

        # MET filters

        # Weights
        genw = np.ones_like(
            events['MET_pt']) if isData else events['genWeight']
        weights = coffea.analysis_tools.Weights(len(events))
        weights.add('norm', genw if isData else (xsec / sow) * genw)
        eftweights = events['EFTfitCoefficients'] if hasattr(
            events, "EFTfitCoefficients") else []

        # Selections and cuts
        selections = PackedSelection()
        channels2LSS = ['eeSSonZ', 'eeSSoffZ', 'mmSSonZ', 'mmSSoffZ', 'emSS']
        selections.add('eeSSonZ', (eeonZmask) & (eeSSmask) & (trig_eeSS))
        selections.add('eeSSoffZ', (eeoffZmask) & (eeSSmask) & (trig_eeSS))
        selections.add('mmSSonZ', (mmonZmask) & (mmSSmask) & (trig_mmSS))
        selections.add('mmSSoffZ', (mmoffZmask) & (mmSSmask) & (trig_mmSS))
        selections.add('emSS', (emSSmask) & (trig_emSS))

        channels3L = ['eemSSonZ', 'eemSSoffZ', 'mmeSSonZ', 'mmeSSoffZ']
        selections.add('eemSSonZ', (ee_eemZmask) & (trig_eem))
        selections.add('eemSSoffZ', (ee_eemOffZmask) & (trig_eem))
        selections.add('mmeSSonZ', (mm_mmeZmask) & (trig_mme))
        selections.add('mmeSSoffZ', (mm_mmeOffZmask) & (trig_mme))

        channels3L += ['eeeSSonZ', 'eeeSSoffZ', 'mmmSSonZ', 'mmmSSoffZ']
        selections.add('eeeSSonZ', (eeeOnZmask) & (trig_eee))
        selections.add('eeeSSoffZ', (eeeOffZmask) & (trig_eee))
        selections.add('mmmSSonZ', (mmmOnZmask) & (trig_mmm))
        selections.add('mmmSSoffZ', (mmmOffZmask) & (trig_mmm))

        levels = ['base', '2jets', '4jets', '4j1b', '4j2b']
        selections.add('base', (nElec + nMuon >= 2))
        selections.add('2jets', (njets >= 2))
        selections.add('4jets', (njets >= 4))
        selections.add('4j1b', (njets >= 4) & (nbtags >= 1))
        selections.add('4j2b', (njets >= 4) & (nbtags >= 2))

        # Variables
        invMass_eeSSonZ = (eeSSonZ.e0 + eeSSonZ.e1).mass
        invMass_eeSSoffZ = (eeSSoffZ.e0 + eeSSoffZ.e1).mass
        invMass_mmSSonZ = (mmSSonZ.m0 + mmSSonZ.m1).mass
        invMass_mmSSoffZ = (mmSSoffZ.m0 + mmSSoffZ.m1).mass
        invMass_emSS = (emSS.e + emSS.m).mass

        varnames = {}
        varnames['met'] = met.pt
        varnames['ht'] = ht
        varnames['njets'] = njets
        varnames['nbtags'] = nbtags
        varnames['invmass'] = {
            'eeSSonZ': invMass_eeSSonZ,
            'eeSSoffZ': invMass_eeSSoffZ,
            'mmSSonZ': invMass_mmSSonZ,
            'mmSSoffZ': invMass_mmSSoffZ,
            'emSS': invMass_emSS,
            'eemSSonZ': mZ_eem,
            'eemSSoffZ': mZ_eem,
            'mmeSSonZ': mZ_mme,
            'mmeSSoffZ': mZ_mme,
            'eeeSSonZ': mZ_eee,
            'eeeSSoffZ': mZ_eee,
            'mmmSSonZ': mZ_mmm,
            'mmmSSoffZ': mZ_mmm,
        }
        varnames['m3l'] = {
            'eemSSonZ': m3l_eem,
            'eemSSoffZ': m3l_eem,
            'mmeSSonZ': m3l_mme,
            'mmeSSoffZ': m3l_mme,
            'eeeSSonZ': m3l_eee,
            'eeeSSoffZ': m3l_eee,
            'mmmSSonZ': m3l_mmm,
            'mmmSSoffZ': m3l_mmm,
        }
        varnames['e0pt'] = e0.pt
        varnames['e0eta'] = e0.eta
        varnames['m0pt'] = m0.pt
        varnames['m0eta'] = m0.eta
        varnames['j0pt'] = j0.pt
        varnames['j0eta'] = j0.eta
        varnames['counts'] = np.ones_like(events.MET.pt)

        # fill Histos
        hout = self.accumulator.identity()
        allweights = weights.weight().flatten(
        )  # Why does it not complain about .flatten() here?
        hout['SumOfEFTweights'].fill(eftweights,
                                     sample=dataset,
                                     SumOfEFTweights=varnames['counts'],
                                     weight=allweights)

        for var, v in varnames.items():
            for ch in channels2LSS + channels3L:
                for lev in levels:
                    weight = weights.weight()
                    cuts = [ch] + [lev]
                    cut = selections.all(*cuts)
                    weights_flat = weight[cut].flatten(
                    )  # Why does it not complain about .flatten() here?
                    weights_ones = np.ones_like(weights_flat, dtype=np.int)
                    eftweightsvalues = eftweights[cut] if len(
                        eftweights) > 0 else []
                    if var == 'invmass':
                        if ch in ['eeeSSoffZ', 'mmmSSoffZ']: continue
                        elif ch in ['eeeSSonZ', 'mmmSSonZ']:
                            continue  #values = v[ch]
                        else:
                            values = ak.flatten(v[ch][cut])
                        hout['invmass'].fill(sample=dataset,
                                             channel=ch,
                                             cut=lev,
                                             invmass=values,
                                             weight=weights_flat)
                    elif var == 'm3l':
                        if ch in [
                                'eeSSonZ', 'eeSSoffZ', 'mmSSonZ', 'mmSSoffZ',
                                'emSS', 'eeeSSoffZ', 'mmmSSoffZ', 'eeeSSonZ',
                                'mmmSSonZ'
                        ]:
                            continue
                        values = ak.flatten(v[ch][cut])
                        hout['m3l'].fill(eftweightsvalues,
                                         sample=dataset,
                                         channel=ch,
                                         cut=lev,
                                         m3l=values,
                                         weight=weights_flat)
                    else:
                        values = v[cut]
                        if var == 'ht':
                            hout[var].fill(eftweightsvalues,
                                           ht=values,
                                           sample=dataset,
                                           channel=ch,
                                           cut=lev,
                                           weight=weights_flat)
                        elif var == 'met':
                            hout[var].fill(eftweightsvalues,
                                           met=values,
                                           sample=dataset,
                                           channel=ch,
                                           cut=lev,
                                           weight=weights_flat)
                        elif var == 'njets':
                            hout[var].fill(eftweightsvalues,
                                           njets=values,
                                           sample=dataset,
                                           channel=ch,
                                           cut=lev,
                                           weight=weights_flat)
                        elif var == 'nbtags':
                            hout[var].fill(eftweightsvalues,
                                           nbtags=values,
                                           sample=dataset,
                                           channel=ch,
                                           cut=lev,
                                           weight=weights_flat)
                        elif var == 'counts':
                            hout[var].fill(counts=values,
                                           sample=dataset,
                                           channel=ch,
                                           cut=lev,
                                           weight=weights_ones)
                        elif var == 'j0eta':
                            if lev == 'base': continue
                            values = ak.flatten(values)
                            #values=np.asarray(values)
                            hout[var].fill(eftweightsvalues,
                                           j0eta=values,
                                           sample=dataset,
                                           channel=ch,
                                           cut=lev,
                                           weight=weights_flat)
                        elif var == 'e0pt':
                            if ch in [
                                    'mmSSonZ', 'mmSSoffZ', 'mmmSSoffZ',
                                    'mmmSSonZ'
                            ]:
                                continue
                            values = ak.flatten(values)
                            #values=np.asarray(values)
                            hout[var].fill(
                                eftweightsvalues,
                                e0pt=values,
                                sample=dataset,
                                channel=ch,
                                cut=lev,
                                weight=weights_flat
                            )  # Crashing here, not sure why. Related to values?
                        elif var == 'm0pt':
                            if ch in [
                                    'eeSSonZ', 'eeSSoffZ', 'eeeSSoffZ',
                                    'eeeSSonZ'
                            ]:
                                continue
                            values = ak.flatten(values)
                            #values=np.asarray(values)
                            hout[var].fill(eftweightsvalues,
                                           m0pt=values,
                                           sample=dataset,
                                           channel=ch,
                                           cut=lev,
                                           weight=weights_flat)
                        elif var == 'e0eta':
                            if ch in [
                                    'mmSSonZ', 'mmSSoffZ', 'mmmSSoffZ',
                                    'mmmSSonZ'
                            ]:
                                continue
                            values = ak.flatten(values)
                            #values=np.asarray(values)
                            hout[var].fill(eftweightsvalues,
                                           e0eta=values,
                                           sample=dataset,
                                           channel=ch,
                                           cut=lev,
                                           weight=weights_flat)
                        elif var == 'm0eta':
                            if ch in [
                                    'eeSSonZ', 'eeSSoffZ', 'eeeSSoffZ',
                                    'eeeSSonZ'
                            ]:
                                continue
                            values = ak.flatten(values)
                            #values=np.asarray(values)
                            hout[var].fill(eftweightsvalues,
                                           m0eta=values,
                                           sample=dataset,
                                           channel=ch,
                                           cut=lev,
                                           weight=weights_flat)
                        elif var == 'j0pt':
                            if lev == 'base': continue
                            values = ak.flatten(values)
                            #values=np.asarray(values)
                            hout[var].fill(eftweightsvalues,
                                           j0pt=values,
                                           sample=dataset,
                                           channel=ch,
                                           cut=lev,
                                           weight=weights_flat)
        return hout
Exemplo n.º 25
0
    def process(self, events):
        def normalize(val, cut):
            return ak.to_numpy(ak.fill_none(
                val[cut],
                np.nan))  #val[cut].pad(1, clip=True).fillna(0).flatten()

        def fill(region, cuts, systematic=None, wmod=None):
            print('filling %s' % region)
            selections = cuts

            cut = selection.all(*selections)
            if 'signal' in region: weight = weights_signal.weight()[cut]
            elif 'muonCR' in region: weight = weights_muonCR.weight()[cut]
            elif 'VtaggingCR' in region:
                weight = weights_VtaggingCR.weight()[cut]
            output['templates'].fill(
                dataset=dataset,
                region=region,
                pt=normalize(candidatejet.pt, cut),
                msd=normalize(candidatejet.msdcorr, cut),
                n2ddt=normalize(candidatejet.n2ddt, cut),
                #gruddt=normalize(candidatejet.gruddt, cut),
                in_v3_ddt=normalize(candidatejet.in_v3_ddt, cut),
                hadW=normalize(candidatejet.nmatcheddau, cut),
                weight=weight,
            ),
            output['event'].fill(
                dataset=dataset,
                region=region,
                MET=events.MET.pt[cut],
                #nJet=fatjets.counts[cut],
                nPFConstituents=normalize(candidatejet.nPFConstituents, cut),
                weight=weight,
            ),
            output['deepAK8'].fill(
                dataset=dataset,
                region=region,
                deepTagMDWqq=normalize(candidatejet.deepTagMDWqq, cut),
                deepTagMDZqq=normalize(candidatejet.deepTagMDZqq, cut),
                msd=normalize(candidatejet.msdcorr, cut),
                #genflavor=genflavor[cut],
                weight=weight,
            ),
            output['in_v3'].fill(
                dataset=dataset,
                region=region,
                #genflavor=genflavor[cut],
                in_v3=normalize(candidatejet.in_v3, cut),
                n2=normalize(candidatejet.n2b1, cut),
                gru=normalize(candidatejet.gru, cut),
                weight=weight,
            ),
            if 'muonCR' in dataset or 'VtaggingCR' in dataset:
                output['muon'].fill(
                    dataset=dataset,
                    region=region,
                    mu_pt=normalize(candidatemuon.pt, cut),
                    mu_eta=normalize(candidatemuon.eta, cut),
                    mu_pfRelIso04_all=normalize(candidatemuon.pfRelIso04_all,
                                                cut),
                    weight=weight,
                ),

        #common jet kinematics
        gru = events.GRU
        IN = events.IN
        fatjets = events.FatJet
        fatjets['msdcorr'] = corrected_msoftdrop(fatjets)
        fatjets['qcdrho'] = 2 * np.log(fatjets.msdcorr / fatjets.pt)
        fatjets['gruddt'] = gru.v25 - shift(
            fatjets, algo='gruddt', year='2017')
        fatjets['gru'] = gru.v25
        fatjets['in_v3'] = IN.v3
        fatjets['in_v3_ddt'] = IN.v3 - shift(
            fatjets, algo='inddt', year='2017')
        fatjets['in_v3_ddt_90pctl'] = IN.v3 - shift(
            fatjets, algo='inddt90pctl', year='2017')
        fatjets['n2ddt'] = fatjets.n2b1 - n2ddt_shift(fatjets, year='2017')
        fatjets['nmatcheddau'] = TTsemileptonicmatch(events)
        dataset = events.metadata['dataset']
        print('process dataset', dataset)
        isRealData = not hasattr(events, 'genWeight')
        output = self.accumulator.identity()
        if (len(events) == 0): return output

        selection = PackedSelection('uint64')

        weights_signal = Weights(len(events))
        weights_muonCR = Weights(len(events))
        weights_VtaggingCR = Weights(len(events))

        if not isRealData:
            output['sumw'][dataset] += ak.sum(events.genWeight)

        #######################
        if 'signal' in self._region:
            if isRealData:
                trigger_fatjet = np.zeros(len(events), dtype='bool')
                for t in self._triggers[self._year]:
                    try:
                        trigger_fatjet = trigger_fatjet | events.HLT[t]
                    except:
                        print('trigger %s not available' % t)
                        continue

            else:
                trigger_fatjet = np.ones(len(events), dtype='bool')

            fatjets["genMatchFull"] = VQQgenmatch(events)
            candidatejet = ak.firsts(fatjets)
            candidatejet["genMatchFull"] = VQQgenmatch(events)
            nelectrons = ak.sum(
                (events.Electron.pt > 10.)
                & (abs(events.Electron.eta) < 2.5)
                & (events.Electron.cutBased >= events.Electron.VETO),
                axis=1,
            )
            nmuons = ak.sum(
                (events.Muon.pt > 10)
                & (abs(events.Muon.eta) < 2.1)
                & (events.Muon.pfRelIso04_all < 0.4)
                & (events.Muon.looseId),
                axis=1,
            )
            ntaus = ak.sum(
                (events.Tau.pt > 20.)
                & (events.Tau.idDecayMode)
                & (events.Tau.rawIso < 5)
                & (abs(events.Tau.eta) < 2.3),
                axis=1,
            )

            cuts = {
                "S_fatjet_trigger":
                trigger_fatjet,
                "S_pt":
                candidatejet.pt > 525,
                "S_eta": (abs(candidatejet.eta) < 2.5),
                "S_msdcorr": (candidatejet.msdcorr > 40),
                "S_rho":
                ((candidatejet.qcdrho > -5.5) & (candidatejet.qcdrho < -2.)),
                "S_jetid": (candidatejet.isTight),
                "S_VQQgenmatch": (candidatejet.genMatchFull),
                "S_noelectron": (nelectrons == 0),
                "S_nomuon": (nmuons == 0),
                "S_notau": (ntaus == 0),
            }

            for name, cut in cuts.items():
                print(name, cut)
                selection.add(name, cut)

            if isRealData:
                genflavor = 0  #candidatejet.pt.zeros_like().pad(1, clip=True).fillna(-1).flatten()
            if not isRealData:
                weights_signal.add('genweight', events.genWeight)
                #add_pileup_weight(weights_signal, events.Pileup.nPU, self._year, dataset)
                add_jetTriggerWeight(weights_signal, candidatejet.msdcorr,
                                     candidatejet.pt, self._year)
                bosons = getBosons(events.GenPart)
                genBosonPt = ak.fill_none(ak.firsts(bosons.pt), 0)
                add_VJets_NLOkFactor(weights_signal, genBosonPt, self._year,
                                     dataset)
                #genflavor = matchedBosonFlavor(candidatejet, bosons).pad(1, clip=True).fillna(-1).flatten()

            allcuts_signal = set()
            output['cutflow_signal'][dataset]['none'] += float(
                weights_signal.weight().sum())
            for cut in cuts:
                allcuts_signal.add(cut)
                output['cutflow_signal'][dataset][cut] += float(
                    weights_signal.weight()[selection.all(
                        *allcuts_signal)].sum())

            fill('signal', cuts.keys())

        #######################
        if 'muonCR' in self._region:

            if isRealData:
                trigger_muon = np.zeros(len(events), dtype='bool')
                for t in self._muontriggers[self._year]:
                    trigger_muon = trigger_muon | events.HLT[t]
            else:
                trigger_muon = np.ones(len(events), dtype='bool')

            candidatejet = ak.firsts(fatjets)
            candidatemuon = events.Muon[:, :5]

            jets = events.Jet[((events.Jet.pt > 50.)
                               & (abs(events.Jet.eta) < 2.5)
                               & (events.Jet.isTight))][:, :4]

            dphi = abs(jets.delta_phi(candidatejet))

            ak4_away = jets[(dphi > 0.8)]

            nelectrons = ak.sum(
                (events.Electron.pt > 10.)
                & (abs(events.Electron.eta) < 2.5)
                & (events.Electron.cutBased >= events.Electron.VETO),
                axis=1,
            )
            nmuons = ak.sum(
                (events.Muon.pt > 10)
                & (abs(events.Muon.eta) < 2.4)
                & (events.Muon.pfRelIso04_all < 0.25)
                & (events.Muon.looseId),
                axis=1,
            )
            ntaus = ak.sum(
                (events.Tau.pt > 20.)
                & (events.Tau.idDecayMode)
                & (events.Tau.rawIso < 5)
                & (abs(events.Tau.eta) < 2.3)
                & (events.Tau.idMVAoldDM2017v1 >= 16),
                axis=1,
            )

            cuts = {
                "CR1_muon_trigger":
                trigger_muon,
                "CR1_jet_pt": (candidatejet.pt > 525),
                "CR1_jet_eta": (abs(candidatejet.eta) < 2.5),
                "CR1_jet_msd": (candidatejet.msdcorr > 40),
                "CR1_jet_rho":
                ((candidatejet.qcdrho > -5.5) & (candidatejet.qcdrho < -2.)),
                "CR1_mu_pt":
                ak.any(candidatemuon.pt > 55, axis=1),
                "CR1_mu_eta":
                ak.any(abs(candidatemuon.eta) < 2.1, axis=1),
                "CR1_mu_IDLoose":
                ak.any(candidatemuon.looseId, axis=1),
                "CR1_mu_isolationTight":
                ak.any(candidatemuon.pfRelIso04_all < 0.15, axis=1),
                "CR1_muonDphiAK8":
                ak.any(
                    abs(candidatemuon.delta_phi(candidatejet)) > 2 * np.pi / 3,
                    axis=1),
                "CR1_ak4btagMedium08":
                (ak.max(ak4_away.btagCSVV2, axis=1, mask_identity=False) >
                 BTagEfficiency.btagWPs[self._year]['medium']
                 ),  #(ak4_away.btagCSVV2.max() > 0.8838),
                "CR1_noelectron": (nelectrons == 0),
                "CR1_onemuon": (nmuons == 1),
                "CR1_notau": (ntaus == 0),
            }
            for name, cut in cuts.items():
                selection.add(name, cut)

            if isRealData:
                genflavor = 0  #candidatejet.pt.zeros_like().pad(1, clip=True).fillna(-1).flatten()
            if not isRealData:
                weights_muonCR.add('genweight', events.genWeight)
                #add_pileup_weight(weights_muonCR, events.Pileup.nPU, self._year, dataset)
                #add_singleMuTriggerWeight(weights, candidatejet.msdcorr, candidatejet.pt, self._year)
                bosons = getBosons(events.GenPart)
                genBosonPt = ak.fill_none(ak.firsts(bosons.pt), 0)
                #add_VJets_NLOkFactor(weights, genBosonPt, self._year, dataset)
                #genflavor = matchedBosonFlavor(candidatejet, bosons).pad(1, clip=True).fillna(-1).flatten()

            allcuts_ttbar_muoncontrol = set()
            output['cutflow_muonCR'][dataset]['none'] += float(
                weights_muonCR.weight().sum())
            for cut in cuts:
                allcuts_ttbar_muoncontrol.add(cut)
                output['cutflow_muonCR'][dataset][cut] += float(
                    weights_muonCR.weight()[selection.all(
                        *allcuts_ttbar_muoncontrol)].sum())
            fill('muonCR', cuts.keys())

        #######################
        if 'VtaggingCR' in self._region:
            if isRealData:
                trigger_muon = np.zeros(len(events), dtype='bool')
                for t in self._muontriggers[self._year]:
                    trigger_muon = trigger_muon | events.HLT[t]
            else:
                trigger_muon = np.ones(len(events), dtype='bool')

            candidatejet = ak.firsts(fatjets)
            candidatemuon = ak.firsts(events.Muon)

            jets = events.Jet[((events.Jet.pt > 30.)
                               & (abs(events.Jet.eta) < 2.4))][:, :4]

            dr_ak4_ak8 = jets.delta_r(candidatejet)
            dr_ak4_muon = jets.delta_r(candidatemuon)

            ak4_away = jets[(dr_ak4_ak8 > 0.8)]  # & (dr_ak4_muon > 0.4)]
            mu_p4 = ak.zip(
                {
                    "pt": ak.fill_none(candidatemuon.pt, 0),
                    "eta": ak.fill_none(candidatemuon.eta, 0),
                    "phi": ak.fill_none(candidatemuon.phi, 0),
                    "mass": ak.fill_none(candidatemuon.mass, 0),
                },
                with_name="PtEtaPhiMLorentzVector")

            met_p4 = ak.zip(
                {
                    "pt": ak.from_iter([[v] for v in events.MET.pt]),
                    "eta": ak.from_iter([[v] for v in np.zeros(len(events))]),
                    "phi": ak.from_iter([[v] for v in events.MET.phi]),
                    "mass": ak.from_iter([[v] for v in np.zeros(len(events))]),
                },
                with_name="PtEtaPhiMLorentzVector")

            Wleptoniccandidate = mu_p4 + met_p4

            nelectrons = ak.sum(
                ((events.Electron.pt > 10.)
                 & (abs(events.Electron.eta) < 2.5)
                 & (events.Electron.cutBased >= events.Electron.VETO)),
                axis=1,
            )
            n_tight_muon = ak.sum(
                ((events.Muon.pt > 53)
                 & (abs(events.Muon.eta) < 2.1)
                 & (events.Muon.tightId)),
                axis=1,
            )
            n_loose_muon = ak.sum(
                ((events.Muon.pt > 20)
                 & (events.Muon.looseId)
                 & (abs(events.Muon.eta) < 2.4)),
                axis=1,
            )
            ntaus = ak.sum(
                ((events.Tau.pt > 20.)
                 & (events.Tau.idDecayMode)
                 & (events.Tau.rawIso < 5)
                 & (abs(events.Tau.eta) < 2.3)
                 & (events.Tau.idMVAoldDM2017v1 >= 16)),
                axis=1,
            )

            cuts = {
                "CR2_muon_trigger":
                trigger_muon,
                "CR2_jet_pt": (candidatejet.pt > 200),
                "CR2_jet_eta": (abs(candidatejet.eta) < 2.5),
                "CR2_jet_msd": (candidatejet.msdcorr > 40),
                "CR2_mu_pt":
                candidatemuon.pt > 53,
                "CR2_mu_eta": (abs(candidatemuon.eta) < 2.1),
                "CR2_mu_IDTight":
                candidatemuon.tightId,
                "CR2_mu_isolationTight": (candidatemuon.pfRelIso04_all < 0.15),
                "CR2_muonDphiAK8":
                abs(candidatemuon.delta_phi(candidatejet)) > 2 * np.pi / 3,
                "CR2_ak4btagMedium08":
                (ak.max(ak4_away.btagCSVV2, axis=1, mask_identity=False) >
                 BTagEfficiency.btagWPs[self._year]['medium']),
                "CR2_leptonicW":
                ak.flatten(Wleptoniccandidate.pt > 200),
                "CR2_MET": (events.MET.pt > 40.),
                "CR2_noelectron": (nelectrons == 0),
                "CR2_one_tightMuon": (n_tight_muon == 1),
                "CR2_one_looseMuon": (n_loose_muon == 1),
                #"CR2_notau"            : (ntaus==0),
            }

            for name, cut in cuts.items():
                print(name, cut)
                selection.add(name, cut)
            #weights.add('metfilter', events.Flag.METFilters)
            if isRealData:
                genflavor = 0  #candidatejet.pt.zeros_like().pad(1, clip=True).fillna(-1).flatten()
            if not isRealData:
                weights_VtaggingCR.add('genweight', events.genWeight)
                #add_pileup_weight(weights_VtaggingCR, events.Pileup.nPU, self._year, dataset)
                #add_singleMuTriggerWeight(weights, abs(candidatemuon.eta), candidatemuon.pt, self._year)
                bosons = getBosons(events.GenPart)
                genBosonPt = ak.fill_none(ak.firsts(bosons.pt), 0)
                #add_VJets_NLOkFactor(weights, genBosonPt, self._year, dataset)
                #genflavor = matchedBosonFlavor(candidatejet, bosons).pad(1, clip=True).fillna(-1).flatten()

                #b-tag weights
            allcuts_vselection = set()
            output['cutflow_VtaggingCR'][dataset]['none'] += float(
                weights_VtaggingCR.weight().sum())

            for cut in cuts:
                allcuts_vselection.add(cut)
                output['cutflow_VtaggingCR'][dataset][cut] += float(
                    weights_VtaggingCR.weight()[selection.all(
                        *allcuts_vselection)].sum())
            fill('VtaggingCR', cuts.keys())

        return output