def produce_final_states(process, collections, output_commands,
                         sequence, puTag, buildFSAEvent=True,
                         noTracks=False, noPhotons=False):

    muonsrc = collections['muons']
    esrc = collections['electrons']
    tausrc = collections['taus']
    jetsrc = collections['jets']
    pfmetsrc = collections['pfmet']
    mvametsrc = collections['mvamet']
    phosrc = collections['photons']

    # Build the PATFinalStateEventObject
    if buildFSAEvent:
        process.load("FinalStateAnalysis.PatTools."
                     "finalStates.patFinalStateEventProducer_cfi")
        process.patFinalStateEventProducer.electronSrc = cms.InputTag(esrc)
        process.patFinalStateEventProducer.muonSrc = cms.InputTag(muonsrc)
        process.patFinalStateEventProducer.tauSrc = cms.InputTag(tausrc)
        process.patFinalStateEventProducer.jetSrc = cms.InputTag(jetsrc)
        process.patFinalStateEventProducer.phoSrc = cms.InputTag(phosrc)
        process.patFinalStateEventProducer.metSrc = pfmetsrc
        process.patFinalStateEventProducer.puTag = cms.string(puTag)
        process.patFinalStateEventProducer.mets.pfmet = pfmetsrc
        process.patFinalStateEventProducer.mets.mvamet = mvametsrc
        sequence += process.patFinalStateEventProducer

    # Always keep
    output_commands.append('*_patFinalStateEventProducer_*_*')

    # Apply some loose PT cuts on the objects we use to create the final states
    # so the combinatorics don't blow up
    process.muonsForFinalStates = cms.EDFilter(
        "PATMuonRefSelector",
        src=cms.InputTag(muonsrc),
        cut=cms.string('max(pt, userFloat("maxCorPt")) > 4 '
                       '& (isGlobalMuon | isTrackerMuon)'),
        filter=cms.bool(False),
    )

    process.electronsForFinalStates = cms.EDFilter(
        "PATElectronRefSelector",
        src=cms.InputTag(esrc),
        cut=cms.string('abs(superCluster().eta) < 3.0 '
                       '& max(pt, userFloat("maxCorPt")) > 7'),
        filter=cms.bool(False),
    )

    process.photonsForFinalStates = cms.EDFilter(
        "PATPhotonRefSelector",
        src=cms.InputTag(phosrc),
        cut=cms.string('abs(superCluster().eta()) < 3.0 & pt > 10'),
        filter=cms.bool(False),
    )

    # Require that the PT of the jet (either corrected jet or tau)
    # to be greater than 17
    process.tausForFinalStates = cms.EDFilter(
        "PATTauRefSelector",
        src=cms.InputTag(tausrc),
        cut=cms.string('abs(eta) < 2.5 & pt > 17 & tauID("decayModeFinding")'),
        filter=cms.bool(False),
    )


    process.jetsForFinalStates = cms.EDProducer("PATJetCleaner",
        src = cms.InputTag(jetsrc),
        # preselection (any string-based cut on pat::Jet)
        preselection = cms.string("pt>20 & abs(eta) < 2.5 & userFloat('idLoose') & userFloat('fullDiscriminant')"),
        # overlap checking configurables
        checkOverlaps = cms.PSet(
         muons = cms.PSet(
          src = cms.InputTag("muonsForFinalStates"),
          algorithm = cms.string("byDeltaR"),
          preselection = cms.string("pt>10&&isGlobalMuon&&isTrackerMuon&&(chargedHadronIso()+max(photonIso+neutralHadronIso(),0.0))/pt()<0.3"),
          deltaR = cms.double(0.3),
          checkRecoComponents = cms.bool(False),
          pairCut = cms.string(""),
          requireNoOverlaps = cms.bool(True),
        ),
        electrons = cms.PSet(
           src = cms.InputTag("electronsForFinalStates"),
           algorithm = cms.string("byDeltaR"),
           preselection = cms.string("pt>10&&(chargedHadronIso()+max(photonIso()+neutralHadronIso(),0.0))/pt()<0.3"),
           deltaR = cms.double(0.3),
           checkRecoComponents = cms.bool(False),
           pairCut = cms.string(""),
           requireNoOverlaps = cms.bool(True),
         ),
         ),
         # finalCut (any string-based cut on pat::Jet)
         finalCut = cms.string('')
    )

    process.selectObjectsForFinalStates = cms.Sequence(
        process.muonsForFinalStates
        + process.electronsForFinalStates
        + process.tausForFinalStates
	+ process.jetsForFinalStates
    )
    if not noPhotons:
        process.selectObjectsForFinalStates += process.photonsForFinalStates

    sequence += process.selectObjectsForFinalStates

    # Now build all combinatorics for E/Mu/Tau/Photon
    object_types = [('Elec', cms.InputTag("electronsForFinalStates")),
                    ('Mu', cms.InputTag("muonsForFinalStates")),
                    ('Tau', cms.InputTag("tausForFinalStates")),
			('Jet', cms.InputTag("jetsForFinalStates"))]

    if not noPhotons:
        object_types.append(('Pho', cms.InputTag("photonsForFinalStates")))

    process.buildDiObjects = cms.Sequence()

    process.load("FinalStateAnalysis.PatTools."
                 "finalStates.patFinalStatesEmbedExtraCollections_cfi")
    # If we don't have tracks, don't fit the FS vertices
    if noTracks:
        process.patFinalStateVertexFitter.enable = False

    # Build di-object pairs
    for diobject in _combinatorics(object_types, 2):
        # Don't build two jet states
        if (diobject[0][0], diobject[1][0]) == ('Tau', 'Tau'):
            continue
        if (diobject[0][0], diobject[1][0]) == ('Tau', 'Pho'):
            continue
        if (diobject[0][0], diobject[1][0]) == ('Tau', 'Jet'):
            continue
        if (diobject[0][0], diobject[1][0]) == ('Jet', 'Pho'):
            continue
        if (diobject[0][0], diobject[1][0]) == ('Jet', 'Jet'):
            continue

        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3']  # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%sFinalStateProducer" % (diobject[0][0], diobject[1][0]),
            evtSrc=cms.InputTag("patFinalStateEventProducer"),
            leg1Src=diobject[0][1],
            leg2Src=diobject[1][1],
            # X-cleaning
            cut=cms.string(' & '.join(cuts))
        )
        producer_name = "finalState%s%s" % (diobject[0][0], diobject[1][0])
        setattr(process, producer_name + "Raw", producer)
        process.buildDiObjects += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(
            process, process.patFinalStatesEmbedObjects, producer_name)
        process.buildDiObjects += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = cms.EDProducer(
            "PATFinalStateCopier", src=final_module_name)
        setattr(process, producer_name, final_module)
        process.buildDiObjects += final_module
        setattr(process, producer_name, final_module)
        output_commands.append("*_%s_*_*" % producer_name)
    sequence += process.buildDiObjects

    # Build tri-lepton pairs
    process.buildTriObjects = cms.Sequence()
    for triobject in _combinatorics(object_types, 3):
        # Don't build three jet states
        if (triobject[0][0], triobject[1][0], triobject[2][0]) == \
           ('Tau', 'Tau', 'Tau'):
            continue

        n_taus = [x[0] for x in triobject].count('Tau')
        n_phos = [x[0] for x in triobject].count('Pho')
        n_muons = [x[0] for x in triobject].count('Mu')
        n_jets = [x[0] for x in triobject].count('Jet')

        if n_taus > 2:
            continue
        if n_phos > 2:
            continue
        if n_taus and n_phos:
            continue
	if n_jets > 0 and not (n_jets == 2 and n_muons == 1):
	    continue 


        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3']  # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%s%sFinalStateProducer" %
            (triobject[0][0], triobject[1][0], triobject[2][0]),
            evtSrc=cms.InputTag("patFinalStateEventProducer"),
            leg1Src=triobject[0][1],
            leg2Src=triobject[1][1],
            leg3Src=triobject[2][1],
            # X-cleaning
            cut=cms.string(' & '.join(cuts))
        )
        producer_name = "finalState%s%s%s" % (
            triobject[0][0], triobject[1][0], triobject[2][0])
        #setattr(process, producer_name, producer)
        #process.buildTriLeptons += producer
        setattr(process, producer_name + "Raw", producer)
        process.buildTriObjects += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(
            process, process.patFinalStatesEmbedObjects, producer_name)
        process.buildTriObjects += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = cms.EDProducer(
            "PATFinalStateCopier", src=final_module_name)
        setattr(process, producer_name, final_module)
        process.buildTriObjects += final_module
        output_commands.append("*_%s_*_*" % producer_name)
    sequence += process.buildTriObjects

    # Build 4 lepton final states
    process.buildQuadObjects = cms.Sequence()
    for quadobject in _combinatorics(object_types, 4):
        # Don't build states with more than 2 hadronic taus or phos
        n_taus = [x[0] for x in quadobject].count('Tau')
        n_phos = [x[0] for x in quadobject].count('Pho')
        n_jets = [x[0] for x in quadobject].count('Jet')

        if n_taus > 2:
            continue
        if n_phos > 2:
            continue
        if n_taus and n_phos:
            continue
	if n_jets> 0:
            continue


        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3']  # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%s%s%sFinalStateProducer" %
            (quadobject[0][0], quadobject[1][0], quadobject[2][0],
             quadobject[3][0]),
            evtSrc=cms.InputTag("patFinalStateEventProducer"),
            leg1Src=quadobject[0][1],
            leg2Src=quadobject[1][1],
            leg3Src=quadobject[2][1],
            leg4Src=quadobject[3][1],
            # X-cleaning
            cut=cms.string(' & '.join(cuts))
        )
        producer_name = "finalState%s%s%s%s" % (
            quadobject[0][0], quadobject[1][0], quadobject[2][0],
            quadobject[3][0]
        )
        #setattr(process, producer_name, producer)
        #process.buildTriLeptons += producer
        setattr(process, producer_name + "Raw", producer)
        process.buildQuadObjects += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(
            process, process.patFinalStatesEmbedObjects, producer_name)
        process.buildQuadObjects += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = cms.EDProducer(
            "PATFinalStateCopier", src=final_module_name)
        setattr(process, producer_name, final_module)
        process.buildQuadObjects += final_module
        output_commands.append("*_%s_*_*" % producer_name)
    sequence += process.buildQuadObjects
Exemple #2
0
def produce_final_states(process,
                         collections,
                         output_commands,
                         sequence,
                         puTag,
                         buildFSAEvent=True,
                         noTracks=False,
                         noPhotons=False,
                         zzMode=False,
                         rochCor="",
                         eleCor=""):

    muonsrc = collections['muons']
    esrc = collections['electrons']
    tausrc = collections['taus']
    jetsrc = collections['jets']
    pfmetsrc = collections['pfmet']
    mvametsrc = collections['mvamet']
    phosrc = collections['photons']
    try:
        fsrsrc = collections['fsr']
    except KeyError:
        fsrsrc = 'boostedFsrPhotons'

    # Build the PATFinalStateEventObject
    if buildFSAEvent:
        process.load("FinalStateAnalysis.PatTools."
                     "finalStates.patFinalStateEventProducer_cfi")
        process.patFinalStateEventProducer.electronSrc = cms.InputTag(esrc)
        process.patFinalStateEventProducer.muonSrc = cms.InputTag(muonsrc)
        process.patFinalStateEventProducer.tauSrc = cms.InputTag(tausrc)
        process.patFinalStateEventProducer.jetSrc = cms.InputTag(jetsrc)
        process.patFinalStateEventProducer.phoSrc = cms.InputTag(phosrc)
        process.patFinalStateEventProducer.metSrc = pfmetsrc
        process.patFinalStateEventProducer.puTag = cms.string(puTag)
        process.patFinalStateEventProducer.mets.pfmet = pfmetsrc
        process.patFinalStateEventProducer.mets.mvamet = mvametsrc
        sequence += process.patFinalStateEventProducer

    # Always keep
    output_commands.append('*_patFinalStateEventProducer_*_*')

    # Apply some loose PT cuts on the objects we use to create the final states
    # so the combinatorics don't blow up
    if zzMode:
        import hzzPreselection
        muon_string, elec_string = hzzPreselection.getStrings()
    else:
        muon_string = ('max(pt, userFloat("maxCorPt")) > 4 &'
                       '& (isGlobalMuon | isTrackerMuon)')

        elec_string = ('abs(superCluster().eta) < 3.0 '
                       '& max(pt, userFloat("maxCorPt")) > 7')

    # Initialize final-state object sequence
    process.selectObjectsForFinalStates = cms.Sequence()

    # Are we applying Rochester Corrections to the muons?
    if rochCor != "":
        if rochCor not in ["RochCor2012", "RochCor2011A", "RochCor2011B"]:
            raise RuntimeError(rochCor + ": not a valid option")

        print "-- Applying Muon Rochester Corrections --"

        process.rochCorMuons = cms.EDProducer("PATMuonRochesterCorrector",
                                              src=cms.InputTag(muonsrc),
                                              corr_type=cms.string("p4_" +
                                                                   rochCor))

        muonsrc = "rochCorMuons"

        process.selectObjectsForFinalStates += process.rochCorMuons

    # Are we applying electron energy corrections?
    if eleCor != "":
        if eleCor not in [
                "Summer12_DR53X_HCP2012", "2012Jul13ReReco", "Fall11"
        ]:
            raise RuntimeError(eleCor + ": not a valid option")

        print "-- Applying Electron Energy Corrections --"

        process.corrElectrons = cms.EDProducer(
            "PATElectronEnergyCorrector",
            src=cms.InputTag(esrc),
            corr_type=cms.string("EGCorr_" + eleCor + "SmearedRegression"))

        esrc = "corrElectrons"

        process.selectObjectsForFinalStates += process.corrElectrons

    process.muonsRank = cms.EDProducer("PATMuonRanker",
                                       src=cms.InputTag(muonsrc))

    process.muonsForFinalStates = cms.EDFilter(
        "PATMuonRefSelector",
        src=cms.InputTag("muonsRank"),
        cut=cms.string(muon_string),
        filter=cms.bool(False),
    )

    process.electronsRank = cms.EDProducer("PATElectronRanker",
                                           src=cms.InputTag(esrc))

    process.electronsForFinalStates = cms.EDFilter(
        "PATElectronRefSelector",
        src=cms.InputTag("electronsRank"),
        cut=cms.string(elec_string),
        filter=cms.bool(False),
    )

    process.photonsForFinalStates = cms.EDFilter(
        "PATPhotonRefSelector",
        src=cms.InputTag(phosrc),
        cut=cms.string('abs(superCluster().eta()) < 3.0 & pt > 10'),
        filter=cms.bool(False),
    )

    process.tausES = cms.EDProducer("ESTauProducer", src=cms.InputTag(tausrc))

    process.tausRank = cms.EDProducer("PATTauRanker",
                                      src=cms.InputTag("tausES"))

    # Require that the PT of the jet (either corrected jet or tau)
    # to be greater than 17
    process.tausForFinalStates = cms.EDFilter(
        "PATTauRefSelector",
        src=cms.InputTag("tausRank"),
        cut=cms.string('abs(eta) < 2.5 & pt > 17 & tauID("decayModeFinding")'),
        filter=cms.bool(False),
    )

    process.jetsFiltered = cms.EDProducer(
        "PATJetCleaner",
        src=cms.InputTag(jetsrc),
        # I leave it loose here, can be tightened at the last step
        preselection=cms.string(
            "pt>20 & abs(eta) < 2.5 & "
            "userFloat('idLoose') & userInt('fullIdLoose')"),
        # overlap checking configurables
        checkOverlaps=cms.PSet(
            muons=cms.PSet(
                src=cms.InputTag("muonsForFinalStates"),
                algorithm=cms.string("byDeltaR"),
                preselection=cms.string(
                    "pt>10&&isGlobalMuon&&isTrackerMuon&&"
                    "(userIso(0)+max(photonIso()+neutralHadronIso()"
                    "-0.5*puChargedHadronIso(),0))/pt()<0.3"),
                deltaR=cms.double(0.3),
                checkRecoComponents=cms.bool(False),
                pairCut=cms.string(""),
                requireNoOverlaps=cms.bool(True),
            ),
            electrons=cms.PSet(
                src=cms.InputTag("electronsForFinalStates"),
                algorithm=cms.string("byDeltaR"),
                preselection=cms.string(
                    "pt>10&&userFloat('wp95')>0"
                    "&&(userIso(0)+max(userIso(1)+neutralHadronIso()"
                    "-0.5*userIso(2),0.0))/pt()<0.3"),
                deltaR=cms.double(0.3),
                checkRecoComponents=cms.bool(False),
                pairCut=cms.string(""),
                requireNoOverlaps=cms.bool(True),
            ),
        ),
        # finalCut (any string-based cut on pat::Jet)
        finalCut=cms.string(''))
    process.jetsForFinalStates = cms.EDProducer(
        "PATJetRanker", src=cms.InputTag("jetsFiltered"))

    process.selectObjectsForFinalStates = cms.Sequence(
        process.muonsRank + process.muonsForFinalStates +
        process.electronsRank + process.electronsForFinalStates +
        process.tausES + process.tausRank + process.tausForFinalStates +
        process.jetsFiltered + process.jetsForFinalStates)
    if not noPhotons:
        process.selectObjectsForFinalStates += process.photonsForFinalStates

    sequence += process.selectObjectsForFinalStates

    # Now build all combinatorics for E/Mu/Tau/Photon
    object_types = [('Elec', cms.InputTag("electronsForFinalStates")),
                    ('Mu', cms.InputTag("muonsForFinalStates")),
                    ('Tau', cms.InputTag("tausForFinalStates")),
                    ('Jet', cms.InputTag("jetsForFinalStates"))]

    if not noPhotons:
        object_types.append(('Pho', cms.InputTag("photonsForFinalStates")))

    process.buildDiObjects = cms.Sequence()

    process.load("FinalStateAnalysis.PatTools."
                 "finalStates.patFinalStatesEmbedExtraCollections_cfi")
    # If we don't have tracks, don't fit the FS vertices
    if noTracks:
        process.patFinalStateVertexFitter.enable = False

    # Build di-object pairs
    for diobject in _combinatorics(object_types, 2):
        # Don't build two jet states
        if (diobject[0][0], diobject[1][0]) == ('Tau', 'Tau'):
            continue
        if (diobject[0][0], diobject[1][0]) == ('Tau', 'Pho'):
            continue
        if (diobject[0][0], diobject[1][0]) == ('Tau', 'Jet'):
            continue
        if (diobject[0][0], diobject[1][0]) == ('Jet', 'Pho'):
            continue
        if (diobject[0][0], diobject[1][0]) == ('Jet', 'Jet'):
            continue

        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3']  # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%sFinalStateProducer" % (diobject[0][0], diobject[1][0]),
            evtSrc=cms.InputTag("patFinalStateEventProducer"),
            leg1Src=diobject[0][1],
            leg2Src=diobject[1][1],
            # X-cleaning
            cut=cms.string(' & '.join(cuts)))
        producer_name = "finalState%s%s" % (diobject[0][0], diobject[1][0])
        setattr(process, producer_name + "Raw", producer)
        process.buildDiObjects += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(
            process, process.patFinalStatesEmbedObjects, producer_name)
        process.buildDiObjects += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = cms.EDProducer("PATFinalStateCopier",
                                      src=final_module_name)
        setattr(process, producer_name, final_module)
        process.buildDiObjects += final_module
        setattr(process, producer_name, final_module)
        output_commands.append("*_%s_*_*" % producer_name)
    sequence += process.buildDiObjects

    # Build tri-lepton pairs
    process.buildTriObjects = cms.Sequence()
    for triobject in _combinatorics(object_types, 3):
        # Don't build three jet states
        if (triobject[0][0], triobject[1][0], triobject[2][0]) == \
           ('Tau', 'Tau', 'Tau'):
            continue

        n_taus = [x[0] for x in triobject].count('Tau')
        n_phos = [x[0] for x in triobject].count('Pho')
        n_muons = [x[0] for x in triobject].count('Mu')
        n_jets = [x[0] for x in triobject].count('Jet')

        if n_taus > 2:
            continue
        if n_phos > 2:
            continue
        if n_taus and n_phos:
            continue
        if n_jets > 0 and not (n_jets == 2 and n_muons == 1):
            continue

        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3']  # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%s%sFinalStateProducer" %
            (triobject[0][0], triobject[1][0], triobject[2][0]),
            evtSrc=cms.InputTag("patFinalStateEventProducer"),
            leg1Src=triobject[0][1],
            leg2Src=triobject[1][1],
            leg3Src=triobject[2][1],
            # X-cleaning
            cut=cms.string(' & '.join(cuts)))
        producer_name = "finalState%s%s%s" % (triobject[0][0], triobject[1][0],
                                              triobject[2][0])
        #setattr(process, producer_name, producer)
        #process.buildTriLeptons += producer
        setattr(process, producer_name + "Raw", producer)
        process.buildTriObjects += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(
            process, process.patFinalStatesEmbedObjects, producer_name)
        process.buildTriObjects += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = cms.EDProducer("PATFinalStateCopier",
                                      src=final_module_name)
        setattr(process, producer_name, final_module)
        process.buildTriObjects += final_module
        output_commands.append("*_%s_*_*" % producer_name)
    sequence += process.buildTriObjects

    # Build 4 lepton final states
    process.buildQuadObjects = cms.Sequence()
    for quadobject in _combinatorics(object_types, 4):
        # Don't build states with more than 2 hadronic taus or phos
        n_taus = [x[0] for x in quadobject].count('Tau')
        n_phos = [x[0] for x in quadobject].count('Pho')
        n_jets = [x[0] for x in quadobject].count('Jet')

        if n_taus > 2:
            continue
        if n_phos > 2:
            continue
        if n_taus and n_phos:
            continue
        if n_jets > 0:
            continue

        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3']  # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%s%s%sFinalStateProducer" %
            (quadobject[0][0], quadobject[1][0], quadobject[2][0],
             quadobject[3][0]),
            evtSrc=cms.InputTag("patFinalStateEventProducer"),
            leg1Src=quadobject[0][1],
            leg2Src=quadobject[1][1],
            leg3Src=quadobject[2][1],
            leg4Src=quadobject[3][1],
            # X-cleaning
            cut=cms.string(' & '.join(cuts)))
        producer_name = "finalState%s%s%s%s" % (
            quadobject[0][0], quadobject[1][0], quadobject[2][0],
            quadobject[3][0])
        #setattr(process, producer_name, producer)
        #process.buildTriLeptons += producer
        setattr(process, producer_name + "Raw", producer)
        process.buildQuadObjects += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(
            process, process.patFinalStatesEmbedObjects, producer_name)
        process.buildQuadObjects += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = cms.EDProducer("PATFinalStateCopier",
                                      src=final_module_name)
        setattr(process, producer_name, final_module)
        process.buildQuadObjects += final_module
        output_commands.append("*_%s_*_*" % producer_name)
    sequence += process.buildQuadObjects

    # Build 4 lepton final states w/ FSR
    if zzMode:
        zz_object_types = [('Elec', cms.InputTag("electronsForFinalStates")),
                           ('Mu', cms.InputTag("muonsForFinalStates"))]

        process.buildQuadHzzObjects = cms.Sequence()
        for quadobject in _combinatorics(zz_object_types, 4):
            n_elec = [x[0] for x in quadobject].count('Elec')
            n_muon = [x[0] for x in quadobject].count('Mu')

            if n_elec % 2 == 1:
                continue
            if n_muon % 2 == 1:
                continue

            # Define some basic selections for building combinations
            cuts = ['smallestDeltaR() > 0.3']  # basic x-cleaning

            producer = cms.EDProducer(
                "PAT%s%s%s%sFinalStateHzzProducer" %
                (quadobject[0][0], quadobject[1][0], quadobject[2][0],
                 quadobject[3][0]),
                evtSrc=cms.InputTag("patFinalStateEventProducer"),
                leg1Src=quadobject[0][1],
                leg2Src=quadobject[1][1],
                leg3Src=quadobject[2][1],
                leg4Src=quadobject[3][1],
                photonSrc=cms.InputTag(fsrsrc),
                # X-cleaning
                cut=cms.string(''))
            producer_name = "finalState%s%s%s%sHzz" % (
                quadobject[0][0], quadobject[1][0], quadobject[2][0],
                quadobject[3][0])
            #setattr(process, producer_name, producer)
            #process.buildTriLeptons += producer
            setattr(process, producer_name + "Raw", producer)
            process.buildQuadHzzObjects += producer

            # Embed the other collections
            embedder_seq = helpers.cloneProcessingSnippet(
                process, process.patFinalStatesEmbedObjects, producer_name)

            process.buildQuadHzzObjects += embedder_seq

            # Do some trickery so the final module has a nice output name
            final_module_name = chain_sequence(embedder_seq,
                                               producer_name + "Raw")
            final_module = cms.EDProducer("PATFinalStateCopier",
                                          src=final_module_name)

            setattr(process, producer_name, final_module)
            process.buildQuadHzzObjects += final_module
            output_commands.append("*_%s_*_*" % producer_name)

        sequence += process.buildQuadHzzObjects
