def analyze(self, E, PARAMS=None):
    if self.TRIGGER and self.SP is not None:
        if not Selections.passedTrigger(E): return

    Event = E.getPrimitives('EVENT')

    # take 10% of data: event numbers ending in 7
    if 'DoubleMuon' in self.NAME and not self.ARGS.IDPHI:
        if Event.event % 10 != 7: return

    DSAmuons = E.getPrimitives('DSAMUON')
    PATmuons = E.getPrimitives('PATMUON')
    Dimuons3 = E.getPrimitives('DIMUON')

    BASECUTS = '_Combined_REP_PC'

    eventWeight = 1.
    try:
        eventWeight = 1. if Event.weight > 0. else -1.
    except:
        pass

    def nDSA(selDims):
        return len([d for d in selDims if d.composition == 'DSA'])

    selectedDimuons, selectedDSAmuons, selectedPATmuons = Selector.SelectObjects(E, BASECUTS, Dimuons3, DSAmuons, PATmuons, bumpFPTE=self.ARGS.BUMPFPTE)
    if selectedDimuons is not None:

        self.seqCounts['none'] += 1
        self.HISTS['SEQ'].Fill(0., eventWeight)

        self.DSAseqCounts['none'] += nDSA(selectedDimuons)
        self.HISTS['DSA-SEQ'].Fill(0., eventWeight*nDSA(selectedDimuons))

    for idx, omit in enumerate(CUTS):
        CUTSTRING = BASECUTS + '_' + '_'.join([c for c in CUTS if c != omit])
        selectedDimuons, selectedDSAmuons, selectedPATmuons = Selector.SelectObjects(E, CUTSTRING, Dimuons3, DSAmuons, PATmuons, bumpFPTE=self.ARGS.BUMPFPTE)
        if selectedDimuons is not None:
            self.omitCounts[omit] += 1
            self.HISTS['NM1'].Fill(idx+1., eventWeight)

            self.DSAomitCounts[omit] += nDSA(selectedDimuons)
            self.HISTS['DSA-NM1'].Fill(idx+1., eventWeight*nDSA(selectedDimuons))

    for idx in range(len(CUTS)):
        CUTSTRING = BASECUTS + '_' + '_'.join(CUTS[:idx+1])
        selectedDimuons, selectedDSAmuons, selectedPATmuons = Selector.SelectObjects(E, CUTSTRING, Dimuons3, DSAmuons, PATmuons, bumpFPTE=self.ARGS.BUMPFPTE)
        if selectedDimuons is not None:
            self.seqCounts[CUTS[idx]] += 1
            self.HISTS['SEQ'].Fill(idx+1., eventWeight)

            self.DSAseqCounts[CUTS[idx]] += nDSA(selectedDimuons)
            self.HISTS['DSA-SEQ'].Fill(idx+1., eventWeight*nDSA(selectedDimuons))

            if idx == len(CUTS)-1:
                self.omitCounts['none'] += 1
                self.HISTS['NM1'].Fill(0., eventWeight)

                self.DSAomitCounts['none'] += nDSA(selectedDimuons)
                self.HISTS['DSA-NM1'].Fill(0., eventWeight*nDSA(selectedDimuons))
Exemple #2
0
def analyze(self, E, PARAMS=None):
    if self.TRIGGER and self.SP is not None:
        if not Selections.passedTrigger(E): return

    Event = E.getPrimitives('EVENT')

    # take 10% of data: event numbers ending in 7
    if 'DoubleMuon' in self.NAME and '_IDPHI' not in self.CUTS:
        if Event.event % 10 != 7: return

    DSAmuons = E.getPrimitives('DSAMUON')
    PATmuons = E.getPrimitives('PATMUON')
    Dimuons3 = E.getPrimitives('DIMUON')

    eventWeight = 1.
    try:
        eventWeight = 1. if Event.weight > 0. else -1.
    except:
        pass

    selectedDimuons, selectedDSAmuons, selectedPATmuons = Selector.SelectObjects(
        E, '_Combined_NS_NH_FPTE_HLT_PT', Dimuons3, DSAmuons, PATmuons)
    if selectedDimuons is not None:
        for dim in selectedDimuons:
            if dim.composition != 'DSA': continue
            self.HISTS['Lxy-before'].Fill(dim.Lxy(), eventWeight)
            self.HISTS['LxySig-before'].Fill(dim.LxySig(), eventWeight)

    selectedDimuons, selectedDSAmuons, selectedPATmuons = Selector.SelectObjects(
        E, '_Combined_NS_NH_FPTE_HLT_REP_PT', Dimuons3, DSAmuons, PATmuons)
    if selectedDimuons is not None:
        for dim in selectedDimuons:
            if dim.composition != 'DSA': continue
            self.HISTS['Lxy-after'].Fill(dim.Lxy(), eventWeight)
            self.HISTS['LxySig-after'].Fill(dim.LxySig(), eventWeight)
