Ejemplo n.º 1
0
    def process(self, event):
        '''
        '''
        self.readCollections(event.input)
        self.tree.reset()

        # output of reco analysis
        self.fillEvent(self.tree, event)
        self.fillCheckHNLReco(self.tree, event)
        self.fillHNLReco(self.tree, event)
        if hasattr(event, 'dimuonChi2'):
            self.fillDiMuon(self.tree, 'dimuonChi2', event.dimuonChi2)
            self.fillDisplacedMuon(self.tree, 'dMu1Chi2', event.dMu1Chi2)
            self.fillDisplacedMuon(self.tree, 'dMu2Chi2', event.dMu2Chi2)
            self.fillDiMuon(self.tree, 'dimuonDxy', event.dimuonDxy)
            self.fillDisplacedMuon(self.tree, 'dMu1Dxy', event.dMu1Dxy)
            self.fillDisplacedMuon(self.tree, 'dMu2Dxy', event.dMu2Dxy)
            self.fillDiMuon(self.tree, 'dimuonMaxPt', event.dimuonMaxPt)
            self.fillDisplacedMuon(self.tree, 'dMu1MaxPt', event.dMu1MaxPt)
            self.fillDisplacedMuon(self.tree, 'dMu2MaxPt', event.dMu2MaxPt)
            self.fillDiMuon(self.tree, 'dimuonMinDr12', event.dimuonMinDr12)
            self.fillDisplacedMuon(self.tree, 'dMu1MinDr12', event.dMu1MinDr12)
            self.fillDisplacedMuon(self.tree, 'dMu2MinDr12', event.dMu2MinDr12)
            self.fillDiMuon(self.tree, 'dimuonMaxDr0a12',
                            event.dimuonMaxDr0a12)
            self.fillDisplacedMuon(self.tree, 'dMu1MaxDr0a12',
                                   event.dMu1MaxDr0a12)
            self.fillDisplacedMuon(self.tree, 'dMu2MaxDr0a12',
                                   event.dMu2MaxDr0a12)

        # output of MC analysis
        self.fillHNL(self.tree, 'hnl', event.the_hnl)

        # the prompt lepton
        self.fillParticle(self.tree, 'l0', event.the_hnl.l0())
        if hasattr(event.the_hnl.l0(), 'bestelectron'):
            self.fillEle(self.tree, 'l0_matched_electron',
                         event.the_hnl.l0().bestelectron)
        if hasattr(event.the_hnl.l0(), 'bestphoton'):
            self.fillPhoton(self.tree, 'l0_matched_photon',
                            event.the_hnl.l0().bestphoton)
        if hasattr(event.the_hnl.l0(), 'bestmuon'):
            self.fillMuon(self.tree, 'l0_matched_muon',
                          event.the_hnl.l0().bestmuon)
            self.fillMuonTrack(self.tree, 'l0_matched_muon_track',
                               event.the_hnl.l0().bestmuon.bestTrack())
        if hasattr(event.the_hnl.l0(), 'besttau'):
            self.fillTau(self.tree, 'l0_matched_tau',
                         event.the_hnl.l0().besttau)
        if hasattr(event.the_hnl.l0(), 'bestdsmuon'):
            self.fillParticle(self.tree, 'l0_matched_dsmuon',
                              event.the_hnl.l0().bestdsmuon)
            self.fillMuonTrack(self.tree, 'l0_matched_dsmuon_track',
                               event.the_hnl.l0().bestdsmuon)
        if hasattr(event.the_hnl.l0(), 'bestdgmuon'):
            self.fillParticle(self.tree, 'l0_matched_dgmuon',
                              event.the_hnl.l0().bestdgmuon)
            self.fillMuonTrack(self.tree, 'l0_matched_dgmuon_track',
                               event.the_hnl.l0().bestdgmuon)
        if event.the_hnl.l0().bestmatch != None:
            self.fillParticle(self.tree, 'l0_bestmatch',
                              event.the_hnl.l0().bestmatch)
        self.fill(self.tree, 'l0_bestmatchtype',
                  event.the_hnl.l0().bestmatchtype)

        # displaced leptons (from the HN)
        self.fillParticle(self.tree, 'l1', event.the_hnl.l1())
        if hasattr(event.the_hnl.l1(), 'bestelectron'):
            self.fillEle(self.tree, 'l1_matched_electron',
                         event.the_hnl.l1().bestelectron)
        if hasattr(event.the_hnl.l1(), 'bestphoton'):
            self.fillPhoton(self.tree, 'l1_matched_photon',
                            event.the_hnl.l1().bestphoton)
        if hasattr(event.the_hnl.l1(), 'bestmuon'):
            self.fillMuon(self.tree, 'l1_matched_muon',
                          event.the_hnl.l1().bestmuon)
            self.fillMuonTrack(self.tree, 'l1_matched_muon_track',
                               event.the_hnl.l1().bestmuon.bestTrack())
        if hasattr(event.the_hnl.l1(), 'besttau'):
            self.fillTau(self.tree, 'l1_matched_tau',
                         event.the_hnl.l1().besttau)
        if hasattr(event.the_hnl.l1(), 'bestdsmuon'):
            self.fillParticle(self.tree, 'l1_matched_dsmuon',
                              event.the_hnl.l1().bestdsmuon)
            self.fillMuonTrack(self.tree, 'l1_matched_dsmuon_track',
                               event.the_hnl.l1().bestdsmuon)
        if hasattr(event.the_hnl.l1(), 'bestdgmuon'):
            self.fillParticle(self.tree, 'l1_matched_dgmuon',
                              event.the_hnl.l1().bestdgmuon)
            self.fillMuonTrack(self.tree, 'l1_matched_dgmuon_track',
                               event.the_hnl.l1().bestdgmuon)
        if event.the_hnl.l1().bestmatch != None:
            self.fillParticle(self.tree, 'l1_bestmatch',
                              event.the_hnl.l1().bestmatch)
        self.fill(self.tree, 'l1_bestmatchtype',
                  event.the_hnl.l1().bestmatchtype)

        self.fillParticle(self.tree, 'l2', event.the_hnl.l2())
        if hasattr(event.the_hnl.l2(), 'bestelectron'):
            self.fillEle(self.tree, 'l2_matched_electron',
                         event.the_hnl.l2().bestelectron)
        if hasattr(event.the_hnl.l2(), 'bestphoton'):
            self.fillPhoton(self.tree, 'l2_matched_photon',
                            event.the_hnl.l2().bestphoton)
        if hasattr(event.the_hnl.l2(), 'bestmuon'):
            self.fillMuon(self.tree, 'l2_matched_muon',
                          event.the_hnl.l2().bestmuon)
            self.fillMuonTrack(self.tree, 'l2_matched_muon_track',
                               event.the_hnl.l2().bestmuon.bestTrack())
        if hasattr(event.the_hnl.l2(), 'besttau'):
            self.fillTau(self.tree, 'l2_matched_tau',
                         event.the_hnl.l2().besttau)
        if hasattr(event.the_hnl.l2(), 'bestdsmuon'):
            self.fillParticle(self.tree, 'l2_matched_dsmuon',
                              event.the_hnl.l2().bestdsmuon)
            self.fillMuonTrack(self.tree, 'l2_matched_dsmuon_track',
                               event.the_hnl.l2().bestdsmuon)
        if hasattr(event.the_hnl.l2(), 'bestdgmuon'):
            self.fillParticle(self.tree, 'l2_matched_dgmuon',
                              event.the_hnl.l2().bestdgmuon)
            self.fillMuonTrack(self.tree, 'l2_matched_dgmuon_track',
                               event.the_hnl.l2().bestdgmuon)
        if event.the_hnl.l2().bestmatch != None:
            self.fillParticle(self.tree, 'l2_bestmatch',
                              event.the_hnl.l2().bestmatch)
        self.fill(self.tree, 'l2_bestmatchtype',
                  event.the_hnl.l2().bestmatchtype)

        # final neutrino
        self.fillGenParticle(self.tree, 'n', event.the_hnl.met())

        # true primary vertex
        self.fill(self.tree, 'pv_x', event.the_hn.vx())
        self.fill(self.tree, 'pv_y', event.the_hn.vy())
        self.fill(self.tree, 'pv_z', event.the_hn.vz())

        # true HN decay vertex
        self.fill(self.tree, 'sv_x',
                  event.the_hn.lep1.vertex().x()
                  )  # don't use the final lepton to get the vertex from!
        self.fill(self.tree, 'sv_y',
                  event.the_hn.lep1.vertex().y()
                  )  # don't use the final lepton to get the vertex from!
        self.fill(self.tree, 'sv_z',
                  event.the_hn.lep1.vertex().z()
                  )  # don't use the final lepton to get the vertex from!

        # displacements
        self.fill(self.tree, 'hnl_2d_disp',
                  displacement2D(event.the_hn.lep1, event.the_hn))
        self.fill(self.tree, 'hnl_3d_disp',
                  displacement3D(event.the_hn.lep1, event.the_hn))

        # reco secondary vertex and displacement
        if event.recoSv:
            self.fill(self.tree, 'sv_reco_x', event.recoSv.x())
            self.fill(self.tree, 'sv_reco_y', event.recoSv.y())
            self.fill(self.tree, 'sv_reco_z', event.recoSv.z())
            self.fill(self.tree, 'sv_reco_xe', event.recoSv.xError())
            self.fill(self.tree, 'sv_reco_ye', event.recoSv.yError())
            self.fill(self.tree, 'sv_reco_ze', event.recoSv.zError())
            self.fill(self.tree, 'sv_reco_prob', event.recoSv.prob)
            self.fill(self.tree, 'sv_reco_cos', event.recoSv.disp2DFromBS_cos)

            self.fill(self.tree, 'hnl_2d_reco_disp',
                      event.recoSv.disp2DFromBS.value())  # from beamspot
            self.fill(self.tree, 'hnl_3d_reco_disp',
                      event.recoSv.disp3DFromBS.value())  # from PV

            self.fill(self.tree, 'hnl_2d_reco_disp_sig',
                      event.recoSv.disp2DFromBS_sig)  # from beamspot
            self.fill(self.tree, 'hnl_3d_reco_disp_sig',
                      event.recoSv.disp3DFromBS_sig)  # from PV

        # flag if the event is in CMS acceptance |eta|<2.4 (general CMS is 2.5, but the muon system is 2.4)
        is_in_acc =  abs(event.the_hnl.l0().eta())<2.4 and \
                     abs(event.the_hnl.l1().eta())<2.4 and \
                     abs(event.the_hnl.l2().eta())<2.4

        self.fill(self.tree, 'is_in_acc', is_in_acc)

        self.fillTree(event)