def produce_final_states(process, collections, output_commands,
                         sequence, puTag, buildFSAEvent=True,
                         noTracks=False, noPhotons=False, zzMode=False,
                         rochCor="", eleCor=""):

    muonsrc = collections['muons']
    esrc = collections['electrons']
    tausrc = collections['taus']
    jetsrc = collections['jets']
    pfmetsrc = collections['pfmet']
    mvametsrc = collections['mvamet']
    phosrc = collections['photons']
    try:
        fsrsrc = collections['fsr']
    except KeyError:
        fsrsrc = 'boostedFsrPhotons'

    # Build the PATFinalStateEventObject
    if buildFSAEvent:
        process.load("FinalStateAnalysis.PatTools."
                     "finalStates.patFinalStateEventProducer_cfi")
        process.patFinalStateEventProducer.electronSrc = cms.InputTag(esrc)
        process.patFinalStateEventProducer.muonSrc = cms.InputTag(muonsrc)
        process.patFinalStateEventProducer.tauSrc = cms.InputTag(tausrc)
        process.patFinalStateEventProducer.jetSrc = cms.InputTag(jetsrc)
        process.patFinalStateEventProducer.phoSrc = cms.InputTag(phosrc)
        process.patFinalStateEventProducer.metSrc = pfmetsrc
        process.patFinalStateEventProducer.puTag = cms.string(puTag)
        process.patFinalStateEventProducer.mets.pfmet = pfmetsrc
        process.patFinalStateEventProducer.mets.mvamet = mvametsrc
        if 'extraWeights' in collections:
            process.patFinalStateEventProducer.extraWeights = collections['extraWeights']
        sequence += process.patFinalStateEventProducer

    # Always keep
    output_commands.append('*_patFinalStateEventProducer_*_*')

    # Apply some loose PT cuts on the objects we use to create the final states
    # so the combinatorics don't blow up
    if zzMode:
        import hzzPreselection
        muon_string, elec_string = hzzPreselection.getStrings()
    else:
        muon_string = (
                'max(pt, userFloat("maxCorPt")) > 4 &'
                '& (isGlobalMuon | isTrackerMuon)' )

        elec_string = (
                'abs(superCluster().eta) < 3.0 '
                '& max(pt, userFloat("maxCorPt")) > 7' )


    # Initialize final-state object sequence
    process.selectObjectsForFinalStates = cms.Sequence()

    # Are we applying Rochester Corrections to the muons?
    if rochCor != "":
        if rochCor not in ["RochCor2012", "RochCor2011A", "RochCor2011B"]:
            raise RuntimeError(rochCor + ": not a valid option")

        print "-- Applying Muon Rochester Corrections --"

        process.rochCorMuons = cms.EDProducer(
            "PATMuonRochesterCorrector",
            src=cms.InputTag(muonsrc),
            corr_type=cms.string("p4_" + rochCor)
        )

        muonsrc = "rochCorMuons"

        process.selectObjectsForFinalStates += process.rochCorMuons

    # Are we applying electron energy corrections?
    if eleCor != "":
        if eleCor not in ["Summer12_DR53X_HCP2012",
                          "2012Jul13ReReco", "Fall11"]:
            raise RuntimeError(eleCor + ": not a valid option")

        print "-- Applying Electron Energy Corrections --"

        process.corrElectrons = cms.EDProducer(
            "PATElectronEnergyCorrector",
            src=cms.InputTag(esrc),
            corr_type=cms.string("EGCorr_" + eleCor + "SmearedRegression")
        )

        esrc = "corrElectrons"

        process.selectObjectsForFinalStates += process.corrElectrons

    process.muonsRank = cms.EDProducer(
        "PATMuonRanker",
        src=cms.InputTag(muonsrc))

    process.muonsForFinalStates = cms.EDFilter(
        "PATMuonRefSelector",
        src=cms.InputTag("muonsRank"),
        cut=cms.string(muon_string),
        filter=cms.bool(False),
    )

    process.electronsRank = cms.EDProducer(
        "PATElectronRanker", src=cms.InputTag(esrc))

    process.electronsForFinalStates = cms.EDFilter(
        "PATElectronRefSelector",
        src=cms.InputTag("electronsRank"),
        cut=cms.string(elec_string),
        filter=cms.bool(False),
    )

    process.photonsForFinalStates = cms.EDFilter(
        "PATPhotonRefSelector",
        src=cms.InputTag(phosrc),
        cut=cms.string('abs(superCluster().eta()) < 3.0 & pt > 10'),
        filter=cms.bool(False),
    )

    process.tausRank = cms.EDProducer(
        "PATTauRanker",
        src=cms.InputTag(tausrc))

    # Require that the PT of the jet (either corrected jet or tau)
    # to be greater than 17
    process.tausForFinalStates = cms.EDFilter(
        "PATTauRefSelector",
        src=cms.InputTag("tausRank"),
        cut=cms.string('abs(eta) < 2.5 & pt > 17 & tauID("decayModeFinding")'),
        filter=cms.bool(False),
    )

    process.jetsFiltered = cms.EDProducer(
        "PATJetCleaner",
        src=cms.InputTag(jetsrc),
        # I leave it loose here, can be tightened at the last step
        preselection=cms.string(
            "pt>20 & abs(eta) < 2.5 & "
            "userFloat('idLoose')"),
                # & userInt('fullIdLoose')"),
        # overlap checking configurables
        checkOverlaps=cms.PSet(
            muons=cms.PSet(
                src=cms.InputTag("muonsForFinalStates"),
                algorithm=cms.string("byDeltaR"),
                preselection=cms.string(
                    "pt>10&&isGlobalMuon&&isTrackerMuon&&"
                    "(userIso(0)+max(photonIso()+neutralHadronIso()"
                    "-0.5*puChargedHadronIso(),0))/pt()<0.3"),
                deltaR=cms.double(0.3),
                checkRecoComponents=cms.bool(False),
                pairCut=cms.string(""),
                requireNoOverlaps=cms.bool(True),
            ),
            electrons=cms.PSet(
                src=cms.InputTag("electronsForFinalStates"),
                algorithm=cms.string("byDeltaR"),
                preselection=cms.string(
                    "pt>10&&userFloat('wp95')>0"
                    "&&(userIso(0)+max(userIso(1)+neutralHadronIso()"
                    "-0.5*userIso(2),0.0))/pt()<0.3"),
                deltaR=cms.double(0.3),
                checkRecoComponents=cms.bool(False),
                pairCut=cms.string(""),
                requireNoOverlaps=cms.bool(True),
            ),
        ),
        # finalCut (any string-based cut on pat::Jet)
        finalCut=cms.string('')
    )
    process.jetsForFinalStates = cms.EDProducer(
        "PATJetRanker",
        src=cms.InputTag("jetsFiltered"))

    process.selectObjectsForFinalStates = cms.Sequence(
        process.muonsRank
        + process.muonsForFinalStates
        + process.electronsRank
        + process.electronsForFinalStates
        + process.tausRank
        + process.tausForFinalStates
        + process.jetsFiltered
        + process.jetsForFinalStates
    )
    if not noPhotons:
        process.selectObjectsForFinalStates += process.photonsForFinalStates

    sequence += process.selectObjectsForFinalStates

    # Now build all combinatorics for E/Mu/Tau/Photon
    object_types = [('Elec', cms.InputTag("electronsForFinalStates")),
                    ('Mu', cms.InputTag("muonsForFinalStates")),
                    ('Tau', cms.InputTag("tausForFinalStates")),
                    ('Jet', cms.InputTag("jetsForFinalStates"))]

    if not noPhotons:
        object_types.append(('Pho', cms.InputTag("photonsForFinalStates")))

    process.buildDiObjects = cms.Sequence()


    process.load("FinalStateAnalysis.PatTools."
                 "finalStates.patFinalStatesEmbedExtraCollections_cfi")
    # If we don't have tracks, don't fit the FS vertices
    if noTracks:
        process.patFinalStateVertexFitter.enable = False

    # Build di-object pairs
    for diobject in _combinatorics(object_types, 2):
        # Don't build two jet states
        if (diobject[0][0], diobject[1][0]) == ('Tau', 'Tau'):
            continue
        if (diobject[0][0], diobject[1][0]) == ('Tau', 'Pho'):
            continue
        if (diobject[0][0], diobject[1][0]) == ('Tau', 'Jet'):
            continue
        if (diobject[0][0], diobject[1][0]) == ('Jet', 'Pho'):
            continue
        if (diobject[0][0], diobject[1][0]) == ('Jet', 'Jet'):
            continue

        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3']  # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%sFinalStateProducer" % (diobject[0][0], diobject[1][0]),
            evtSrc=cms.InputTag("patFinalStateEventProducer"),
            leg1Src=diobject[0][1],
            leg2Src=diobject[1][1],
            # X-cleaning
            cut=cms.string(' & '.join(cuts))
        )
        producer_name = "finalState%s%s" % (diobject[0][0], diobject[1][0])
        setattr(process, producer_name + "Raw", producer)
        process.buildDiObjects += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(
            process, process.patFinalStatesEmbedObjects, producer_name)
        process.buildDiObjects += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = cms.EDProducer(
            "PATFinalStateCopier", src=final_module_name)
        setattr(process, producer_name, final_module)
        process.buildDiObjects += final_module
        setattr(process, producer_name, final_module)
        output_commands.append("*_%s_*_*" % producer_name)
    sequence += process.buildDiObjects

    # Build tri-lepton pairs
    process.buildTriObjects = cms.Sequence()
    for triobject in _combinatorics(object_types, 3):
        # Don't build three jet states
        if (triobject[0][0], triobject[1][0], triobject[2][0]) == \
           ('Tau', 'Tau', 'Tau'):
            continue

        n_taus = [x[0] for x in triobject].count('Tau')
        n_phos = [x[0] for x in triobject].count('Pho')
        n_muons = [x[0] for x in triobject].count('Mu')
        n_jets = [x[0] for x in triobject].count('Jet')

        if n_taus > 2:
            continue
        if n_phos > 2:
            continue
        if n_taus and n_phos:
            continue
        if n_jets > 0 and not (n_jets == 2 and n_muons == 1):
            continue

        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3']  # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%s%sFinalStateProducer" %
            (triobject[0][0], triobject[1][0], triobject[2][0]),
            evtSrc=cms.InputTag("patFinalStateEventProducer"),
            leg1Src=triobject[0][1],
            leg2Src=triobject[1][1],
            leg3Src=triobject[2][1],
            # X-cleaning
            cut=cms.string(' & '.join(cuts))
        )
        producer_name = "finalState%s%s%s" % (
            triobject[0][0], triobject[1][0], triobject[2][0])
        #setattr(process, producer_name, producer)
        #process.buildTriLeptons += producer
        setattr(process, producer_name + "Raw", producer)
        process.buildTriObjects += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(
            process, process.patFinalStatesEmbedObjects, producer_name)
        process.buildTriObjects += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = cms.EDProducer(
            "PATFinalStateCopier", src=final_module_name)
        setattr(process, producer_name, final_module)
        process.buildTriObjects += final_module
        output_commands.append("*_%s_*_*" % producer_name)
    sequence += process.buildTriObjects

    # Build 4 lepton final states
    process.buildQuadObjects = cms.Sequence()
    for quadobject in _combinatorics(object_types, 4):
        # Don't build states with more than 2 hadronic taus or phos
        n_taus = [x[0] for x in quadobject].count('Tau')
        n_phos = [x[0] for x in quadobject].count('Pho')
        n_jets = [x[0] for x in quadobject].count('Jet')

        if n_taus > 2:
            continue
        if n_phos > 2:
            continue
        if n_taus and n_phos:
            continue
        if n_jets > 0:
            continue

        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3']  # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%s%s%sFinalStateProducer" %
            (quadobject[0][0], quadobject[1][0], quadobject[2][0],
             quadobject[3][0]),
            evtSrc=cms.InputTag("patFinalStateEventProducer"),
            leg1Src=quadobject[0][1],
            leg2Src=quadobject[1][1],
            leg3Src=quadobject[2][1],
            leg4Src=quadobject[3][1],
            # X-cleaning
            cut=cms.string(' & '.join(cuts))
        )
        producer_name = "finalState%s%s%s%s" % (
            quadobject[0][0], quadobject[1][0], quadobject[2][0],
            quadobject[3][0]
        )
        #setattr(process, producer_name, producer)
        #process.buildTriLeptons += producer
        setattr(process, producer_name + "Raw", producer)
        process.buildQuadObjects += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(
            process, process.patFinalStatesEmbedObjects, producer_name)
        process.buildQuadObjects += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = cms.EDProducer(
            "PATFinalStateCopier", src=final_module_name)
        setattr(process, producer_name, final_module)
        process.buildQuadObjects += final_module
        output_commands.append("*_%s_*_*" % producer_name)
    sequence += process.buildQuadObjects

    # Build 4 lepton final states w/ FSR
    if zzMode:
        zz_object_types = [('Elec', cms.InputTag("electronsForFinalStates")),
                           ('Mu',   cms.InputTag("muonsForFinalStates"))]

        process.buildQuadHzzObjects = cms.Sequence()
        for quadobject in _combinatorics(zz_object_types, 4):
            n_elec = [x[0] for x in quadobject].count('Elec')
            n_muon = [x[0] for x in quadobject].count('Mu')

            if n_elec%2 == 1:
                continue
            if n_muon%2 == 1:
                continue

            # Define some basic selections for building combinations
            cuts = ['smallestDeltaR() > 0.3']  # basic x-cleaning

            producer = cms.EDProducer(
                "PAT%s%s%s%sFinalStateHzzProducer" %
                (quadobject[0][0], quadobject[1][0], quadobject[2][0],
                 quadobject[3][0]),
                evtSrc    = cms.InputTag("patFinalStateEventProducer"),
                leg1Src   = quadobject[0][1],
                leg2Src   = quadobject[1][1],
                leg3Src   = quadobject[2][1],
                leg4Src   = quadobject[3][1],
                photonSrc = cms.InputTag(fsrsrc),
                # X-cleaning
                cut       = cms.string('')
            )
            producer_name = "finalState%s%s%s%sHzz" % (
                quadobject[0][0], quadobject[1][0], quadobject[2][0],
                quadobject[3][0]
            )
            #setattr(process, producer_name, producer)
            #process.buildTriLeptons += producer
            setattr(process, producer_name + "Raw", producer)
            process.buildQuadHzzObjects += producer

            # Embed the other collections
            embedder_seq = helpers.cloneProcessingSnippet(
                process, process.patFinalStatesEmbedObjects, producer_name)

            process.buildQuadHzzObjects += embedder_seq

            # Do some trickery so the final module has a nice output name
            final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
            final_module = cms.EDProducer(
                "PATFinalStateCopier", src=final_module_name)

            setattr(process, producer_name, final_module)
            process.buildQuadHzzObjects += final_module
            output_commands.append("*_%s_*_*" % producer_name)

        sequence += process.buildQuadHzzObjects