Exemple #3
0
def analyze(self, E, PARAMS=None):
    if self.TRIGGER and self.SP is not None:
        if not Selections.passedTrigger(E): return
    DSAmuons = E.getPrimitives('DSAMUON')
    PATmuons = E.getPrimitives('PATMUON')
    Dimuons3 = E.getPrimitives('DIMUON')
    Event    = E.getPrimitives('EVENT')

    eventWeight = 1.
    try:
        eventWeight = 1. if Event.weight > 0. else -1.
    except:
        pass

    selectedDimuons, selectedDSAmuons, selectedPATmuons = Selector.SelectObjects(E, self.CUTS, Dimuons3, DSAmuons, PATmuons)
    if selectedDimuons is None: return

    for dim in selectedDimuons:
        if dim.composition == 'DSA': continue
        idxList = (dim.idx2,) if dim.composition == 'HYBRID' else dim.ID
        for idx in idxList:
            mu = PATmuons[idx]
            self.HISTS['pT'].Fill(mu.pt)
            if mu.highPurity:
                self.HISTS['pT-HP'].Fill(mu.pt)

    if self.SP is not None:
        if '4Mu' in self.NAME:
            mu11, mu12, mu21, mu22, X1, X2, H, P, extramu = E.getPrimitives('GEN')
            genMuons = (mu11, mu12, mu21, mu22)
            genMuonPairs = ((mu11, mu12), (mu21, mu22))
        elif '2Mu2J' in self.NAME:
            mu1, mu2, j1, j2, X, XP, H, P, extramu = E.getPrimitives('GEN')
            genMuons = (mu1, mu2)
            genMuonPairs = ((mu1, mu2),)

        # do the signal matching
        if len(genMuonPairs) == 1:
            genMuonPair = genMuonPairs[0]
            dimuonMatches, muonMatches, exitcode = matchedDimuons(genMuonPair, selectedDimuons)
            if len(dimuonMatches) > 0:
                realMatches = {0:dimuonMatches[0]}
            else:
                realMatches = {}
        else:
            realMatches, dimuonMatches, muon0Matches, muon1Matches = matchedDimuonPairs(genMuonPairs, selectedDimuons)

        for pairIndex in realMatches:
            genMuon = genMuonPairs[pairIndex][0]
            dim = realMatches[pairIndex]['dim']
            if dim.composition == 'DSA': continue
            idxList = (dim.idx2,) if dim.composition == 'HYBRID' else dim.ID
            for idx in idxList:
                mu = PATmuons[idx]
                self.HISTS['GM-pT'].Fill(mu.pt)
                if mu.highPurity:
                    self.HISTS['GM-pT-HP'].Fill(mu.pt)