Ejemplo n.º 2
0
    def process(self, event):
        '''
        '''
        self.readCollections(event.input)
        self.tree.reset()
        # import pdb;pdb.set_trace() #zhud: debug

        if not eval(self.skimFunction):
            return False

        self.fillEvent(self.tree, event)
        self.fillHNL(self.tree, 'hnl', event.the_hnl)

        # the prompt lepton
        self.fillGenParticle(self.tree, 'l0', event.the_hnl.l0())
        if hasattr(event.the_hnl.l0(), 'bestelectron'):
            self.fillEle(self.tree, 'l0_matched_electron',
                         event.the_hnl.l0().bestelectron)
        if hasattr(event.the_hnl.l0(), 'bestphoton'):
            self.fillPhoton(self.tree, 'l0_matched_photon',
                            event.the_hnl.l0().bestphoton)
        if hasattr(event.the_hnl.l0(), 'bestmuon'):
            self.fillMuon(self.tree, 'l0_matched_muon',
                          event.the_hnl.l0().bestmuon)
            self.fillMuonTrack(self.tree, 'l0_matched_muon_track',
                               event.the_hnl.l0().bestmuon.bestTrack())
        if hasattr(event.the_hnl.l0(), 'besttau'):
            self.fillTau(self.tree, 'l0_matched_tau',
                         event.the_hnl.l0().besttau)
        if hasattr(event.the_hnl.l0(), 'bestdsmuon'):
            self.fillParticle(self.tree, 'l0_matched_dsmuon',
                              event.the_hnl.l0().bestdsmuon)
            self.fillMuonTrack(self.tree, 'l0_matched_dsmuon_track',
                               event.the_hnl.l0().bestdsmuon)
        if hasattr(event.the_hnl.l0(), 'bestdgmuon'):
            self.fillParticle(self.tree, 'l0_matched_dgmuon',
                              event.the_hnl.l0().bestdgmuon)
            self.fillMuonTrack(self.tree, 'l0_matched_dgmuon_track',
                               event.the_hnl.l0().bestdgmuon)

        # displaced leptons (from the HN)
        self.fillGenParticle(self.tree, 'l1', event.the_hnl.l1())
        if hasattr(event.the_hnl.l1(), 'bestelectron'):
            self.fillEle(self.tree, 'l1_matched_electron',
                         event.the_hnl.l1().bestelectron)
        if hasattr(event.the_hnl.l1(), 'bestphoton'):
            self.fillPhoton(self.tree, 'l1_matched_photon',
                            event.the_hnl.l1().bestphoton)
        if hasattr(event.the_hnl.l1(), 'bestmuon'):
            self.fillMuon(self.tree, 'l1_matched_muon',
                          event.the_hnl.l1().bestmuon)
            self.fillMuonTrack(self.tree, 'l1_matched_muon_track',
                               event.the_hnl.l1().bestmuon.bestTrack())
        if hasattr(event.the_hnl.l1(), 'besttau'):
            self.fillTau(self.tree, 'l1_matched_tau',
                         event.the_hnl.l1().besttau)
        if hasattr(event.the_hnl.l1(), 'bestdsmuon'):
            self.fillParticle(self.tree, 'l1_matched_dsmuon',
                              event.the_hnl.l1().bestdsmuon)
            self.fillMuonTrack(self.tree, 'l1_matched_dsmuon_track',
                               event.the_hnl.l1().bestdsmuon)
        if hasattr(event.the_hnl.l1(), 'bestdgmuon'):
            self.fillParticle(self.tree, 'l1_matched_dgmuon',
                              event.the_hnl.l1().bestdgmuon)
            self.fillMuonTrack(self.tree, 'l1_matched_dgmuon_track',
                               event.the_hnl.l1().bestdgmuon)

        self.fillGenParticle(self.tree, 'l2', event.the_hnl.l2())
        if hasattr(event.the_hnl.l2(), 'bestelectron'):
            self.fillEle(self.tree, 'l2_matched_electron',
                         event.the_hnl.l2().bestelectron)
        if hasattr(event.the_hnl.l2(), 'bestphoton'):
            self.fillPhoton(self.tree, 'l2_matched_photon',
                            event.the_hnl.l2().bestphoton)
        if hasattr(event.the_hnl.l2(), 'bestmuon'):
            self.fillMuon(self.tree, 'l2_matched_muon',
                          event.the_hnl.l2().bestmuon)
            self.fillMuonTrack(self.tree, 'l2_matched_muon_track',
                               event.the_hnl.l2().bestmuon.bestTrack())
        if hasattr(event.the_hnl.l2(), 'besttau'):
            self.fillTau(self.tree, 'l2_matched_tau',
                         event.the_hnl.l2().besttau)
        if hasattr(event.the_hnl.l2(), 'bestdsmuon'):
            self.fillParticle(self.tree, 'l2_matched_dsmuon',
                              event.the_hnl.l2().bestdsmuon)
            self.fillMuonTrack(self.tree, 'l2_matched_dsmuon_track',
                               event.the_hnl.l2().bestdsmuon)
        if hasattr(event.the_hnl.l2(), 'bestdgmuon'):
            self.fillParticle(self.tree, 'l2_matched_dgmuon',
                              event.the_hnl.l2().bestdgmuon)
            self.fillMuonTrack(self.tree, 'l2_matched_dgmuon_track',
                               event.the_hnl.l2().bestdgmuon)

        # final neutrino
        self.fillGenParticle(self.tree, 'n', event.the_hnl.met())

        # true primary vertex
        self.fill(self.tree, 'pv_x', event.the_hn.vx())
        self.fill(self.tree, 'pv_y', event.the_hn.vy())
        self.fill(self.tree, 'pv_z', event.the_hn.vz())

        # true HN decay vertex
        self.fill(self.tree, 'sv_x',
                  event.the_hn.lep1.vertex().x()
                  )  # don't use the final lepton to get the vertex from!
        self.fill(self.tree, 'sv_y',
                  event.the_hn.lep1.vertex().y()
                  )  # don't use the final lepton to get the vertex from!
        self.fill(self.tree, 'sv_z',
                  event.the_hn.lep1.vertex().z()
                  )  # don't use the final lepton to get the vertex from!

        # displacements
        self.fill(self.tree, 'hnl_2d_disp',
                  displacement2D(event.the_hn.lep1, event.the_hn))
        self.fill(self.tree, 'hnl_3d_disp',
                  displacement3D(event.the_hn.lep1, event.the_hn))

        # reco secondary vertex and displacement
        if event.recoSv:
            self.fill(self.tree, 'sv_reco_x', event.recoSv.x())
            self.fill(self.tree, 'sv_reco_y', event.recoSv.y())
            self.fill(self.tree, 'sv_reco_z', event.recoSv.z())
            self.fill(self.tree, 'sv_reco_xe', event.recoSv.xError())
            self.fill(self.tree, 'sv_reco_ye', event.recoSv.yError())
            self.fill(self.tree, 'sv_reco_ze', event.recoSv.zError())
            self.fill(self.tree, 'sv_reco_prob', event.recoSv.prob)
            self.fill(self.tree, 'sv_reco_cos', event.recoSv.disp2DFromBS_cos)

            self.fill(self.tree, 'hnl_2d_reco_disp',
                      event.recoSv.disp2DFromBS.value())  # from beamspot
            self.fill(self.tree, 'hnl_3d_reco_disp',
                      event.recoSv.disp3DFromBS.value())  # from PV

            self.fill(self.tree, 'hnl_2d_reco_disp_sig',
                      event.recoSv.disp2DFromBS_sig)  # from beamspot
            self.fill(self.tree, 'hnl_3d_reco_disp_sig',
                      event.recoSv.disp3DFromBS_sig)  # from PV

        # flag if the event is in CMS acceptance |eta|<2.5
        is_in_acc =  abs(event.the_hnl.l0().eta())<2.5 and \
                     abs(event.the_hnl.l1().eta())<2.5 and \
                     abs(event.the_hnl.l2().eta())<2.5

        self.fill(self.tree, 'is_in_acc', is_in_acc)

        self.fillTree(event)