def configurePatTuple(process, isMC=True, **kwargs):
    # Stuff we always keep
    output_commands = [
        '*_addPileupInfo_*_*',
        'edmMergeableCounter_*_*_*',
        '*_lumiProducer_*_*',
        '*_particleFlow_*_*',
        '*_offlineBeamSpot_*_*',
        '*_trackCandidates_*_*',
        '*_gsfTrackCandidates_*_*',
        #'*_generalTracks_*_*',
        '*_electronGsfTracks_*_*',
        '*_offlinePrimaryVertices*_*_*',
        '*_ak5PFJets_*_*',
        '*_ak5GenJets_*_*',
        '*_hltTriggerSummaryAOD_*_*',
        'edmTriggerResults_TriggerResults_*_%s' % process.name_(),
        '*_MEtoEDMConverter*_*_%s' % process.name_(),
        'LHEEventProduct_*_*_*',
        'GenEventInfoProduct_generator_*_*',
        '*_kt6PFJetsForRhoComputationVoronoi_rho_*',
        '*_kt6PFJetsForIso_rho_*',
    ]
    # Define our patTuple production sequence
    process.tuplize = cms.Sequence()
    # Only keep interesting genParticles
    process.load("FinalStateAnalysis.RecoTools.genParticleTrimmer_cfi")
    process.genParticles = process.prunedGenParticles.clone()
    if isMC:
        #process.tuplize += process.genParticles
        #output_commands.append('*_genParticles_*_%s' % process.name_())
        output_commands.append('*_genParticles_*_*')

    output_commands.append('*_tauGenJetsSelectorAllHadrons_*_*')
    output_commands.append('*_tauGenJets_*_*')
    output_commands.append('*_ak5GenJets_*_*')
    # Select vertices
    process.load("FinalStateAnalysis.RecoTools.vertexSelection_cff")
    output_commands.append('*_selectedPrimaryVertex_*_*')
    output_commands.append('*_selectPrimaryVerticesQuality_*_*')
    process.tuplize += process.selectPrimaryVertices

    # Run the ZZ recipe for rho
    from RecoJets.JetProducers.kt4PFJets_cfi import kt4PFJets \
            as zzCantDoAnythingRight
    process.kt6PFJetsForIso = zzCantDoAnythingRight.clone(
        rParam = cms.double(0.6),
        doAreaFastjet = cms.bool(True),
        doRhoFastjet = cms.bool(True),
        Rho_EtaMax = cms.double(2.5),
        Ghost_EtaMax = cms.double(2.5),
    )
    process.tuplize += process.kt6PFJetsForIso

    # Rerun tau-ID
    process.load('Configuration/StandardSequences/Services_cff')
    process.load('Configuration/StandardSequences/GeometryIdeal_cff')
    process.load('Configuration/StandardSequences/MagneticField_cff')
    process.load('Configuration/StandardSequences/FrontierConditions_GlobalTag_cff')
    process.load("RecoTauTag.Configuration.RecoPFTauTag_cff")

    # Optimization - remove PFTauTagInfo compatibility layer
    process.recoTauClassicHPSSequence.remove(process.pfRecoTauTagInfoProducer)
    assert(process.combinatoricRecoTaus.modifiers[3].name.value() == 'TTIworkaround')
    del process.combinatoricRecoTaus.modifiers[3]

    process.tuplize += process.recoTauClassicHPSSequence
    ## Run rho computation
    #from RecoJets.Configuration.RecoPFJets_cff import kt6PFJets
    #kt6PFJets.Rho_EtaMax = cms.double(2.5)
    #kt6PFJets.doRhoFastjet = True
    #process.kt6PFJets = kt6PFJets
    #process.tuplize += process.kt6PFJets

    # Run pat default sequence
    process.load("PhysicsTools.PatAlgos.patSequences_cff")
    # Embed PF Isolation in electrons & muons
    pfTools.usePFIso(process)
    # Custom veto cones
    process.elPFIsoValuePU04PFIdPFIso.deposits.vetos = cms.vstring()
    process.elPFIsoValueChargedAll04PFIdPFIso.deposits.vetos = cms.vstring(
        'EcalBarrel:ConeVeto(0.01)','EcalEndcaps:ConeVeto(0.015)')

    # Unembed junk
    process.patMuons.embedCaloMETMuonCorrs = False
    process.patMuons.embedTcMETMuonCorrs = False
    process.patMuons.embedTrack = True
    process.patMuons.pvSrc = cms.InputTag("selectedPrimaryVertex")

    # Do extra electron ID
    process.load("FinalStateAnalysis.PatTools.electrons.electronID_cff")
    process.tuplize += process.recoElectronID
    process.patElectrons.electronIDSources = process.electronIDSources
    process.patElectrons.embedTrack = True

    # Run EGamma electron energy calibration
    process.load("EgammaCalibratedGsfElectrons.CalibratedElectronProducers.calibratedGsfElectrons_cfi")
    process.RandomNumberGeneratorService.calibratedGsfElectrons = cms.PSet(
        initialSeed = cms.untracked.uint32(1), # A frickin billion
        engineName = cms.untracked.string('TRandom3')
    )
    process.calibratedGsfElectrons.inputDataset = kwargs['dataset']
    process.calibratedGsfElectrons.isMC = bool(isMC)
    process.calibratedGsfElectrons.isAOD = True
    process.calibratedGsfElectrons.updateEnergyError = cms.bool(True)
    # Run a sanity check on the calibration configuration.
    from FinalStateAnalysis.PatTools.electrons.patElectronEmbedCalibratedGsf_cfi \
            import validate_egamma_calib_config
    validate_egamma_calib_config(process)

    process.tuplize += process.calibratedGsfElectrons
    # Keep the calibratedGsfElectrons - we embed refs to this into the
    # pat::Electrons
    output_commands.append('*_calibratedGsfElectrons_*_*')

    # Now run PAT
    process.tuplize += process.patDefaultSequence

    # Use HPS taus
    tautools.switchToPFTauHPS(process)
    # Disable tau IsoDeposits
    process.patDefaultSequence.remove(process.patPFTauIsolation)
    process.patTaus.isoDeposits = cms.PSet()
    process.patTaus.userIsolation = cms.PSet()

    # Disable gen match embedding - we keep it in the ntuple
    process.patMuons.embedGenMatch = False
    process.patElectrons.embedGenMatch = False
    process.patTaus.embedGenMatch = False
    process.patTaus.embedGenJetMatch = False

    # Use PFJets and turn on JEC
    jec = [ 'L1FastJet', 'L2Relative', 'L3Absolute' ]
    if not isMC:
        jec.extend([ 'L2L3Residual' ])
    # Use AK5 PFJets
    jettools.switchJetCollection(process,
                                 cms.InputTag('ak5PFJets'),
                                 doJTA = False,
                                 doBTagging = True,
                                 jetCorrLabel = ('AK5PF', jec),
                                 #jetCorrLabel = None,
                                 doType1MET = False,
                                 doJetID = True,
                                 genJetCollection = cms.InputTag("ak5GenJets"))
    process.patJets.embedPFCandidates = False
    process.patJets.embedCaloTowers = False
    process.patJets.embedGenJetMatch = False
    process.patJets.addAssociatedTracks = False
    process.patJets.embedGenPartonMatch = False
    process.patJetCorrFactors.useRho = True
    # Let's use the same rho as in the TauID, so we don't need to do it twice.
    process.patJetCorrFactors.rho = cms.InputTag(
        "kt6PFJetsForRhoComputationVoronoi", "rho")

    # Use PFMEt
    mettools.addPfMET(process)
    if not isMC:
        coreTools.runOnData(process)
        process.patMETsPF.addGenMET = False
    output_commands.append('patJets_selectedPatJets_*_*')

    # Customize/embed all our sequences
    process.load("FinalStateAnalysis.PatTools.patJetProduction_cff")
    # We have to keep all jets (for the MVA MET...)
    process.patJetGarbageRemoval.cut = 'pt > 0'

    final_jet_collection = chain_sequence(
        process.customizeJetSequence, "patJets")
    process.customizeJetSequence.insert(0, process.patJets)
    # Make it a "complete" sequence
    process.customizeJetSequence += process.selectedPatJets
    # We can't mess up the selected pat jets because the taus use them.
    process.selectedPatJets.src = final_jet_collection
    process.patDefaultSequence.replace(process.patJets,
                                       process.customizeJetSequence)

    # Produce the electron collections
    process.load("FinalStateAnalysis.PatTools.patElectronProduction_cff")
    final_electron_collection = chain_sequence(
        process.customizeElectronSequence, "selectedPatElectrons")
    process.tuplize += process.customizeElectronSequence
    process.customizeElectronSequence.insert(0, process.selectedPatElectrons)
    process.patDefaultSequence.replace(process.selectedPatElectrons,
                                       process.customizeElectronSequence)
    # We have to do the pat Jets before the pat electrons since we embed them
    process.customizeElectronSequence.insert(0, process.selectedPatJets)
    process.cleanPatElectrons.src = final_electron_collection
    # The "effective area" calculation needs to know if it is data/mc, etc.
    process.patElectronMVAIsoEmbedding.target = kwargs['target']
    process.patElectronEffectiveAreaEmbedder.target = kwargs['target']

    process.load("FinalStateAnalysis.PatTools.patMuonProduction_cff")
    final_muon_collection = chain_sequence(
        process.customizeMuonSequence, "selectedPatMuons")
    process.customizeMuonSequence.insert(0, process.selectedPatMuons)
    process.patDefaultSequence.replace(process.selectedPatMuons,
                                       process.customizeMuonSequence)
    process.cleanPatMuons.src = final_muon_collection
    # The "effective area" calculation needs to know if it is data/mc, etc.
    process.patMuonMVAIdIsoEmbedding.target = kwargs['target']
    process.patMuonEffectiveAreaEmbedder.target = kwargs['target']

    process.load("FinalStateAnalysis.PatTools.patTauProduction_cff")
    final_tau_collection = chain_sequence(
        process.customizeTauSequence, "selectedPatTaus")
    # Inject into the pat sequence
    process.customizeTauSequence.insert(0, process.selectedPatTaus)
    process.patDefaultSequence.replace(process.selectedPatTaus,
                                       process.customizeTauSequence)
    process.cleanPatTaus.src = final_tau_collection
    # Remove muons and electrons
    process.cleanPatTaus.checkOverlaps.muons.requireNoOverlaps = False
    process.cleanPatTaus.checkOverlaps.electrons.requireNoOverlaps = False
    # Don't apply any prselections
    process.cleanPatTaus.preselection = 'abs(eta) < 2.5 & (pt > 18 | userFloat("jetPt") > 18)'

    # Setup MET production
    process.load("FinalStateAnalysis.PatTools.patMETProduction_cff")
    final_met_collection = chain_sequence(
        process.customizeMETSequence, "patMETsPF")
    process.tuplize += process.customizeMETSequence
    # The MET systematics depend on all other systematics
    process.systematicsMET.tauSrc = cms.InputTag("cleanPatTaus")
    process.systematicsMET.muonSrc = cms.InputTag("cleanPatMuons")
    process.systematicsMET.electronSrc = cms.InputTag("cleanPatElectrons")

    # Keep all the data formats needed for the systematics
    output_commands.append('recoLeafCandidates_*_*_%s'
                           % process.name_())

    # Define the default lepton cleaning
    process.cleanPatElectrons.preselection = cms.string('pt > 5')
    process.cleanPatElectrons.checkOverlaps.muons.requireNoOverlaps = False
    # Make sure we don't kill any good taus by calling them electrons
    # Note that we don't actually remove these overlaps.
    process.cleanPatElectrons.checkOverlaps.taus = cms.PSet(
        src = final_tau_collection,
        algorithm = cms.string("byDeltaR"),
        preselection = cms.string(
            "tauID('decayModeFinding') > 0.5 &&"
            "tauID('byLooseCombinedIsolationDeltaBetaCorr') > 0.5 &&"
            "tauID('againstElectronLoose') > 0.5 && "
            "pt > 10"
        ),
        deltaR = cms.double(0.1),
        checkRecoComponents = cms.bool(False),
        pairCut = cms.string(""),
        requireNoOverlaps = cms.bool(False),
    )

    output_commands.append('*_cleanPatTaus_*_*')
    output_commands.append('*_cleanPatElectrons_*_*')
    output_commands.append('*_cleanPatMuons_*_*')
    output_commands.append('*_%s_*_*' % final_met_collection.value())

    #process.load("PhysicsTools.PatAlgos.triggerLayer1.triggerMatcher_cfi")
    #trigtools.switchOnTriggerMatchEmbedding(process)
    trigtools.switchOnTrigger(process)

    # Build the PATFinalStateEventObject
    process.load("FinalStateAnalysis.PatTools.finalStates.patFinalStateEventProducer_cfi")
    process.patFinalStateEventProducer.electronSrc = final_electron_collection
    process.patFinalStateEventProducer.muonSrc = cms.InputTag("cleanPatMuons")
    process.patFinalStateEventProducer.tauSrc = cms.InputTag("cleanPatTaus")
    process.patFinalStateEventProducer.jetSrc = cms.InputTag("selectedPatJets")
    process.patFinalStateEventProducer.metSrc = final_met_collection
    process.tuplize += process.patFinalStateEventProducer
    output_commands.append('*_patFinalStateEventProducer_*_*')
    process.patFinalStateEventProducer.puTag = cms.string(kwargs['puTag'])

    # Now build the PATFinalStateLS object, which holds LumiSection info.
    process.load(
        "FinalStateAnalysis.PatTools.finalStates.patFinalStateLSProducer_cfi")
    process.tuplize += process.finalStateLS
    output_commands.append('*_finalStateLS_*_*')
    if isMC:
        process.finalStateLS.xSec = kwargs['xSec']

    # Apply some loose PT cuts on the objects we use to create the final states
    # so the combinatorics don't blow up
    process.muonsForFinalStates = cms.EDFilter(
        "PATMuonRefSelector",
        src = cms.InputTag("cleanPatMuons"),
        cut = cms.string('pt > 4'),
        filter = cms.bool(False),
    )

    process.electronsForFinalStates = cms.EDFilter(
        "PATElectronRefSelector",
        src = cms.InputTag("cleanPatElectrons"),
        cut = cms.string('abs(eta) < 2.5 & pt > 4'),
        filter = cms.bool(False),
    )

    # Require that the PT of the jet (either corrected jet or tau)
    # to be greater than 17
    process.tausForFinalStates = cms.EDFilter(
        "PATTauRefSelector",
        src = cms.InputTag("cleanPatTaus"),
        cut = cms.string('abs(eta) < 2.5 & pt > 17 & tauID("decayModeFinding")'),
        filter = cms.bool(False),
    )

    process.selectObjectsForFinalStates = cms.Sequence(
        process.muonsForFinalStates
        + process.electronsForFinalStates
        + process.tausForFinalStates
    )

    process.tuplize += process.selectObjectsForFinalStates

    # Now build all of our DiLeptons and TriLepton final states
    lepton_types = [('Elec', cms.InputTag("electronsForFinalStates")),
                    ('Mu', cms.InputTag("muonsForFinalStates")),
                    ('Tau', cms.InputTag("tausForFinalStates"))]
    #lepton_types = [('Elec', cms.InputTag("cleanPatElectrons")),
                    #('Mu', cms.InputTag("cleanPatMuons")),
                    #('Tau', cms.InputTag("cleanPatTaus"))]

    process.buildDiLeptons = cms.Sequence()

    process.load(
        "FinalStateAnalysis.PatTools.finalStates.patFinalStatesEmbedExtraCollections_cfi")

    # Build di-lepton pairs
    for dilepton in _combinatorics(lepton_types, 2):
        # Don't build two jet states
        if (dilepton[0][0], dilepton[1][0]) == ('Tau', 'Tau'):
            continue

        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3'] # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%sFinalStateProducer" % (dilepton[0][0], dilepton[1][0]),
            evtSrc = cms.InputTag("patFinalStateEventProducer"),
            leg1Src = dilepton[0][1],
            leg2Src = dilepton[1][1],
            # X-cleaning
            cut = cms.string(' & '.join(cuts))
        )
        producer_name = "finalState%s%s" % (dilepton[0][0], dilepton[1][0])
        setattr(process, producer_name + "Raw", producer)
        process.buildDiLeptons += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(process,
            process.patFinalStatesEmbedObjects, producer_name)
        process.buildDiLeptons += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = getattr(process, final_module_name.value())
        final_module.setLabel(producer_name)
        setattr(process, producer_name, final_module)
        output_commands.append("*_%s_*_*" % producer_name)

    process.tuplize += process.buildDiLeptons
    # Build tri-lepton pairs
    process.buildTriLeptons = cms.Sequence()
    for trilepton in _combinatorics(lepton_types, 3):
        # Don't build three jet states
        if (trilepton[0][0], trilepton[1][0], trilepton[2][0]) == \
           ('Tau', 'Tau', 'Tau'):
            continue

        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3'] # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%s%sFinalStateProducer" %
            (trilepton[0][0], trilepton[1][0], trilepton[2][0]),
            evtSrc = cms.InputTag("patFinalStateEventProducer"),
            leg1Src = trilepton[0][1],
            leg2Src = trilepton[1][1],
            leg3Src = trilepton[2][1],
            # X-cleaning
            cut = cms.string(' & '.join(cuts))
        )
        producer_name = "finalState%s%s%s" % (
            trilepton[0][0], trilepton[1][0], trilepton[2][0])
        #setattr(process, producer_name, producer)
        #process.buildTriLeptons += producer
        setattr(process, producer_name + "Raw", producer)
        process.buildTriLeptons += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(process,
            process.patFinalStatesEmbedObjects, producer_name)
        process.buildTriLeptons += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = getattr(process, final_module_name.value())
        final_module.setLabel(producer_name)
        setattr(process, producer_name, final_module)
        output_commands.append("*_%s_*_*" % producer_name)
    process.tuplize += process.buildTriLeptons

    # Build 4 lepton final states
    process.buildQuadLeptons = cms.Sequence()
    for quadlepton in _combinatorics(lepton_types, 4):
        # Don't build states with more than 2 hadronic taus
        if [x[0] for x in quadlepton].count('Tau') > 2:
            continue

        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3'] # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%s%s%sFinalStateProducer" %
            (quadlepton[0][0], quadlepton[1][0], quadlepton[2][0],
             quadlepton[3][0]),
            evtSrc = cms.InputTag("patFinalStateEventProducer"),
            leg1Src = quadlepton[0][1],
            leg2Src = quadlepton[1][1],
            leg3Src = quadlepton[2][1],
            leg4Src = quadlepton[3][1],
            # X-cleaning
            cut = cms.string(' & '.join(cuts))
        )
        producer_name = "finalState%s%s%s%s" % (
            quadlepton[0][0], quadlepton[1][0], quadlepton[2][0],
            quadlepton[3][0]
        )
        #setattr(process, producer_name, producer)
        #process.buildTriLeptons += producer
        setattr(process, producer_name + "Raw", producer)
        process.buildQuadLeptons += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(process,
            process.patFinalStatesEmbedObjects, producer_name)
        process.buildQuadLeptons += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = getattr(process, final_module_name.value())
        final_module.setLabel(producer_name)
        setattr(process, producer_name, final_module)
        output_commands.append("*_%s_*_*" % producer_name)
    process.tuplize += process.buildQuadLeptons

    # Tell the framework to shut up!
    process.load("FWCore.MessageLogger.MessageLogger_cfi")
    process.MessageLogger.cerr.FwkReport.reportEvery = 1000

    return process.tuplize, output_commands