def analyze(self, E, PARAMS=None):
    if self.TRIGGER and self.SP is not None:
        if not Selections.passedTrigger(E): return
    DSAmuons = E.getPrimitives('DSAMUON')
    PATmuons = E.getPrimitives('PATMUON')
    Dimuons3 = E.getPrimitives('DIMUON')
    Event = E.getPrimitives('EVENT')

    eventWeight = 1.
    try:
        eventWeight = 1. if Event.weight > 0. else -1.
    except:
        pass

    if self.SP is not None:
        if '4Mu' in self.NAME:
            mu11, mu12, mu21, mu22, X1, X2, H, P, extramu = E.getPrimitives(
                'GEN')
            genMuons = (mu11, mu12, mu21, mu22)
            genMuonPairs = ((mu11, mu12), (mu21, mu22))
        elif '2Mu2J' in self.NAME:
            mu1, mu2, j1, j2, X, XP, H, P, extramu = E.getPrimitives('GEN')
            genMuons = (mu1, mu2)
            genMuonPairs = ((mu1, mu2), )

        for pTCut in xrange(31):

            selectedDimuons, selectedDSAmuons, selectedPATmuons = Selector.SelectObjectsReordered(
                E,
                self.CUTS,
                Dimuons3,
                DSAmuons,
                PATmuons,
                keepHybrids=True,
                option=3,
                pTCut=float(pTCut))
            if selectedDimuons is None: continue

            # do the signal matching
            if len(genMuonPairs) == 1:
                genMuonPair = genMuonPairs[0]
                dimuonMatches, muonMatches, exitcode = matchedDimuons(
                    genMuonPair, selectedDimuons)
                if len(dimuonMatches) > 0:
                    realMatches = {0: dimuonMatches[0]}
                else:
                    realMatches = {}
            else:
                realMatches, dimuonMatches, muon0Matches, muon1Matches = matchedDimuonPairs(
                    genMuonPairs, selectedDimuons)

            if len(realMatches) > 0:
                self.HISTS['nMatches'].Fill(float(pTCut), eventWeight)
def analyze(self, E, PARAMS=None):
    if self.TRIGGER and self.SP is not None:
        if not Selections.passedTrigger(E): return

    Event = E.getPrimitives('EVENT')

    CUTSTRING = '_Combined_NS_NH_FPTE_HLT_REP_PT_TRK_NDT_DCA_PC_LXYE_MASS_CHI2_VTX_COSA_NPP_LXYSIG_OS_DPHI'

    DSAmuons = E.getPrimitives('DSAMUON')
    PATmuons = E.getPrimitives('PATMUON')
    Dimuons3 = E.getPrimitives('DIMUON')

    # gen stuff
    if self.SP is not None:
        if '4Mu' in self.NAME:
            mu11, mu12, mu21, mu22, X1, X2, H, P, extramu = E.getPrimitives(
                'GEN')
            genMuons = (mu11, mu12, mu21, mu22)
            genMuonPairs = ((mu11, mu12), (mu21, mu22))
        elif '2Mu2J' in self.NAME:
            mu1, mu2, j1, j2, X, XP, H, P, extramu = E.getPrimitives('GEN')
            genMuons = (mu1, mu2)
            genMuonPairs = ((mu1, mu2), )

    # do the selection
    for key in ('before', 'after'):
        selectedDimuons, selectedDSAmuons, selectedPATmuons = Selector.SelectObjects(
            E, CUTSTRING, Dimuons3, DSAmuons, PATmuons, applyDeltaR=key)
        if selectedDimuons is None: continue
        DSADimuons = [
            dim for dim in selectedDimuons if dim.composition == 'DSA'
        ]

        if self.SP is not None:
            if len(genMuonPairs) == 1:
                genMuonPair = genMuonPairs[0]
                dimuonMatches, muonMatches, exitcode = matchedDimuons(
                    genMuonPair, DSADimuons)
                if len(dimuonMatches) > 0:
                    realMatches = {0: dimuonMatches[0]}
                else:
                    realMatches = {}
            else:
                realMatches, dimuonMatches, muon0Matches, muon1Matches = matchedDimuonPairs(
                    genMuonPairs, DSADimuons)

            for pairIndex in realMatches:
                genMuon = genMuonPairs[pairIndex][0]
                self.HISTS['Lxy_{}'.format(key)].Fill(genMuon.Lxy())
