def fillHistosAndCount(histos, files, lls, njs, testRun=False) :
    "Fill the histograms, and provide a dict of event counters[sample][sel] for the summary"
    treename = 'SusySel'
    counts = dict()
    for sample, filename in files.iteritems() :
        countsSample = collections.defaultdict(float)
        histosSample = histos[sample]
        file = r.TFile.Open(filename)
        tree = file.Get(treename)
        nEvents = tree.GetEntries()
        nEventsToProcess = nEvents if not testRun else nEvents/10
        print "processing %s (%d entries %s) %s"%(sample, nEventsToProcess, ", 10% test" if testRun else "", datetime.datetime.now())
        for iEvent, event in enumerate(tree) :
            if iEvent > nEventsToProcess : break
            l0, l1, met, pars = addTlv(event.l0), addTlv(event.l1), addTlv(event.met), event.pars
            jets, lepts = [addTlv(j) for j in event.jets], [addTlv(l) for l in event.lepts]
            ll = getDilepType(l0, l1)
            nJets = len(jets)
            nj = 'eq1j' if nJets==1 else 'ge2j'
            assert nJets>0,"messed something up in the selection upstream"
            if ll not in lls or nj not in njs : continue
            pt0 = l0.p4.Pt()
            pt1 = l1.p4.Pt()
            j0  = jets[0]
            mll  = (l0.p4 + l1.p4).M()
            mtllmet = computeMt(l0.p4 + l1.p4, met.p4)
            ht      = computeHt(met.p4, [l0.p4, l1.p4]+[j.p4 for j in jets])
            metrel  = computeMetRel(met.p4, [l0.p4, l1.p4]+[j.p4 for j in jets])
            mtl0    = computeMt(l0.p4, met.p4)
            mtl1    = computeMt(l1.p4, met.p4)
            mtmin   = min([mtl0, mtl1])
            mtmax   = max([mtl0, mtl1])
            mlj     = computeMlj(l0.p4, l1.p4, j0.p4)
            dphill  = abs(phi_mpi_pi(l0.p4.DeltaPhi(l1.p4)))
            detall  = fabs(l0.p4.Eta() - l1.p4.Eta())
            l3Veto  =  not thirdLepZcandidateIsInWindow(l0, l1, lepts)
            mljj = None
            if nJets >1 :
                j0, j1 = jets[0], jets[1]
                mt2j   = computeMt2j(l0.p4, l1.p4, j0.p4, j1.p4, met.p4)
                mljj   = computeMljj(l0.p4, l1.p4, j0.p4, j1.p4)
                dphijj = fabs(phi_mpi_pi(j0.p4.DeltaPhi(j1.p4)))
                detajj = fabs(j0.p4.Eta() - j1.p4.Eta())
            if passSelection(pt0, pt1, mll, mtllmet, ht, metrel, l3Veto,
                             detall, mtmax, mlj, mljj,
                             ll, nj) :
                llnj = llnjKey(ll, nj)
                weight = pars.weight
                varHistos = histosSample[llnj]
                varValues = dict([(v, eval(v)) for v in variablesToPlot()])
                fillVarHistos(varHistos, varValues, weight, nj)
                countsSample[llnj] += weight
        file.Close()
        file.Delete()
        counts[sample] = countsSample
    return counts
def createOutTree(filenames, dilepChan, nJetChan, tag='', overwrite=False) :
    assert dilepChan in ['ee','mm','em']
    assert nJetChan in ['eq1j', 'ge2j']
    outFilenames = dict()
    for sample, filename in filenames.iteritems() :
        outFilename = '/tmp/'+sample+'_'+dilepChan+'_'+nJetChan+'.root'
        if os.path.exists(outFilename) and not overwrite :
            outFilenames[sample] = outFilename
            continue
        outFile = r.TFile.Open(outFilename, 'recreate')
        outTree = r.TTree("training","Training tree")
        outTree.Branch('vars', vars, '/F:'.join(leafNames))
        outTree.SetDirectory(outFile)
        file = r.TFile.Open(filename)
        tree = file.Get(treename)
        print "processing %s %s %s (%d entries)"%(sample, dilepChan, nJetChan, tree.GetEntries())
        for iEvent, event in enumerate(tree) :
            resetVars(vars)
            l0 = addTlv(event.l0)
            l1 = addTlv(event.l1)
            met = addTlv(event.met)
            jets = [addTlv(j) for j in event.jets]
            lepts = [addTlv(l) for l in event.lepts]
            pars = event.pars
            dilepType = getDilepType(event.l0, event.l1)
            nJets = len(jets)
            if dilepType != dilepChan : continue
            if nJets<1 or (nJets>1 and nJetChan=='eq1j') : continue
            if thirdLepZcandidateIsInWindow(l0, l1, lepts, 20.0) : continue
            mt0, mt1 = computeMt(l0.p4, met.p4), computeMt(l1.p4, met.p4)
            vars.pt0 = l0.p4.Pt()
            vars.pt1 = l1.p4.Pt()
            vars.mll = (l0.p4+l1.p4).M()
            vars.mtmin = min([mt0, mt1])
            vars.mtmax = max([mt0, mt1])
            vars.mtllmet = computeMt(l0.p4 + l1.p4, met.p4)
            vars.ht = computeHt(met.p4, [l0.p4, l1.p4]+[j.p4 for j in jets])
            vars.metrel = computeMetRel(met.p4, [l0.p4, l1.p4]+[j.p4 for j in jets])
            vars.dphill = fabs(phi_mpi_pi(l0.p4.DeltaPhi(l1.p4)))
            vars.detall = fabs(l0.p4.Eta() - l1.p4.Eta())
            if nJets >1 :
                j0, j1 = jets[0], jets[1]
                vars.mt2j = computeMt2j(l0.p4, l1.p4, j0.p4, j1.p4, met.p4)
                vars.mljj = computeMljj(l0.p4, l1.p4, j0.p4, j1.p4)
                vars.dphijj = fabs(phi_mpi_pi(j0.p4.DeltaPhi(j1.p4)))
                vars.detajj = fabs(j0.p4.Eta() - j1.p4.Eta())
            outTree.Fill()
        print "filled ",outTree.GetEntries()," entries"
        outFile.Write()
        outFile.Close()
        outFilenames[sample] = outFile.GetName()
    return outFilenames