def configurePatTuple(process, isMC=True, **kwargs):
    '''
    Core function for PATTuple production
    '''
    #fix argparser output
    isMC = bool(isMC)

    ########################
    ##                    ##
    ##  PATTuple content  ##
    ##                    ##
    ########################
    # Stuff we always keep
    output_commands = [
        '*_addPileupInfo_*_*',
        'edmMergeableCounter_*_*_*',
        '*_lumiProducer_*_*',
        '*_particleFlow_*_*',
        '*_offlineBeamSpot_*_*',
        '*_generalTracks_*_*',
        '*_electronGsfTracks_*_*',
        '*_gsfElectrons_*_*',
        '*_gsfElectronCores_*_*',
        '*_offlinePrimaryVertices*_*_*',
        '*_ak5GenJets_*_*',
        '*_hltTriggerSummaryAOD_*_*',
        'edmTriggerResults_TriggerResults_*_%s' % process.name_(),
        '*_MEtoEDMConverter*_*_%s' % process.name_(),
        'LHEEventProduct_*_*_*',
        'GenEventInfoProduct_generator_*_*',
        '*_kt6PFJetsForRhoComputationVoronoi_rho_*',
        '*_kt6PFJetsForIso_rho_*',
        '*_kt6PFJets_rho_*',
        '*_kt6PFJetsHZGPho_rho_*',
        '*_kt6PFJetsCentralHZGEle_rho_*',
        '*_kt6PFJetsCentralHZGMu_rho_*',
        '*_kt6PFJetsCentralNeutralHZGMu_rho_*',
        '*_kt6PFJetsCentral_rho_*',
        '*_kt6PFJetsCentralNeutral_rho_*',  # for zz muons
        '*_photonCore_*_*',
        '*_boostedFsrPhotons_*_*',
        # for Zmumu -> embedded samples
        # https://twiki.cern.ch/twiki/bin/view/CMS/MuonTauReplacementRecHit
        '*_generalTracksORG_*_EmbeddedRECO',
        '*_electronGsfTracksORG_*_EmbeddedRECO',
        'double_TauSpinnerReco_TauSpinnerWT_EmbeddedSPIN',
        'double_ZmumuEvtSelEffCorrWeightProducer_weight_EmbeddedRECO',
        'double_muonRadiationCorrWeightProducer_weight_EmbeddedRECO',
        'GenFilterInfo_generator_minVisPtFilter_EmbeddedRECO',
    ]
    # Define our patTuple production sequence
    process.tuplize = cms.Sequence()
    # Only keep interesting genParticles
    process.load("FinalStateAnalysis.RecoTools.genParticleTrimmer_cfi")
    process.genParticles = process.prunedGenParticles.clone()
    if isMC:
        #process.tuplize += process.genParticles
        #output_commands.append('*_genParticles_*_%s' % process.name_())
        output_commands.append('*_genParticles_*_*')

    output_commands.append('*_tauGenJetsSelectorAllHadrons_*_*')
    output_commands.append('*_tauGenJets_*_*')
    output_commands.append('*_ak5GenJets_*_*')

    ########################
    ##                    ##
    ##        PAT         ##
    ##                    ##
    ########################

    # Run pat default sequence
    process.load("PhysicsTools.PatAlgos.patSequences_cff")

    # Embed PF Isolation in electrons & muons
    pfTools.usePFIso(process)
    # Setup H2Tau custom iso definitions
    setup_h2tau_iso(process)
    # Setup hZg custom iso definitions
    add_hZg_iso_needs(process)

    # Now run PAT
    process.tuplize += process.patDefaultSequence

    # Add FSR photons for ZZ analysis
    process.load("FinalStateAnalysis.PatTools.fsrPhotons_cff")
    process.tuplize += process.fsrPhotonSequence

    ########################
    ##        GEN         ##
    ########################

    # Disable gen match embedding - we keep it in the ntuple
    process.patMuons.embedGenMatch = False
    process.patElectrons.embedGenMatch = False
    process.patTaus.embedGenMatch = False
    process.patTaus.embedGenJetMatch = False
    process.patPhotons.embedGenMatch = False
    if not isMC:
        coreTools.runOnData(process)

    ########################
    ##       MUONS        ##
    ########################

    # Unembed junk
    process.patMuons.embedCaloMETMuonCorrs = False
    process.patMuons.embedTcMETMuonCorrs = False
    process.patMuons.embedTrack = True
    process.patMuons.pvSrc = cms.InputTag("selectedPrimaryVertex")

    process.load("FinalStateAnalysis.PatTools.patMuonProduction_cff")
    final_muon_collection = chain_sequence(
        process.customizeMuonSequence, "selectedPatMuons")
    process.customizeMuonSequence.insert(0, process.selectedPatMuons)
    process.patDefaultSequence.replace(process.selectedPatMuons,
                                       process.customizeMuonSequence)
    process.cleanPatMuons.src = final_muon_collection
    process.patMuonRochesterCorrectionEmbedder.isMC = cms.bool(bool(isMC))

    ########################
    ##        TAUS        ##
    ########################

    # Use HPS taus
    tautools.switchToPFTauHPS(process) #this NEEDS a sequence called patDefaultSequence
    # Disable tau IsoDeposits
    process.patDefaultSequence.remove(process.patPFTauIsolation)
    process.patTaus.isoDeposits = cms.PSet()
    process.patTaus.userIsolation = cms.PSet()

    process.load("FinalStateAnalysis.PatTools.patTauProduction_cff")
    # Require all taus to pass decay mode finding and have high PT
    process.patTauGarbageRemoval.cut = cms.string(
        "pt > 17 && abs(eta) < 2.5 && tauID('decayModeFindingNewDMs')")
    final_tau_collection = chain_sequence(
        process.customizeTauSequence, "selectedPatTaus")
    # Inject into the pat sequence
    process.customizeTauSequence.insert(0, process.selectedPatTaus)
    process.patDefaultSequence.replace(process.selectedPatTaus,
                                       process.customizeTauSequence)
    process.cleanPatTaus.src = final_tau_collection
    # Remove muons and electrons
    process.cleanPatTaus.checkOverlaps.muons.requireNoOverlaps = False
    process.cleanPatTaus.checkOverlaps.electrons.requireNoOverlaps = False
    # Cuts already applied by the garbage removal
    process.cleanPatTaus.preselection = ''
    process.cleanPatTaus.finalCut = ''

    ########################
    ##     ELECTRONS      ##
    ########################

    # Use POG recommendations for (these) electron Isos
    process.elPFIsoValueGamma04PFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.08)')
    process.elPFIsoValueGamma04NoPFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.08)')
    process.elPFIsoValueCharged04PFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.015)')
    process.elPFIsoValueCharged04NoPFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.015)')

    # Do extra electron ID
    process.load("FinalStateAnalysis.PatTools.electrons.electronID_cff")
    if cmssw_major_version() == 4:
        process.patDefaultSequence.replace(process.patElectrons,
                                           process.recoElectronID42X +
                                           process.patElectrons)
        process.patElectrons.electronIDSources = process.electronIDSources42X
    else:
        process.patDefaultSequence.replace(process.patElectrons,
                                           process.recoElectronID5YX +
                                           process.patElectrons)
        process.patElectrons.electronIDSources = process.electronIDSources5YX

    process.electronMatch.checkCharge = cms.bool(False)
    process.patElectrons.embedTrack = False
    process.patElectrons.embedPFCandidate = False
    process.patElectrons.embedGsfElectronCore = False
    process.patElectrons.embedSuperCluster = True

    # Produce the electron collections
    process.load("FinalStateAnalysis.PatTools.patElectronProduction_cff")

    # Electron Energy Regression and Calibrations
    process.load(
        "EgammaAnalysis.ElectronTools.electronRegressionEnergyProducer_cfi")
    process.load("EgammaAnalysis.ElectronTools.calibratedPatElectrons_cfi")

    #setup the energy regression for the specific dataset
    if kwargs['eleReg']:
        print "-- Applying Electron Regression and Calibration --"

        process.customizeElectronSequence += process.eleRegressionEnergy
        process.customizeElectronSequence += process.calibratedPatElectrons

        process.eleRegressionEnergy.energyRegressionType = cms.uint32(2)
        process.calibratedPatElectrons.correctionsType = cms.int32(2)

        if isMC:
            process.calibratedPatElectrons.inputDataset = cms.string(
                "Summer12_LegacyPaper")
        else:
            process.calibratedPatElectrons.inputDataset = cms.string(
                "22Jan2013ReReco")

        process.calibratedPatElectrons.combinationType = cms.int32(3)
        process.calibratedPatElectrons.lumiRatio = cms.double(1.0)
        process.calibratedPatElectrons.synchronization = cms.bool(True)
        process.calibratedPatElectrons.isMC = cms.bool(isMC == 1)
        process.calibratedPatElectrons.verbose = cms.bool(False)

    final_electron_collection = chain_sequence(
        process.customizeElectronSequence, "selectedPatElectrons",
        # Some of the EGamma modules have non-standard src InputTags,
        # specify them here.
        ("src", "inputPatElectronsTag", "inputElectronsTag")
    )

    #process.tuplize += process.customizeElectronSequence #why do we need this?
    process.customizeElectronSequence.insert(0, process.selectedPatElectrons)
    process.patDefaultSequence.replace(process.selectedPatElectrons,
                                       process.customizeElectronSequence)
    # We have to do the pat Jets before the pat electrons since we embed them
    process.customizeElectronSequence.insert(0, process.selectedPatJets)

    # Define cleanPatElectrons input collection
    process.cleanPatElectrons.src = final_electron_collection

    # Define the default lepton cleaning
    process.cleanPatElectrons.preselection = cms.string(
        'pt > 5')
    process.cleanPatElectrons.checkOverlaps.muons.requireNoOverlaps = False
    # Make sure we don't kill any good taus by calling them electrons
    # Note that we don't actually remove these overlaps.
    process.cleanPatElectrons.checkOverlaps.taus = cms.PSet(
        src=final_tau_collection,
        algorithm=cms.string("byDeltaR"),
        preselection=cms.string(
            "tauID('decayModeFinding') > 0.5 &&"
            "tauID('byLooseCombinedIsolationDeltaBetaCorr') > 0.5 &&"
            "tauID('againstElectronLoose') > 0.5 && "
            "pt > 10"
        ),
        deltaR=cms.double(0.1),
        checkRecoComponents=cms.bool(False),
        pairCut=cms.string(""),
        requireNoOverlaps=cms.bool(False),
    )

    ########################
    ##        JETS        ##
    ########################

    # Use PFJets and turn on JEC
    jec = ['L1FastJet', 'L2Relative', 'L3Absolute']
    # If we are running on data (not MC), or embedded sample,
    # apply the MC-DATA residual correction.
    if not isMC or kwargs['embedded']:
        jec.extend(['L2L3Residual'])

    # tmp
    # define the b-tag squences for offline reconstruction
    process.load("RecoBTag.SecondaryVertex.secondaryVertex_cff")
    process.load("RecoBTau.JetTagComputer.combinedMVA_cff")
    process.load('RecoVertex/AdaptiveVertexFinder/inclusiveVertexing_cff')
    process.load('RecoBTag/SecondaryVertex/bToCharmDecayVertexMerger_cfi')
    #process.load("PhysicsTools.PatAlgos.patSequences_cff")

    # Define options for BTagging - these are release dependent.
    btag_options = {'doBTagging': True}
    if cmssw_major_version() == 5:
        btag_options['btagInfo'] = [
            'impactParameterTagInfos',
            'secondaryVertexTagInfos',
            'softMuonTagInfos',
            'secondaryVertexNegativeTagInfos',
            'inclusiveSecondaryVertexFinderFilteredTagInfos'
        ]
        btag_options['btagdiscriminators'] = [
            'trackCountingHighEffBJetTags',
            'trackCountingHighPurBJetTags',    
            'simpleSecondaryVertexHighEffBJetTags',
            'simpleSecondaryVertexHighPurBJetTags',
            'simpleInclusiveSecondaryVertexHighEffBJetTags',
            'simpleInclusiveSecondaryVertexHighPurBJetTags',        
            'combinedSecondaryVertexMVABJetTags',
            'combinedSecondaryVertexBJetTags',
            'jetBProbabilityBJetTags', 
            'jetProbabilityBJetTags',   
        ]

    #Avoid embedding
    process.patJets.embedPFCandidates = True
    process.patJets.embedCaloTowers = False
    process.patJets.embedGenJetMatch = True
    process.patJets.addAssociatedTracks = True
    process.patJets.embedGenPartonMatch = True

    # Add AK5chs PFJets
    jettools.addJetCollection(
        process,
        cms.InputTag('ak5PFchsJets'),
        algoLabel = "AK5",
        typeLabel = "PFchs",
        doJTA              = True,
        jetCorrLabel       = ('AK5PFchs', jec),
        doType1MET         = False,
        doL1Cleaning       = False,
        doL1Counters       = False,
        genJetCollection   = cms.InputTag('ak5GenJets'),
        doJetID            = True,
        **btag_options
    )

    # Use AK5 PFJets
    jettools.switchJetCollection(
        process,
        cms.InputTag('ak5PFJets'),
        doJTA=True,
        jetCorrLabel=('AK5PF', jec),
        #jetCorrLabel = None,
        doType1MET=False,
        doJetID=True,
        genJetCollection=cms.InputTag("ak5GenJets"),
        **btag_options
    )

    # Customize/embed all our sequences
    process.load("FinalStateAnalysis.PatTools.patJetProduction_cff")
    helpers.cloneProcessingSnippet( process, process.customizeJetSequence, 'AK5PFchs' )
    process.patJetGarbageRemoval.cut = 'pt > 12'
    final_jet_collection = chain_sequence(
        process.customizeJetSequence, "patJets")
    process.customizeJetSequence.insert(0, process.patJets)
    # Make it a "complete" sequence
    process.customizeJetSequence += process.selectedPatJets
#    process.customizeJetSequence += process.btagging
    # We can't mess up the selected pat jets because the taus use them.
    process.selectedPatJets.src = final_jet_collection
    process.patDefaultSequence.replace(process.patJets,
                                       process.customizeJetSequence)

    process.customizeJetSequenceAK5PFchs.remove( process.patJetsPUIDAK5PFchs )
    process.customizeJetSequenceAK5PFchs.remove( process.pileupJetIdProducerAK5PFchs )
    process.patJetGarbageRemovalAK5PFchs.cut = 'pt > 20'
    process.patJetCorrFactorsAK5PFchs.payload = cms.string('AK5PFchs') 
    final_jetchs_collection = chain_sequence(
        process.customizeJetSequenceAK5PFchs, "patJetsAK5PFchs")
    process.customizeJetSequenceAK5PFchs.insert(0, process.patJetsAK5PFchs)
    # Make it a "complete" sequence
    process.customizeJetSequenceAK5PFchs += process.selectedPatJetsAK5PFchs
    # We can't mess up the selected pat jets because the taus use them.
    process.selectedPatJetsAK5PFchs.src = final_jetchs_collection
    process.selectedPatJetsAK5chsPF  = process.selectedPatJetsAK5PFchs.clone() #that's what we keep
    process.customizeJetSequenceAK5PFchs += process.selectedPatJetsAK5chsPF
    process.patDefaultSequence.replace(process.patJetsAK5PFchs,
                                       process.customizeJetSequenceAK5PFchs)

    output_commands.append('*_selectedPatJets_*_*')
    output_commands.append('*_selectedPatJetsAK5chsPF_*_*')
    output_commands.append('*SecondaryVertexTagInfo*_*_*_*')
    output_commands.append('*TrackIPTagInfo*_*_*_*')
    output_commands.append('*SoftLeptonTagInfo*_*_*_*')
    output_commands.append('*_ak5PFJets_*_*')
    output_commands.append('*_ak5PFchsJets_*_*')

    ########################
    ##        MET         ##
    ########################

    # Use PFMEt
    mettools.addPfMET(process)

    # We cut out a lot of the junky taus and jets - but we need these
    # to correctly apply the MET uncertainties.  So, let's make a
    # non-cleaned version of the jet and tau sequence.
    process.jetsForMetSyst = helpers.cloneProcessingSnippet(
        process, process.customizeJetSequence, 'ForMETSyst')
    process.tausForMetSyst = helpers.cloneProcessingSnippet(
        process, process.customizeTauSequence, 'ForMETSyst')
    # Don't apply any cut for these
    process.patTauGarbageRemovalForMETSyst.cut = ''
    process.patJetGarbageRemovalForMETSyst.cut = ''
    process.tuplize += process.jetsForMetSyst
    process.tuplize += process.tausForMetSyst
    # We have to make our clone of cleanPatTaus separately, since e/mu
    # cleaning is applied - therefore it isn't in the customizeTausSequence.
    process.cleanPatTausForMETSyst = process.cleanPatTaus.clone(
        src=cms.InputTag(process.cleanPatTaus.src.value() + "ForMETSyst"))
    process.cleanPatTausForMETSyst.preselection = ''
    process.cleanPatTausForMETSyst.finalCut = ''
    process.patTausEmbedJetInfoForMETSyst.jetSrc = \
        final_jet_collection.value() + "ForMETSyst"
    process.tuplize += process.cleanPatTausForMETSyst

    # Setup MET production
    process.load("FinalStateAnalysis.PatTools.patMETProduction_cff")
    # The MET systematics depend on all other systematics
    process.systematicsMET.tauSrc = cms.InputTag("cleanPatTausForMETSyst")
    process.systematicsMET.muonSrc = cms.InputTag("cleanPatMuons")
    process.systematicsMET.electronSrc = cms.InputTag("cleanPatElectrons")

    final_met_collection = chain_sequence(
        process.customizeMETSequence, "patMETsPF")
    process.tuplize += process.customizeMETSequence
    process.patMETsPF.addGenMET = bool(isMC)
    output_commands.append('*_%s_*_*' % final_met_collection.value())

    # Make a version with the MVA MET reconstruction method
    process.load("FinalStateAnalysis.PatTools.met.mvaMetOnPatTuple_cff")
    process.tuplize += process.pfMEtMVAsequence
    mva_met_sequence = helpers.cloneProcessingSnippet(
        process, process.customizeMETSequence, "MVA")
    final_mvamet_collection = chain_sequence(
        mva_met_sequence, "patMEtMVA")
    process.tuplize += mva_met_sequence
    output_commands.append('*_%s_*_*' % final_mvamet_collection.value())

    # Keep all the data formats needed for the systematics
    output_commands.append('recoLeafCandidates_*_*_%s'
                           % process.name_())
    # We can drop to jet and tau MET specific products. They were only used for
    # computation of the MET numbers.
    output_commands.append('drop recoLeafCandidates_*ForMETSyst_*_%s'
                           % process.name_())

    ########################
    ##      PHOTONS       ##
    ########################

    #alter the photon matching to accept various fakes
    # and sort matches by d-pt-rel
    if isMC:
        process.photonMatch = cms.EDProducer(
            "MCMatcherByPt",
            src=cms.InputTag("photons"),
            maxDPtRel=cms.double(100.0),
            mcPdgId=cms.vint32(),
            mcStatus=cms.vint32(1),
            resolveByMatchQuality=cms.bool(False),
            maxDeltaR=cms.double(0.3),
            checkCharge=cms.bool(False),
            resolveAmbiguities=cms.bool(True),
            matched=cms.InputTag("genParticles")
        )

    # Setup pat::Photon Production
    process.load("FinalStateAnalysis.PatTools.patPhotonProduction_cff")
    final_photon_collection = chain_sequence(process.customizePhotonSequence,
                                             "selectedPatPhotons")
    #setup PHOSPHOR for a specific dataset
    if cmssw_major_version() == 4:  # for now 2011 = CMSSW42X
        process.patPhotonPHOSPHOREmbedder.year = cms.uint32(2011)
    else:  # 2012 is 5YX
        process.patPhotonPHOSPHOREmbedder.year = cms.uint32(2012)
    process.patPhotonPHOSPHOREmbedder.isMC = cms.bool(bool(isMC))
    #inject photons into pat sequence
    process.customizePhotonSequence.insert(0, process.selectedPatPhotons)
    process.patDefaultSequence.replace(process.selectedPatPhotons,
                                       process.customizePhotonSequence)
    process.cleanPatPhotons.src = final_photon_collection

    ########################
    ##      TRIGGER       ##
    ########################

    trigtools.switchOnTrigger(process)

    #configure the PAT trigger
    if kwargs['HLTprocess']:
        process.patTrigger.processName = cms.string(kwargs['HLTprocess'])
        process.patTriggerEvent.processName = cms.string(kwargs['HLTprocess'])

    ########################
    ##   --------------   ##
    ########################

    output_commands.append('*_cleanPatTaus_*_*')
    output_commands.append('*_cleanPatElectrons_*_*')
    output_commands.append('*_cleanPatMuons_*_*')
    output_commands.append('*_cleanPatPhotons_*_*')

    ########################
    ##                    ##
    ##        FSA         ##
    ##                    ##
    ########################

    # Now build the PATFinalStateLS object, which holds LumiSection info.
    process.load(
        "FinalStateAnalysis.PatTools.finalStates.patFinalStateLSProducer_cfi")
    process.tuplize += process.finalStateLS
    output_commands.append('*_finalStateLS_*_*')
    if isMC:
        process.finalStateLS.xSec = kwargs['xSec']

    # Tell the framework to shut up!
    process.load("FWCore.MessageLogger.MessageLogger_cfi")
    process.MessageLogger.cerr.FwkReport.reportEvery = 1000

    # Which collections are used to build the final states
    fs_daughter_inputs = {
        'electrons':  'cleanPatElectrons',
        'muons':  'cleanPatMuons',
        'taus':  'cleanPatTaus',
        'photons':  'cleanPatPhotons',
        'jets':  'selectedPatJets',
        'pfmet':  final_met_collection,
        'mvamet':  final_mvamet_collection,
    }

    # Setup all the PATFinalState objects
    produce_final_states(process, fs_daughter_inputs, output_commands,
                         process.tuplize, kwargs['puTag'],
                         zzMode=kwargs.get('zzMode', False))

    return process.tuplize, output_commands