def analyze(self, E, PARAMS=None):
    Event = E.getPrimitives('EVENT')

    for key in self.COUNTS:
        weight = PileupWeight(Event.nTruePV, variation=key)
        self.COUNTS[key]['sumWeights'] += weight

    if self.TRIGGER and self.SP is not None:
        if not Selections.passedTrigger(E): return

    DSAmuons = E.getPrimitives('DSAMUON')
    PATmuons = E.getPrimitives('PATMUON')
    Dimuons3 = E.getPrimitives('DIMUON')

    cutstring = CUTSTRING
    selectedDimuons, selectedDSAmuons, selectedPATmuons = Selector.SelectObjects(E, cutstring, Dimuons3, DSAmuons, PATmuons)
    if selectedDimuons is not None:
        for dim in selectedDimuons:
            if dim.composition != 'DSA': continue
            if dim.LxySig() < 7.: continue

            for key in self.COUNTS:
                weight = PileupWeight(Event.nTruePV, variation=key)
                self.COUNTS[key]['counts'] += weight
def analyze(self, E, PARAMS=None):
    if self.TRIGGER and self.SP is not None:
        if not Selections.passedTrigger(E): return

    Event = E.getPrimitives('EVENT')

    DSAmuons = E.getPrimitives('DSAMUON')
    PATmuons = E.getPrimitives('PATMUON')
    Dimuons3 = E.getPrimitives('DIMUON')

    for attr in ('DSAmuons', 'PATmuons', 'Dimuons3'):
        setattr(self, attr, locals()[attr])

    def modifiedName(name):
        if 'DoubleMuon' in name:
            return 'Data' + name[17]
        if 'QCD' in name:
            return 'QCD'
        return name

    # no LxySig, no Dphi, and no blinding
    # LxySig < 1 applied below; iDphi and Dphi kept track of in dump
    CUTSTRING = '_Combined_NS_NH_FPTE_HLT_REP_PT_TRK_NDT_DCA_PC_LXYE_MASS_CHI2_VTX_COSA_NPP_OS'

    selectedDimuons, selectedDSAmuons, selectedPATmuons = Selector.SelectObjects(
        E, CUTSTRING, Dimuons3, DSAmuons, PATmuons)
    if selectedDimuons is None: return

    for dim in selectedDimuons:
        if dim.composition == 'PAT' and dim.LxySig() < 1.:
            daddyMuons = self.getOriginalDSAMuons(dim)

            if sum([len(daddyMuons[idx]) for idx in daddyMuons]) < 2:
                print 'After original: Something is wrong: why did you not find 2 DSA muons leading to 2 PAT muons?'

            selectedDSAIndices = []
            for patIdx in daddyMuons:
                # dirty disambiguation
                if len(daddyMuons[patIdx]) == 0:
                    print 'In Loop: Something is wrong: why did you not find 2 DSA muons leading to 2 PAT muons?'
                elif len(daddyMuons[patIdx]) > 1:
                    thisDSAmuon = list(
                        sorted(daddyMuons[patIdx],
                               key=lambda mu: mu.pt,
                               reverse=True))[0]
                    selectedDSAIndices.append(thisDSAmuon.idx)
                else:
                    thisDSAmuon = daddyMuons[patIdx][0]
                    selectedDSAIndices.append(thisDSAmuon.idx)

            parentDSADim = None
            if len(selectedDSAIndices) == 2:
                for DSADim in Dimuons3:
                    if DSADim.composition != 'DSA': continue
                    if selectedDSAIndices[
                            0] in DSADim.ID and selectedDSAIndices[
                                1] in DSADim.ID:
                        parentDSADim = DSADim
                        break

            if parentDSADim is None: continue

            print '{:9s} {:d} {:7d} {:10d} ::: PAT {:2d} {:2d} <-- DSA {:2d} {:2d} ::: {:9.4f} {:9.4f} ::: {:6.4f} {:6.4f}'.format(
                modifiedName(self.NAME),
                Event.run,
                Event.lumi,
                Event.event,
                dim.ID[0],
                dim.ID[1],
                parentDSADim.ID[0],
                parentDSADim.ID[1],
                dim.LxySig(),
                parentDSADim.LxySig(),
                dim.deltaPhi,
                parentDSADim.deltaPhi,
            )