Ejemplo n.º 3
0
    def process(self, event):
        '''
        '''
        self.readCollections(event.input)
        self.tree.reset()

        # output of reco analysis
        self.fillEvent(self.tree, event)

        self.fill(self.tree, 'n_cands', len(event.dimuonsvtx))

        # different candidates
        if len(event.dimuonsvtx):
            #             self.fillHNCandidate(self.tree, 'hnl_minchi2'    , event.hnl_minchi2    )
            #             self.fillHNCandidate(self.tree, 'hnl_maxpt'      , event.hnl_maxpt      )
            #             self.fillHNCandidate(self.tree, 'hnl_mindr'      , event.hnl_mindr      )
            #             self.fillHNCandidate(self.tree, 'hnl_maxdphi'    , event.hnl_maxdphi    )
            #             self.fillHNCandidate(self.tree, 'hnl_mindeta'    , event.hnl_mindeta    )
            #             self.fillHNCandidate(self.tree, 'hnl_maxdisp2dbs', event.hnl_maxdisp2dbs)
            #             self.fillHNCandidate(self.tree, 'hnl_maxdisp2dpv', event.hnl_maxdisp2dpv)
            #             self.fillHNCandidate(self.tree, 'hnl_maxdisp3dpv', event.hnl_maxdisp3dpv)
            #             self.fillHNCandidate(self.tree, 'hnl_maxdls2dbs' , event.hnl_maxdls2dbs )
            #             self.fillHNCandidate(self.tree, 'hnl_maxdls2dpv' , event.hnl_maxdls2dpv )
            #             self.fillHNCandidate(self.tree, 'hnl_maxdls3dpv' , event.hnl_maxdls3dpv )
            self.fillHNCandidate(self.tree, 'hnl_maxcos', event.hnl_maxcos)

            self.fillParticle(self.tree, 'mu1', event.hnl_maxcos.lep1())
            self.fill(self.tree, 'mu1_type', event.hnl_maxcos.lep1().type)
            self.fillParticle(self.tree, 'mu2', event.hnl_maxcos.lep2())
            self.fill(self.tree, 'mu2_type', event.hnl_maxcos.lep2().type)

        # output of MC analysis
        self.fillHNL(self.tree, 'hnl', event.the_hnl)

        # the prompt lepton
        self.fillParticle(self.tree, 'l0', event.the_hnl.l0())
        if hasattr(event.the_hnl.l0(), 'bestelectron'):
            self.fillEle(self.tree, 'l0_matched_electron',
                         event.the_hnl.l0().bestelectron)
        if hasattr(event.the_hnl.l0(), 'bestphoton'):
            self.fillPhoton(self.tree, 'l0_matched_photon',
                            event.the_hnl.l0().bestphoton)
        if hasattr(event.the_hnl.l0(), 'bestmuon'):
            self.fillMuon(self.tree, 'l0_matched_muon',
                          event.the_hnl.l0().bestmuon)
            self.fillMuonTrack(self.tree, 'l0_matched_muon_track',
                               event.the_hnl.l0().bestmuon.bestTrack())
        if hasattr(event.the_hnl.l0(), 'besttau'):
            self.fillTau(self.tree, 'l0_matched_tau',
                         event.the_hnl.l0().besttau)
        if hasattr(event.the_hnl.l0(), 'bestdsmuon'):
            self.fillParticle(self.tree, 'l0_matched_dsmuon',
                              event.the_hnl.l0().bestdsmuon)
            self.fillMuonTrack(self.tree, 'l0_matched_dsmuon_track',
                               event.the_hnl.l0().bestdsmuon)
        if hasattr(event.the_hnl.l0(), 'bestdgmuon'):
            self.fillParticle(self.tree, 'l0_matched_dgmuon',
                              event.the_hnl.l0().bestdgmuon)
            self.fillMuonTrack(self.tree, 'l0_matched_dgmuon_track',
                               event.the_hnl.l0().bestdgmuon)
        if event.the_hnl.l0().bestmatch != None:
            self.fillParticle(self.tree, 'l0_bestmatch',
                              event.the_hnl.l0().bestmatch)
        self.fill(self.tree, 'l0_bestmatch_type',
                  event.the_hnl.l0().bestmatchtype)

        # displaced leptons (from the HN)
        self.fillParticle(self.tree, 'l1', event.the_hnl.l1())
        if hasattr(event.the_hnl.l1(), 'bestelectron'):
            self.fillEle(self.tree, 'l1_matched_electron',
                         event.the_hnl.l1().bestelectron)
        if hasattr(event.the_hnl.l1(), 'bestphoton'):
            self.fillPhoton(self.tree, 'l1_matched_photon',
                            event.the_hnl.l1().bestphoton)
        if hasattr(event.the_hnl.l1(), 'bestmuon'):
            self.fillMuon(self.tree, 'l1_matched_muon',
                          event.the_hnl.l1().bestmuon)
            self.fillMuonTrack(self.tree, 'l1_matched_muon_track',
                               event.the_hnl.l1().bestmuon.bestTrack())
        if hasattr(event.the_hnl.l1(), 'besttau'):
            self.fillTau(self.tree, 'l1_matched_tau',
                         event.the_hnl.l1().besttau)
        if hasattr(event.the_hnl.l1(), 'bestdsmuon'):
            self.fillParticle(self.tree, 'l1_matched_dsmuon',
                              event.the_hnl.l1().bestdsmuon)
            self.fillMuonTrack(self.tree, 'l1_matched_dsmuon_track',
                               event.the_hnl.l1().bestdsmuon)
        if hasattr(event.the_hnl.l1(), 'bestdgmuon'):
            self.fillParticle(self.tree, 'l1_matched_dgmuon',
                              event.the_hnl.l1().bestdgmuon)
            self.fillMuonTrack(self.tree, 'l1_matched_dgmuon_track',
                               event.the_hnl.l1().bestdgmuon)
        if event.the_hnl.l1().bestmatch != None:
            self.fillParticle(self.tree, 'l1_bestmatch',
                              event.the_hnl.l1().bestmatch)
        self.fill(self.tree, 'l1_bestmatch_type',
                  event.the_hnl.l1().bestmatchtype)

        self.fillParticle(self.tree, 'l2', event.the_hnl.l2())
        if hasattr(event.the_hnl.l2(), 'bestelectron'):
            self.fillEle(self.tree, 'l2_matched_electron',
                         event.the_hnl.l2().bestelectron)
        if hasattr(event.the_hnl.l2(), 'bestphoton'):
            self.fillPhoton(self.tree, 'l2_matched_photon',
                            event.the_hnl.l2().bestphoton)
        if hasattr(event.the_hnl.l2(), 'bestmuon'):
            self.fillMuon(self.tree, 'l2_matched_muon',
                          event.the_hnl.l2().bestmuon)
            self.fillMuonTrack(self.tree, 'l2_matched_muon_track',
                               event.the_hnl.l2().bestmuon.bestTrack())
        if hasattr(event.the_hnl.l2(), 'besttau'):
            self.fillTau(self.tree, 'l2_matched_tau',
                         event.the_hnl.l2().besttau)
        if hasattr(event.the_hnl.l2(), 'bestdsmuon'):
            self.fillParticle(self.tree, 'l2_matched_dsmuon',
                              event.the_hnl.l2().bestdsmuon)
            self.fillMuonTrack(self.tree, 'l2_matched_dsmuon_track',
                               event.the_hnl.l2().bestdsmuon)
        if hasattr(event.the_hnl.l2(), 'bestdgmuon'):
            self.fillParticle(self.tree, 'l2_matched_dgmuon',
                              event.the_hnl.l2().bestdgmuon)
            self.fillMuonTrack(self.tree, 'l2_matched_dgmuon_track',
                               event.the_hnl.l2().bestdgmuon)
        if event.the_hnl.l2().bestmatch != None:
            self.fillParticle(self.tree, 'l2_bestmatch',
                              event.the_hnl.l2().bestmatch)
        self.fill(self.tree, 'l2_bestmatch_type',
                  event.the_hnl.l2().bestmatchtype)

        # final neutrino
        self.fillGenParticle(self.tree, 'n', event.the_hnl.met())

        # true primary vertex
        self.fill(self.tree, 'pv_x', event.the_hn.vx())
        self.fill(self.tree, 'pv_y', event.the_hn.vy())
        self.fill(self.tree, 'pv_z', event.the_hn.vz())

        # true HN decay vertex
        self.fill(self.tree, 'sv_x',
                  event.the_hn.lep1.vertex().x()
                  )  # don't use the final lepton to get the vertex from!
        self.fill(self.tree, 'sv_y',
                  event.the_hn.lep1.vertex().y()
                  )  # don't use the final lepton to get the vertex from!
        self.fill(self.tree, 'sv_z',
                  event.the_hn.lep1.vertex().z()
                  )  # don't use the final lepton to get the vertex from!

        # displacements
        self.fill(self.tree, 'hnl_2d_disp',
                  displacement2D(event.the_hn.lep1, event.the_hn))
        self.fill(self.tree, 'hnl_3d_disp',
                  displacement3D(event.the_hn.lep1, event.the_hn))

        # reco secondary vertex and displacement
        if event.recoSv:
            self.fill(self.tree, 'sv_reco_x', event.recoSv.x())
            self.fill(self.tree, 'sv_reco_y', event.recoSv.y())
            self.fill(self.tree, 'sv_reco_z', event.recoSv.z())
            self.fill(self.tree, 'sv_reco_xe', event.recoSv.xError())
            self.fill(self.tree, 'sv_reco_ye', event.recoSv.yError())
            self.fill(self.tree, 'sv_reco_ze', event.recoSv.zError())
            self.fill(self.tree, 'sv_reco_prob', event.recoSv.prob)
            self.fill(self.tree, 'sv_reco_cos', event.recoSv.disp2DFromBS_cos)

            self.fill(self.tree, 'hnl_2d_reco_disp',
                      event.recoSv.disp2DFromBS.value())  # from beamspot
            self.fill(self.tree, 'hnl_3d_reco_disp',
                      event.recoSv.disp3DFromBS.value())  # from PV

            self.fill(self.tree, 'hnl_2d_reco_disp_sig',
                      event.recoSv.disp2DFromBS_sig)  # from beamspot
            self.fill(self.tree, 'hnl_3d_reco_disp_sig',
                      event.recoSv.disp3DFromBS_sig)  # from PV

        # flag if the event is in CMS acceptance |eta|<2.4 (general CMS is 2.5, but the muon system is 2.4)
        is_in_acc =  abs(event.the_hnl.l0().eta())<2.4 and \
                     abs(event.the_hnl.l1().eta())<2.4 and \
                     abs(event.the_hnl.l2().eta())<2.4

        self.fill(self.tree, 'is_in_acc', is_in_acc)

        self.fillTree(event)