def configurePatTuple(process, isMC=True, **kwargs):

    # Stuff we always keep
    output_commands = [
#        '*',
        '*_addPileupInfo_*_*',
        'edmMergeableCounter_*_*_*',
        '*_lumiProducer_*_*',
        '*_particleFlow_*_*',
        '*_offlineBeamSpot_*_*',
        '*_generalTracks_*_*',
        '*_electronGsfTracks_*_*',
        '*_offlinePrimaryVertices*_*_*',
        '*_ak5GenJets_*_*',
        '*_hltTriggerSummaryAOD_*_*',
        'edmTriggerResults_TriggerResults_*_%s' % process.name_(),
        '*_MEtoEDMConverter*_*_%s' % process.name_(),
        'LHEEventProduct_*_*_*',
        'GenEventInfoProduct_generator_*_*',
        '*_kt6PFJetsForRhoComputationVoronoi_rho_*',
        '*_kt6PFJetsForIso_rho_*',
        '*_kt6PFJets_rho_*',
        '*_kt6PFJetsCentralHZGPho_rho_*',
        '*_kt6PFJetsCentralHZGEle_rho_*',
        '*_kt6PFJetsCentralHZGMu_rho_*',
        '*_kt6PFJetsCentralNeutralHZGMu_rho_*',
        '*_kt6PFJetsCentral_rho_*',
        '*_kt6PFJetsCentralNeutral_rho_*', #for zz muons
        '*_photonCore_*_*',
        # for Zmumu -> embedded samples
        '*_generator_weight_*', # 2k11
        "GenFilterInfo_generator_minVisPtFilter_*", #2k12
        '*_genDaughters_*_*',
        '*_boosted*_*_*',
        '*_tmfTracks_*_*',
    ]
    # Define our patTuple production sequence
    process.tuplize = cms.Sequence()
    # Only keep interesting genParticles
    process.load("FinalStateAnalysis.RecoTools.genParticleTrimmer_cfi")
    process.genParticles = process.prunedGenParticles.clone()
    if isMC:
        #process.tuplize += process.genParticles
        #output_commands.append('*_genParticles_*_%s' % process.name_())
        output_commands.append('*_genParticles_*_*')

    output_commands.append('*_tauGenJetsSelectorAllHadrons_*_*')
    output_commands.append('*_tauGenJets_*_*')
    output_commands.append('*_ak5GenJets_*_*')
    # Select vertices
    process.load("FinalStateAnalysis.RecoTools.vertexSelection_cff")
    output_commands.append('*_selectedPrimaryVertex_*_*')
    output_commands.append('*_selectPrimaryVerticesQuality_*_*')
    process.tuplize += process.selectPrimaryVertices

    # Run the ZZ recipe for rho
    from RecoJets.JetProducers.kt4PFJets_cfi import kt4PFJets \
            as zzCantDoAnythingRight

    process.kt6PFJetsForIso = zzCantDoAnythingRight.clone(
        rParam = cms.double(0.6),
        doAreaFastjet = cms.bool(True),
        doRhoFastjet = cms.bool(True),
        Rho_EtaMax = cms.double(2.5),
        Ghost_EtaMax = cms.double(2.5),
    )
    process.tuplize += process.kt6PFJetsForIso

    # Standard services
    process.load('Configuration.StandardSequences.Services_cff')
    # tack on seeds for FSA PATTuple modules
    add_fsa_random_seeds(process)
    
    
    if cmssw_major_version() == 5 and cmssw_minor_version() >= 3: 
        process.load('Configuration.Geometry.GeometryIdeal_cff')
    else:
        process.load('Configuration.StandardSequences.GeometryIdeal_cff')
        
    process.load('Configuration.StandardSequences.MagneticField_cff')
    process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff')

    # Rerun tau ID
    if cmssw_major_version() == 4:
        process.load("RecoTauTag.Configuration.RecoPFTauTag_cff")
        # Optimization - remove PFTauTagInfo compatibility layer
        process.recoTauClassicHPSSequence.remove(process.pfRecoTauTagInfoProducer)
        process.recoTauClassicHPSSequence.remove(process.ak5PFJetTracksAssociatorAtVertex)
        assert(process.combinatoricRecoTaus.modifiers[3].name.value() == 'TTIworkaround')
        del process.combinatoricRecoTaus.modifiers[3]
        # Don't build junky taus below 19 GeV
        process.combinatoricRecoTaus.builders[0].minPtToBuild = cms.double(17)
        process.tuplize += process.recoTauClassicHPSSequence
    else:
        # We can run less tau stuff in 52, since HPS taus already built.
        process.load("RecoTauTag.Configuration.updateHPSPFTaus_cff")
        process.tuplize += process.updateHPSPFTaus

    ## Run rho computation.  Only necessary in 42X
    if cmssw_major_version() == 4:
        from RecoJets.Configuration.RecoPFJets_cff import kt6PFJets
        kt6PFJets.Rho_EtaMax = cms.double(4.4)
        kt6PFJets.doRhoFastjet = True
        process.kt6PFJets = kt6PFJets
        process.tuplize += process.kt6PFJets

    # In 4_X we have to rerun ak5PFJets with area computation enabled.
    if cmssw_major_version() == 4:
        process.load("RecoJets.Configuration.RecoPFJets_cff")
        process.ak5PFJets.doAreaFastjet = True
        process.tuplize += process.ak5PFJets
        # Only keep the new ak5PFJets
        output_commands.append('*_ak5PFJets_*_%s' % process.name_())
    else:
        # Just keep the normal ones
        output_commands.append('*_ak5PFJets_*_*')

    # In the embedded samples, we need to re-run the b-tagging
    if kwargs['embedded']:
       process.load('RecoBTag/Configuration/RecoBTag_cff')
       process.load('RecoJets/JetAssociationProducers/ak5JTA_cff')
       process.ak5JetTracksAssociatorAtVertex.jets   = cms.InputTag("ak5PFJets")
       process.ak5JetTracksAssociatorAtVertex.tracks = cms.InputTag("tmfTracks")
       process.tuplize += process.ak5JetTracksAssociatorAtVertex
       process.tuplize += process.btagging

    # Run pat default sequence
    process.load("PhysicsTools.PatAlgos.patSequences_cff")
    # Embed PF Isolation in electrons & muons
    pfTools.usePFIso(process)
    # Setup H2Tau custom iso definitions
    setup_h2tau_iso(process)
    # Setup hZg custom iso definitions
    add_hZg_iso_needs(process)
    
    # Use POG recommendations for (these) electron Isos
    process.elPFIsoValueGamma04PFIdPFIso.deposits[0].vetos = cms.vstring('EcalEndcaps:ConeVeto(0.08)')
    process.elPFIsoValueGamma04NoPFIdPFIso.deposits[0].vetos = cms.vstring('EcalEndcaps:ConeVeto(0.08)')
    process.elPFIsoValueCharged04PFIdPFIso.deposits[0].vetos = cms.vstring('EcalEndcaps:ConeVeto(0.015)')
    process.elPFIsoValueCharged04NoPFIdPFIso.deposits[0].vetos = cms.vstring('EcalEndcaps:ConeVeto(0.015)')

    # Unembed junk
    process.patMuons.embedCaloMETMuonCorrs = False
    process.patMuons.embedTcMETMuonCorrs = False
    process.patMuons.embedTrack = True
    process.patMuons.pvSrc = cms.InputTag("selectedPrimaryVertex")

    # Do extra electron ID
    process.load("FinalStateAnalysis.PatTools.electrons.electronID_cff")
    process.tuplize += process.recoElectronID
    process.patElectrons.electronIDSources = process.electronIDSources
    process.patElectrons.embedTrack = True

    # Now run PAT
    process.tuplize += process.patDefaultSequence

    # Add FSR photons for ZZ analysis
    process.load("FinalStateAnalysis.PatTools.fsrPhotons_cff")
    process.tuplize += process.fsrPhotonSequence

    # Use HPS taus
    tautools.switchToPFTauHPS(process)
    # Disable tau IsoDeposits
    process.patDefaultSequence.remove(process.patPFTauIsolation)
    process.patTaus.isoDeposits = cms.PSet()
    process.patTaus.userIsolation = cms.PSet()

    # Disable gen match embedding - we keep it in the ntuple
    process.patMuons.embedGenMatch = False
    process.patElectrons.embedGenMatch = False
    process.patTaus.embedGenMatch = False
    process.patTaus.embedGenJetMatch = False

    # Use PFJets and turn on JEC
    jec = [ 'L1FastJet', 'L2Relative', 'L3Absolute' ]
    # If we are running on data (not MC), or embedded sample,
    # apply the MC-DATA residual correction.
    if not isMC or kwargs['embedded']:
        jec.extend([ 'L2L3Residual' ])

    # Define options for BTagging - these are release dependent.
    btag_options = {'doBTagging' : True}
    if cmssw_major_version() == 5:
        btag_options['btagInfo'] = [
            'impactParameterTagInfos',
            'secondaryVertexTagInfos',
            'softMuonTagInfos',
            'secondaryVertexNegativeTagInfos'
        ]
        btag_options['btagdiscriminators'] = [
            'trackCountingHighEffBJetTags',
            'simpleSecondaryVertexHighEffBJetTags',
            'combinedSecondaryVertexMVABJetTags',
            'combinedSecondaryVertexBJetTags',
        ]

    # Use AK5 PFJets
    jettools.switchJetCollection(
        process,
        cms.InputTag('ak5PFJets'),
        doJTA = False,
        jetCorrLabel = ('AK5PF', jec),
        #jetCorrLabel = None,
        doType1MET = False,
        doJetID = True,
        genJetCollection = cms.InputTag("ak5GenJets"),
        **btag_options
    )
    process.patJets.embedPFCandidates = False
    process.patJets.embedCaloTowers = False
    process.patJets.embedGenJetMatch = False
    process.patJets.addAssociatedTracks = False
    process.patJets.embedGenPartonMatch = False
    #process.patJetCorrFactors.useRho = True
    ## Let's use the same rho as in the TauID, so we don't need to do it twice.
    #process.patJetCorrFactors.rho = cms.InputTag(
        #"kt6PFJetsForRhoComputationVoronoi", "rho")

    # Use PFMEt
    mettools.addPfMET(process)
    if not isMC:
        coreTools.runOnData(process)
        process.patMETsPF.addGenMET = False
    output_commands.append('*_selectedPatJets_*_*')

    # Customize/embed all our sequences
    process.load("FinalStateAnalysis.PatTools.patJetProduction_cff")
    # We have to keep all jets (for the MVA MET...)
    process.patJetGarbageRemoval.cut = 'pt > 0'

    final_jet_collection = chain_sequence(
        process.customizeJetSequence, "patJets")
    process.customizeJetSequence.insert(0, process.patJets)
    # Make it a "complete" sequence
    process.customizeJetSequence += process.selectedPatJets
    # We can't mess up the selected pat jets because the taus use them.
    process.selectedPatJets.src = final_jet_collection
    process.patDefaultSequence.replace(process.patJets,
                                       process.customizeJetSequence)

    # Produce the electron collections
    process.load("FinalStateAnalysis.PatTools.patElectronProduction_cff")
    final_electron_collection = chain_sequence(
        process.customizeElectronSequence, "selectedPatElectrons")
    process.tuplize += process.customizeElectronSequence
    process.customizeElectronSequence.insert(0, process.selectedPatElectrons)
    process.patDefaultSequence.replace(process.selectedPatElectrons,
                                       process.customizeElectronSequence)
    # We have to do the pat Jets before the pat electrons since we embed them
    process.customizeElectronSequence.insert(0, process.selectedPatJets)
    process.cleanPatElectrons.src = final_electron_collection
    #setup the energy regression for the specific dataset
    process.patElectronEnergyCorrections.isMC  = cms.bool(bool(isMC))
    process.patElectronEnergyCorrections.isAOD = \
                                               cms.bool(bool(kwargs['isAOD']))
    process.patElectronEnergyCorrections.dataSet = \
                                     cms.string(kwargs['calibrationTarget'])

    process.load("FinalStateAnalysis.PatTools.patMuonProduction_cff")
    final_muon_collection = chain_sequence(
        process.customizeMuonSequence, "selectedPatMuons")
    process.customizeMuonSequence.insert(0, process.selectedPatMuons)
    process.patDefaultSequence.replace(process.selectedPatMuons,
                                       process.customizeMuonSequence)
    process.cleanPatMuons.src = final_muon_collection
    process.patMuonRochesterCorrectionEmbedder.isMC = cms.bool(bool(isMC))
    

    process.load("FinalStateAnalysis.PatTools.patTauProduction_cff")
    final_tau_collection = chain_sequence(
        process.customizeTauSequence, "selectedPatTaus")
    # Inject into the pat sequence
    process.customizeTauSequence.insert(0, process.selectedPatTaus)
    process.patDefaultSequence.replace(process.selectedPatTaus,
                                       process.customizeTauSequence)
    process.cleanPatTaus.src = final_tau_collection
    # Remove muons and electrons
    process.cleanPatTaus.checkOverlaps.muons.requireNoOverlaps = False
    process.cleanPatTaus.checkOverlaps.electrons.requireNoOverlaps = False
    # Apply a loose preselection
    process.cleanPatTaus.preselection = 'abs(eta) < 2.5 & pt > 17'
    # Don't apply any "final" cut
    process.cleanPatTaus.finalCut = ''

    # Setup pat::Photon Production
    process.load("FinalStateAnalysis.PatTools.patPhotonProduction_cff")
    final_photon_collection = chain_sequence(process.customizePhotonSequence,
                                             "selectedPatPhotons")
    #inject photons into pat sequence
    process.customizePhotonSequence.insert(0,process.selectedPatPhotons)
    process.patDefaultSequence.replace(process.selectedPatPhotons,
                                       process.customizePhotonSequence)
    process.cleanPatPhotons.src = final_photon_collection

    # Setup MET production
    process.load("FinalStateAnalysis.PatTools.patMETProduction_cff")
    final_met_collection = chain_sequence(
        process.customizeMETSequence, "patMETsPF")
    process.tuplize += process.customizeMETSequence
    # The MET systematics depend on all other systematics
    process.systematicsMET.tauSrc = cms.InputTag("cleanPatTaus")
    process.systematicsMET.muonSrc = cms.InputTag("cleanPatMuons")
    process.systematicsMET.electronSrc = cms.InputTag("cleanPatElectrons")

    # Keep all the data formats needed for the systematics
    output_commands.append('recoLeafCandidates_*_*_%s'
                           % process.name_())

    # Define the default lepton cleaning
    process.cleanPatElectrons.preselection = cms.string('pt > 5')
    process.cleanPatElectrons.checkOverlaps.muons.requireNoOverlaps = False
    # Make sure we don't kill any good taus by calling them electrons
    # Note that we don't actually remove these overlaps.
    process.cleanPatElectrons.checkOverlaps.taus = cms.PSet(
        src = final_tau_collection,
        algorithm = cms.string("byDeltaR"),
        preselection = cms.string(
            "tauID('decayModeFinding') > 0.5 &&"
            "tauID('byLooseCombinedIsolationDeltaBetaCorr') > 0.5 &&"
            "tauID('againstElectronLoose') > 0.5 && "
            "pt > 10"
        ),
        deltaR = cms.double(0.1),
        checkRecoComponents = cms.bool(False),
        pairCut = cms.string(""),
        requireNoOverlaps = cms.bool(False),
    )

    output_commands.append('*_cleanPatTaus_*_*')
    output_commands.append('*_cleanPatElectrons_*_*')
    output_commands.append('*_cleanPatMuons_*_*')
    output_commands.append('*_cleanPatPhotons_*_*')
    output_commands.append('*_%s_*_*' % final_met_collection.value())

    trigtools.switchOnTrigger(process)

    # Now build the PATFinalStateLS object, which holds LumiSection info.
    process.load(
        "FinalStateAnalysis.PatTools.finalStates.patFinalStateLSProducer_cfi")
    process.tuplize += process.finalStateLS
    output_commands.append('*_finalStateLS_*_*')
    if isMC:
        process.finalStateLS.xSec = kwargs['xSec']

    # Tell the framework to shut up!
    process.load("FWCore.MessageLogger.MessageLogger_cfi")
    process.MessageLogger.cerr.FwkReport.reportEvery = 1000

    # Which collections are used to build the final states
    fs_daughter_inputs = {
        'electrons' : 'cleanPatElectrons',
        'muons' : 'cleanPatMuons',
        'taus' : 'cleanPatTaus',
        'photons' : 'cleanPatPhotons',
        'jets' : 'selectedPatJets',        
        'met' : final_met_collection,
    }

    # Setup all the PATFinalState objects
    produce_final_states(process, fs_daughter_inputs, output_commands,
                         process.tuplize, kwargs['puTag'])

    return process.tuplize, output_commands