def fillHistos() :
    filenames = getInputFiles()
    hs_nlep = dict()
    hs_nillep = dict()
    hs_npairs = dict()
    hs_masses = dict()
    hs_bestm = dict()
    hs_bestlpt = dict()
    hs_bestleta= dict()
    hs_bestdphi= dict()
    hs_bestdrj = dict()
    for sample, filename in filenames.iteritems() :
        file = r.TFile.Open(filename)
        tree = file.Get(treename)
        print "processing %s (%d entries)"%(sample, tree.GetEntries())
        iEvent = 0
        h_nlep   = r.TH1F('h_nlep_'+sample, '; N_{lep, low-p_{T}};entries/bin', 5, -0.5, 4.5)
        h_nillep = r.TH1F('h_nillep_'+sample,
                          'separated from signal leptons; N_{lep, iso-lep, low-p_{T}};entries/bin',
                          5, -0.5, 4.5)
        h_npairs  = r.TH1F('h_npairs_'+sample, '; N_{valid pairs}; entries/bin', 5, -0.5, 4.5)
        h_masses  = r.TH1F('h_masses_'+sample, '; m_{ll}, any valid pair [GeV]; entries/bin', 25, 0.0, 200.0)
        h_bestm   = r.TH1F('h_bestm_'+sample, '; m_{ll}, best pair [GeV]; entries/bin', 25, 0.0, 200.0)
        h_bestlpt = r.TH1F('h_bestlpt_'+sample, '; p_{T}, best soft lepton [GeV]; entries/bin', 25, 0.0, 200.0)
        h_bestleta= r.TH1F('h_bestleta_'+sample, '; #eta, best soft lepton; entries/bin', 25, -3.0, +3.0)
        h_bestdphi= r.TH1F('h_bestdphi'+sample, '; |#Delta#phi(l_{hard},l_{soft})|, best pair [rad]; entries/bin',
                           25, 0.0, +2.*math.pi)
        h_bestdrj = r.TH1F('h_bestdrj'+sample, '; min#DeltaR(l_{soft}), best soft lep; entries/bin',
                           20, 0.0, 2.0)
        for event in tree :
            l0 = addTlv(event.l0)
            l1 = addTlv(event.l1)
            met = addTlv(event.met)
            jets = [addTlv(j) for j in event.jets]
            lepts = [addTlv(l) for l in event.lepts]
            pars = event.pars
            weight, evtN, runN = pars.weight, pars.eventNumber, pars.runNumber
            h_nlep.Fill(float(len(lepts)), weight)
            if len(lepts) < 1 : continue
            lepts = filter(lambda l : lepIsSeparatedFromOther(l.p4, [l0.p4, l1.p4]), lepts)
            h_nillep.Fill(float(len(lepts)), weight)
            validPairs = [(lh, ls) for lh in [l0, l1] for ls in lepts if lepPairIsZcand(lh, ls)]
            h_npairs.Fill(float(len(validPairs)), weight)
            pairsSortedByBestM = sorted(validPairs, key=deltaMZ0)
            for i,(lh,ls) in enumerate(pairsSortedByBestM) :
                m = (lh.p4+ls.p4).M()
                h_masses.Fill(m, weight)
                if i==0 :
                    h_bestm.Fill(m, weight)
                    h_bestlpt.Fill(ls.p4.Pt(), weight)
                    h_bestleta.Fill(ls.p4.Eta(), weight)
                    h_bestdphi.Fill(abs(phi_mpi_pi(ls.p4.DeltaPhi(lh.p4))), weight)
                    if len(jets) :
                        minDrJ = sorted([ls.p4.DeltaR(j.p4) for j in jets])[0]
                        h_bestdrj.Fill(minDrJ, weight)
            if iEvent<10 : print "jets [%d], lepts[%d]"%(len(jets), len(lepts))
            iEvent += 1
        hs_nlep    [sample] = h_nlep
        hs_nillep  [sample] = h_nillep
        hs_npairs  [sample] = h_npairs
        hs_masses  [sample] = h_masses
        hs_bestm   [sample] = h_bestm
        hs_bestlpt [sample] = h_bestlpt
        hs_bestleta[sample] = h_bestleta
        hs_bestdphi[sample] = h_bestdphi
        hs_bestdrj [sample] = h_bestdrj
    return {'hs_nlep'    : hs_nlep,
            'hs_nillep'  : hs_nillep,
            'hs_npairs'  : hs_npairs,
            'hs_masses'  : hs_masses,
            'hs_bestm'   : hs_bestm,
            'hs_bestlpt' : hs_bestlpt,
            'hs_bestleta': hs_bestleta,
            'hs_bestdphi': hs_bestdphi,
            'hs_bestdrj' : hs_bestdrj
            }