Ejemplo n.º 4
0
    def process(self, event):
        '''
        '''
        self.readCollections(event.input)
        self.tree.reset()
        self.event = event
        # event variables
        self.fillEvent(self.tree, event)
        self.fill(self.tree, 'n_cands', len(event.dimuonsvtx))
        self.fill(self.tree, 'rho', event.rho)

        # reco HNL
        self.fillHNL(self.tree, 'hnl', event.the_3lep_cand)
        self.fill(self.tree, 'hnl_iso03_abs_rhoArea',
                  event.the_3lep_cand.abs_tot_iso03_rhoArea)
        self.fill(self.tree, 'hnl_iso04_abs_rhoArea',
                  event.the_3lep_cand.abs_tot_iso04_rhoArea)
        self.fill(self.tree, 'hnl_iso05_abs_rhoArea',
                  event.the_3lep_cand.abs_tot_iso05_rhoArea)
        self.fill(self.tree, 'hnl_iso03_abs_deltaBeta',
                  event.the_3lep_cand.abs_tot_iso03_deltaBeta)
        self.fill(self.tree, 'hnl_iso04_abs_deltaBeta',
                  event.the_3lep_cand.abs_tot_iso04_deltaBeta)
        self.fill(self.tree, 'hnl_iso05_abs_deltaBeta',
                  event.the_3lep_cand.abs_tot_iso05_deltaBeta)
        #        self.fill    (self.tree, 'hnl_iso_abs_met'      , event.the_3lep_cand.abs_ch_iso_met  )
        self.fill(self.tree, 'hnl_iso03_rel_rhoArea',
                  event.the_3lep_cand.rel_tot_iso03_rhoArea)
        self.fill(self.tree, 'hnl_iso04_rel_rhoArea',
                  event.the_3lep_cand.rel_tot_iso04_rhoArea)
        self.fill(self.tree, 'hnl_iso05_rel_rhoArea',
                  event.the_3lep_cand.rel_tot_iso05_rhoArea)
        self.fill(self.tree, 'hnl_iso03_rel_deltaBeta',
                  event.the_3lep_cand.rel_tot_iso03_deltaBeta)
        self.fill(self.tree, 'hnl_iso04_rel_deltaBeta',
                  event.the_3lep_cand.rel_tot_iso04_deltaBeta)
        self.fill(self.tree, 'hnl_iso05_rel_deltaBeta',
                  event.the_3lep_cand.rel_tot_iso05_deltaBeta)
        #        self.fill    (self.tree, 'hnl_iso_rel_met'      , event.the_3lep_cand.rel_ch_iso_met  )
        self.fillMuon(self.tree, 'l1', event.the_3lep_cand.l1())
        self.fillMuon(self.tree, 'l2', event.the_3lep_cand.l2())
        if self.cfg_ana.promptLepType == 'ele':
            self.fillEle(self.tree, 'l0', event.the_3lep_cand.l0())
        if self.cfg_ana.promptLepType == 'mu':
            self.fillMuon(self.tree, 'l0', event.the_3lep_cand.l0())

        # output of MC analysis ONLY FOR SIGNAL
        if hasattr(event, 'the_hnl'):
            self.fillHNL(self.tree, 'hnl_gen', event.the_hnl)
            self.fillParticle(self.tree, 'l0_gen', event.the_hnl.l0())
            self.fillParticle(self.tree, 'l1_gen', event.the_hnl.l1())
            self.fillParticle(self.tree, 'l2_gen', event.the_hnl.l2())
            self.fillParticle(self.tree, 'n_gen', event.the_hnl.met())

        # reco primary vertex
        pv = event.goodVertices[0]
        self.fill(self.tree, 'pv_x', pv.x())
        self.fill(self.tree, 'pv_y', pv.y())
        self.fill(self.tree, 'pv_z', pv.z())
        self.fill(self.tree, 'pv_xe', pv.xError())
        self.fill(self.tree, 'pv_ye', pv.yError())
        self.fill(self.tree, 'pv_ze', pv.zError())

        # true primary vertex
        if hasattr(event, 'the_hnl'):
            self.fill(self.tree, 'pv_gen_x', event.the_hn.vx())
            self.fill(self.tree, 'pv_gen_y', event.the_hn.vy())
            self.fill(self.tree, 'pv_gen_z', event.the_hn.vz())

        # beamspot
        self.fill(self.tree, 'bs_x', event.beamspot.x0())
        self.fill(self.tree, 'bs_y', event.beamspot.y0())
        self.fill(self.tree, 'bs_z', event.beamspot.z0())
        self.fill(self.tree, 'bs_sigma_x', event.beamspot.BeamWidthX())
        self.fill(self.tree, 'bs_sigma_y', event.beamspot.BeamWidthY())
        self.fill(self.tree, 'bs_sigma_z', event.beamspot.sigmaZ())
        self.fill(self.tree, 'bs_dxdz', event.beamspot.dxdz())
        self.fill(self.tree, 'bs_dydz', event.beamspot.dydz())

        # true HN decay vertex
        if hasattr(event, 'the_hn'):
            self.fill(self.tree, 'sv_gen_x',
                      event.the_hn.lep1.vertex().x()
                      )  # don't use the final lepton to get the vertex from!
            self.fill(self.tree, 'sv_gen_y',
                      event.the_hn.lep1.vertex().y()
                      )  # don't use the final lepton to get the vertex from!
            self.fill(self.tree, 'sv_gen_z',
                      event.the_hn.lep1.vertex().z()
                      )  # don't use the final lepton to get the vertex from!

            # displacements
            self.fill(self.tree, 'hnl_2d_gen_disp',
                      displacement2D(event.the_hn.lep1, event.the_hn))
            self.fill(self.tree, 'hnl_3d_gen_disp',
                      displacement3D(event.the_hn.lep1, event.the_hn))

        # HLT bits & matches
        trig_list = [trig.name for trig in event.trigger_infos if trig.fired]
        if self.cfg_ana.promptLepType == 'ele':
            self.fill(
                self.tree, 'hlt_Ele27_WPTight_Gsf',
                any('HLT_Ele27_WPTight_Gsf' in name for name in trig_list))
            self.fill(
                self.tree, 'hlt_Ele32_WPTight_Gsf',
                any('HLT_Ele32_WPTight_Gsf' in name for name in trig_list))
            self.fill(
                self.tree, 'hlt_Ele35_WPTight_Gsf',
                any('HLT_Ele35_WPTight_Gsf' in name for name in trig_list))
            self.fill(
                self.tree, 'hlt_Ele115_CaloIdVT_GsfTrkIdT',
                any('HLT_Ele115_CaloIdVT_GsfTrkIdT' in name
                    for name in trig_list))
            self.fill(
                self.tree, 'hlt_Ele135_CaloIdVT_GsfTrkIdT',
                any('HLT_Ele135_CaloIdVT_GsfTrkIdT' in name
                    for name in trig_list))
        if self.cfg_ana.promptLepType == 'mu':
            self.fill(self.tree, 'hlt_soMu24',
                      any('HLT_IsoMu24' in name for name in trig_list))
            self.fill(self.tree, 'hlt_soMu27',
                      any('HLT_IsoMu27' in name for name in trig_list))
            self.fill(self.tree, 'hlt_u50',
                      any('HLT_Mu50' in name for name in trig_list))

        # reco secondary vertex and displacement
        self.fill(self.tree, 'sv_x', event.recoSv.x())
        self.fill(self.tree, 'sv_y', event.recoSv.y())
        self.fill(self.tree, 'sv_z', event.recoSv.z())
        self.fill(self.tree, 'sv_xe', event.recoSv.xError())
        self.fill(self.tree, 'sv_ye', event.recoSv.yError())
        self.fill(self.tree, 'sv_ze', event.recoSv.zError())
        self.fill(self.tree, 'sv_prob', event.recoSv.prob)
        self.fill(self.tree, 'sv_cos', event.recoSv.disp2DFromBS_cos)

        self.fill(self.tree, 'hnl_2d_disp',
                  event.recoSv.disp2DFromBS.value())  # from beamspot
        self.fill(self.tree, 'hnl_3d_disp',
                  event.recoSv.disp3DFromBS.value())  # from PV

        self.fill(self.tree, 'hnl_2d_disp_sig',
                  event.recoSv.disp2DFromBS_sig)  # from beamspot
        self.fill(self.tree, 'hnl_3d_disp_sig',
                  event.recoSv.disp3DFromBS_sig)  # from PV

        # jet/met variables
        self.fillExtraMetInfo(self.tree, event)

        #        set_trace()
        # met filter flags
        self.fill(self.tree, 'Flag_goodVertices', event.Flag_goodVertices)
        self.fill(self.tree, 'Flag_globalSuperTightHalo2016Filter',
                  event.Flag_globalSuperTightHalo2016Filter)
        self.fill(self.tree, 'Flag_HBHENoiseFilter',
                  event.Flag_HBHENoiseFilter)
        self.fill(self.tree, 'Flag_HBHENoiseIsoFilter',
                  event.Flag_HBHENoiseIsoFilter)
        self.fill(self.tree, 'Flag_EcalDeadCellTriggerPrimitiveFilter',
                  event.Flag_EcalDeadCellTriggerPrimitiveFilter)
        self.fill(self.tree, 'Flag_BadPFMuonFilter',
                  event.Flag_BadPFMuonFilter)
        self.fill(self.tree, 'Flag_BadChargedCandidateFilter',
                  event.Flag_BadChargedCandidateFilter)
        self.fill(self.tree, 'Flag_eeBadScFilter', event.Flag_eeBadScFilter)
        self.fill(self.tree, 'Flag_ecalBadCalibFilter',
                  event.Flag_ecalBadCalibFilter)
        #        self.fill(self.tree, 'Flag_any_met_filters', event.Flag_goodVertices or event.Flag_globalSuperTightHalo2016Filter or event.Flag_HBHENoiseFilter or event.Flag_HBHENoiseIsoFilter or event.Flag_EcalDeadCellTriggerPrimitiveFilter or event.Flag_BadPFMuonFilter or event.Flag_BadChargedCandidateFilter or event.Flag_eeBadScFilter or event.Flag_ecalBadCalibFilter)

        if len(event.cleanJets) > 0:
            self.fillJet(self.tree, 'j1', event.cleanJets[0], fill_extra=False)
        if len(event.cleanJets) > 1:
            self.fillJet(self.tree, 'j2', event.cleanJets[1], fill_extra=False)
        if len(event.cleanBJets) > 0:
            self.fillJet(self.tree,
                         'bj1',
                         event.cleanBJets[0],
                         fill_extra=False)
        if len(event.cleanBJets) > 1:
            self.fillJet(self.tree,
                         'bj2',
                         event.cleanBJets[1],
                         fill_extra=False)

        self.fill(self.tree, 'htj', event.HT_cleanJets)
        self.fill(self.tree, 'htbj', event.HT_bJets)
        self.fill(self.tree, 'nj', len(event.cleanJets))
        self.fill(self.tree, 'nbj', len(event.cleanBJets))

        # gen match
        if self.cfg_comp.isMC == True:
            stable_genp = [
                pp for pp in event.genParticles
                if ((pp.status() == 23 or pp.status() == 1) and (
                    pp.vertex().z() != 0))
            ]
            stable_genp += [
                pp for pp in event.genp_packed
                if ((pp.status() == 23 or pp.status() == 1) and (
                    pp.vertex().z() != 0))
            ]
            # particle status: http://home.thep.lu.se/~torbjorn/pythia81html/ParticleProperties.html
            # 1 ... stable; 23 ... from hardest scattering subprocess

            tomatch = [(event.the_3lep_cand.l0(), 0.05 * 0.05),
                       (event.the_3lep_cand.l1(), 0.2 * 0.2),
                       (event.the_3lep_cand.l2(), 0.2 * 0.2)]

            for ilep, idr2 in tomatch:
                bestmatch, dr2 = bestMatch(ilep, stable_genp)
                if (dr2 < idr2 and abs(
                    (ilep.pt() - bestmatch.pt()) / ilep.pt()) < 0.2):
                    ilep.bestmatch = bestmatch

            # relevant for signal: check if reco matched with gen, save a bool
            if hasattr(event.the_3lep_cand.l0(), 'bestmatch'):
                self.fillSimpleGenParticle(self.tree, 'l0_gen_match',
                                           event.the_3lep_cand.l0().bestmatch)
            if hasattr(event.the_3lep_cand.l1(), 'bestmatch'):
                self.fillSimpleGenParticle(self.tree, 'l1_gen_match',
                                           event.the_3lep_cand.l1().bestmatch)
            if hasattr(event.the_3lep_cand.l2(), 'bestmatch'):
                self.fillSimpleGenParticle(self.tree, 'l2_gen_match',
                                           event.the_3lep_cand.l2().bestmatch)

            # FIXME! matching by pointer does not work, so let's trick it with deltaR
            if hasattr(event, 'the_hnl'):
                if hasattr(event.the_3lep_cand.l0(), 'bestmatch'):
                    self.fill(
                        self.tree, 'l0_is_real',
                        deltaR(event.the_3lep_cand.l0().bestmatch,
                               event.the_hnl.l0()) < 0.01)
                if hasattr(event.the_3lep_cand.l1(), 'bestmatch'):
                    self.fill(
                        self.tree, 'l1_is_real',
                        deltaR(event.the_3lep_cand.l1().bestmatch,
                               event.the_hnl.l1()) < 0.05)
                if hasattr(event.the_3lep_cand.l2(), 'bestmatch'):
                    self.fill(
                        self.tree, 'l2_is_real',
                        deltaR(event.the_3lep_cand.l2().bestmatch,
                               event.the_hnl.l2()) < 0.05)

        # extra lepton veto
        self.fill(self.tree, 'pass_e_veto', len(event.veto_eles) == 0)
        self.fill(self.tree, 'pass_m_veto', len(event.veto_mus) == 0)

        # save vetoing lepton invariant masses
        if len(event.veto_eles):
            self.fillEle(self.tree, 'veto_ele', event.veto_save_ele)
            self.fill(self.tree, 'hnl_m_0Vele',
                      (event.veto_save_ele.p4() +
                       event.the_3lep_cand.l0().p4()).mass())
            self.fill(self.tree, 'hnl_m_1Vele',
                      (event.veto_save_ele.p4() +
                       event.the_3lep_cand.l1().p4()).mass())
            self.fill(self.tree, 'hnl_m_2Vele',
                      (event.veto_save_ele.p4() +
                       event.the_3lep_cand.l2().p4()).mass())
        if len(event.veto_mus):
            self.fillMuon(self.tree, 'veto_mu', event.veto_save_mu)
            self.fill(self.tree, 'hnl_m_0Vmu',
                      (event.veto_save_mu.p4() +
                       event.the_3lep_cand.l0().p4()).mass())
            self.fill(self.tree, 'hnl_m_1Vmu',
                      (event.veto_save_mu.p4() +
                       event.the_3lep_cand.l1().p4()).mass())
            self.fill(self.tree, 'hnl_m_2Vmu',
                      (event.veto_save_mu.p4() +
                       event.the_3lep_cand.l2().p4()).mass())
        # LHE weight
        self.fill(self.tree, 'lhe_weight',
                  np.sign(getattr(event, 'LHE_originalWeight', 1.)))

        self.fillTree(event)