def analyze(self, E, PARAMS=None):
    if self.TRIGGER and self.SP is not None:
        if not Selections.passedTrigger(E): return

    Event = E.getPrimitives('EVENT')

    # take 10% of data: event numbers ending in 7
    if 'DoubleMuon' in self.NAME and '_IDPHI' not in self.CUTS:
        self.DATACOUNTER['all'] += 1
        if Event.event % 10 != 7: return
        self.DATACOUNTER['selected'] += 1

    DSAmuons = E.getPrimitives('DSAMUON')
    PATmuons = E.getPrimitives('PATMUON')
    Dimuons3 = E.getPrimitives('DIMUON')

    eventWeight = 1.
    try:
        eventWeight = 1. if Event.weight > 0. else -1.
    except:
        pass

    selectedDimuons, selectedDSAmuons, selectedPATmuons = Selector.SelectObjects(
        E, self.CUTS, Dimuons3, DSAmuons, PATmuons)
    if selectedDimuons is None: return

    for dim in selectedDimuons:
        if dim.composition == 'DSA':
            self.HISTS['nDimuon'].Fill(len(selectedDimuons), eventWeight)
            self.HISTS['nDSA'].Fill(len(DSAmuons), eventWeight)
            self.HISTS['nDSA12'].Fill(
                len([d for d in DSAmuons if d.nCSCHits + d.nDTHits > 12]),
                eventWeight)
            self.HISTS['nDSA12-pT'].Fill(
                len([
                    d for d in DSAmuons
                    if d.nCSCHits + d.nDTHits > 12 and d.pt > 5.
                ]), eventWeight)
            self.HISTS['nDSA-DT'].Fill(
                len([d for d in DSAmuons if d.nCSCHits == 0]), eventWeight)
            break

    def getOriginalMuons(dim):
        if dim.composition == 'PAT':
            return PATmuons[dim.idx1], PATmuons[dim.idx2]
        elif dim.composition == 'DSA':
            return DSAmuons[dim.idx1], DSAmuons[dim.idx2]
        else:
            return DSAmuons[dim.idx1], PATmuons[dim.idx2]

    for dim in selectedDimuons:
        RTYPE = dim.composition[:3]
        for QKEY in DIMQUANTITIES:
            KEY = RTYPE + '-' + QKEY
            if QKEY not in ('mind0Sig', 'minNHits', 'qsum'):
                self.HISTS[KEY].Fill(DIMQUANTITIES[QKEY]['LAMBDA'](dim),
                                     eventWeight)
            elif QKEY in ('mind0Sig', 'minNHits'):
                self.HISTS[KEY].Fill(
                    DIMQUANTITIES[QKEY]['LAMBDA'](*getOriginalMuons(dim)),
                    eventWeight,
                )  # ew
            else:
                self.HISTS[KEY].Fill(
                    DIMQUANTITIES[QKEY]['LAMBDA'](dim.mu1, dim.mu2),
                    eventWeight)

        if RTYPE == 'DSA':
            for QKEY in DSAQUANTITIES:
                KEY = RTYPE + '-' + QKEY
                for mu in getOriginalMuons(dim):
                    self.HISTS[KEY].Fill(DSAQUANTITIES[QKEY]['LAMBDA'](mu),
                                         eventWeight)

        if RTYPE == 'PAT':
            for QKEY in PATQUANTITIES:
                KEY = RTYPE + '-' + QKEY
                for mu in getOriginalMuons(dim):
                    self.HISTS[KEY].Fill(PATQUANTITIES[QKEY]['LAMBDA'](mu),
                                         eventWeight)

        if RTYPE == 'HYB':
            DSAmu, PATmu = getOriginalMuons(dim)

            for QKEY in DSAQUANTITIES:
                KEY = 'HYB-DSA' + '-' + QKEY
                self.HISTS[KEY].Fill(DSAQUANTITIES[QKEY]['LAMBDA'](DSAmu),
                                     eventWeight)

            for QKEY in PATQUANTITIES:
                KEY = 'HYB-PAT' + '-' + QKEY
                self.HISTS[KEY].Fill(PATQUANTITIES[QKEY]['LAMBDA'](PATmu),
                                     eventWeight)

        self.HISTS[RTYPE + '-LxySigVSdeltaPhi'].Fill(
            DIMQUANTITIES['deltaPhi']['LAMBDA'](dim),
            DIMQUANTITIES['LxySig']['LAMBDA'](dim), eventWeight)

        # temporary 2D histograms
        if dim.composition != 'DSA':
            mu1, mu2 = getOriginalMuons(dim)
            FC2, FMED = PAT2DQUANTITIES['normChi2']['LAMBDA'], PAT2DQUANTITIES[
                'isMedium']['LAMBDA']

            for mu in (mu1, mu2) if RTYPE == 'PAT' else (mu2, ):
                self.HISTS['PAT-normChi2VSisMedium'].Fill(
                    FMED(mu), FC2(mu), eventWeight)

        if dim.composition == 'DSA':
            mu1, mu2 = getOriginalMuons(dim)
            for QKEY in DSA2DQUANTITIES:
                KEY = 'DSA-12-' + QKEY
                F = DSA2DQUANTITIES[QKEY]['LAMBDA']
                self.HISTS[KEY].Fill(F(mu1), F(mu2), eventWeight)

            F = DSAQUANTITIES['FPTE']['LAMBDA']
            self.HISTS['REF-DSA-FPTE'].Fill(F(dim.mu1), eventWeight)
            self.HISTS['REF-DSA-FPTE'].Fill(F(dim.mu2), eventWeight)

        if self.SP is None and dim.LxySig() > 20.:
            mu1, mu2 = getOriginalMuons(dim)
            if dim.composition == 'PAT':
                for QKEY in PAT2DQUANTITIES:
                    KEY = 'PAT-12-' + QKEY
                    F = PAT2DQUANTITIES[QKEY]['LAMBDA']
                    if QKEY in ('hitsBeforeVtx', 'missingHitsAfterVtx'):
                        self.HISTS[KEY].Fill(F(dim.mu1), F(dim.mu2),
                                             eventWeight)
                    else:
                        self.HISTS[KEY].Fill(F(mu1), F(mu2), eventWeight)

                print '{:13s} {:d} {:7d} {:10d} {:2d} ::: {:3s} {:2d} {:2d} ::: {:6.2f} {:2d} {:1d} {:1d} {:1d} {:1d} {:6.2f} {:2d} {:1d} {:1d} {:1d} {:1d} ::: {:9.4f} {:8.4f} {:5.2f} {:6.2f} {:6.2f}'.format(
                    self.NAME, Event.run, Event.lumi, Event.event,
                    int(eventWeight), dim.composition[:3], dim.idx1, dim.idx2,
                    mu1.normChi2, mu1.nTrackerLayers, mu1.nPixelHits,
                    int(mu1.highPurity), int(mu1.isGlobal), int(mu1.isMedium),
                    mu2.normChi2, mu2.nTrackerLayers, mu2.nPixelHits,
                    int(mu2.highPurity), int(mu2.isGlobal), int(mu2.isMedium),
                    dim.LxySig(), dim.Lxy(), dim.normChi2, mu1.d0Sig(),
                    mu2.d0Sig())
            elif dim.composition == 'DSA':
                print '{:13s} {:d} {:7d} {:10d} {:2d} ::: {:3s} {:2d} {:2d} ::: {:6.2f} {:2s} {:1s} {:1s} {:1s} {:1s} {:6.2f} {:2s} {:1s} {:1s} {:1s} {:1s} ::: {:9.4f} {:8.4f} {:5.2f} {:6.2f} {:6.2f}'.format(
                    self.NAME, Event.run, Event.lumi, Event.event,
                    int(eventWeight), dim.composition[:3], dim.idx1, dim.idx2,
                    mu1.normChi2, '-', '-', '-', '-', '-', mu2.normChi2, '-',
                    '-', '-', '-', '-', dim.LxySig(), dim.Lxy(), dim.normChi2,
                    mu1.d0Sig(), mu2.d0Sig())
            else:
                print '{:13s} {:d} {:7d} {:10d} {:2d} ::: {:3s} {:2d} {:2d} ::: {:6.2f} {:2s} {:1s} {:1s} {:1s} {:1s} {:6.2f} {:2d} {:1d} {:1d} {:1d} {:1d} ::: {:9.4f} {:8.4f} {:5.2f} {:6.2f} {:6.2f}'.format(
                    self.NAME, Event.run, Event.lumi, Event.event,
                    int(eventWeight), dim.composition[:3], dim.idx1, dim.idx2,
                    mu1.normChi2, '-', '-', '-', '-', '-', mu2.normChi2,
                    mu2.nTrackerLayers, mu2.nPixelHits, int(mu2.highPurity),
                    int(mu2.isGlobal), int(mu2.isMedium), dim.LxySig(),
                    dim.Lxy(), dim.normChi2, mu1.d0Sig(), mu2.d0Sig())

    if self.SP is not None:
        if '4Mu' in self.NAME:
            mu11, mu12, mu21, mu22, X1, X2, H, P, extramu = E.getPrimitives(
                'GEN')
            genMuons = (mu11, mu12, mu21, mu22)
            genMuonPairs = ((mu11, mu12), (mu21, mu22))
        elif '2Mu2J' in self.NAME:
            mu1, mu2, j1, j2, X, XP, H, P, extramu = E.getPrimitives('GEN')
            genMuons = (mu1, mu2)
            genMuonPairs = ((mu1, mu2), )

        # do the signal matching
        if len(genMuonPairs) == 1:
            genMuonPair = genMuonPairs[0]
            dimuonMatches, muonMatches, exitcode = matchedDimuons(
                genMuonPair, selectedDimuons)
            if len(dimuonMatches) > 0:
                realMatches = {0: dimuonMatches[0]}
            else:
                realMatches = {}
        else:
            realMatches, dimuonMatches, muon0Matches, muon1Matches = matchedDimuonPairs(
                genMuonPairs, selectedDimuons)

        for pairIndex in realMatches:
            genMuon = genMuonPairs[pairIndex][0]
            dim = realMatches[pairIndex]['dim']
            self.HISTS['GEN-Lxy'].Fill(genMuon.Lxy(), eventWeight)

            RTYPE = dim.composition[:3]
            KEY = 'GEN-Lxy-' + RTYPE
            self.HISTS[KEY].Fill(genMuon.Lxy(), eventWeight)

            KEY = RTYPE + '-' + 'LxyRes'
            self.HISTS[KEY].Fill(dim.Lxy() - genMuon.Lxy(), eventWeight)

            KEY = RTYPE + '-' + 'LxyRes' + 'VSGEN-Lxy'
            self.HISTS[KEY].Fill(genMuon.Lxy(),
                                 dim.Lxy() - genMuon.Lxy(), eventWeight)

            KEY = RTYPE + '-' + 'LxyPull'
            self.HISTS[KEY].Fill((dim.Lxy() - genMuon.Lxy()) / dim.LxyErr(),
                                 eventWeight)

            KEY = RTYPE + '-' + 'LxyRes' + 'VS' + RTYPE + '-' + 'LxyErr'
            self.HISTS[KEY].Fill(dim.LxyErr(),
                                 dim.Lxy() - genMuon.Lxy(), eventWeight)

            # temporary 2D histograms
            if RTYPE == 'DSA': continue

            mu1, mu2 = getOriginalMuons(dim)
            FC2, FMED = PAT2DQUANTITIES['normChi2']['LAMBDA'], PAT2DQUANTITIES[
                'isMedium']['LAMBDA']

            for mu in (mu1, mu2) if RTYPE == 'PAT' else (mu2, ):
                self.HISTS['PAT-normChi2VSGEN-Lxy'].Fill(
                    genMuon.Lxy(), FC2(mu), eventWeight)
                self.HISTS['PAT-isMediumVSGEN-Lxy'].Fill(
                    genMuon.Lxy(), FMED(mu), eventWeight)

            # permanent
            if RTYPE != 'PAT': continue
            mu1, mu2 = PATmuons[dim.idx1], PATmuons[dim.idx2]
            for QKEY in PAT2DQUANTITIES:
                KEY = RTYPE + '-' + '12' + '-' + QKEY
                F = PAT2DQUANTITIES[QKEY]['LAMBDA']
                if QKEY in ('hitsBeforeVtx', 'missingHitsAfterVtx'):
                    self.HISTS[KEY].Fill(F(dim.mu1), F(dim.mu2), eventWeight)
                else:
                    self.HISTS[KEY].Fill(F(mu1), F(mu2), eventWeight)