def configurePatTuple(process, isMC=True, **kwargs):
    # Stuff we always keep
    output_commands = [
        '*_addPileupInfo_*_*',
        'edmMergeableCounter_*_*_*',
        '*_lumiProducer_*_*',
        '*_particleFlow_*_*',
        '*_offlineBeamSpot_*_*',
        '*_generalTracks_*_*',
        '*_electronGsfTracks_*_*',
        '*_gsfElectrons_*_*',
        '*_gsfElectronCores_*_*',
        '*_offlinePrimaryVertices*_*_*',
        '*_ak5GenJets_*_*',
        '*_hltTriggerSummaryAOD_*_*',
        'edmTriggerResults_TriggerResults_*_%s' % process.name_(),
        '*_MEtoEDMConverter*_*_%s' % process.name_(),
        'LHEEventProduct_*_*_*',
        'GenEventInfoProduct_generator_*_*',
        '*_kt6PFJetsForRhoComputationVoronoi_rho_*',
        '*_kt6PFJetsForIso_rho_*',
        '*_kt6PFJets_rho_*',
        '*_kt6PFJetsHZGPho_rho_*',
        '*_kt6PFJetsCentralHZGEle_rho_*',
        '*_kt6PFJetsCentralHZGMu_rho_*',
        '*_kt6PFJetsCentralNeutralHZGMu_rho_*',
        '*_kt6PFJetsCentral_rho_*',
        '*_kt6PFJetsCentralNeutral_rho_*',  # for zz muons
        '*_photonCore_*_*',
        '*_boostedFsrPhotons_*_*',
        # for Zmumu -> embedded samples
        # https://twiki.cern.ch/twiki/bin/view/CMS/MuonTauReplacementRecHit
        '*_generalTracksORG_*_EmbeddedRECO',
        '*_electronGsfTracksORG_*_EmbeddedRECO',
        'double_TauSpinnerReco_TauSpinnerWT_EmbeddedSPIN',
        'double_ZmumuEvtSelEffCorrWeightProducer_weight_EmbeddedRECO',
        'double_muonRadiationCorrWeightProducer_weight_EmbeddedRECO',
        'GenFilterInfo_generator_minVisPtFilter_EmbeddedRECO',
    ]
    # Define our patTuple production sequence
    process.tuplize = cms.Sequence()
    # Only keep interesting genParticles
    process.load("FinalStateAnalysis.RecoTools.genParticleTrimmer_cfi")
    process.genParticles = process.prunedGenParticles.clone()
    if isMC:
        #process.tuplize += process.genParticles
        #output_commands.append('*_genParticles_*_%s' % process.name_())
        output_commands.append('*_genParticles_*_*')

    output_commands.append('*_tauGenJetsSelectorAllHadrons_*_*')
    output_commands.append('*_tauGenJets_*_*')
    output_commands.append('*_ak5GenJets_*_*')
    # Select vertices
    process.load("FinalStateAnalysis.RecoTools.vertexSelection_cff")
    output_commands.append('*_selectedPrimaryVertex*_*_*')
    output_commands.append('*_selectPrimaryVerticesQuality*_*_*')
    process.tuplize += process.selectPrimaryVertices

    # Run the ZZ recipe for rho
    from RecoJets.JetProducers.kt4PFJets_cfi import kt4PFJets \
        as zzCantDoAnythingRight

    process.kt6PFJetsForIso = zzCantDoAnythingRight.clone(
        rParam=cms.double(0.6),
        doAreaFastjet=cms.bool(True),
        doRhoFastjet=cms.bool(True),
        Rho_EtaMax=cms.double(2.5),
        Ghost_EtaMax=cms.double(2.5),
    )
    process.tuplize += process.kt6PFJetsForIso

    # Standard services
    process.load('Configuration.StandardSequences.Services_cff')
    # tack on seeds for FSA PATTuple modules
    add_fsa_random_seeds(process)

    if cmssw_major_version() == 5 and cmssw_minor_version() >= 3:
        process.load('Configuration.Geometry.GeometryDB_cff')
    else:
        process.load('Configuration.StandardSequences.GeometryDB_cff')

    process.load('Configuration.StandardSequences.MagneticField_cff')
    process.load(
        'Configuration.StandardSequences.FrontierConditions_GlobalTag_cff')

    # Rerun tau ID
    process.load("RecoTauTag.Configuration.RecoPFTauTag_cff")
    # Optimization - remove PFTauTagInfo compatibility layer
    process.recoTauClassicHPSSequence.remove(
        process.pfRecoTauTagInfoProducer)
    process.recoTauClassicHPSSequence.remove(
        process.ak5PFJetTracksAssociatorAtVertex)
    assert(process.combinatoricRecoTaus.modifiers[3].name.value() ==
           'TTIworkaround')
    del process.combinatoricRecoTaus.modifiers[3]
    # Don't build junky taus below 19 GeV
    process.combinatoricRecoTaus.builders[0].minPtToBuild = cms.double(17)
    process.tuplize += process.recoTauClassicHPSSequence

    ## Run rho computation.  Only necessary in 42X
    if cmssw_major_version() == 4:
        # This function call can klobber everything if it isn't done
        # before the other things are attached to the process, so do it now.
        # The klobbering would occur through usePFIso->setupPFIso->_loadPFBRECO
        from CommonTools.ParticleFlow.Tools.pfIsolation import _loadPFBRECO
        _loadPFBRECO(process)
        process.load("RecoJets.Configuration.RecoPFJets_cff")
        process.kt6PFJets.Rho_EtaMax = cms.double(4.4)
        process.kt6PFJets.doRhoFastjet = True
        process.tuplize += process.kt6PFJets

    # In 4_X we have to rerun ak5PFJets with area computation enabled.
    if cmssw_major_version() == 4:
        process.load("RecoJets.Configuration.RecoPFJets_cff")
        process.ak5PFJets.doAreaFastjet = True
        process.tuplize += process.ak5PFJets
        # Only keep the new ak5PFJets
        output_commands.append('*_ak5PFJets_*_%s' % process.name_())
    else:
        # Just keep the normal ones
        output_commands.append('*_ak5PFJets_*_*')

    # Run pat default sequence
    process.load("PhysicsTools.PatAlgos.patSequences_cff")
    # Embed PF Isolation in electrons & muons
    pfTools.usePFIso(process)
    # Setup H2Tau custom iso definitions
    setup_h2tau_iso(process)
    # Setup hZg custom iso definitions
    add_hZg_iso_needs(process)

    #alter the photon matching to accept various fakes
    # and sort matches by d-pt-rel
    if isMC:
        process.photonMatch = cms.EDProducer(
            "MCMatcherByPt",
            src=cms.InputTag("photons"),
            maxDPtRel=cms.double(100.0),
            mcPdgId=cms.vint32(),
            mcStatus=cms.vint32(1),
            resolveByMatchQuality=cms.bool(False),
            maxDeltaR=cms.double(0.3),
            checkCharge=cms.bool(False),
            resolveAmbiguities=cms.bool(True),
            matched=cms.InputTag("genParticles")
        )

    # Use POG recommendations for (these) electron Isos
    process.elPFIsoValueGamma04PFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.08)')
    process.elPFIsoValueGamma04NoPFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.08)')
    process.elPFIsoValueCharged04PFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.015)')
    process.elPFIsoValueCharged04NoPFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.015)')

    # Unembed junk
    process.patMuons.embedCaloMETMuonCorrs = False
    process.patMuons.embedTcMETMuonCorrs = False
    process.patMuons.embedTrack = True
    process.patMuons.pvSrc = cms.InputTag("selectedPrimaryVertex")

    # Do extra electron ID
    process.load("FinalStateAnalysis.PatTools.electrons.electronID_cff")
    if cmssw_major_version() == 4:
        process.patDefaultSequence.replace(process.patElectrons,
                                           process.recoElectronID42X +
                                           process.patElectrons)
        process.patElectrons.electronIDSources = process.electronIDSources42X
    else:
        process.patDefaultSequence.replace(process.patElectrons,
                                           process.recoElectronID5YX +
                                           process.patElectrons)
        process.patElectrons.electronIDSources = process.electronIDSources5YX

    process.electronMatch.checkCharge = cms.bool(False)
    process.patElectrons.embedTrack = False
    process.patElectrons.embedPFCandidate = False
    process.patElectrons.embedGsfElectronCore = False
    process.patElectrons.embedSuperCluster = True

    # Now run PAT
    process.tuplize += process.patDefaultSequence

    # Add FSR photons for ZZ analysis
    process.load("FinalStateAnalysis.PatTools.fsrPhotons_cff")
    process.tuplize += process.fsrPhotonSequence

    # Use HPS taus
    tautools.switchToPFTauHPS(process)
    # Disable tau IsoDeposits
    process.patDefaultSequence.remove(process.patPFTauIsolation)
    process.patTaus.isoDeposits = cms.PSet()
    process.patTaus.userIsolation = cms.PSet()

    # Disable gen match embedding - we keep it in the ntuple
    process.patMuons.embedGenMatch = False
    process.patElectrons.embedGenMatch = False
    process.patTaus.embedGenMatch = False
    process.patTaus.embedGenJetMatch = False
    process.patPhotons.embedGenMatch = False

    # Use PFJets and turn on JEC
    jec = ['L1FastJet', 'L2Relative', 'L3Absolute']
    # If we are running on data (not MC), or embedded sample,
    # apply the MC-DATA residual correction.
    if not isMC or kwargs['embedded']:
        jec.extend(['L2L3Residual'])

    # Define options for BTagging - these are release dependent.
    btag_options = {'doBTagging': True}
    if cmssw_major_version() == 5:
        btag_options['btagInfo'] = [
            'impactParameterTagInfos',
            'secondaryVertexTagInfos',
            'softMuonTagInfos',
            'secondaryVertexNegativeTagInfos'
        ]
        btag_options['btagdiscriminators'] = [
            'trackCountingHighEffBJetTags',
            'simpleSecondaryVertexHighEffBJetTags',
            'combinedSecondaryVertexMVABJetTags',
            'combinedSecondaryVertexBJetTags',
        ]

    # Use AK5 PFJets
    jettools.switchJetCollection(
        process,
        cms.InputTag('ak5PFJets'),
        doJTA=False,
        jetCorrLabel=('AK5PF', jec),
        #jetCorrLabel = None,
        doType1MET=False,
        doJetID=True,
        genJetCollection=cms.InputTag("ak5GenJets"),
        **btag_options
    )
    process.patJets.embedPFCandidates = False
    process.patJets.embedCaloTowers = False
    process.patJets.embedGenJetMatch = False
    process.patJets.addAssociatedTracks = False
    process.patJets.embedGenPartonMatch = False
    #process.patJetCorrFactors.useRho = True
    ## Let's use the same rho as in the TauID, so we don't need to do it twice.
    #process.patJetCorrFactors.rho = cms.InputTag(
        #"kt6PFJetsForRhoComputationVoronoi", "rho")

    # Use PFMEt
    mettools.addPfMET(process)
    if not isMC:
        coreTools.runOnData(process)
        process.patMETsPF.addGenMET = False
    output_commands.append('*_selectedPatJets_*_*')

    # Customize/embed all our sequences
    process.load("FinalStateAnalysis.PatTools.patJetProduction_cff")
    process.patJetGarbageRemoval.cut = 'pt > 12'

    final_jet_collection = chain_sequence(
        process.customizeJetSequence, "patJets")
    process.customizeJetSequence.insert(0, process.patJets)
    # Make it a "complete" sequence
    process.customizeJetSequence += process.selectedPatJets
    # We can't mess up the selected pat jets because the taus use them.
    process.selectedPatJets.src = final_jet_collection
    process.patDefaultSequence.replace(process.patJets,
                                       process.customizeJetSequence)

    # Produce the electron collections
    process.load("FinalStateAnalysis.PatTools.patElectronProduction_cff")

    # Electron Energy Regression and Calibrations
    process.load(
        "EgammaAnalysis.ElectronTools.electronRegressionEnergyProducer_cfi")
    process.load("EgammaAnalysis.ElectronTools.calibratedPatElectrons_cfi")

    #setup the energy regression for the specific dataset
    if kwargs['eleReg']:
        print "-- Applying Electron Regression and Calibration --"

        process.customizeElectronSequence += process.eleRegressionEnergy
        process.customizeElectronSequence += process.calibratedPatElectrons

        process.eleRegressionEnergy.energyRegressionType = cms.uint32(2)
        process.calibratedPatElectrons.correctionsType = cms.int32(2)

        if isMC:
            process.calibratedPatElectrons.inputDataset = cms.string(
                "Summer12_LegacyPaper")
        else:
            process.calibratedPatElectrons.inputDataset = cms.string(
                "22Jan2013ReReco")

        process.calibratedPatElectrons.combinationType = cms.int32(3)
        process.calibratedPatElectrons.lumiRatio = cms.double(1.0)
        process.calibratedPatElectrons.synchronization = cms.bool(True)
        process.calibratedPatElectrons.isMC = cms.bool(isMC == 1)
        process.calibratedPatElectrons.verbose = cms.bool(False)

    final_electron_collection = chain_sequence(
        process.customizeElectronSequence, "selectedPatElectrons",
        # Some of the EGamma modules have non-standard src InputTags,
        # specify them here.
        ("src", "inputPatElectronsTag", "inputElectronsTag")
    )

    process.tuplize += process.customizeElectronSequence
    process.customizeElectronSequence.insert(0, process.selectedPatElectrons)
    process.patDefaultSequence.replace(process.selectedPatElectrons,
                                       process.customizeElectronSequence)
    # We have to do the pat Jets before the pat electrons since we embed them
    process.customizeElectronSequence.insert(0, process.selectedPatJets)

    # Define cleanPatElectrons input collection
    process.cleanPatElectrons.src = final_electron_collection

    process.load("FinalStateAnalysis.PatTools.patMuonProduction_cff")
    final_muon_collection = chain_sequence(
        process.customizeMuonSequence, "selectedPatMuons")
    process.customizeMuonSequence.insert(0, process.selectedPatMuons)
    process.patDefaultSequence.replace(process.selectedPatMuons,
                                       process.customizeMuonSequence)
    process.cleanPatMuons.src = final_muon_collection
    process.patMuonRochesterCorrectionEmbedder.isMC = cms.bool(bool(isMC))

    process.load("FinalStateAnalysis.PatTools.patTauProduction_cff")
    # Require all taus to pass decay mode finding and have high PT
    process.patTauGarbageRemoval.cut = cms.string(
        "pt > 17 && abs(eta) < 2.5 && tauID('decayModeFinding')")
    final_tau_collection = chain_sequence(
        process.customizeTauSequence, "selectedPatTaus")
    # Inject into the pat sequence
    process.customizeTauSequence.insert(0, process.selectedPatTaus)
    process.patDefaultSequence.replace(process.selectedPatTaus,
                                       process.customizeTauSequence)
    process.cleanPatTaus.src = final_tau_collection
    # Remove muons and electrons
    process.cleanPatTaus.checkOverlaps.muons.requireNoOverlaps = False
    process.cleanPatTaus.checkOverlaps.electrons.requireNoOverlaps = False
    # Cuts already applied by the garbage removal
    process.cleanPatTaus.preselection = ''
    process.cleanPatTaus.finalCut = ''

    # Setup pat::Photon Production
    process.load("FinalStateAnalysis.PatTools.patPhotonProduction_cff")
    final_photon_collection = chain_sequence(process.customizePhotonSequence,
                                             "selectedPatPhotons")
    #setup PHOSPHOR for a specific dataset
    if cmssw_major_version() == 4:  # for now 2011 = CMSSW42X
        process.patPhotonPHOSPHOREmbedder.year = cms.uint32(2011)
    else:  # 2012 is 5YX
        process.patPhotonPHOSPHOREmbedder.year = cms.uint32(2012)
    process.patPhotonPHOSPHOREmbedder.isMC = cms.bool(bool(isMC))
    #inject photons into pat sequence
    process.customizePhotonSequence.insert(0, process.selectedPatPhotons)
    process.patDefaultSequence.replace(process.selectedPatPhotons,
                                       process.customizePhotonSequence)
    process.cleanPatPhotons.src = final_photon_collection

    # We cut out a lot of the junky taus and jets - but we need these
    # to correctly apply the MET uncertainties.  So, let's make a
    # non-cleaned version of the jet and tau sequence.
    process.jetsForMetSyst = helpers.cloneProcessingSnippet(
        process, process.customizeJetSequence, 'ForMETSyst')
    process.tausForMetSyst = helpers.cloneProcessingSnippet(
        process, process.customizeTauSequence, 'ForMETSyst')
    # Don't apply any cut for these
    process.patTauGarbageRemovalForMETSyst.cut = ''
    process.patJetGarbageRemovalForMETSyst.cut = ''
    process.tuplize += process.jetsForMetSyst
    process.tuplize += process.tausForMetSyst
    # We have to make our clone of cleanPatTaus separately, since e/mu
    # cleaning is applied - therefore it isn't in the customizeTausSequence.
    process.cleanPatTausForMETSyst = process.cleanPatTaus.clone(
        src=cms.InputTag(process.cleanPatTaus.src.value() + "ForMETSyst"))
    process.cleanPatTausForMETSyst.preselection = ''
    process.cleanPatTausForMETSyst.finalCut = ''
    process.patTausEmbedJetInfoForMETSyst.jetSrc = \
        final_jet_collection.value() + "ForMETSyst"
    process.tuplize += process.cleanPatTausForMETSyst

    # Setup MET production
    process.load("FinalStateAnalysis.PatTools.patMETProduction_cff")
    # The MET systematics depend on all other systematics
    process.systematicsMET.tauSrc = cms.InputTag("cleanPatTausForMETSyst")
    process.systematicsMET.muonSrc = cms.InputTag("cleanPatMuons")
    process.systematicsMET.electronSrc = cms.InputTag("cleanPatElectrons")

    final_met_collection = chain_sequence(
        process.customizeMETSequence, "patMETsPF")
    process.tuplize += process.customizeMETSequence
    output_commands.append('*_%s_*_*' % final_met_collection.value())

    # Make a version with the MVA MET reconstruction method
    process.load("FinalStateAnalysis.PatTools.met.mvaMetOnPatTuple_cff")
    process.tuplize += process.pfMEtMVAsequence
    mva_met_sequence = helpers.cloneProcessingSnippet(
        process, process.customizeMETSequence, "MVA")
    final_mvamet_collection = chain_sequence(
        mva_met_sequence, "patMEtMVA")
    process.tuplize += mva_met_sequence
    output_commands.append('*_%s_*_*' % final_mvamet_collection.value())

    # Keep all the data formats needed for the systematics
    output_commands.append('recoLeafCandidates_*_*_%s'
                           % process.name_())
    # We can drop to jet and tau MET specific products. They were only used for
    # computation of the MET numbers.
    output_commands.append('drop recoLeafCandidates_*ForMETSyst_*_%s'
                           % process.name_())

    # Define the default lepton cleaning
    process.cleanPatElectrons.preselection = cms.string(
        'pt > 5')
    process.cleanPatElectrons.checkOverlaps.muons.requireNoOverlaps = False
    # Make sure we don't kill any good taus by calling them electrons
    # Note that we don't actually remove these overlaps.
    process.cleanPatElectrons.checkOverlaps.taus = cms.PSet(
        src=final_tau_collection,
        algorithm=cms.string("byDeltaR"),
        preselection=cms.string(
            "tauID('decayModeFinding') > 0.5 &&"
            "tauID('byLooseCombinedIsolationDeltaBetaCorr') > 0.5 &&"
            "tauID('againstElectronLoose') > 0.5 && "
            "pt > 10"
        ),
        deltaR=cms.double(0.1),
        checkRecoComponents=cms.bool(False),
        pairCut=cms.string(""),
        requireNoOverlaps=cms.bool(False),
    )

    output_commands.append('*_cleanPatTaus_*_*')
    output_commands.append('*_cleanPatElectrons_*_*')
    output_commands.append('*_cleanPatMuons_*_*')
    output_commands.append('*_cleanPatPhotons_*_*')

    trigtools.switchOnTrigger(process)

    #configure the PAT trigger
    if kwargs['HLTprocess']:
        process.patTrigger.processName = cms.string(kwargs['HLTprocess'])
        process.patTriggerEvent.processName = cms.string(kwargs['HLTprocess'])

    # Now build the PATFinalStateLS object, which holds LumiSection info.
    process.load(
        "FinalStateAnalysis.PatTools.finalStates.patFinalStateLSProducer_cfi")
    process.tuplize += process.finalStateLS
    output_commands.append('*_finalStateLS_*_*')
    if isMC:
        process.finalStateLS.xSec = kwargs['xSec']

    # Tell the framework to shut up!
    process.load("FWCore.MessageLogger.MessageLogger_cfi")
    process.MessageLogger.cerr.FwkReport.reportEvery = 1000

    # Which collections are used to build the final states
    fs_daughter_inputs = {
        'electrons':  'cleanPatElectrons',
        'muons':  'cleanPatMuons',
        'taus':  'cleanPatTaus',
        'photons':  'cleanPatPhotons',
        'jets':  'selectedPatJets',
        'pfmet':  final_met_collection,
        'mvamet':  final_mvamet_collection,
    }

    # Setup all the PATFinalState objects
    produce_final_states(process, fs_daughter_inputs, output_commands,
                         process.tuplize, kwargs['puTag'],
                         zzMode=kwargs.get('zzMode', False))

    return process.tuplize, output_commands