Ejemplo n.º 5
0
    def process(self, event, fill=True):
        '''
        '''
        self.readCollections(event.input)
        self.tree.reset()

        self.counters.counter('HNLTreeProducer').inc('all events')

        # save the event only if it is in the correct final state
        if not eval(self.finalStateFilter):
            return True
        self.counters.counter('HNLTreeProducer').inc('pass final state')

        # get ahold of the objects to save
        final_state = self.cfg_ana.promptLepType + self.cfg_ana.L1L2LeptonType
        dileptonsvtx = event.dileptonsvtx_dict[final_state]
        the_3lep_cand = event.the_3lep_cand_dict[final_state]
        recoSv = event.recoSv_dict[final_state]

        # save the event only if it passes the skim selection (if it exists)
        # import pdb ; pdb.set_trace()
        if not eval(self.skimFilter):
            return True

        self.counters.counter('HNLTreeProducer').inc('pass skim')

        # also cleaned jet collections depend on the final state
        cleanJets = event.cleanJets[final_state]
        cleanBJets = event.cleanBJets[final_state]
        cleanJets30 = event.cleanJets30[final_state]

        # adjust the weights, according to the final state
        event.eventWeight = getattr(event, 'puWeight', 1.)  * \
                            getattr(event, 'LHE_originalWeight', 1.)  * \
                            getattr(event, 'weight_%s' %final_state, 1.)

        the_3lep_cand.l0().weight = getattr(the_3lep_cand.l0(),
                                            'weight_%s' % final_state, 1.)
        the_3lep_cand.l0().weight_id = getattr(the_3lep_cand.l0(),
                                               'weight_%s_id' % final_state,
                                               1.)
        the_3lep_cand.l0().weight_iso = getattr(the_3lep_cand.l0(),
                                                'weight_%s_iso' % final_state,
                                                1.)
        the_3lep_cand.l0().weight_reco = getattr(
            the_3lep_cand.l0(), 'weight_%s_reco' % final_state, 1.)
        the_3lep_cand.l0().weight_idiso = getattr(
            the_3lep_cand.l0(), 'weight_%s_idiso' % final_state, 1.)
        the_3lep_cand.l0().weight_trigger = getattr(
            the_3lep_cand.l0(), 'weight_%s_trigger' % final_state, 1.)
        the_3lep_cand.l0().weight_tracking = getattr(
            the_3lep_cand.l0(), 'weight_%s_tracking' % final_state, 1.)

        the_3lep_cand.l1().weight = getattr(the_3lep_cand.l1(),
                                            'weight_%s' % final_state, 1.)
        the_3lep_cand.l1().weight_id = getattr(the_3lep_cand.l1(),
                                               'weight_%s_id' % final_state,
                                               1.)
        the_3lep_cand.l1().weight_iso = getattr(the_3lep_cand.l1(),
                                                'weight_%s_iso' % final_state,
                                                1.)
        the_3lep_cand.l1().weight_reco = getattr(
            the_3lep_cand.l1(), 'weight_%s_reco' % final_state, 1.)
        the_3lep_cand.l1().weight_idiso = getattr(
            the_3lep_cand.l1(), 'weight_%s_idiso' % final_state, 1.)
        the_3lep_cand.l1().weight_trigger = getattr(
            the_3lep_cand.l1(), 'weight_%s_trigger' % final_state, 1.)
        the_3lep_cand.l1().weight_tracking = getattr(
            the_3lep_cand.l1(), 'weight_%s_tracking' % final_state, 1.)

        the_3lep_cand.l2().weight = getattr(the_3lep_cand.l2(),
                                            'weight_%s' % final_state, 1.)
        the_3lep_cand.l2().weight_id = getattr(the_3lep_cand.l2(),
                                               'weight_%s_id' % final_state,
                                               1.)
        the_3lep_cand.l2().weight_iso = getattr(the_3lep_cand.l2(),
                                                'weight_%s_iso' % final_state,
                                                1.)
        the_3lep_cand.l2().weight_reco = getattr(
            the_3lep_cand.l2(), 'weight_%s_reco' % final_state, 1.)
        the_3lep_cand.l2().weight_idiso = getattr(
            the_3lep_cand.l2(), 'weight_%s_idiso' % final_state, 1.)
        the_3lep_cand.l2().weight_trigger = getattr(
            the_3lep_cand.l2(), 'weight_%s_trigger' % final_state, 1.)
        the_3lep_cand.l2().weight_tracking = getattr(
            the_3lep_cand.l2(), 'weight_%s_tracking' % final_state, 1.)

        # event variables
        self.fillEvent(self.tree, event)
        self.fill(self.tree, 'n_cands', len(dileptonsvtx))
        # these are PRESELECTED leptons according to the preselection given via cfg

        # reco HNL
        self.fillHNL(self.tree, 'hnl', the_3lep_cand)
        if self.cfg_ana.L1L2LeptonType == 'mm':
            self.fillMuon(self.tree, 'l1', the_3lep_cand.l1())
            self.fillMuon(self.tree, 'l2', the_3lep_cand.l2())
        if self.cfg_ana.L1L2LeptonType == 'ee':
            self.fillEle(self.tree, 'l1', the_3lep_cand.l1())
            self.fillEle(self.tree, 'l2', the_3lep_cand.l2())
        if self.cfg_ana.L1L2LeptonType == 'em':
            self.fillEle(self.tree, 'l1', the_3lep_cand.l1())
            self.fillMuon(self.tree, 'l2', the_3lep_cand.l2())

        if self.cfg_ana.promptLepType == 'e':
            self.fillEle(self.tree, 'l0', the_3lep_cand.l0())
        if self.cfg_ana.promptLepType == 'm':
            self.fillMuon(self.tree, 'l0', the_3lep_cand.l0())

        # output of MC analysis ONLY FOR SIGNAL
        if hasattr(event, 'the_hnl'):
            self.fillHNL(self.tree, 'hnl_gen', event.the_hnl)
            self.fillParticle(self.tree, 'l0_gen', event.the_hnl.l0())
            self.fillParticle(self.tree, 'l1_gen', event.the_hnl.l1())
            self.fillParticle(self.tree, 'l2_gen', event.the_hnl.l2())
            self.fillParticle(self.tree, 'n_gen', event.the_hnl.met())

        # reco primary vertex
        pv = event.goodVertices[0]
        self.fill(self.tree, 'pv_x', pv.x())
        self.fill(self.tree, 'pv_y', pv.y())
        self.fill(self.tree, 'pv_z', pv.z())
        self.fill(self.tree, 'pv_xe', pv.xError())
        self.fill(self.tree, 'pv_ye', pv.yError())
        self.fill(self.tree, 'pv_ze', pv.zError())

        # true primary vertex
        if hasattr(event, 'the_hnl'):
            self.fill(self.tree, 'pv_gen_x', event.the_hn.vx())
            self.fill(self.tree, 'pv_gen_y', event.the_hn.vy())
            self.fill(self.tree, 'pv_gen_z', event.the_hn.vz())

        # beamspot
        self.fill(self.tree, 'bs_x', event.beamspot.x0())
        self.fill(self.tree, 'bs_y', event.beamspot.y0())
        self.fill(self.tree, 'bs_z', event.beamspot.z0())
        self.fill(self.tree, 'bs_sigma_x', event.beamspot.BeamWidthX())
        self.fill(self.tree, 'bs_sigma_y', event.beamspot.BeamWidthY())
        self.fill(self.tree, 'bs_sigma_z', event.beamspot.sigmaZ())
        self.fill(self.tree, 'bs_dxdz', event.beamspot.dxdz())
        self.fill(self.tree, 'bs_dydz', event.beamspot.dydz())

        # true HN decay vertex
        if hasattr(event, 'the_hn'):
            self.fill(self.tree, 'sv_gen_x',
                      event.the_hn.lep1.vertex().x()
                      )  # don't use the final lepton to get the vertex from!
            self.fill(self.tree, 'sv_gen_y',
                      event.the_hn.lep1.vertex().y()
                      )  # don't use the final lepton to get the vertex from!
            self.fill(self.tree, 'sv_gen_z',
                      event.the_hn.lep1.vertex().z()
                      )  # don't use the final lepton to get the vertex from!

            # displacements
            self.fill(self.tree, 'hnl_2d_gen_disp',
                      displacement2D(event.the_hn.lep1, event.the_hn))
            self.fill(self.tree, 'hnl_3d_gen_disp',
                      displacement3D(event.the_hn.lep1, event.the_hn))

        # HLT bits & matches
        trig_list = [trig.name for trig in event.trigger_infos if trig.fired]
        if self.cfg_ana.promptLepType == 'e':
            self.fill(
                self.tree, 'hlt_Ele25_eta2p1_WPTight_Gsf',
                any('HLT_Ele25_eta2p1_WPTight_Gsf' in name
                    for name in trig_list))
            self.fill(
                self.tree, 'hlt_Ele27_WPTight_Gsf',
                any('HLT_Ele27_WPTight_Gsf' in name for name in trig_list))
            self.fill(
                self.tree, 'hlt_Ele32_WPTight_Gsf',
                any('HLT_Ele32_WPTight_Gsf' in name for name in trig_list))
            self.fill(
                self.tree, 'hlt_Ele35_WPTight_Gsf',
                any('HLT_Ele35_WPTight_Gsf' in name for name in trig_list))
            self.fill(
                self.tree, 'hlt_Ele115_CaloIdVT_GsfTrkIdT',
                any('HLT_Ele115_CaloIdVT_GsfTrkIdT' in name
                    for name in trig_list))
            self.fill(
                self.tree, 'hlt_Ele135_CaloIdVT_GsfTrkIdT',
                any('HLT_Ele135_CaloIdVT_GsfTrkIdT' in name
                    for name in trig_list))
        if self.cfg_ana.promptLepType == 'm':
            self.fill(self.tree, 'hlt_IsoMu22',
                      any('HLT_IsoMu22' in name for name in trig_list))
            self.fill(self.tree, 'hlt_IsoTkMu22',
                      any('HLT_IsoTkMu22' in name for name in trig_list))
            self.fill(self.tree, 'hlt_IsoMu22_eta2p1',
                      any('HLT_IsoMu22_eta2p1' in name for name in trig_list))
            self.fill(
                self.tree, 'hlt_IsoTkMu22_eta2p1',
                any('HLT_IsoTkMu22_eta2p1' in name for name in trig_list))
            self.fill(self.tree, 'hlt_IsoMu24',
                      any('HLT_IsoMu24' in name for name in trig_list))
            self.fill(self.tree, 'hlt_IsoTkMu24',
                      any('HLT_IsoTkMu24' in name for name in trig_list))
            self.fill(self.tree, 'hlt_IsoMu27',
                      any('HLT_IsoMu27' in name for name in trig_list))
            self.fill(self.tree, 'hlt_IsoTkMu27',
                      any('HLT_IsoTkMu27' in name for name in trig_list))
            self.fill(self.tree, 'hlt_Mu50',
                      any('HLT_Mu50' in name for name in trig_list))
            self.fill(self.tree, 'hlt_TkMu50',
                      any('HLT_TkMu50' in name for name in trig_list))

        # reco secondary vertex and displacement
        self.fillVertex(self.tree, 'sv', recoSv)

        self.fill(self.tree, 'hnl_2d_disp',
                  recoSv.disp2DFromBS.value())  # from beamspot
        self.fill(self.tree, 'hnl_3d_disp',
                  recoSv.disp3DFromBS.value())  # from PV

        self.fill(self.tree, 'hnl_2d_disp_sig',
                  recoSv.disp2DFromBS_sig)  # from beamspot
        self.fill(self.tree, 'hnl_3d_disp_sig',
                  recoSv.disp3DFromBS_sig)  # from PV

        # jet/met variables
        self.fillExtraMetInfo(self.tree, event)

        # met filter flags
        self.fill(self.tree, 'pass_met_filters', event.pass_met_filters)

        if len(cleanJets) > 0:
            self.fillJet(self.tree, 'j1', cleanJets[0], fill_extra=False)
        if len(cleanJets) > 1:
            self.fillJet(self.tree, 'j2', cleanJets[1], fill_extra=False)
        if len(cleanBJets) > 0:
            self.fillJet(self.tree, 'bj1', cleanBJets[0], fill_extra=False)
        if len(cleanBJets) > 1:
            self.fillJet(self.tree, 'bj2', cleanBJets[1], fill_extra=False)

        self.fill(self.tree, 'nj', len(cleanJets))
        self.fill(self.tree, 'nj30', len(cleanJets30))
        self.fill(self.tree, 'nbj', len(cleanBJets))

        # FIXME! RM what is this?
        # gen match
        if self.cfg_comp.isMC == True and hasattr(event, 'genParticles'):
            stable_genp = [
                pp for pp in event.genParticles if pp.status() == 1
            ]  # and pp.vertex().z()!=0)]
            stable_genp += [
                pp for pp in event.genp_packed if pp.status() == 1
            ]  # and pp.vertex().z()!=0)]
            # particle status: http://home.thep.lu.se/~torbjorn/pythia81html/ParticleProperties.html
            # 1 ... stable; 23 ... from hardest scattering subprocess
            #            stable_genp += [pp for pp in event.genParticles if (pp.status()==23  and pp.vertex().z()!=0)]
            #            stable_genp += [pp for pp in event.genp_packed  if (pp.status()==23  and pp.vertex().z()!=0)]

            tomatch = [(the_3lep_cand.l0(), 0.05 * 0.05),
                       (the_3lep_cand.l1(), 0.2 * 0.2),
                       (the_3lep_cand.l2(), 0.2 * 0.2)]

            for ilep, idr2 in tomatch:
                bestmatch, dr2 = bestMatch(ilep, stable_genp)
                if (dr2 < idr2 and abs(
                    (ilep.pt() - bestmatch.pt()) / ilep.pt()) < 0.2):
                    ilep.bestmatch = bestmatch

            # relevant for mc: check if reco matched with gen, save a float
            if hasattr(the_3lep_cand.l0(), 'bestmatch'):
                LEP0 = the_3lep_cand.l0()
                self.fillSimpleGenParticle(self.tree, 'l0_gen_match',
                                           LEP0.bestmatch)
                self.fill(self.tree, 'l0_good_match',
                          deltaR(LEP0.bestmatch, LEP0))
#                if deltaR(LEP0.bestmatch, LEP0) < 0.04 and LEP0.pdgId() == LEP0.bestmatch.pdgId():
#                    self.fill(self.tree, 'l0_good_match', 1)

            if hasattr(the_3lep_cand.l1(), 'bestmatch'):
                LEP1 = the_3lep_cand.l1()
                self.fillSimpleGenParticle(self.tree, 'l1_gen_match',
                                           LEP1.bestmatch)
                self.fill(self.tree, 'l1_good_match',
                          deltaR(LEP1.bestmatch, LEP1))
#                if deltaR(LEP1.bestmatch, LEP1) < 0.04 and LEP1.pdgId() == LEP1.bestmatch.pdgId():
#                    self.fill(self.tree, 'l1_good_match', 1)

            if hasattr(the_3lep_cand.l2(), 'bestmatch'):
                LEP2 = the_3lep_cand.l2()
                self.fillSimpleGenParticle(self.tree, 'l2_gen_match',
                                           LEP2.bestmatch)
                self.fill(self.tree, 'l2_good_match',
                          deltaR(LEP2.bestmatch, LEP2))
#                if deltaR(LEP2.bestmatch, LEP2) < 0.04 and LEP2.pdgId() == LEP2.bestmatch.pdgId():
#                    self.fill(self.tree, 'l2_good_match', 1)