def configurePatTuple(process, isMC=True, **kwargs):
    '''
    Core function for PATTuple production
    '''
    #fix argparser output
    isMC = bool(isMC)

    ########################
    ##                    ##
    ##  PATTuple content  ##
    ##                    ##
    ########################
    # Stuff we always keep
    output_commands = [
        '*_addPileupInfo_*_*',
        'edmMergeableCounter_*_*_*',
        '*_lumiProducer_*_*',
        '*_particleFlow_*_*',
        '*_offlineBeamSpot_*_*',
        '*_generalTracks_*_*',
        '*_electronGsfTracks_*_*',
        '*_gsfElectrons_*_*',
        '*_gsfElectronCores_*_*',
        '*_offlinePrimaryVertices*_*_*',
        '*_ak5GenJets_*_*',
        '*_hltTriggerSummaryAOD_*_*',
        'edmTriggerResults_TriggerResults_*_%s' % process.name_(),
        '*_MEtoEDMConverter*_*_%s' % process.name_(),
        'LHEEventProduct_*_*_*',
        'GenEventInfoProduct_generator_*_*',
        '*_kt6PFJetsForRhoComputationVoronoi_rho_*',
        '*_kt6PFJetsForIso_rho_*',
        '*_kt6PFJets_rho_*',
        '*_kt6PFJetsHZGPho_rho_*',
        '*_kt6PFJetsCentralHZGEle_rho_*',
        '*_kt6PFJetsCentralHZGMu_rho_*',
        '*_kt6PFJetsCentralNeutralHZGMu_rho_*',
        '*_kt6PFJetsCentral_rho_*',
        '*_kt6PFJetsCentralNeutral_rho_*',  # for zz muons
        '*_photonCore_*_*',
        '*_boostedFsrPhotons_*_*',
        # for Zmumu -> embedded samples
        # https://twiki.cern.ch/twiki/bin/view/CMS/MuonTauReplacementRecHit
        '*_generalTracksORG_*_EmbeddedRECO',
        '*_electronGsfTracksORG_*_EmbeddedRECO',
        'double_TauSpinnerReco_TauSpinnerWT_EmbeddedSPIN',
        'double_ZmumuEvtSelEffCorrWeightProducer_weight_EmbeddedRECO',
        'double_muonRadiationCorrWeightProducer_weight_EmbeddedRECO',
        'GenFilterInfo_generator_minVisPtFilter_EmbeddedRECO',
    ]
    # Define our patTuple production sequence
    process.tuplize = cms.Sequence()
    # Only keep interesting genParticles
    process.load("FinalStateAnalysis.RecoTools.genParticleTrimmer_cfi")
    process.genParticles = process.prunedGenParticles.clone()
    if isMC:
        #process.tuplize += process.genParticles
        #output_commands.append('*_genParticles_*_%s' % process.name_())
        output_commands.append('*_genParticles_*_*')

    output_commands.append('*_tauGenJetsSelectorAllHadrons_*_*')
    output_commands.append('*_tauGenJets_*_*')
    output_commands.append('*_ak5GenJets_*_*')

    ########################
    ##                    ##
    ##        PAT         ##
    ##                    ##
    ########################

    # Run pat default sequence
    process.load("PhysicsTools.PatAlgos.patSequences_cff")

    # Embed PF Isolation in electrons & muons
    pfTools.usePFIso(process)
    # Setup H2Tau custom iso definitions
    setup_h2tau_iso(process)
    # Setup hZg custom iso definitions
    add_hZg_iso_needs(process)

    # Now run PAT
    process.tuplize += process.patDefaultSequence

    # Add FSR photons for ZZ analysis
    process.load("FinalStateAnalysis.PatTools.fsrPhotons_cff")
    process.tuplize += process.fsrPhotonSequence

    ########################
    ##        GEN         ##
    ########################

    # Disable gen match embedding - we keep it in the ntuple
    process.patMuons.embedGenMatch = False
    process.patElectrons.embedGenMatch = False
    process.patTaus.embedGenMatch = False
    process.patTaus.embedGenJetMatch = False
    process.patPhotons.embedGenMatch = False
    if not isMC:
        coreTools.runOnData(process)

    ########################
    ##       MUONS        ##
    ########################

    # Unembed junk
    process.patMuons.embedCaloMETMuonCorrs = False
    process.patMuons.embedTcMETMuonCorrs = False
    process.patMuons.embedTrack = True
    process.patMuons.pvSrc = cms.InputTag("selectedPrimaryVertex")

    process.load("FinalStateAnalysis.PatTools.patMuonProduction_cff")
    final_muon_collection = chain_sequence(process.customizeMuonSequence,
                                           "selectedPatMuons")
    process.customizeMuonSequence.insert(0, process.selectedPatMuons)
    process.patDefaultSequence.replace(process.selectedPatMuons,
                                       process.customizeMuonSequence)
    process.cleanPatMuons.src = final_muon_collection
    process.patMuonRochesterCorrectionEmbedder.isMC = cms.bool(bool(isMC))

    ########################
    ##        TAUS        ##
    ########################

    # Use HPS taus
    tautools.switchToPFTauHPS(
        process)  #this NEEDS a sequence called patDefaultSequence
    # Disable tau IsoDeposits
    process.patDefaultSequence.remove(process.patPFTauIsolation)
    process.patTaus.isoDeposits = cms.PSet()
    process.patTaus.userIsolation = cms.PSet()

    process.load("FinalStateAnalysis.PatTools.patTauProduction_cff")
    # Require all taus to pass decay mode finding and have high PT
    process.patTauGarbageRemoval.cut = cms.string(
        "pt > 17 && abs(eta) < 2.5 && tauID('decayModeFindingNewDMs')")
    final_tau_collection = chain_sequence(process.customizeTauSequence,
                                          "selectedPatTaus")
    # Inject into the pat sequence
    process.customizeTauSequence.insert(0, process.selectedPatTaus)
    process.patDefaultSequence.replace(process.selectedPatTaus,
                                       process.customizeTauSequence)
    process.cleanPatTaus.src = final_tau_collection
    # Remove muons and electrons
    process.cleanPatTaus.checkOverlaps.muons.requireNoOverlaps = False
    process.cleanPatTaus.checkOverlaps.electrons.requireNoOverlaps = False
    # Cuts already applied by the garbage removal
    process.cleanPatTaus.preselection = ''
    process.cleanPatTaus.finalCut = ''

    ########################
    ##     ELECTRONS      ##
    ########################

    # Use POG recommendations for (these) electron Isos
    process.elPFIsoValueGamma04PFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.08)')
    process.elPFIsoValueGamma04NoPFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.08)')
    process.elPFIsoValueCharged04PFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.015)')
    process.elPFIsoValueCharged04NoPFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.015)')

    # Do extra electron ID
    process.load("FinalStateAnalysis.PatTools.electrons.electronID_cff")
    if cmssw_major_version() == 4:
        process.patDefaultSequence.replace(
            process.patElectrons,
            process.recoElectronID42X + process.patElectrons)
        process.patElectrons.electronIDSources = process.electronIDSources42X
    else:
        process.patDefaultSequence.replace(
            process.patElectrons,
            process.recoElectronID5YX + process.patElectrons)
        process.patElectrons.electronIDSources = process.electronIDSources5YX

    process.electronMatch.checkCharge = cms.bool(False)
    process.patElectrons.embedTrack = False
    process.patElectrons.embedPFCandidate = False
    process.patElectrons.embedGsfElectronCore = False
    process.patElectrons.embedSuperCluster = True

    # Produce the electron collections
    process.load("FinalStateAnalysis.PatTools.patElectronProduction_cff")

    # Electron Energy Regression and Calibrations
    process.load(
        "EgammaAnalysis.ElectronTools.electronRegressionEnergyProducer_cfi")
    process.load("EgammaAnalysis.ElectronTools.calibratedPatElectrons_cfi")

    #setup the energy regression for the specific dataset
    if kwargs['eleReg']:
        print "-- Applying Electron Regression and Calibration --"

        process.customizeElectronSequence += process.eleRegressionEnergy
        process.customizeElectronSequence += process.calibratedPatElectrons

        process.eleRegressionEnergy.energyRegressionType = cms.uint32(2)
        process.calibratedPatElectrons.correctionsType = cms.int32(2)

        if isMC:
            process.calibratedPatElectrons.inputDataset = cms.string(
                "Summer12_LegacyPaper")
        else:
            process.calibratedPatElectrons.inputDataset = cms.string(
                "22Jan2013ReReco")

        process.calibratedPatElectrons.combinationType = cms.int32(3)
        process.calibratedPatElectrons.lumiRatio = cms.double(1.0)
        process.calibratedPatElectrons.synchronization = cms.bool(True)
        process.calibratedPatElectrons.isMC = cms.bool(isMC == 1)
        process.calibratedPatElectrons.verbose = cms.bool(False)

    final_electron_collection = chain_sequence(
        process.customizeElectronSequence,
        "selectedPatElectrons",
        # Some of the EGamma modules have non-standard src InputTags,
        # specify them here.
        ("src", "inputPatElectronsTag", "inputElectronsTag"))

    #process.tuplize += process.customizeElectronSequence #why do we need this?
    process.customizeElectronSequence.insert(0, process.selectedPatElectrons)
    process.patDefaultSequence.replace(process.selectedPatElectrons,
                                       process.customizeElectronSequence)
    # We have to do the pat Jets before the pat electrons since we embed them
    process.customizeElectronSequence.insert(0, process.selectedPatJets)

    # Define cleanPatElectrons input collection
    process.cleanPatElectrons.src = final_electron_collection

    # Define the default lepton cleaning
    process.cleanPatElectrons.preselection = cms.string('pt > 5')
    process.cleanPatElectrons.checkOverlaps.muons.requireNoOverlaps = False
    # Make sure we don't kill any good taus by calling them electrons
    # Note that we don't actually remove these overlaps.
    process.cleanPatElectrons.checkOverlaps.taus = cms.PSet(
        src=final_tau_collection,
        algorithm=cms.string("byDeltaR"),
        preselection=cms.string(
            "tauID('decayModeFinding') > 0.5 &&"
            "tauID('byLooseCombinedIsolationDeltaBetaCorr') > 0.5 &&"
            "tauID('againstElectronLoose') > 0.5 && "
            "pt > 10"),
        deltaR=cms.double(0.1),
        checkRecoComponents=cms.bool(False),
        pairCut=cms.string(""),
        requireNoOverlaps=cms.bool(False),
    )

    ########################
    ##        JETS        ##
    ########################

    # Use PFJets and turn on JEC
    jec = ['L1FastJet', 'L2Relative', 'L3Absolute']
    # If we are running on data (not MC), or embedded sample,
    # apply the MC-DATA residual correction.
    if not isMC or kwargs['embedded']:
        jec.extend(['L2L3Residual'])

    # tmp
    # define the b-tag squences for offline reconstruction
    process.load("RecoBTag.SecondaryVertex.secondaryVertex_cff")
    process.load("RecoBTau.JetTagComputer.combinedMVA_cff")
    process.load('RecoVertex/AdaptiveVertexFinder/inclusiveVertexing_cff')
    process.load('RecoBTag/SecondaryVertex/bToCharmDecayVertexMerger_cfi')
    #process.load("PhysicsTools.PatAlgos.patSequences_cff")

    # Define options for BTagging - these are release dependent.
    btag_options = {'doBTagging': True}
    if cmssw_major_version() == 5:
        btag_options['btagInfo'] = [
            'impactParameterTagInfos', 'secondaryVertexTagInfos',
            'softMuonTagInfos', 'secondaryVertexNegativeTagInfos',
            'inclusiveSecondaryVertexFinderFilteredTagInfos'
        ]
        btag_options['btagdiscriminators'] = [
            'trackCountingHighEffBJetTags',
            'trackCountingHighPurBJetTags',
            'simpleSecondaryVertexHighEffBJetTags',
            'simpleSecondaryVertexHighPurBJetTags',
            'simpleInclusiveSecondaryVertexHighEffBJetTags',
            'simpleInclusiveSecondaryVertexHighPurBJetTags',
            'combinedSecondaryVertexMVABJetTags',
            'combinedSecondaryVertexBJetTags',
            'jetBProbabilityBJetTags',
            'jetProbabilityBJetTags',
        ]

    #Avoid embedding
    process.patJets.embedPFCandidates = True
    process.patJets.embedCaloTowers = False
    process.patJets.embedGenJetMatch = True
    process.patJets.addAssociatedTracks = True
    process.patJets.embedGenPartonMatch = True

    # Add AK5chs PFJets
    jettools.addJetCollection(process,
                              cms.InputTag('ak5PFchsJets'),
                              algoLabel="AK5",
                              typeLabel="PFchs",
                              doJTA=True,
                              jetCorrLabel=('AK5PFchs', jec),
                              doType1MET=False,
                              doL1Cleaning=False,
                              doL1Counters=False,
                              genJetCollection=cms.InputTag('ak5GenJets'),
                              doJetID=True,
                              **btag_options)

    # Use AK5 PFJets
    jettools.switchJetCollection(
        process,
        cms.InputTag('ak5PFJets'),
        doJTA=True,
        jetCorrLabel=('AK5PF', jec),
        #jetCorrLabel = None,
        doType1MET=False,
        doJetID=True,
        genJetCollection=cms.InputTag("ak5GenJets"),
        **btag_options)

    # Customize/embed all our sequences
    process.load("FinalStateAnalysis.PatTools.patJetProduction_cff")
    helpers.cloneProcessingSnippet(process, process.customizeJetSequence,
                                   'AK5PFchs')
    process.patJetGarbageRemoval.cut = 'pt > 12'
    final_jet_collection = chain_sequence(process.customizeJetSequence,
                                          "patJets")
    process.customizeJetSequence.insert(0, process.patJets)
    # Make it a "complete" sequence
    process.customizeJetSequence += process.selectedPatJets
    #    process.customizeJetSequence += process.btagging
    # We can't mess up the selected pat jets because the taus use them.
    process.selectedPatJets.src = final_jet_collection
    process.patDefaultSequence.replace(process.patJets,
                                       process.customizeJetSequence)

    process.customizeJetSequenceAK5PFchs.remove(process.patJetsPUIDAK5PFchs)
    process.customizeJetSequenceAK5PFchs.remove(
        process.pileupJetIdProducerAK5PFchs)
    process.patJetGarbageRemovalAK5PFchs.cut = 'pt > 20'
    process.patJetCorrFactorsAK5PFchs.payload = cms.string('AK5PFchs')
    final_jetchs_collection = chain_sequence(
        process.customizeJetSequenceAK5PFchs, "patJetsAK5PFchs")
    process.customizeJetSequenceAK5PFchs.insert(0, process.patJetsAK5PFchs)
    # Make it a "complete" sequence
    process.customizeJetSequenceAK5PFchs += process.selectedPatJetsAK5PFchs
    # We can't mess up the selected pat jets because the taus use them.
    process.selectedPatJetsAK5PFchs.src = final_jetchs_collection
    process.selectedPatJetsAK5chsPF = process.selectedPatJetsAK5PFchs.clone(
    )  #that's what we keep
    process.customizeJetSequenceAK5PFchs += process.selectedPatJetsAK5chsPF
    process.patDefaultSequence.replace(process.patJetsAK5PFchs,
                                       process.customizeJetSequenceAK5PFchs)

    output_commands.append('*_selectedPatJets_*_*')
    output_commands.append('*_selectedPatJetsAK5chsPF_*_*')
    output_commands.append('*SecondaryVertexTagInfo*_*_*_*')
    output_commands.append('*TrackIPTagInfo*_*_*_*')
    output_commands.append('*SoftLeptonTagInfo*_*_*_*')
    output_commands.append('*_ak5PFJets_*_*')
    output_commands.append('*_ak5PFchsJets_*_*')

    ########################
    ##        MET         ##
    ########################

    # Use PFMEt
    mettools.addPfMET(process)

    # We cut out a lot of the junky taus and jets - but we need these
    # to correctly apply the MET uncertainties.  So, let's make a
    # non-cleaned version of the jet and tau sequence.
    process.jetsForMetSyst = helpers.cloneProcessingSnippet(
        process, process.customizeJetSequence, 'ForMETSyst')
    process.tausForMetSyst = helpers.cloneProcessingSnippet(
        process, process.customizeTauSequence, 'ForMETSyst')
    # Don't apply any cut for these
    process.patTauGarbageRemovalForMETSyst.cut = ''
    process.patJetGarbageRemovalForMETSyst.cut = ''
    process.tuplize += process.jetsForMetSyst
    process.tuplize += process.tausForMetSyst
    # We have to make our clone of cleanPatTaus separately, since e/mu
    # cleaning is applied - therefore it isn't in the customizeTausSequence.
    process.cleanPatTausForMETSyst = process.cleanPatTaus.clone(
        src=cms.InputTag(process.cleanPatTaus.src.value() + "ForMETSyst"))
    process.cleanPatTausForMETSyst.preselection = ''
    process.cleanPatTausForMETSyst.finalCut = ''
    process.patTausEmbedJetInfoForMETSyst.jetSrc = \
        final_jet_collection.value() + "ForMETSyst"
    process.tuplize += process.cleanPatTausForMETSyst

    # Setup MET production
    process.load("FinalStateAnalysis.PatTools.patMETProduction_cff")
    # The MET systematics depend on all other systematics
    process.systematicsMET.tauSrc = cms.InputTag("cleanPatTausForMETSyst")
    process.systematicsMET.muonSrc = cms.InputTag("cleanPatMuons")
    process.systematicsMET.electronSrc = cms.InputTag("cleanPatElectrons")

    final_met_collection = chain_sequence(process.customizeMETSequence,
                                          "patMETsPF")
    process.tuplize += process.customizeMETSequence
    process.patMETsPF.addGenMET = bool(isMC)
    output_commands.append('*_%s_*_*' % final_met_collection.value())

    # Make a version with the MVA MET reconstruction method
    process.load("FinalStateAnalysis.PatTools.met.mvaMetOnPatTuple_cff")
    process.tuplize += process.pfMEtMVAsequence
    mva_met_sequence = helpers.cloneProcessingSnippet(
        process, process.customizeMETSequence, "MVA")
    final_mvamet_collection = chain_sequence(mva_met_sequence, "patMEtMVA")
    process.tuplize += mva_met_sequence
    output_commands.append('*_%s_*_*' % final_mvamet_collection.value())

    # Keep all the data formats needed for the systematics
    output_commands.append('recoLeafCandidates_*_*_%s' % process.name_())
    # We can drop to jet and tau MET specific products. They were only used for
    # computation of the MET numbers.
    output_commands.append('drop recoLeafCandidates_*ForMETSyst_*_%s' %
                           process.name_())

    ########################
    ##      PHOTONS       ##
    ########################

    #alter the photon matching to accept various fakes
    # and sort matches by d-pt-rel
    if isMC:
        process.photonMatch = cms.EDProducer(
            "MCMatcherByPt",
            src=cms.InputTag("photons"),
            maxDPtRel=cms.double(100.0),
            mcPdgId=cms.vint32(),
            mcStatus=cms.vint32(1),
            resolveByMatchQuality=cms.bool(False),
            maxDeltaR=cms.double(0.3),
            checkCharge=cms.bool(False),
            resolveAmbiguities=cms.bool(True),
            matched=cms.InputTag("genParticles"))

    # Setup pat::Photon Production
    process.load("FinalStateAnalysis.PatTools.patPhotonProduction_cff")
    final_photon_collection = chain_sequence(process.customizePhotonSequence,
                                             "selectedPatPhotons")
    #setup PHOSPHOR for a specific dataset
    if cmssw_major_version() == 4:  # for now 2011 = CMSSW42X
        process.patPhotonPHOSPHOREmbedder.year = cms.uint32(2011)
    else:  # 2012 is 5YX
        process.patPhotonPHOSPHOREmbedder.year = cms.uint32(2012)
    process.patPhotonPHOSPHOREmbedder.isMC = cms.bool(bool(isMC))
    #inject photons into pat sequence
    process.customizePhotonSequence.insert(0, process.selectedPatPhotons)
    process.patDefaultSequence.replace(process.selectedPatPhotons,
                                       process.customizePhotonSequence)
    process.cleanPatPhotons.src = final_photon_collection

    ########################
    ##      TRIGGER       ##
    ########################

    trigtools.switchOnTrigger(process)

    #configure the PAT trigger
    if kwargs['HLTprocess']:
        process.patTrigger.processName = cms.string(kwargs['HLTprocess'])
        process.patTriggerEvent.processName = cms.string(kwargs['HLTprocess'])

    ########################
    ##   --------------   ##
    ########################

    output_commands.append('*_cleanPatTaus_*_*')
    output_commands.append('*_cleanPatElectrons_*_*')
    output_commands.append('*_cleanPatMuons_*_*')
    output_commands.append('*_cleanPatPhotons_*_*')

    ########################
    ##                    ##
    ##        FSA         ##
    ##                    ##
    ########################

    # Now build the PATFinalStateLS object, which holds LumiSection info.
    process.load(
        "FinalStateAnalysis.PatTools.finalStates.patFinalStateLSProducer_cfi")
    process.tuplize += process.finalStateLS
    output_commands.append('*_finalStateLS_*_*')
    if isMC:
        process.finalStateLS.xSec = kwargs['xSec']

    # Tell the framework to shut up!
    process.load("FWCore.MessageLogger.MessageLogger_cfi")
    process.MessageLogger.cerr.FwkReport.reportEvery = 1000

    # Which collections are used to build the final states
    fs_daughter_inputs = {
        'electrons': 'cleanPatElectrons',
        'muons': 'cleanPatMuons',
        'taus': 'cleanPatTaus',
        'photons': 'cleanPatPhotons',
        'jets': 'selectedPatJets',
        'pfmet': final_met_collection,
        'mvamet': final_mvamet_collection,
    }

    # Setup all the PATFinalState objects
    produce_final_states(process,
                         fs_daughter_inputs,
                         output_commands,
                         process.tuplize,
                         kwargs['puTag'],
                         zzMode=kwargs.get('zzMode', False))

    return process.tuplize, output_commands
def configurePatTuple(process, isMC=True, **kwargs):

    # Stuff we always keep
    output_commands = [
        #        '*',
        '*_addPileupInfo_*_*',
        'edmMergeableCounter_*_*_*',
        '*_lumiProducer_*_*',
        '*_particleFlow_*_*',
        '*_offlineBeamSpot_*_*',
        '*_generalTracks_*_*',
        '*_electronGsfTracks_*_*',
        '*_offlinePrimaryVertices*_*_*',
        '*_ak5GenJets_*_*',
        '*_hltTriggerSummaryAOD_*_*',
        'edmTriggerResults_TriggerResults_*_%s' % process.name_(),
        '*_MEtoEDMConverter*_*_%s' % process.name_(),
        'LHEEventProduct_*_*_*',
        'GenEventInfoProduct_generator_*_*',
        '*_kt6PFJetsForRhoComputationVoronoi_rho_*',
        '*_kt6PFJetsForIso_rho_*',
        '*_kt6PFJets_rho_*',
        '*_kt6PFJetsCentralHZGPho_rho_*',
        '*_kt6PFJetsCentralHZGEle_rho_*',
        '*_kt6PFJetsCentralHZGMu_rho_*',
        '*_kt6PFJetsCentralNeutralHZGMu_rho_*',
        '*_kt6PFJetsCentral_rho_*',
        '*_kt6PFJetsCentralNeutral_rho_*',  #for zz muons
        '*_photonCore_*_*',
        # for Zmumu -> embedded samples
        '*_generator_weight_*',  # 2k11
        "GenFilterInfo_generator_minVisPtFilter_*",  #2k12
        '*_genDaughters_*_*',
        '*_boosted*_*_*',
        '*_tmfTracks_*_*',
    ]
    # Define our patTuple production sequence
    process.tuplize = cms.Sequence()
    # Only keep interesting genParticles
    process.load("FinalStateAnalysis.RecoTools.genParticleTrimmer_cfi")
    process.genParticles = process.prunedGenParticles.clone()
    if isMC:
        #process.tuplize += process.genParticles
        #output_commands.append('*_genParticles_*_%s' % process.name_())
        output_commands.append('*_genParticles_*_*')

    output_commands.append('*_tauGenJetsSelectorAllHadrons_*_*')
    output_commands.append('*_tauGenJets_*_*')
    output_commands.append('*_ak5GenJets_*_*')
    # Select vertices
    process.load("FinalStateAnalysis.RecoTools.vertexSelection_cff")
    output_commands.append('*_selectedPrimaryVertex_*_*')
    output_commands.append('*_selectPrimaryVerticesQuality_*_*')
    process.tuplize += process.selectPrimaryVertices

    # Run the ZZ recipe for rho
    from RecoJets.JetProducers.kt4PFJets_cfi import kt4PFJets \
            as zzCantDoAnythingRight

    process.kt6PFJetsForIso = zzCantDoAnythingRight.clone(
        rParam=cms.double(0.6),
        doAreaFastjet=cms.bool(True),
        doRhoFastjet=cms.bool(True),
        Rho_EtaMax=cms.double(2.5),
        Ghost_EtaMax=cms.double(2.5),
    )
    process.tuplize += process.kt6PFJetsForIso

    # Standard services
    process.load('Configuration.StandardSequences.Services_cff')
    # tack on seeds for FSA PATTuple modules
    add_fsa_random_seeds(process)

    if cmssw_major_version() == 5 and cmssw_minor_version() >= 3:
        process.load('Configuration.Geometry.GeometryIdeal_cff')
    else:
        process.load('Configuration.StandardSequences.GeometryIdeal_cff')

    process.load('Configuration.StandardSequences.MagneticField_cff')
    process.load(
        'Configuration.StandardSequences.FrontierConditions_GlobalTag_cff')

    # Rerun tau ID
    if cmssw_major_version() == 4:
        process.load("RecoTauTag.Configuration.RecoPFTauTag_cff")
        # Optimization - remove PFTauTagInfo compatibility layer
        process.recoTauClassicHPSSequence.remove(
            process.pfRecoTauTagInfoProducer)
        process.recoTauClassicHPSSequence.remove(
            process.ak5PFJetTracksAssociatorAtVertex)
        assert (process.combinatoricRecoTaus.modifiers[3].name.value() ==
                'TTIworkaround')
        del process.combinatoricRecoTaus.modifiers[3]
        # Don't build junky taus below 19 GeV
        process.combinatoricRecoTaus.builders[0].minPtToBuild = cms.double(17)
        process.tuplize += process.recoTauClassicHPSSequence
    else:
        # We can run less tau stuff in 52, since HPS taus already built.
        process.load("RecoTauTag.Configuration.updateHPSPFTaus_cff")
        process.tuplize += process.updateHPSPFTaus

    ## Run rho computation.  Only necessary in 42X
    if cmssw_major_version() == 4:
        from RecoJets.Configuration.RecoPFJets_cff import kt6PFJets
        kt6PFJets.Rho_EtaMax = cms.double(4.4)
        kt6PFJets.doRhoFastjet = True
        process.kt6PFJets = kt6PFJets
        process.tuplize += process.kt6PFJets

    # In 4_X we have to rerun ak5PFJets with area computation enabled.
    if cmssw_major_version() == 4:
        process.load("RecoJets.Configuration.RecoPFJets_cff")
        process.ak5PFJets.doAreaFastjet = True
        process.tuplize += process.ak5PFJets
        # Only keep the new ak5PFJets
        output_commands.append('*_ak5PFJets_*_%s' % process.name_())
    else:
        # Just keep the normal ones
        output_commands.append('*_ak5PFJets_*_*')

    # In the embedded samples, we need to re-run the b-tagging
    if kwargs['embedded']:
        process.load('RecoBTag/Configuration/RecoBTag_cff')
        process.load('RecoJets/JetAssociationProducers/ak5JTA_cff')
        process.ak5JetTracksAssociatorAtVertex.jets = cms.InputTag("ak5PFJets")
        process.ak5JetTracksAssociatorAtVertex.tracks = cms.InputTag(
            "tmfTracks")
        process.tuplize += process.ak5JetTracksAssociatorAtVertex
        process.tuplize += process.btagging

    # Run pat default sequence
    process.load("PhysicsTools.PatAlgos.patSequences_cff")
    # Embed PF Isolation in electrons & muons
    pfTools.usePFIso(process)
    # Setup H2Tau custom iso definitions
    setup_h2tau_iso(process)
    # Setup hZg custom iso definitions
    add_hZg_iso_needs(process)

    # Use POG recommendations for (these) electron Isos
    process.elPFIsoValueGamma04PFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.08)')
    process.elPFIsoValueGamma04NoPFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.08)')
    process.elPFIsoValueCharged04PFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.015)')
    process.elPFIsoValueCharged04NoPFIdPFIso.deposits[0].vetos = cms.vstring(
        'EcalEndcaps:ConeVeto(0.015)')

    # Unembed junk
    process.patMuons.embedCaloMETMuonCorrs = False
    process.patMuons.embedTcMETMuonCorrs = False
    process.patMuons.embedTrack = True
    process.patMuons.pvSrc = cms.InputTag("selectedPrimaryVertex")

    # Do extra electron ID
    process.load("FinalStateAnalysis.PatTools.electrons.electronID_cff")
    process.tuplize += process.recoElectronID
    process.patElectrons.electronIDSources = process.electronIDSources
    process.patElectrons.embedTrack = True

    # Now run PAT
    process.tuplize += process.patDefaultSequence

    # Add FSR photons for ZZ analysis
    process.load("FinalStateAnalysis.PatTools.fsrPhotons_cff")
    process.tuplize += process.fsrPhotonSequence

    # Use HPS taus
    tautools.switchToPFTauHPS(process)
    # Disable tau IsoDeposits
    process.patDefaultSequence.remove(process.patPFTauIsolation)
    process.patTaus.isoDeposits = cms.PSet()
    process.patTaus.userIsolation = cms.PSet()

    # Disable gen match embedding - we keep it in the ntuple
    process.patMuons.embedGenMatch = False
    process.patElectrons.embedGenMatch = False
    process.patTaus.embedGenMatch = False
    process.patTaus.embedGenJetMatch = False

    # Use PFJets and turn on JEC
    jec = ['L1FastJet', 'L2Relative', 'L3Absolute']
    # If we are running on data (not MC), or embedded sample,
    # apply the MC-DATA residual correction.
    if not isMC or kwargs['embedded']:
        jec.extend(['L2L3Residual'])

    # Define options for BTagging - these are release dependent.
    btag_options = {'doBTagging': True}
    if cmssw_major_version() == 5:
        btag_options['btagInfo'] = [
            'impactParameterTagInfos', 'secondaryVertexTagInfos',
            'softMuonTagInfos', 'secondaryVertexNegativeTagInfos'
        ]
        btag_options['btagdiscriminators'] = [
            'trackCountingHighEffBJetTags',
            'simpleSecondaryVertexHighEffBJetTags',
            'combinedSecondaryVertexMVABJetTags',
            'combinedSecondaryVertexBJetTags',
        ]

    # Use AK5 PFJets
    jettools.switchJetCollection(
        process,
        cms.InputTag('ak5PFJets'),
        doJTA=False,
        jetCorrLabel=('AK5PF', jec),
        #jetCorrLabel = None,
        doType1MET=False,
        doJetID=True,
        genJetCollection=cms.InputTag("ak5GenJets"),
        **btag_options)
    process.patJets.embedPFCandidates = False
    process.patJets.embedCaloTowers = False
    process.patJets.embedGenJetMatch = False
    process.patJets.addAssociatedTracks = False
    process.patJets.embedGenPartonMatch = False
    #process.patJetCorrFactors.useRho = True
    ## Let's use the same rho as in the TauID, so we don't need to do it twice.
    #process.patJetCorrFactors.rho = cms.InputTag(
    #"kt6PFJetsForRhoComputationVoronoi", "rho")

    # Use PFMEt
    mettools.addPfMET(process)
    if not isMC:
        coreTools.runOnData(process)
        process.patMETsPF.addGenMET = False
    output_commands.append('*_selectedPatJets_*_*')

    # Customize/embed all our sequences
    process.load("FinalStateAnalysis.PatTools.patJetProduction_cff")
    # We have to keep all jets (for the MVA MET...)
    process.patJetGarbageRemoval.cut = 'pt > 0'

    final_jet_collection = chain_sequence(process.customizeJetSequence,
                                          "patJets")
    process.customizeJetSequence.insert(0, process.patJets)
    # Make it a "complete" sequence
    process.customizeJetSequence += process.selectedPatJets
    # We can't mess up the selected pat jets because the taus use them.
    process.selectedPatJets.src = final_jet_collection
    process.patDefaultSequence.replace(process.patJets,
                                       process.customizeJetSequence)

    # Produce the electron collections
    process.load("FinalStateAnalysis.PatTools.patElectronProduction_cff")
    final_electron_collection = chain_sequence(
        process.customizeElectronSequence, "selectedPatElectrons")
    process.tuplize += process.customizeElectronSequence
    process.customizeElectronSequence.insert(0, process.selectedPatElectrons)
    process.patDefaultSequence.replace(process.selectedPatElectrons,
                                       process.customizeElectronSequence)
    # We have to do the pat Jets before the pat electrons since we embed them
    process.customizeElectronSequence.insert(0, process.selectedPatJets)
    process.cleanPatElectrons.src = final_electron_collection
    #setup the energy regression for the specific dataset
    process.patElectronEnergyCorrections.isMC = cms.bool(bool(isMC))
    process.patElectronEnergyCorrections.isAOD = \
                                               cms.bool(bool(kwargs['isAOD']))
    process.patElectronEnergyCorrections.dataSet = \
                                     cms.string(kwargs['calibrationTarget'])

    process.load("FinalStateAnalysis.PatTools.patMuonProduction_cff")
    final_muon_collection = chain_sequence(process.customizeMuonSequence,
                                           "selectedPatMuons")
    process.customizeMuonSequence.insert(0, process.selectedPatMuons)
    process.patDefaultSequence.replace(process.selectedPatMuons,
                                       process.customizeMuonSequence)
    process.cleanPatMuons.src = final_muon_collection
    process.patMuonRochesterCorrectionEmbedder.isMC = cms.bool(bool(isMC))

    process.load("FinalStateAnalysis.PatTools.patTauProduction_cff")
    final_tau_collection = chain_sequence(process.customizeTauSequence,
                                          "selectedPatTaus")
    # Inject into the pat sequence
    process.customizeTauSequence.insert(0, process.selectedPatTaus)
    process.patDefaultSequence.replace(process.selectedPatTaus,
                                       process.customizeTauSequence)
    process.cleanPatTaus.src = final_tau_collection
    # Remove muons and electrons
    process.cleanPatTaus.checkOverlaps.muons.requireNoOverlaps = False
    process.cleanPatTaus.checkOverlaps.electrons.requireNoOverlaps = False
    # Apply a loose preselection
    process.cleanPatTaus.preselection = 'abs(eta) < 2.5 & pt > 17'
    # Don't apply any "final" cut
    process.cleanPatTaus.finalCut = ''

    # Setup pat::Photon Production
    process.load("FinalStateAnalysis.PatTools.patPhotonProduction_cff")
    final_photon_collection = chain_sequence(process.customizePhotonSequence,
                                             "selectedPatPhotons")
    #inject photons into pat sequence
    process.customizePhotonSequence.insert(0, process.selectedPatPhotons)
    process.patDefaultSequence.replace(process.selectedPatPhotons,
                                       process.customizePhotonSequence)
    process.cleanPatPhotons.src = final_photon_collection

    # Setup MET production
    process.load("FinalStateAnalysis.PatTools.patMETProduction_cff")
    final_met_collection = chain_sequence(process.customizeMETSequence,
                                          "patMETsPF")
    process.tuplize += process.customizeMETSequence
    # The MET systematics depend on all other systematics
    process.systematicsMET.tauSrc = cms.InputTag("cleanPatTaus")
    process.systematicsMET.muonSrc = cms.InputTag("cleanPatMuons")
    process.systematicsMET.electronSrc = cms.InputTag("cleanPatElectrons")

    # Keep all the data formats needed for the systematics
    output_commands.append('recoLeafCandidates_*_*_%s' % process.name_())

    # Define the default lepton cleaning
    process.cleanPatElectrons.preselection = cms.string('pt > 5')
    process.cleanPatElectrons.checkOverlaps.muons.requireNoOverlaps = False
    # Make sure we don't kill any good taus by calling them electrons
    # Note that we don't actually remove these overlaps.
    process.cleanPatElectrons.checkOverlaps.taus = cms.PSet(
        src=final_tau_collection,
        algorithm=cms.string("byDeltaR"),
        preselection=cms.string(
            "tauID('decayModeFinding') > 0.5 &&"
            "tauID('byLooseCombinedIsolationDeltaBetaCorr') > 0.5 &&"
            "tauID('againstElectronLoose') > 0.5 && "
            "pt > 10"),
        deltaR=cms.double(0.1),
        checkRecoComponents=cms.bool(False),
        pairCut=cms.string(""),
        requireNoOverlaps=cms.bool(False),
    )

    output_commands.append('*_cleanPatTaus_*_*')
    output_commands.append('*_cleanPatElectrons_*_*')
    output_commands.append('*_cleanPatMuons_*_*')
    output_commands.append('*_cleanPatPhotons_*_*')
    output_commands.append('*_%s_*_*' % final_met_collection.value())

    trigtools.switchOnTrigger(process)

    # Now build the PATFinalStateLS object, which holds LumiSection info.
    process.load(
        "FinalStateAnalysis.PatTools.finalStates.patFinalStateLSProducer_cfi")
    process.tuplize += process.finalStateLS
    output_commands.append('*_finalStateLS_*_*')
    if isMC:
        process.finalStateLS.xSec = kwargs['xSec']

    # Tell the framework to shut up!
    process.load("FWCore.MessageLogger.MessageLogger_cfi")
    process.MessageLogger.cerr.FwkReport.reportEvery = 1000

    # Which collections are used to build the final states
    fs_daughter_inputs = {
        'electrons': 'cleanPatElectrons',
        'muons': 'cleanPatMuons',
        'taus': 'cleanPatTaus',
        'photons': 'cleanPatPhotons',
        'jets': 'selectedPatJets',
        'met': final_met_collection,
    }

    # Setup all the PATFinalState objects
    produce_final_states(process, fs_daughter_inputs, output_commands,
                         process.tuplize, kwargs['puTag'])

    return process.tuplize, output_commands
def produce_final_states(process, collections, output_commands, sequence, puTag,
                         buildFSAEvent=True, noTracks=False):

    muonsrc = collections['muons']
    esrc = collections['electrons']
    tausrc = collections['taus']
    jetsrc = collections['jets']
    metsrc = collections['met']

    # Build the PATFinalStateEventObject
    if buildFSAEvent == True:
        process.load("FinalStateAnalysis.PatTools.finalStates.patFinalStateEventProducer_cfi")
        process.patFinalStateEventProducer.electronSrc = cms.InputTag(esrc)
        process.patFinalStateEventProducer.muonSrc = cms.InputTag(muonsrc)
        process.patFinalStateEventProducer.tauSrc = cms.InputTag(tausrc)
        process.patFinalStateEventProducer.jetSrc = cms.InputTag(jetsrc)
        process.patFinalStateEventProducer.metSrc = metsrc
        process.patFinalStateEventProducer.puTag = cms.string(puTag)
        sequence += process.patFinalStateEventProducer
    elif buildFSAEvent == 'eFix':
        # Temporary workaround for the 2012-05-28 PAT tuples
        # Copy the existing FS Event, but update the electron collection ref.
        process.patFinalStateEventProducer = cms.EDProducer(
            "PATFinalStateElectronFixer",
            fseSrc = cms.InputTag("patFinalStateEventProducer"),
            electronSrc = cms.InputTag(esrc)
        )
        sequence += process.patFinalStateEventProducer

    # Always keep
    output_commands.append('*_patFinalStateEventProducer_*_*')

    # Apply some loose PT cuts on the objects we use to create the final states
    # so the combinatorics don't blow up
    process.muonsForFinalStates = cms.EDFilter(
        "PATMuonRefSelector",
        src = cms.InputTag(muonsrc),
        cut = cms.string('pt > 4'),
        filter = cms.bool(False),
    )

    process.electronsForFinalStates = cms.EDFilter(
        "PATElectronRefSelector",
        src = cms.InputTag(esrc),
        cut = cms.string('abs(eta) < 2.5 & pt > 4'),
        filter = cms.bool(False),
    )

    # Require that the PT of the jet (either corrected jet or tau)
    # to be greater than 17
    process.tausForFinalStates = cms.EDFilter(
        "PATTauRefSelector",
        src = cms.InputTag(tausrc),
        cut = cms.string('abs(eta) < 2.5 & pt > 17 & tauID("decayModeFinding")'),
        filter = cms.bool(False),
    )

    process.selectObjectsForFinalStates = cms.Sequence(
        process.muonsForFinalStates
        + process.electronsForFinalStates
        + process.tausForFinalStates
    )

    sequence += process.selectObjectsForFinalStates

    # Now build all of our DiLeptons and TriLepton final states
    lepton_types = [('Elec', cms.InputTag("electronsForFinalStates")),
                    ('Mu', cms.InputTag("muonsForFinalStates")),
                    ('Tau', cms.InputTag("tausForFinalStates"))]

    process.buildDiLeptons = cms.Sequence()

    process.load(
        "FinalStateAnalysis.PatTools.finalStates.patFinalStatesEmbedExtraCollections_cfi")
    # If we don't have tracks, don't fit the FS vertices
    if noTracks:
        process.patFinalStateVertexFitter.enable = False

    # Build di-lepton pairs
    for dilepton in _combinatorics(lepton_types, 2):
        # Don't build two jet states
        if (dilepton[0][0], dilepton[1][0]) == ('Tau', 'Tau'):
            continue

        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3'] # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%sFinalStateProducer" % (dilepton[0][0], dilepton[1][0]),
            evtSrc = cms.InputTag("patFinalStateEventProducer"),
            leg1Src = dilepton[0][1],
            leg2Src = dilepton[1][1],
            # X-cleaning
            cut = cms.string(' & '.join(cuts))
        )
        producer_name = "finalState%s%s" % (dilepton[0][0], dilepton[1][0])
        setattr(process, producer_name + "Raw", producer)
        process.buildDiLeptons += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(process,
            process.patFinalStatesEmbedObjects, producer_name)
        process.buildDiLeptons += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = cms.EDProducer(
            "PATFinalStateCopier",
            src = final_module_name
        )
        setattr(process, producer_name, final_module)
        process.buildDiLeptons += final_module
        setattr(process, producer_name, final_module)
        output_commands.append("*_%s_*_*" % producer_name)

    sequence += process.buildDiLeptons
    # Build tri-lepton pairs
    process.buildTriLeptons = cms.Sequence()
    for trilepton in _combinatorics(lepton_types, 3):
        # Don't build three jet states
        if (trilepton[0][0], trilepton[1][0], trilepton[2][0]) == \
           ('Tau', 'Tau', 'Tau'):
            continue

        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3'] # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%s%sFinalStateProducer" %
            (trilepton[0][0], trilepton[1][0], trilepton[2][0]),
            evtSrc = cms.InputTag("patFinalStateEventProducer"),
            leg1Src = trilepton[0][1],
            leg2Src = trilepton[1][1],
            leg3Src = trilepton[2][1],
            # X-cleaning
            cut = cms.string(' & '.join(cuts))
        )
        producer_name = "finalState%s%s%s" % (
            trilepton[0][0], trilepton[1][0], trilepton[2][0])
        #setattr(process, producer_name, producer)
        #process.buildTriLeptons += producer
        setattr(process, producer_name + "Raw", producer)
        process.buildTriLeptons += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(process,
            process.patFinalStatesEmbedObjects, producer_name)
        process.buildTriLeptons += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = cms.EDProducer(
            "PATFinalStateCopier",
            src = final_module_name
        )
        setattr(process, producer_name, final_module)
        process.buildTriLeptons += final_module
        output_commands.append("*_%s_*_*" % producer_name)
    sequence += process.buildTriLeptons

    # Build 4 lepton final states
    process.buildQuadLeptons = cms.Sequence()
    for quadlepton in _combinatorics(lepton_types, 4):
        # Don't build states with more than 2 hadronic taus
        if [x[0] for x in quadlepton].count('Tau') > 2:
            continue

        # Define some basic selections for building combinations
        cuts = ['smallestDeltaR() > 0.3'] # basic x-cleaning

        producer = cms.EDProducer(
            "PAT%s%s%s%sFinalStateProducer" %
            (quadlepton[0][0], quadlepton[1][0], quadlepton[2][0],
             quadlepton[3][0]),
            evtSrc = cms.InputTag("patFinalStateEventProducer"),
            leg1Src = quadlepton[0][1],
            leg2Src = quadlepton[1][1],
            leg3Src = quadlepton[2][1],
            leg4Src = quadlepton[3][1],
            # X-cleaning
            cut = cms.string(' & '.join(cuts))
        )
        producer_name = "finalState%s%s%s%s" % (
            quadlepton[0][0], quadlepton[1][0], quadlepton[2][0],
            quadlepton[3][0]
        )
        #setattr(process, producer_name, producer)
        #process.buildTriLeptons += producer
        setattr(process, producer_name + "Raw", producer)
        process.buildQuadLeptons += producer
        # Embed the other collections
        embedder_seq = helpers.cloneProcessingSnippet(process,
            process.patFinalStatesEmbedObjects, producer_name)
        process.buildQuadLeptons += embedder_seq
        # Do some trickery so the final module has a nice output name
        final_module_name = chain_sequence(embedder_seq, producer_name + "Raw")
        final_module = cms.EDProducer(
            "PATFinalStateCopier",
            src = final_module_name
        )
        setattr(process, producer_name, final_module)
        process.buildQuadLeptons += final_module
        output_commands.append("*_%s_*_*" % producer_name)
    sequence += process.buildQuadLeptons