# matching by pointer does not work, so let's trick it with deltaR
            if hasattr(event, 'the_hnl'):
                if hasattr(the_3lep_cand.l0(), 'bestmatch'):
                    self.fill(
                        self.tree, 'l0_is_real',
                        deltaR(the_3lep_cand.l0().bestmatch,
                               event.the_hnl.l0()) < 0.01)
                if hasattr(the_3lep_cand.l1(), 'bestmatch'):
                    self.fill(
                        self.tree, 'l1_is_real',
                        deltaR(the_3lep_cand.l1().bestmatch,
                               event.the_hnl.l1()) < 0.05)
                if hasattr(the_3lep_cand.l2(), 'bestmatch'):
                    self.fill(
                        self.tree, 'l2_is_real',
                        deltaR(the_3lep_cand.l2().bestmatch,
                               event.the_hnl.l2()) < 0.05)

            # print('event:', event.eventId, 'lumi:', event.lumi)

        # extra lepton veto
        self.fill(self.tree, 'pass_e_veto', len(event.veto_eles) == 0)
        self.fill(self.tree, 'pass_m_veto', len(event.veto_mus) == 0)

        # LHE weight
        self.fill(self.tree, 'lhe_weight',
                  np.sign(getattr(event, 'LHE_originalWeight', 1.)))

        # weights for ctau reweighing (only for signal!)
        if 'HN3L' in self.cfg_comp.name:
            for iv2 in new_v2s:
                # 'stringify' the coupling
                # reduce precision to avoid nasty numbers e.g. 6.000000000000001e-05
                iv2_name = np.format_float_scientific(iv2,
                                                      unique=False,
                                                      precision=1,
                                                      exp_digits=2)
                iv2_name = iv2_name.replace('-', 'm')
                self.fill(self.tree, 'ctau_w_v2_%s' % iv2_name,
                          event.ctau_weights[iv2]['ctau_weight'])
                self.fill(self.tree, 'xs_w_v2_%s' % iv2_name,
                          event.ctau_weights[iv2]['xs_weight'])
            if event.the_gen_w is not None:
                self.fillParticle(self.tree, 'w_gen', event.the_gen_w)

        self.fill(self.tree, 'pass_mmm', getattr(event, 'pass_mmm', -1.))
        self.fill(self.tree, 'pass_mem', getattr(event, 'pass_mem', -1.))
        self.fill(self.tree, 'pass_eee', getattr(event, 'pass_eee', -1.))
        self.fill(self.tree, 'pass_eem', getattr(event, 'pass_eem', -1.))

        #         import pdb ; pdb.set_trace()

        if fill:
            self.fillTree(event)