def makeXvalEvaluator(evt,
                      modelFile1,
                      modelFile2,
                      modelFile3,
                      modelFile4,
                      modelFile5,
                      input_names,
                      output_names,
                      mvaType="Tensorflow"):
    model_1 = op.mvaEvaluator(modelFile1,
                              mvaType=mvaType,
                              otherArgs=(input_names, output_name))
    model_2 = op.mvaEvaluator(modelFile2,
                              mvaType=mvaType,
                              otherArgs=(input_names, output_name))
    model_3 = op.mvaEvaluator(modelFile3,
                              mvaType=mvaType,
                              otherArgs=(input_names, output_name))
    model_4 = op.mvaEvaluator(modelFile4,
                              mvaType=mvaType,
                              otherArgs=(input_names, output_name))
    model_5 = op.mvaEvaluator(modelFile5,
                              mvaType=mvaType,
                              otherArgs=(input_names, output_name))
    methName = model_1.evaluate._name
    assert model_2.evaluate._name == methName
    assert model_3.evaluate._name == methName
    assert model_4.evaluate._name == methName
    assert model_5.evaluate._name == methName
    switchModelEval = op.multiSwitch((evt % 5 == 0, model_1.evaluate._objStb),
                                     (evt % 5 == 1, model_2.evaluate._objStb),
                                     (evt % 5 == 2, model_3.evaluate._objStb),
                                     (evt % 5 == 3, model_4.evaluate._objStb),
                                     model_5.evaluate._objStb)
    return op.MVAEvaluator(getattr(switchModelEval, methName))
Beispiel #2
0
def makeOddEvenEvaluator(isOdd, oddPath, evenPath, mvaType="TMVA"):
    model_odd  = op.mvaEvaluator(oddPath , mvaType=mvaType)
    model_even = op.mvaEvaluator(evenPath, mvaType=mvaType)
    methName = model_even.evaluate._name
    assert model_odd.evaluate._name == methName
    switchModelEval = op.switch(isOdd, model_odd.evaluate._objStb, model_even.evaluate._objStb)
    return op.MVAEvaluator(getattr(switchModelEval, methName))
    def definePlots(self, t, noSel, sample=None, sampleCfg=None): 
        noSel = super(PlotterNanoHHtobbWWDL,self).prepareObjects(t, noSel, sample, sampleCfg, 'DL')
        #----- Machine Learning Model -----#                
        path_model = os.path.join(os.path.abspath(os.path.dirname(__file__)),'MachineLearning','model.pb')
        if not os.path.exists(path_model):
            raise RuntimeError('Could not find model file %s'%path_model)
        try:
            LBN = op.mvaEvaluator(path_model,mvaType='Tensorflow',otherArgs=(["input_1", "input_2"], "model/output/Softmax"))
        except:
            raise RuntimeError('Could not load model %s'%path_model)

        #---- Parameters -----#

        plots = []

        cutFlowPlots = []

        era = sampleCfg['era']

        self.sample = sample
        self.sampleCfg = sampleCfg
        self.era = era

        self.yieldPlots = makeYieldPlots(self.args.Synchronization)

        #----- Ratio reweighting variables (before lepton and jet selection) -----#
        if self.args.BtagReweightingOff or self.args.BtagReweightingOn:
            plots.append(objectsNumberPlot(channel="NoChannel",suffix='NoSelection',sel=noSel,objCont=self.ak4Jets,objName='Ak4Jets',Nmax=15,xTitle='N(Ak4 jets)'))
            plots.append(CutFlowReport("BtagReweightingCutFlowReport",noSel))
            return plots

        #----- Stitching study -----#
        if self.args.DYStitchingPlots or self.args.WJetsStitchingPlots:
            if self.args.DYStitchingPlots and sampleCfg['group'] != 'DY':
                raise RuntimeError("Stitching is only done on DY MC samples")
            if self.args.WJetsStitchingPlots and sampleCfg['group'] != 'Wjets':
                raise RuntimeError("Stitching is only done on WJets MC samples")
            plots.extend(makeLHEPlots(noSel,t.LHE))
            plots.append(objectsNumberPlot(channel="NoChannel",suffix='NoSelection',sel=noSel,objCont=self.ak4Jets,objName='Ak4Jets',Nmax=15,xTitle='N(Ak4 jets)'))
            plots.append(CutFlowReport("DYStitchingCutFlowReport",noSel))
            return plots


        #----- Dileptons -----#
        selObjectDict = makeDoubleLeptonSelection(self,noSel,plot_yield=True)
        # selObjectDict : keys -> level (str)
        #                 values -> [ElEl,MuMu,ElMu] x Selection object

        # Select the jets selections that will be done depending on user input #
        jet_level = ["Ak4","Ak8","Resolved0Btag","Resolved1Btag","Resolved2Btag","Boosted"]
        jetplot_level = [arg for (arg,boolean) in self.args.__dict__.items() if arg in jet_level and boolean]
        if len(jetplot_level) == 0:  
            jetplot_level = jet_level # If nothing said, will do all
        jetsel_level = copy(jetplot_level)  # A plot level might need a previous selection that needs to be defined but not necessarily plotted
        if "Resolved0Btag" in jetsel_level or "Resolved1Btag" in jetsel_level or "Resolved2Btag" in jetsel_level:
            jetsel_level.append("Ak4") # Resolved needs the Ak4 selection
        if "Boosted" in jetsel_level:
            jetsel_level.append("Ak8") # Boosted needs the Ak8 selection

        # Loop over lepton selection and start plotting #
        for selectionType, selectionList in selObjectDict.items():
            print ("... Processing %s lepton type"%selectionType)
            #----- Select correct dilepton -----#
            if selectionType == "Preselected":  
                OSElElDilepton = self.OSElElDileptonPreSel
                OSMuMuDilepton = self.OSMuMuDileptonPreSel
                OSElMuDilepton = self.OSElMuDileptonPreSel
            elif selectionType == "Fakeable":
                OSElElDilepton = self.ElElDileptonFakeSel
                OSMuMuDilepton = self.MuMuDileptonFakeSel
                OSElMuDilepton = self.ElMuDileptonFakeSel
            elif selectionType == "Tight":
                OSElElDilepton = switch_on_index([0],op.rng_len(self.ElElDileptonTightSel)>=1,self.ElElDileptonTightSel,self.ElElDileptonFakeExtrapolationSel)
                OSMuMuDilepton = switch_on_index([0],op.rng_len(self.MuMuDileptonTightSel)>=1,self.MuMuDileptonTightSel,self.MuMuDileptonFakeExtrapolationSel)
                OSElMuDilepton = switch_on_index([0],op.rng_len(self.ElMuDileptonTightSel)>=1,self.ElMuDileptonTightSel,self.ElMuDileptonFakeExtrapolationSel)
            elif selectionType == "FakeExtrapolation":
                OSElElDilepton = self.ElElDileptonFakeExtrapolationSel
                OSMuMuDilepton = self.MuMuDileptonFakeExtrapolationSel
                OSElMuDilepton = self.ElMuDileptonFakeExtrapolationSel

            #----- Separate selections ------#
            ElElSelObjectDilepton = selectionList[0]
            MuMuSelObjectDilepton = selectionList[1]
            ElMuSelObjectDilepton = selectionList[2]

            #----- Channel and trigger plots -----#

            if not self.args.OnlyYield:
                ChannelDictList = []
                ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDilepton.sel,'suffix':ElElSelObjectDilepton.selName})
                ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDilepton.sel,'suffix':MuMuSelObjectDilepton.selName})
                ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDilepton.sel,'suffix':ElMuSelObjectDilepton.selName})

                for channelDict in ChannelDictList:
                    #----- Trigger plots -----#
                    plots.extend(doubleLeptonTriggerPlots(**channelDict,triggerDict=self.triggersPerPrimaryDataset))
                    #----- Dilepton plots -----#
                    #plots.extend(doubleLeptonChannelPlot(**channelDict,DilepElEl=OSElElDilepton,DilepMuMu=OSMuMuDilepton,DilepElMu=OSElMuDilepton))

            LeptonKeys = ['channel','sel','dilepton','suffix','is_MC']
            JetKeys    = ['channel','sel','leadjet','subleadjet','lead_is_b','sublead_is_b','suffix','is_MC']
            commonItems = ['channel','sel','suffix']
                
            #----- Ak4 jets selection -----#
            if "Ak4" in jetsel_level:
                print ("...... Processing Ak4 jet selection")
                ElElSelObjectDileptonAk4Jets = makeAtLeastTwoAk4JetSelection(self,ElElSelObjectDilepton,copy_sel=True,plot_yield=True)
                MuMuSelObjectDileptonAk4Jets = makeAtLeastTwoAk4JetSelection(self,MuMuSelObjectDilepton,copy_sel=True,plot_yield=True)
                ElMuSelObjectDileptonAk4Jets = makeAtLeastTwoAk4JetSelection(self,ElMuSelObjectDilepton,copy_sel=True,plot_yield=True)

                # Jet and lepton plots #
                ChannelDictList = []
                if "Ak4" in jetplot_level:
                    # Cut flow report #
                    cutFlowPlots.append(CutFlowReport(ElElSelObjectDileptonAk4Jets.selName,ElElSelObjectDileptonAk4Jets.sel))
                    cutFlowPlots.append(CutFlowReport(MuMuSelObjectDileptonAk4Jets.selName,MuMuSelObjectDileptonAk4Jets.sel))
                    cutFlowPlots.append(CutFlowReport(ElMuSelObjectDileptonAk4Jets.selName,ElMuSelObjectDileptonAk4Jets.sel))
                    if not self.args.OnlyYield:
                        ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDileptonAk4Jets.sel,'dilepton':OSElElDilepton[0],'leadjet':self.ak4Jets[0],'subleadjet':self.ak4Jets[1],'lead_is_b':False,'sublead_is_b':False,'suffix':ElElSelObjectDileptonAk4Jets.selName,'is_MC':self.is_MC})
                        ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDileptonAk4Jets.sel,'dilepton':OSMuMuDilepton[0],'leadjet':self.ak4Jets[0],'subleadjet':self.ak4Jets[1],'lead_is_b':False,'sublead_is_b':False,'suffix':MuMuSelObjectDileptonAk4Jets.selName,'is_MC':self.is_MC})
                        ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDileptonAk4Jets.sel,'dilepton':OSElMuDilepton[0],'leadjet':self.ak4Jets[0],'subleadjet':self.ak4Jets[1],'lead_is_b':False,'sublead_is_b':False,'suffix':ElMuSelObjectDileptonAk4Jets.selName,'is_MC':self.is_MC})

                JetsN = {'objName':'Ak4Jets','objCont':self.ak4Jets,'Nmax':15,'xTitle':'N(Ak4 jets)'}
                                                            
                for channelDict in ChannelDictList:
                    # Dilepton #
                    plots.extend(makeDileptonPlots(**{k:channelDict[k] for k in LeptonKeys}))
                    # Number of jets #
                    plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**JetsN))
                    # Ak4 Jets #
                    plots.extend(makeTwoAk4JetsPlots(**{k:channelDict[k] for k in JetKeys}))
                    # MET #
                    plots.extend(makeMETPlots(**{k:channelDict[k] for k in commonItems}, met=self.corrMET))

            ##### Ak8 jets selection #####
            if "Ak8" in jetsel_level:
                print ("...... Processing Ak8 jet selection")
                ElElSelObjectDileptonAk8Jets = makeAtLeastOneAk8JetSelection(self,ElElSelObjectDilepton,copy_sel=True,plot_yield=True)
                MuMuSelObjectDileptonAk8Jets = makeAtLeastOneAk8JetSelection(self,MuMuSelObjectDilepton,copy_sel=True,plot_yield=True)
                ElMuSelObjectDileptonAk8Jets = makeAtLeastOneAk8JetSelection(self,ElMuSelObjectDilepton,copy_sel=True,plot_yield=True)

                # Fatjets plots #
                ChannelDictList = []
                if "Ak8" in jetplot_level:
                    # Cut flow report #
                    cutFlowPlots.append(CutFlowReport(ElElSelObjectDileptonAk8Jets.selName,ElElSelObjectDileptonAk8Jets.sel))
                    cutFlowPlots.append(CutFlowReport(MuMuSelObjectDileptonAk8Jets.selName,MuMuSelObjectDileptonAk8Jets.sel))
                    cutFlowPlots.append(CutFlowReport(ElMuSelObjectDileptonAk8Jets.selName,ElMuSelObjectDileptonAk8Jets.sel))
                    if not self.args.OnlyYield:
                        ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDileptonAk8Jets.sel,'dilepton':OSElElDilepton[0],'fatjet':self.ak8Jets[0],'suffix':ElElSelObjectDileptonAk8Jets.selName,'is_MC':self.is_MC})
                        ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDileptonAk8Jets.sel,'dilepton':OSMuMuDilepton[0],'fatjet':self.ak8Jets[0],'suffix':MuMuSelObjectDileptonAk8Jets.selName,'is_MC':self.is_MC})
                        ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDileptonAk8Jets.sel,'dilepton':OSElMuDilepton[0],'fatjet':self.ak8Jets[0],'suffix':ElMuSelObjectDileptonAk8Jets.selName,'is_MC':self.is_MC})

                FatJetKeys = ['channel','sel','fatjet','suffix']
                FatJetsN = {'objName':'Ak8Jets','objCont':self.ak8Jets,'Nmax':5,'xTitle':'N(Ak8 jets)'}
                
                for channelDict in ChannelDictList:
                    # Dilepton #
                    plots.extend(makeDileptonPlots(**{k:channelDict[k] for k in LeptonKeys}))
                    # Number of jets #
                    plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**FatJetsN))
                    # Ak8 Jets #
                    plots.extend(makeDoubleLeptonAk8JetsPlots(**{k:channelDict[k] for k in FatJetKeys}))
                    # MET #
                    plots.extend(makeMETPlots(**{k:channelDict[k] for k in commonItems}, met=self.corrMET))

                         
            #----- Resolved selection -----#
            if any(item in ["Resolved0Btag","Resolved1Btag","Resolved2Btag"] for item in jetsel_level): # If any of resolved category is asked
                #----- select the jets -----#
                aka4JetsByBtagScore = op.sort(self.ak4Jets, lambda jet : -jet.btagDeepFlavB)

                container0b2j = [ t.Jet[self.ak4LightJetsByBtagScore[i].idx] for i in range(2) ]
                container1b1j = [ t.Jet[op.switch(op.rng_len(self.ak4BJets) == 1, self.ak4BJets[0].idx,  aka4JetsByBtagScore[0].idx)] ,
                                  t.Jet[op.switch(op.rng_len(self.ak4BJets) == 1, self.ak4LightJetsByBtagScore[0].idx,  aka4JetsByBtagScore[1].idx)]]
                container2b0j = [ t.Jet[op.switch(op.rng_len(self.ak4BJets) >= 2, self.ak4BJets[i].idx, aka4JetsByBtagScore[i].idx)] for i in range(2) ]

                ChannelDictList = []
                #----- Resolved selection : 0 Btag -----#
                if "Resolved0Btag" in jetsel_level:
                    print ("...... Processing Resolved jet (0 btag) selection")
                    ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag = makeExclusiveResolvedNoBtagSelection(self,ElElSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)
                    MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag = makeExclusiveResolvedNoBtagSelection(self,MuMuSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)
                    ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag = makeExclusiveResolvedNoBtagSelection(self,ElMuSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)

                    if "Resolved0Btag" in jetplot_level:
                        # Cut flow report #
                        cutFlowPlots.append(CutFlowReport(ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName,ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel))
                        cutFlowPlots.append(CutFlowReport(MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName,MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel))
                        cutFlowPlots.append(CutFlowReport(ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName,ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel))
                        if not self.args.OnlyYield:
                            ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel,'dilepton':OSElElDilepton[0],'leadjet':container0b2j[0],'subleadjet':container0b2j[1],'lead_is_b':False,'sublead_is_b':False,'suffix':ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName,'is_MC':self.is_MC})
                            ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel,'dilepton':OSMuMuDilepton[0],'leadjet':container0b2j[0],'subleadjet':container0b2j[1],'lead_is_b':False,'sublead_is_b':False,'suffix':MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName,'is_MC':self.is_MC})
                            ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel,'dilepton':OSElMuDilepton[0],'leadjet':container0b2j[0],'subleadjet':container0b2j[1],'lead_is_b':False,'sublead_is_b':False,'suffix':ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName,'is_MC':self.is_MC})
                #----  Resolved selection : 1 Btag  -----#
                if "Resolved1Btag" in jetsel_level:
                    print ("...... Processing Resolved jet (1 btag) selection")
                    ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag = makeExclusiveResolvedOneBtagSelection(self,ElElSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)
                    MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag = makeExclusiveResolvedOneBtagSelection(self,MuMuSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)
                    ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag = makeExclusiveResolvedOneBtagSelection(self,ElMuSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)

                    if "Resolved1Btag" in jetplot_level:
                        # Cut flow report #
                        cutFlowPlots.append(CutFlowReport(ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName,ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel))
                        cutFlowPlots.append(CutFlowReport(MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName,MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel))
                        cutFlowPlots.append(CutFlowReport(ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName,ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel))
                        if not self.args.OnlyYield:
                            ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel,'dilepton':OSElElDilepton[0],'leadjet':container1b1j[0],'subleadjet':container1b1j[1],'lead_is_b':True,'sublead_is_b':False,'suffix':ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName,'is_MC':self.is_MC})
                            ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel,'dilepton':OSMuMuDilepton[0],'leadjet':container1b1j[0],'subleadjet':container1b1j[1],'lead_is_b':True,'sublead_is_b':False,'suffix':MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName,'is_MC':self.is_MC})
                            ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel,'dilepton':OSElMuDilepton[0],'leadjet':container1b1j[0],'subleadjet':container1b1j[1],'lead_is_b':True,'sublead_is_b':False,'suffix':ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName,'is_MC':self.is_MC})
                #----- Resolved selection : 2 Btags -----#
                if "Resolved2Btag" in jetsel_level:
                    print ("...... Processing Resolved jet (2 btags) selection")
                    ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags = makeExclusiveResolvedTwoBtagsSelection(self,ElElSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)
                    MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags = makeExclusiveResolvedTwoBtagsSelection(self,MuMuSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)
                    ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags = makeExclusiveResolvedTwoBtagsSelection(self,ElMuSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)

                    if "Resolved2Btag" in jetplot_level:
                        # Cut flow report #
                        cutFlowPlots.append(CutFlowReport(ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName,ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel))
                        cutFlowPlots.append(CutFlowReport(MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName,MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel))
                        cutFlowPlots.append(CutFlowReport(ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName,ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel))
                        if not self.args.OnlyYield:
                            ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel,'dilepton':OSElElDilepton[0],'leadjet':container2b0j[0],'subleadjet':container2b0j[1],'lead_is_b':True,'sublead_is_b':True,'suffix':ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName,'is_MC':self.is_MC})
                            ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel,'dilepton':OSMuMuDilepton[0],'leadjet':container2b0j[0],'subleadjet':container2b0j[1],'lead_is_b':True,'sublead_is_b':True,'suffix':MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName,'is_MC':self.is_MC})
                            ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel,'dilepton':OSElMuDilepton[0],'leadjet':container2b0j[0],'subleadjet':container2b0j[1],'lead_is_b':True,'sublead_is_b':True,'suffix':ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName,'is_MC':self.is_MC})

                # Lepton + jet Plots #

                ResolvedJetsN = {'objName':'Ak4BJets','objCont':self.ak4BJets,'Nmax':5,'xTitle':'N(Ak4 Bjets)'}
        
                for channelDict in ChannelDictList:
                    # Dilepton #
                    plots.extend(makeDileptonPlots(**{k:channelDict[k] for k in LeptonKeys}))
                    # Number of jets #
                    plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**ResolvedJetsN))
                    plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**JetsN))
                    # Ak4 Jets #
                    plots.extend(makeTwoAk4JetsPlots(**{k:channelDict[k] for k in JetKeys}))
                    # MET #
                    plots.extend(makeMETPlots(**{k:channelDict[k] for k in commonItems}, met=self.corrMET))
            
            #----- Boosted selection -----#
            if "Boosted" in jetsel_level:
                print ("...... Processing Boosted jet selection")
                ElElSelObjectDileptonAk8JetsInclusiveBoosted = makeInclusiveBoostedSelection(self,ElElSelObjectDileptonAk8Jets,copy_sel=True,plot_yield=True)
                MuMuSelObjectDileptonAk8JetsInclusiveBoosted = makeInclusiveBoostedSelection(self,MuMuSelObjectDileptonAk8Jets,copy_sel=True,plot_yield=True)
                ElMuSelObjectDileptonAk8JetsInclusiveBoosted = makeInclusiveBoostedSelection(self,ElMuSelObjectDileptonAk8Jets,copy_sel=True,plot_yield=True)

                # Lepton + jet Plots #
                ChannelDictList = []
                if "Boosted" in jetplot_level:
                    # Cut flow report #
                    cutFlowPlots.append(CutFlowReport(ElElSelObjectDileptonAk8JetsInclusiveBoosted.selName,ElElSelObjectDileptonAk8JetsInclusiveBoosted.sel))
                    cutFlowPlots.append(CutFlowReport(MuMuSelObjectDileptonAk8JetsInclusiveBoosted.selName,MuMuSelObjectDileptonAk8JetsInclusiveBoosted.sel))
                    cutFlowPlots.append(CutFlowReport(ElMuSelObjectDileptonAk8JetsInclusiveBoosted.selName,ElMuSelObjectDileptonAk8JetsInclusiveBoosted.sel))
                    if not self.args.OnlyYield:
                        ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDileptonAk8JetsInclusiveBoosted.sel,'dilepton':OSElElDilepton[0],'fatjet':self.ak8BJets[0],'suffix':ElElSelObjectDileptonAk8JetsInclusiveBoosted.selName,'is_MC':self.is_MC})
                        ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDileptonAk8JetsInclusiveBoosted.sel,'dilepton':OSMuMuDilepton[0],'fatjet':self.ak8BJets[0],'suffix':MuMuSelObjectDileptonAk8JetsInclusiveBoosted.selName,'is_MC':self.is_MC})
                        ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDileptonAk8JetsInclusiveBoosted.sel,'dilepton':OSElMuDilepton[0],'fatjet':self.ak8BJets[0],'suffix':ElMuSelObjectDileptonAk8JetsInclusiveBoosted.selName,'is_MC':self.is_MC})

                BoostedJetsN = {'objName':'Ak8BJets','objCont':self.ak8BJets,'Nmax':5,'xTitle':'N(Ak8 Bjets)'}
                
                for channelDict in ChannelDictList:
                    # Dilepton #
                    plots.extend(makeDileptonPlots(**{k:channelDict[k] for k in LeptonKeys}))
                    # Number of jets #
                    plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**BoostedJetsN))
                    plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**FatJetsN))
                    # Ak8 Jets #
                    plots.extend(makeDoubleLeptonAk8JetsPlots(**{k:channelDict[k] for k in FatJetKeys}))
                    # MET #
                    plots.extend(makeMETPlots(**{k:channelDict[k] for k in commonItems}, met=self.corrMET))
            
            #----- High-level combinations -----#
            # NOTE : very time consuming 
            ChannelDictList = []
            if not self.args.OnlyYield:
                # Resolved No Btag #
                if "Resolved0Btag" in jetplot_level:
                    ChannelDictList.append({'channel': 'ElEl','met': self.corrMET,'l1':OSElElDilepton[0][0],'l2':OSElElDilepton[0][1],'j1':container0b2j[0],'j2':container0b2j[1],'sel':ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel,'suffix':ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName})
                    ChannelDictList.append({'channel': 'MuMu','met': self.corrMET,'l1':OSMuMuDilepton[0][0],'l2':OSMuMuDilepton[0][1],'j1':container0b2j[0],'j2':container0b2j[1],'sel':MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel,'suffix':MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName})
                    ChannelDictList.append({'channel': 'ElMu','met': self.corrMET,'l1':OSElMuDilepton[0][0],'l2':OSElMuDilepton[0][1],'j1':container0b2j[0],'j2':container0b2j[1],'sel':ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel,'suffix':ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName})
                # Resolved One Btag #
                if "Resolved1Btag" in jetplot_level:
                    ChannelDictList.append({'channel': 'ElEl','met': self.corrMET,'l1':OSElElDilepton[0][0],'l2':OSElElDilepton[0][1],'j1':container1b1j[0],'j2':container1b1j[1],'sel':ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel,'suffix':ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName})
                    ChannelDictList.append({'channel': 'MuMu','met': self.corrMET,'l1':OSMuMuDilepton[0][0],'l2':OSMuMuDilepton[0][1],'j1':container1b1j[0],'j2':container1b1j[1],'sel':MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel,'suffix':MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName})
                    ChannelDictList.append({'channel': 'ElMu','met': self.corrMET,'l1':OSElMuDilepton[0][0],'l2':OSElMuDilepton[0][1],'j1':container1b1j[0],'j2':container1b1j[1],'sel':ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel,'suffix':ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName})
                # Resolved Two Btags  #
                if "Resolved2Btag" in jetplot_level:
                    ChannelDictList.append({'channel': 'ElEl','met': self.corrMET,'l1':OSElElDilepton[0][0],'l2':OSElElDilepton[0][1],'j1':container2b0j[0],'j2':container2b0j[1],'sel':ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel,'suffix':ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName})
                    ChannelDictList.append({'channel': 'MuMu','met': self.corrMET,'l1':OSMuMuDilepton[0][0],'l2':OSMuMuDilepton[0][1],'j1':container2b0j[0],'j2':container2b0j[1],'sel':MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel,'suffix':MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName})
                    ChannelDictList.append({'channel': 'ElMu','met': self.corrMET,'l1':OSElMuDilepton[0][0],'l2':OSElMuDilepton[0][1],'j1':container2b0j[0],'j2':container2b0j[1],'sel':ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel,'suffix':ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName})
                # Boosted #
                if "Boosted" in jetplot_level:
                    ChannelDictList.append({'channel': 'ElEl','met': self.corrMET,'l1':OSElElDilepton[0][0],'l2':OSElElDilepton[0][1],'j1':self.ak8BJets[0].subJet1,'j2':self.ak8BJets[0].subJet2,'sel':ElElSelObjectDileptonAk8JetsInclusiveBoosted.sel,'suffix':ElElSelObjectDileptonAk8JetsInclusiveBoosted.selName})
                    ChannelDictList.append({'channel': 'MuMu','met': self.corrMET,'l1':OSMuMuDilepton[0][0],'l2':OSMuMuDilepton[0][1],'j1':self.ak8BJets[0].subJet1,'j2':self.ak8BJets[0].subJet2,'sel':MuMuSelObjectDileptonAk8JetsInclusiveBoosted.sel,'suffix':MuMuSelObjectDileptonAk8JetsInclusiveBoosted.selName})
                    ChannelDictList.append({'channel': 'ElMu','met': self.corrMET,'l1':OSElMuDilepton[0][0],'l2':OSElMuDilepton[0][1],'j1':self.ak8BJets[0].subJet1,'j2':self.ak8BJets[0].subJet2,'sel':ElMuSelObjectDileptonAk8JetsInclusiveBoosted.sel,'suffix':ElMuSelObjectDileptonAk8JetsInclusiveBoosted.selName})

            for channelDict in ChannelDictList:
                plots.extend(makeDoubleLeptonHighLevelQuantities(**channelDict,HLL=self.HLL))

            #----- Machine Learning plots -----#
            selObjectDictList = []
            if not self.args.OnlyYield:
                if "Ak4" in jetplot_level:
                    selObjectDictList.append({'channel':'ElEl','selObject':ElElSelObjectDileptonAk4Jets})
                    selObjectDictList.append({'channel':'MuMu','selObject':MuMuSelObjectDileptonAk4Jets})
                    selObjectDictList.append({'channel':'ElMu','selObject':ElMuSelObjectDileptonAk4Jets})
#                if "Ak8" in jetplot_level:
#                    selObjectDictList.append({'channel':'ElEl','selObject':ElElSelObjectDileptonAk8Jets})
#                    selObjectDictList.append({'channel':'MuMu','selObject':MuMuSelObjectDileptonAk8Jets})
#                    selObjectDictList.append({'channel':'ElMu','selObject':ElMuSelObjectDileptonAk8Jets})
                if "Resolved0Btag" in jetplot_level:
                    selObjectDictList.append({'channel':'ElEl','selObject':ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag})
                    selObjectDictList.append({'channel':'MuMu','selObject':MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag})
                    selObjectDictList.append({'channel':'ElMu','selObject':ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag})
                if "Resolved1Btag" in jetplot_level:
                    selObjectDictList.append({'channel':'ElEl','selObject':ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag})
                    selObjectDictList.append({'channel':'MuMu','selObject':MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag})
                    selObjectDictList.append({'channel':'ElMu','selObject':ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag})
                if "Resolved2Btag" in jetplot_level:
                    selObjectDictList.append({'channel':'ElEl','selObject':ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags})
                    selObjectDictList.append({'channel':'MuMu','selObject':MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags})
                    selObjectDictList.append({'channel':'ElMu','selObject':ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags})
#                if "Boosted" in jetplot_level:
#                    selObjectDictList.append({'channel':'ElEl','selObject':ElElSelObjectDileptonAk8JetsInclusiveBoosted})
#                    selObjectDictList.append({'channel':'MuMu','selObject':MuMuSelObjectDileptonAk8JetsInclusiveBoosted})
#                    selObjectDictList.append({'channel':'ElMu','selObject':ElMuSelObjectDileptonAk8JetsInclusiveBoosted})

            dileptons = {'ElEl':OSElElDilepton[0],'MuMu':OSMuMuDilepton[0],'ElMu':OSElMuDilepton[0]}
            for selObjectDict in selObjectDictList:
                dilepton = dileptons[selObjectDict['channel']]
                plots.extend(makeDoubleLeptonMachineLearningPlots(channel=selObjectDict['channel'],l1=dilepton[0],l2=dilepton[1],jets=self.ak4Jets,sel=selObjectDict['selObject'].sel,suffix=selObjectDict['selObject'].selName,model=LBN))
    
        #----- Add the Yield plots -----#
        plots.extend(self.yieldPlots.returnPlots())

        #plots.extend(cutFlowPlots)

        #----- Return -----#
        return plots
Beispiel #4
0
    def definePlots(self, t, noSel, sample=None, sampleCfg=None): 
        noSel = super(PlotterNanoHHtobbWWSL,self).prepareObjects(t, noSel, sample, sampleCfg, 'SL')
        # --------------------------- Machine Learning Model --------------------------- #
        # -------- for JPA --------- #
        era = sampleCfg['era']
        # ----------------------------------- NodeList ------------------------------------- #
        # keep the exact same order of nodes as mentioned in respective xml files
        ResolvedJPANodeList = ['2b2Wj','2b1Wj','1b2Wj','2b0Wj','1b1Wj','1b0Wj','0b']
        BoostedJPANodeList  = ['Hbb2Wj','Hbb1Wj','Hbb0Wj']

        basepath = os.path.join(os.path.abspath(os.path.dirname(__file__)),'MachineLearning','ml-models','JPA_Loose_ttH')
        resolvedModelDict = getResolvedJpaModelDict(basepath, ResolvedJPANodeList, era)        
        boostedModelDict  = getBoostedJpaModelDict(basepath, BoostedJPANodeList, era)
        
        # ---------- LBN+DNN models ----------- #
        #path_model_resolved = os.path.join('/home/ucl/cp3/gsaha/bamboodev/HHbbWWAnalysis/MachineLearning/ml-models/DNN/Resolved','Resolved'+str(era)+'.pb')
        #path_model_boosted  = os.path.join('/home/ucl/cp3/gsaha/bamboodev/HHbbWWAnalysis/MachineLearning/ml-models/DNN/Boosted','Boosted_allEras_x512.pb')
        path_model_resolved_SM  = os.path.join('/home/ucl/cp3/gsaha/bamboodev/HHbbWWAnalysis/MachineLearning/ml-models/DNN/Resolved','Resolved'+str(era)+'SMv2.pb')
        #        path_model_resolved_BSM = os.path.join('/home/ucl/cp3/gsaha/bamboodev/HHbbWWAnalysis/MachineLearning/ml-models/DNN/Resolved','Resolved'+str(era)+'BSMv2.pb')
        #        path_model_resolved_BSM = os.path.join('/home/ucl/cp3/gsaha/bamboodev/HHbbWWAnalysis/MachineLearning/ml-models/DNN/Resolved','Resolved'+str(era)+'BSMv3_w0p1.pb')
        path_model_resolved_BSM = os.path.join('/home/ucl/cp3/gsaha/bamboodev/HHbbWWAnalysis/MachineLearning/ml-models/DNN/Resolved','Resolved'+str(era)+'BSMv3_w1.pb')
        path_model_boosted_SM   = os.path.join('/home/ucl/cp3/gsaha/bamboodev/HHbbWWAnalysis/MachineLearning/ml-models/DNN/Boosted','BoostedSMv2.pb')
        #        path_model_boosted_BSM  = os.path.join('/home/ucl/cp3/gsaha/bamboodev/HHbbWWAnalysis/MachineLearning/ml-models/DNN/Boosted','BoostedBSMv2.pb')
        #        path_model_boosted_BSM  = os.path.join('/home/ucl/cp3/gsaha/bamboodev/HHbbWWAnalysis/MachineLearning/ml-models/DNN/Boosted','BoostedBSMv3_w0p1_256x4.pb')
        path_model_boosted_BSM  = os.path.join('/home/ucl/cp3/gsaha/bamboodev/HHbbWWAnalysis/MachineLearning/ml-models/DNN/Boosted','BoostedBSMv3_w1_256x4.pb')
        logger.info('DNN_Model_Resolved SM : {}'.format(path_model_resolved_SM))
        logger.info('DNN_Model_Resolved BSM : {}'.format(path_model_resolved_BSM))
        logger.info('DNN_Model_Boosted SM : {}'.format(path_model_boosted_SM))
        logger.info('DNN_Model_Boosted BSM : {}'.format(path_model_boosted_BSM))
        plots = []
        cutFlowPlots = []
        
        self.sample = sample
        self.sampleCfg = sampleCfg
        self.era = era
        
        self.yieldPlots = makeYieldPlots(self.args.Synchronization)
        
        #----- Ratio reweighting variables (before lepton and jet selection) -----#
        #if self.args.BtagReweightingOff or self.args.BtagReweightingOn:
        #    #plots.append(objectsNumberPlot(channel="NoChannel",suffix='NoSelection',sel=noSel,objCont=self.ak4Jets,objName='Ak4Jets',Nmax=15,xTitle='N(Ak4 jets)'))
        #    #plots.append(CutFlowReport("BtagReweightingCutFlowReport",noSel))
        #    return plots
            
        #----- Stitching study -----#
        if self.args.DYStitchingPlots or self.args.WJetsStitchingPlots:
            if self.args.DYStitchingPlots and sampleCfg['group'] != 'DY':
                raise RuntimeError("Stitching is only done on DY MC samples")
            if self.args.WJetsStitchingPlots and sampleCfg['group'] != 'Wjets':
                raise RuntimeError("Stitching is only done on WJets MC samples")
            #plots.extend(makeLHEPlots(noSel,t.LHE))
            #plots.append(objectsNumberPlot(channel="NoChannel",suffix='NoSelection',sel=noSel,objCont=self.ak4Jets,objName='Ak4Jets',Nmax=15,xTitle='N(Ak4 jets)'))
            #plots.append(CutFlowReport("DYStitchingCutFlowReport",noSel))
            return plots
            
            
        #----- Singleleptons -----#
        ElSelObj,MuSelObj = makeSingleLeptonSelection(self,noSel,plot_yield=True)

        #----- Apply jet corrections -----#
        ElSelObject.sel = self.beforeJetselection(ElSelObj.sel,'El')
        MuSelObject.sel = self.beforeJetselection(MuSelObj.sel,'Mu')

        # selObjectDict : keys -> level (str)
        #                 values -> [El,Mu] x Selection object
        # Select the jets selections that will be done depending on user input #
        resolved_args = ["Res2b2Wj","Res2b1Wj","Res1b2Wj","Res2b0Wj","Res1b1Wj","Res1b0Wj","Res0b","Resolved"]
        boosted_args  = ["Hbb2Wj","Hbb1Wj","Hbb0Wj","Boosted"]
        jet_level = resolved_args + boosted_args
        jet_level.append("Ak4")  # to call all resolved categories
        jet_level.append("Ak8")  # to call all boosted categories
        jetplot_level = [arg for (arg,boolean) in self.args.__dict__.items() if arg in jet_level and boolean]
        if len(jetplot_level) == 0:  
            jetplot_level = jet_level # If nothing said, will do all
        jetsel_level = copy(jetplot_level)  # A plot level might need a previous selection that needs to be defined but not necessarily plotted

        if any(item in boosted_args for item in jetsel_level):
            jetsel_level.append("Ak8") # SemiBoosted & Boosted needs the Ak8 selection
        if any(item in resolved_args for item in jetsel_level):
            jetsel_level.append("Ak4") # Resolved needs the Ak4 selection 

        logger.info ('jetSel_Level: {}'.format(jetsel_level))
            
        # Selections:    
        #---- Lepton selection ----#
        ElColl = [t.Electron[op.switch(op.rng_len(self.electronsTightSel) == 1, 
                                       self.electronsTightSel[0].idx, 
                                       self.electronsFakeSel[0].idx)]]
        MuColl = [t.Muon[op.switch(op.rng_len(self.muonsTightSel) == 1, 
                                   self.muonsTightSel[0].idx, 
                                   self.muonsFakeSel[0].idx)]]

        '''
        if not self.args.OnlyYield:
            ChannelDictList = []
            ChannelDictList.append({'channel':'El','sel':ElSelObj.sel,'suffix':ElSelObj.selName})
            ChannelDictList.append({'channel':'Mu','sel':MuSelObj.sel,'suffix':MuSelObj.selName})
            for channelDict in ChannelDictList:
                #----- Trigger plots -----#
                plots.extend(singleLeptonTriggerPlots(**channelDict, triggerDict=self.triggersPerPrimaryDataset))
        '''

        LeptonKeys   = ['channel','sel','lepton','suffix','is_MC']
        JetKeys      = ['channel','sel','jet1','jet2','jet3','jet4','suffix','nJet','nbJet','is_MC']
        commonItems  = ['channel','sel','suffix']
            
        #----- Ak4 jets selection -----#
        if "Ak4" in jetsel_level:
            logger.info ("... Processing Ak4Jets Selection for Resolved category : nAk4Jets >= 3")

            ElSelObjResolved = makeResolvedSelection(self,ElSelObj,copy_sel=True,plot_yield=True)
            MuSelObjResolved = makeResolvedSelection(self,MuSelObj,copy_sel=True,plot_yield=True)
        
        #----- Ak8-b jets selection -----#
        if "Ak8" in jetsel_level:
            logger.info ("...... Processing Ak8b jet selection for SemiBoosted & Boosted Category")

            ElSelObjBoosted = makeBoostedSelection(self,ElSelObj,copy_sel=True,plot_yield=True)
            MuSelObjBoosted = makeBoostedSelection(self,MuSelObj,copy_sel=True,plot_yield=True)
            

        self.nodes       = ['Ewk','GGF','H','Top','VBF','WJets']
        inputsEventNr    = returnEventNr(self, t)
        output_name      = "Identity"
        ClassicInputKeys = ['lepton','jpaSelectedJets','L1out','L2out','jpaArg']
        LBNInputKeys     = ['lepton','jet1','jet2','jet3','jet4']

        # ========================== JPA Resolved Categories ========================= #
        if any(item in resolved_args for item in jetsel_level):
            ChannelDictListR = []

            # dict = {'key':'Node', 'value' : [refined selObj, [JPAjetIndices]]}
            elL1OutList, elL2OutList, ElResolvedSelObjJetsIdxPerJpaNodeDict = findJPACategoryResolved (self, ElSelObjResolved, ElColl[0],self.muonsPreSel, self.electronsPreSel, 
                                                                                                       self.ak4Jets, self.ak4BJetsLoose,self.ak4BJets, self.corrMET, 
                                                                                                       resolvedModelDict, t.event,self.HLL, ResolvedJPANodeList, 
                                                                                                       plot_yield=True)
            muL1OutList, muL2OutList, MuResolvedSelObjJetsIdxPerJpaNodeDict = findJPACategoryResolved (self, MuSelObjResolved, MuColl[0],self.muonsPreSel, self.electronsPreSel, 
                                                                                                       self.ak4Jets, self.ak4BJetsLoose,self.ak4BJets, self.corrMET, 
                                                                                                       resolvedModelDict, t.event,self.HLL, ResolvedJPANodeList,
                                                                                                       plot_yield=True)

            if "Res2b2Wj" in jetplot_level or "Resolved" in jetplot_level:
                logger.info ('...... JPA : 2b2Wj Node Selection')
                ElSelObjResolved2b2Wj        = ElResolvedSelObjJetsIdxPerJpaNodeDict.get('2b2Wj')[0]
                ElSelObjResolved2b2WjJets    = ElResolvedSelObjJetsIdxPerJpaNodeDict.get('2b2Wj')[1]
                MuSelObjResolved2b2Wj        = MuResolvedSelObjJetsIdxPerJpaNodeDict.get('2b2Wj')[0]
                MuSelObjResolved2b2WjJets    = MuResolvedSelObjJetsIdxPerJpaNodeDict.get('2b2Wj')[1]

                if self.args.onlypost:
                    ElSelObjResolved2b2Wj.record_yields = True
                    MuSelObjResolved2b2Wj.record_yields = True
                    ElSelObjResolved2b2Wj.yieldTitle = 'Resolved2b2Wj Channel $e^{\pm}$'
                    MuSelObjResolved2b2Wj.yieldTitle = 'Resolved2b2Wj Channel $\mu^{\pm}$'
                
                if not self.args.OnlyYield:
                    ChannelDictListR.append({'channel':'El','selObj':ElSelObjResolved2b2Wj,'sel':ElSelObjResolved2b2Wj.sel,
                                             'lepton':ElColl[0],'met':self.corrMET,'jpaSelectedJets':ElSelObjResolved2b2WjJets,
                                             'jet1':ElSelObjResolved2b2WjJets[0],'jet2':ElSelObjResolved2b2WjJets[1],
                                             'jet3':ElSelObjResolved2b2WjJets[2],'jet4':ElSelObjResolved2b2WjJets[3],
                                             'nJet':4,'nbJet':2,'suffix':ElSelObjResolved2b2Wj.selName,
                                             'is_MC':self.is_MC,'jpaArg':'Res2b2Wj'})
                    ChannelDictListR.append({'channel':'Mu','selObj':MuSelObjResolved2b2Wj,'sel':MuSelObjResolved2b2Wj.sel,
                                             'lepton':MuColl[0],'met':self.corrMET,'jpaSelectedJets':MuSelObjResolved2b2WjJets,
                                             'jet1':MuSelObjResolved2b2WjJets[0],'jet2':MuSelObjResolved2b2WjJets[1],
                                             'jet3':MuSelObjResolved2b2WjJets[2],'jet4':MuSelObjResolved2b2WjJets[3],
                                             'nJet':4,'nbJet':2,'suffix':MuSelObjResolved2b2Wj.selName,
                                             'is_MC':self.is_MC,'jpaArg':'Res2b2Wj'})
                    
            if "Res2b1Wj" in jetplot_level or "Resolved" in jetplot_level:
                logger.info ('...... JPA : 2b1Wj Node Selection')
                ElSelObjResolved2b1Wj        = ElResolvedSelObjJetsIdxPerJpaNodeDict.get('2b1Wj')[0]
                ElSelObjResolved2b1WjJets    = ElResolvedSelObjJetsIdxPerJpaNodeDict.get('2b1Wj')[1]
                MuSelObjResolved2b1Wj        = MuResolvedSelObjJetsIdxPerJpaNodeDict.get('2b1Wj')[0]
                MuSelObjResolved2b1WjJets    = MuResolvedSelObjJetsIdxPerJpaNodeDict.get('2b1Wj')[1]

                if self.args.onlypost:
                    ElSelObjResolved2b1Wj.record_yields = True
                    MuSelObjResolved2b1Wj.record_yields = True
                    ElSelObjResolved2b1Wj.yieldTitle = 'Resolved2b1Wj Channel $e^{\pm}$'
                    MuSelObjResolved2b1Wj.yieldTitle = 'Resolved2b1Wj Channel $\mu^{\pm}$'
                
                if not self.args.OnlyYield:
                    ChannelDictListR.append({'channel':'El','selObj':ElSelObjResolved2b1Wj,'sel':ElSelObjResolved2b1Wj.sel,
                                            'lep':ElColl[0],'met':self.corrMET,'jpaSelectedJets':ElSelObjResolved2b1WjJets,
                                            'jet1':ElSelObjResolved2b1WjJets[0],'jet2':ElSelObjResolved2b1WjJets[1],
                                            'jet3':ElSelObjResolved2b1WjJets[2],'jet4':None,
                                            'nJet':3,'nbJet':2,'suffix':ElSelObjResolved2b1Wj.selName,
                                            'is_MC':self.is_MC, 'jpaArg':'Res2b1Wj'})
                    ChannelDictListR.append({'channel':'Mu','selObj':MuSelObjResolved2b1Wj,'sel':MuSelObjResolved2b1Wj.sel,
                                            'lep':MuColl[0],'met':self.corrMET,'jpaSelectedJets':MuSelObjResolved2b1WjJets,
                                            'jet1':MuSelObjResolved2b1WjJets[0],'jet2':MuSelObjResolved2b1WjJets[1],
                                            'jet3':MuSelObjResolved2b1WjJets[2],'jet4':None,
                                            'nJet':3,'nbJet':2,'suffix':MuSelObjResolved2b1Wj.selName,
                                            'is_MC':self.is_MC, 'jpaArg':'Res2b1Wj'})
                    
            if "Res1b2Wj" in jetplot_level or "Resolved" in jetplot_level:
                logger.info ('...... JPA : 1b2Wj Node Selection')
                ElSelObjResolved1b2Wj        = ElResolvedSelObjJetsIdxPerJpaNodeDict.get('1b2Wj')[0]
                ElSelObjResolved1b2WjJets    = ElResolvedSelObjJetsIdxPerJpaNodeDict.get('1b2Wj')[1]
                MuSelObjResolved1b2Wj        = MuResolvedSelObjJetsIdxPerJpaNodeDict.get('1b2Wj')[0]
                MuSelObjResolved1b2WjJets    = MuResolvedSelObjJetsIdxPerJpaNodeDict.get('1b2Wj')[1]
                
                if self.args.onlypost:
                    ElSelObjResolved1b2Wj.record_yields = True
                    MuSelObjResolved1b2Wj.record_yields = True
                    ElSelObjResolved1b2Wj.yieldTitle = 'Resolved1b2Wj Channel $e^{\pm}$'
                    MuSelObjResolved1b2Wj.yieldTitle = 'Resolved1b2Wj Channel $\mu^{\pm}$'

                if not self.args.OnlyYield:
                    ChannelDictListR.append({'channel':'El','selObj':ElSelObjResolved1b2Wj,'sel':ElSelObjResolved1b2Wj.sel,
                                             'lep':ElColl[0],'met':self.corrMET,'jpaSelectedJets':ElSelObjResolved1b2WjJets,
                                             'jet1':ElSelObjResolved1b2WjJets[0],'jet2':ElSelObjResolved1b2WjJets[1],
                                             'jet3':ElSelObjResolved1b2WjJets[2],'jet4':None,
                                             'nJet':3,'nbJet':1,'suffix':ElSelObjResolved1b2Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Res1b2Wj'})
                    ChannelDictListR.append({'channel':'Mu','selObj':MuSelObjResolved1b2Wj,'sel':MuSelObjResolved1b2Wj.sel,
                                             'lep':MuColl[0],'met':self.corrMET,'jpaSelectedJets':MuSelObjResolved1b2WjJets,
                                             'jet1':MuSelObjResolved1b2WjJets[0],'jet2':MuSelObjResolved1b2WjJets[1],
                                             'jet3':MuSelObjResolved1b2WjJets[2],'jet4':None,
                                             'nJet':3,'nbJet':1,'suffix':MuSelObjResolved1b2Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Res1b2Wj'})
                    
            if "Res2b0Wj" in jetplot_level or "Resolved" in jetplot_level:
                logger.info ('...... JPA : 2b0Wj Node Selection')
                ElSelObjResolved2b0Wj          = ElResolvedSelObjJetsIdxPerJpaNodeDict.get('2b0Wj')[0]
                ElSelObjResolved2b0WjJets      = ElResolvedSelObjJetsIdxPerJpaNodeDict.get('2b0Wj')[1]
                MuSelObjResolved2b0Wj          = MuResolvedSelObjJetsIdxPerJpaNodeDict.get('2b0Wj')[0]
                MuSelObjResolved2b0WjJets      = MuResolvedSelObjJetsIdxPerJpaNodeDict.get('2b0Wj')[1]

                if self.args.onlypost:
                    ElSelObjResolved2b0Wj.record_yields = True
                    MuSelObjResolved2b0Wj.record_yields = True
                    ElSelObjResolved2b0Wj.yieldTitle = 'Resolved2b0Wj Channel $e^{\pm}$'
                    MuSelObjResolved2b0Wj.yieldTitle = 'Resolved2b0Wj Channel $\mu^{\pm}$'                

                if not self.args.OnlyYield:
                    ChannelDictListR.append({'channel':'El','selObj':ElSelObjResolved2b0Wj,'sel':ElSelObjResolved2b0Wj.sel,
                                             'lep':ElColl[0],'met':self.corrMET,'jpaSelectedJets':ElSelObjResolved2b0WjJets,
                                             'jet1':ElSelObjResolved2b0WjJets[0],'jet2':ElSelObjResolved2b0WjJets[1],
                                             'jet3':None,'jet4':None,
                                             'nJet':2,'nbJet':2,'suffix':ElSelObjResolved2b0Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Res2b0Wj'})
                    ChannelDictListR.append({'channel':'Mu','selObj':MuSelObjResolved2b0Wj,'sel':MuSelObjResolved2b0Wj.sel,
                                             'lep':MuColl[0],'met':self.corrMET,'jpaSelectedJets':MuSelObjResolved2b0WjJets,
                                             'jet1':MuSelObjResolved2b0WjJets[0],'jet2':MuSelObjResolved2b0WjJets[1],
                                             'jet3':None,'jet4':None,
                                             'nJet':2,'nbJet':2,'suffix':MuSelObjResolved2b0Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Res2b0Wj'})
                    
            if "Res1b1Wj" in jetplot_level or "Resolved" in jetplot_level:
                logger.info ('...... JPA : 1b1Wj Node Selection')
                ElSelObjResolved1b1Wj        = ElResolvedSelObjJetsIdxPerJpaNodeDict.get('1b1Wj')[0]
                ElSelObjResolved1b1WjJets    = ElResolvedSelObjJetsIdxPerJpaNodeDict.get('1b1Wj')[1]
                MuSelObjResolved1b1Wj        = MuResolvedSelObjJetsIdxPerJpaNodeDict.get('1b1Wj')[0]
                MuSelObjResolved1b1WjJets    = MuResolvedSelObjJetsIdxPerJpaNodeDict.get('1b1Wj')[1]

                if self.args.onlypost:
                    ElSelObjResolved1b1Wj.record_yields = True
                    MuSelObjResolved1b1Wj.record_yields = True
                    ElSelObjResolved1b1Wj.yieldTitle = 'Resolved1b1Wj Channel $e^{\pm}$'
                    MuSelObjResolved1b1Wj.yieldTitle = 'Resolved1b1Wj Channel $\mu^{\pm}$'

                if not self.args.OnlyYield:
                    ChannelDictListR.append({'channel':'El','selObj':ElSelObjResolved1b1Wj,'sel':ElSelObjResolved1b1Wj.sel,
                                             'lep':ElColl[0],'met':self.corrMET,'jpaSelectedJets':ElSelObjResolved1b1WjJets,
                                             'jet1':ElSelObjResolved1b1WjJets[0],'jet2':ElSelObjResolved1b1WjJets[1],
                                             'jet3':None,'jet4':None,
                                             'nJet':2,'nbJet':1,'suffix':ElSelObjResolved1b1Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Res1b1Wj'})
                    ChannelDictListR.append({'channel':'Mu','selObj':MuSelObjResolved1b1Wj,'sel':MuSelObjResolved1b1Wj.sel,
                                             'lep':MuColl[0],'met':self.corrMET,'jpaSelectedJets':MuSelObjResolved1b1WjJets,
                                             'jet1':MuSelObjResolved1b1WjJets[0],'jet2':MuSelObjResolved1b1WjJets[1],
                                             'jet3':None,'jet4':None,
                                             'nJet':2,'nbJet':1,'suffix':MuSelObjResolved1b1Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Res1b1Wj'})
                    
            if "Res1b0Wj" in jetplot_level or "Resolved" in jetplot_level:
                logger.info('...... JPA : 1b0Wj Node Selection')
                ElSelObjResolved1b0Wj        = ElResolvedSelObjJetsIdxPerJpaNodeDict.get('1b0Wj')[0]
                ElSelObjResolved1b0WjJets    = ElResolvedSelObjJetsIdxPerJpaNodeDict.get('1b0Wj')[1]
                MuSelObjResolved1b0Wj        = MuResolvedSelObjJetsIdxPerJpaNodeDict.get('1b0Wj')[0]
                MuSelObjResolved1b0WjJets    = MuResolvedSelObjJetsIdxPerJpaNodeDict.get('1b0Wj')[1]

                if self.args.onlypost:
                    ElSelObjResolved1b0Wj.record_yields = True
                    MuSelObjResolved1b0Wj.record_yields = True
                    ElSelObjResolved1b0Wj.yieldTitle = 'Resolved1b0Wj Channel $e^{\pm}$'
                    MuSelObjResolved1b0Wj.yieldTitle = 'Resolved1b0Wj Channel $\mu^{\pm}$'

                if not self.args.OnlyYield:
                    ChannelDictListR.append({'channel':'El','selObj':ElSelObjResolved1b0Wj,'sel':ElSelObjResolved1b0Wj.sel,
                                             'lep':ElColl[0],'met':self.corrMET,'jpaSelectedJets':ElSelObjResolved1b0WjJets,
                                             'jet1':ElSelObjResolved1b0WjJets[0],'jet2':None,
                                             'jet3':None,'jet4':None,
                                             'nJet':1,'nbJet':1,'suffix':ElSelObjResolved1b0Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Res1b0Wj'})
                    ChannelDictListR.append({'channel':'Mu','selObj':MuSelObjResolved1b0Wj,'sel':MuSelObjResolved1b0Wj.sel,
                                             'lep':MuColl[0],'met':self.corrMET,'jpaSelectedJets':MuSelObjResolved1b0WjJets,
                                             'jet1':MuSelObjResolved1b0WjJets[0],'jet2':None,
                                             'jet3':None,'jet4':None,
                                             'nJet':1,'nbJet':1,'suffix':MuSelObjResolved1b0Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Res1b0Wj'})
                    

            if "Res0b" in jetplot_level or "Resolved" in jetplot_level:
                logger.info ('...... JPA : 0b Node Selection')
                ElSelObjResolved0b    = ElResolvedSelObjJetsIdxPerJpaNodeDict.get('0b')[0]
                MuSelObjResolved0b    = MuResolvedSelObjJetsIdxPerJpaNodeDict.get('0b')[0]
                print(type(ElSelObjResolved0b))
                if self.args.onlypost:
                    ElSelObjResolved0b.record_yields = True
                    MuSelObjResolved0b.record_yields = True
                    ElSelObjResolved0b.yieldTitle = 'Resolved0b Channel $e^{\pm}$'
                    MuSelObjResolved0b.yieldTitle = 'Resolved0b Channel $\mu^{\pm}$'

                if not self.args.OnlyYield:
                    ChannelDictListR.append({'channel':'El','selObj':ElSelObjResolved0b,'sel':ElSelObjResolved0b.sel,
                                             'lep':ElColl[0],'met':self.corrMET,'jpaSelectedJets':None,
                                             'jet1':None,'jet2':None,
                                             'jet3':None,'jet4':None,
                                             'nJet':1,'nbJet':1,'suffix':ElSelObjResolved0b.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Res0b'})
                    ChannelDictListR.append({'channel':'Mu','selObj':MuSelObjResolved0b,'sel':MuSelObjResolved0b.sel,
                                             'lep':MuColl[0],'met':self.corrMET,'jpaSelectedJets':None,
                                             'jet1':None,'jet2':None,
                                             'jet3':None,'jet4':None,
                                             'nJet':1,'nbJet':1,'suffix':MuSelObjResolved1b0Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Res0b'})
                    
            for channelDict in ChannelDictListR:
                if any(['Res2b2Wj','Res2b1Wj','Res1b2Wj','Res2b0Wj','Res1b1Wj','Res1b0Wj']) in jetplot_level:
                    # Singlelepton #
                    plots.extend(makeSinleptonPlots(**{k:channelDict[k] for k in LeptonKeys}))
                    # Number of jets #
                    #plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**JetsN))
                    #plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**FatJetsN))
                    # Ak4 Jets #
                    plots.extend(makeAk4JetsPlots(**{k:channelDict[k] for k in JetKeys},HLL=self.HLL))
                    # MET #
                    plots.extend(makeMETPlots(**{k:channelDict[k] for k in commonItems}, met=self.corrMET))
                    # High level #
                    ##plots.extend(makeHighLevelPlotsResolved(**{k:channelDict[k] for k in ResolvedKeys},HLL=self.HLL))
                
                inputsCommon  = returnCommonInputs_Resolved(self)
                inputsClassic = returnClassicInputs_Resolved(self, **{k:channelDict[k] for k in ClassicInputKeys})
                inputsLBN     = returnLBNInputs_Resolved(self, **{k:channelDict[k] for k in LBNInputKeys})
                input_names   = [key[0] for key in inputsClassic.keys()] + ['LBN_inputs','eventnr']
                inputs_array  = [op.array("double",val) for val in inputStaticCast(inputsCommon,"float")]
                inputs_array.append(op.array("double",*inputStaticCast(inputsClassic,"float")))
                inputs_array.append(op.array("double",*inputStaticCast(inputsLBN,"float")))
                inputs_array.append(op.array("long",*inputStaticCast(inputsEventNr,"long")))

                DNN_SM  = op.mvaEvaluator (path_model_resolved_SM, mvaType='Tensorflow',otherArgs=(input_names, output_name)) 
                DNN_BSM = op.mvaEvaluator(path_model_resolved_BSM, mvaType='Tensorflow',otherArgs=(input_names, output_name)) 
                DNN_Score_SM  = DNN_SM (*inputs_array) 
                DNN_Score_BSM = DNN_BSM (*inputs_array)

                selObj = channelDict['selObj']
                selObj_1b = makeExclusiveLooseResolvedJetComboSelection(self, selObj, 1, copy_sel=True)
                selObj_2b = makeExclusiveLooseResolvedJetComboSelection(self, selObj, 2, copy_sel=True)
                
                selObjNodesDict_SM     = makeDNNOutputNodesSelections(self,selObj,   DNN_Score_SM, suffix='_SM_')
                selObjNodesDict_SM_1b  = makeDNNOutputNodesSelections(self,selObj_1b,DNN_Score_SM, suffix='_SM_')
                selObjNodesDict_SM_2b  = makeDNNOutputNodesSelections(self,selObj_2b,DNN_Score_SM, suffix='_SM_')

                selObjNodesDict_BSM    = makeDNNOutputNodesSelections(self,selObj,   DNN_Score_BSM, suffix='_BSM_')
                selObjNodesDict_BSM_1b = makeDNNOutputNodesSelections(self,selObj_1b,DNN_Score_BSM, suffix='_BSM_')
                selObjNodesDict_BSM_2b = makeDNNOutputNodesSelections(self,selObj_2b,DNN_Score_BSM, suffix='_BSM_')

                logger.info('Filling SM DNN responses')
                plots.extend(makeDoubleLeptonMachineLearningOutputPlots(selObjNodesDict_SM,    DNN_Score_SM, self.nodes,channel=channelDict['channel']))
                plots.extend(makeDoubleLeptonMachineLearningOutputPlots(selObjNodesDict_SM_1b, DNN_Score_SM, self.nodes,channel=channelDict['channel']))
                plots.extend(makeDoubleLeptonMachineLearningOutputPlots(selObjNodesDict_SM_2b, DNN_Score_SM, self.nodes,channel=channelDict['channel']))
                logger.info('Filling BSM DNN responses')
                plots.extend(makeDoubleLeptonMachineLearningOutputPlots(selObjNodesDict_BSM,    DNN_Score_BSM, self.nodes,channel=channelDict['channel']))
                plots.extend(makeDoubleLeptonMachineLearningOutputPlots(selObjNodesDict_BSM_1b, DNN_Score_BSM, self.nodes,channel=channelDict['channel']))
                plots.extend(makeDoubleLeptonMachineLearningOutputPlots(selObjNodesDict_BSM_2b, DNN_Score_BSM, self.nodes,channel=channelDict['channel']))

        # ========================== JPA Boosted Categories ========================= #
        if any(item in boosted_args for item in jetsel_level):
            ChannelDictListB = []
            FatJetKeys  = ['channel','sel','jet1','jet2','jet3','jet4','has1fat1slim','has1fat2slim','suffix']

            # dict = {'key':'Node', 'value' : [refined selObj, [JPAjetIndices]]}    
            elL1OutList, elL2OutList, ElBoostedSelObjJetsIdxPerJpaNodeDict = findJPACategoryBoosted (self, ElSelObjBoosted, ElColl[0], self.muonsPreSel, self.electronsPreSel, 
                                                                                                     self.ak8BJets, self.ak4JetsCleanedFromAk8b, self.ak4BJetsLoose, 
                                                                                                     self.ak4BJets, self.corrMET, boostedModelDict, t.event, self.HLL, 
                                                                                                     BoostedJPANodeList,
                                                                                                     plot_yield=True)
            muL1OutList, muL2OutList, MuBoostedSelObjJetsIdxPerJpaNodeDict = findJPACategoryBoosted (self, MuSelObjBoosted, MuColl[0], self.muonsPreSel, self.electronsPreSel, 
                                                                                                     self.ak8BJets, self.ak4JetsCleanedFromAk8b, self.ak4BJetsLoose, 
                                                                                                     self.ak4BJets, self.corrMET, boostedModelDict, t.event, self.HLL, 
                                                                                                     BoostedJPANodeList, 
                                                                                                     plot_yield=True)

            if "Hbb2Wj" in jetplot_level or "Boosted" in jetplot_level:
                print ('...... JPA : Hbb2Wj Node Selection')
                ElSelObjBoostedHbb2Wj        = ElBoostedSelObjJetsIdxPerJpaNodeDict.get('Hbb2Wj')[0]
                ElSelObjBoostedHbb2WjJets    = ElBoostedSelObjJetsIdxPerJpaNodeDict.get('Hbb2Wj')[1]
                MuSelObjBoostedHbb2Wj        = MuBoostedSelObjJetsIdxPerJpaNodeDict.get('Hbb2Wj')[0]
                MuSelObjBoostedHbb2WjJets    = MuBoostedSelObjJetsIdxPerJpaNodeDict.get('Hbb2Wj')[1]

                if not self.args.OnlyYield:
                    ChannelDictListB.append({'channel':'El','selObj':ElSelObjBoostedHbb2Wj, 'sel':ElSelObjBoostedHbb2Wj.sel,
                                             'lep':ElColl[0],'met':self.corrMET,'jpaSelectedJets':ElSelObjBoostedHbb2WjJets,
                                             'jet1':self.ak8BJets[0],'jet2':None,'jet3':ElSelObjBoostedHbb2WjJets[0],'jet4':ElSelObjBoostedHbb2WjJets[1],
                                             'has1fat1slim':False,'has1fat2slim':True,'bothAreFat':False,
                                             'suffix':ElSelObjBoostedHbb2Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Hbb2Wj'})
                    ChannelDictListB.append({'channel':'Mu','selObj':MuSelObjBoostedHbb2Wj,'sel':MuSelObjBoostedHbb2Wj.sel,
                                             'lep':MuColl[0],'met':self.corrMET,'jpaSelectedJets':MuSelObjBoostedHbb2WjJets,
                                             'jet1':self.ak8BJets[0],'jet2':None,'jet3':MuSelObjBoostedHbb2WjJets[0],'jet4':MuSelObjBoostedHbb2WjJets[1],
                                             'has1fat1slim':False,'has1fat2slim':True,'bothAreFat':False,
                                             'suffix':MuSelObjBoostedHbb2Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Hbb2Wj'})
                    
            if "Hbb1Wj" in jetplot_level or "Boosted" in jetplot_level:
                print ('...... JPA : Hbb1Wj Node Selection')
                ElSelObjBoostedHbb1Wj        = ElBoostedSelObjJetsIdxPerJpaNodeDict.get('Hbb1Wj')[0]
                ElSelObjBoostedHbb1WjJets    = ElBoostedSelObjJetsIdxPerJpaNodeDict.get('Hbb1Wj')[1]
                MuSelObjBoostedHbb1Wj        = MuBoostedSelObjJetsIdxPerJpaNodeDict.get('Hbb1Wj')[0]
                MuSelObjBoostedHbb1WjJets    = MuBoostedSelObjJetsIdxPerJpaNodeDict.get('Hbb1Wj')[1]

                if not self.args.OnlyYield:
                    ChannelDictListB.append({'channel':'El','selObj':ElSelObjBoostedHbb1Wj,'sel':ElSelObjBoostedHbb1Wj.sel,
                                             'lep':ElColl[0],'met':self.corrMET,'jpaSelectedJets':ElSelObjBoostedHbb1WjJets,
                                             'jet1':self.ak8BJets[0],'jet2':None,'jet3':ElSelObjBoostedHbb1WjJets[0],'jet4':None,
                                             'has1fat1slim':True,'has1fat2slim':False,'bothAreFat':False,
                                             'suffix':ElSelObjBoostedHbb1Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Hbb1Wj'})
                    ChannelDictListB.append({'channel':'Mu','selObj':MuSelObjBoostedHbb1Wj,'sel':MuSelObjBoostedHbb1Wj.sel,
                                             'lep':MuColl[0],'met':self.corrMET,'jpaSelectedJets':MuSelObjBoostedHbb1WjJets,
                                             'jet1':self.ak8BJets[0],'jet2':None,'jet3':MuSelObjBoostedHbb1WjJets[0],'jet4':None,
                                             'has1fat1slim':True,'has1fat2slim':False,'bothAreFat':False,
                                             'suffix':MuSelObjBoostedHbb1Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Hbb1Wj'})
                    
            if "Hbb0Wj" in jetplot_level or "Boosted" in jetplot_level:
                print ('...... JPA : Hbb0Wj Node Selection')
                ElSelObjBoostedHbb0Wj        = ElBoostedSelObjJetsIdxPerJpaNodeDict.get('Hbb0Wj')[0]
                MuSelObjBoostedHbb0Wj        = MuBoostedSelObjJetsIdxPerJpaNodeDict.get('Hbb0Wj')[0]

                if not self.args.OnlyYield:
                    ChannelDictListB.append({'channel':'El','selObj':ElSelObjBoostedHbb0Wj,'sel':ElSelObjBoostedHbb0Wj.sel,
                                             'lep':ElColl[0],'met':self.corrMET,'jpaSelectedJets':None,
                                             'jet1':self.ak8BJets[0],'jet2':None,'jet3':None,'jet4':None,
                                             'has1fat1slim':False,'has1fat2slim':False,'bothAreFat':False,
                                             'suffix':ElSelObjBoostedHbb0Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Hbb0Wj'})
                    ChannelDictListB.append({'channel':'Mu','selObj':MuSelObjBoostedHbb0Wj,'sel':MuSelObjBoostedHbb0Wj.sel,
                                             'lep':MuColl[0],'met':self.corrMET,'jpaSelectedJets':None,
                                             'jet1':self.ak8BJets[0],'jet2':None,'jet3':None,'jet4':None,
                                             'has1fat1slim':False,'has1fat2slim':False,'bothAreFat':False,
                                             'suffix':MuSelObjBoostedHbb0Wj.selName,
                                             'is_MC':self.is_MC, 'jpaArg':'Hbb0Wj'})
                    
            for channelDict in ChannelDictListB:
                if any(['Hbb2Wj','Hbb1Wj']) in jetplot_level:
                    # Dilepton #
                    plots.extend(makeSinleptonPlots(**{k:channelDict[k] for k in LeptonKeys}))
                    # Number of jets #
                    ##plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**FatJetsN))
                    ##plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**SlimJetsN))
                    # Ak8 Jets #
                    plots.extend(makeSingleLeptonAk8JetsPlots(**{k:channelDict[k] for k in FatJetKeys},nMedBJets=self.nMediumBTaggedSubJets, HLL=self.HLL))
                    # MET #
                    plots.extend(makeMETPlots(**{k:channelDict[k] for k in commonItems}, met=self.corrMET))
                    # HighLevel #
                    ##plots.extend(makeHighLevelPlotsBoosted(**{k:channelDict[k] for k in BoostedKeys}, HLL=self.HLL))
                

                inputsCommon  = returnCommonInputs_Boosted(self)
                inputsClassic = returnClassicInputs_Boosted(self, **{k:channelDict[k] for k in ClassicInputKeys})
                inputsLBN     = returnLBNInputs_Boosted(self, **{k:channelDict[k] for k in LBNInputKeys})
                input_names   = [key[0] for key in inputsClassic.keys()] + ['LBN_inputs','eventnr']
                inputs_array  = [op.array("double",val) for val in inputStaticCast(inputsCommon,"float")]
                inputs_array.append(op.array("double",*inputStaticCast(inputsClassic,"float")))
                inputs_array.append(op.array("double",*inputStaticCast(inputsLBN,"float")))
                inputs_array.append(op.array("long",*inputStaticCast(inputsEventNr,"long")))
                
                DNN_SM  = op.mvaEvaluator (path_model_boosted_SM, mvaType='Tensorflow',otherArgs=(input_names, output_name))
                DNN_BSM = op.mvaEvaluator(path_model_boosted_BSM, mvaType='Tensorflow',otherArgs=(input_names, output_name))
                DNN_Score_SM  = DNN_SM (*inputs_array)
                DNN_Score_BSM = DNN_BSM (*inputs_array)
                
                selObjNodesDict_SM     = makeDNNOutputNodesSelections(self,channelDict['selObj'],DNN_Score_SM,suffix='_SM_')
                selObjNodesDict_BSM    = makeDNNOutputNodesSelections(self,channelDict['selObj'],DNN_Score_BSM,suffix='_BSM_')
                logger.info('Filling DNN responses Boosted')
                plots.extend(makeDoubleLeptonMachineLearningOutputPlots(selObjNodesDict_SM,DNN_Score_SM,self.nodes,channel=selObjectDNNDict['channel']))
                plots.extend(makeDoubleLeptonMachineLearningOutputPlots(selObjNodesDict_BSM,DNN_Score_BSM,self.nodes,channel=selObjectDNNDict['channel']))
                
        #----- Add the Yield plots -----#
        plots.append(self.yields)
        #plots.extend(cutFlowPlots)
        return plots
    def defineSkimSelection(self, t, noSel, sample=None, sampleCfg=None):
        noSel = super(SkimmerNanoHHtobbWWSL,
                      self).prepareObjects(t,
                                           noSel,
                                           sample,
                                           sampleCfg,
                                           "SL",
                                           forSkimmer=True)
        era = sampleCfg['era']
        # Initialize varsToKeep dict #
        varsToKeep = dict()
        if not self.inclusive_sel:
            jet_level = ["Resolved2Btag", "Resolved1Btag", "Boosted"]
            # Only one lepton_level must be in args and Only one jet_level must be in args
            if [
                    boolean for (level, boolean) in self.args.__dict__.items()
                    if level in jet_level
            ].count(True) != 1:
                raise RuntimeError(
                    "Only one of the jet arguments must be used, check --help")

            if self.args.Channel not in ["El", "Mu"]:
                raise RuntimeError("Channel must be either 'El' or 'Mu'")

            #----- Machine Learning Model -----#
            model_nums = ["01", "02"]
            path_model_01 = os.path.join(
                os.path.abspath(os.path.dirname(__file__)), 'MachineLearning',
                'ml-models', 'models', 'multi-classification', 'dnn', 'SL',
                model_nums[0], 'model', 'model.pb')
            path_model_02 = os.path.join(
                os.path.abspath(os.path.dirname(__file__)), 'MachineLearning',
                'ml-models', 'models', 'multi-classification', 'dnn', 'SL',
                model_nums[1], 'model', 'model.pb')
            input_names_01 = [
                "lep", "jet", "fat", "met", "hl", "param", "eventnr"
            ]
            input_names_02 = [
                "lep", "jet", "fat", "met", "nu", "hl", "param", "eventnr"
            ]
            output_name = "Identity"

            if not self.args.OnlyYield:
                print("DNN model : %s" % path_model_02)
                if not os.path.exists(path_model_02):
                    raise RuntimeError('Could not find model file %s' %
                                       path_model_02)
                try:
                    DNN_02 = op.mvaEvaluator(path_model_02,
                                             mvaType='Tensorflow',
                                             otherArgs=(input_names_02,
                                                        output_name))
                except:
                    raise RuntimeError('Could not load model %s' %
                                       path_model_02)

            self.nodes = ['GGF', 'VBF', 'TT', 'ST', 'WJets', 'H', 'Other']

            #----- Lepton selection -----#
            # Args are passed within the self #
            #ElSelObj, MuSelObj = makeSingleLeptonSelection(self,noSel,use_dd=False)
            ElSelObj, MuSelObj = makeSingleLeptonSelection(
                self, noSel, use_dd=False, fake_selection=self.args.FakeCR)

            # --- apply jet correction --- #
            ElSelObj.sel = self.beforeJetselection(ElSelObj.sel, 'El')
            MuSelObj.sel = self.beforeJetselection(MuSelObj.sel, 'Mu')

            if self.args.Channel == "El":
                selObj = ElSelObj
                #lepton = self.electronsTightSel[0]
                lepton = self.electronsFakeSel[0]
                lepconep4 = self.getElectronConeP4(lepton)

            if self.args.Channel == "Mu":
                selObj = MuSelObj
                #lepton = self.muonsTightSel[0]
                lepton = self.muonsFakeSel[0]
                lepconep4 = self.getMuonConeP4(lepton)

            #----- Jet selection -----#
            # Since the selections in one line, we can use the non copy option of the selection to modify the selection object internally
            if any([
                    self.args.__dict__[item]
                    for item in ["Resolved2Btag", "Resolved1Btag"]
            ]):
                makeResolvedSelection(self, selObj)
                #VBFJetPairs = mvaEvaluatorSL_nonres_DNN01.VBFJetPairs_Resolved(self)
                VBFJetPairs = self.VBFJetPairsResolved
                if self.args.Resolved2Btag:
                    makeExclusiveResolvedSelection(self, selObj, nbJet=2)
                    print('Resolved2Btag')

                if self.args.Resolved1Btag:
                    makeExclusiveResolvedSelection(self, selObj, nbJet=1)
                    print('Resolved1Btag')

            if self.args.Boosted:
                makeBoostedSelection(self, selObj)
                #VBFJetPairs = mvaEvaluatorSL_nonres_DNN01.VBFJetPairs_Boosted(self)
                VBFJetPairs = self.VBFJetPairsBoosted
                print('BoostedHbb')

        else:
            noSel = self.beforeJetselection(noSel)

        #---------------------------------------------------------------------------------------#
        #                                Synchronization tree                                   #
        #---------------------------------------------------------------------------------------#
        if self.args.Synchronization:
            # Event variables #
            varsToKeep["event"] = None  # Already in tree
            varsToKeep["run"] = None  # Already in tree
            varsToKeep["ls"] = t.luminosityBlock

            varsToKeep["n_presel_mu"] = op.static_cast(
                "UInt_t", op.rng_len(self.muonsPreSel))
            varsToKeep["n_fakeablesel_mu"] = op.static_cast(
                "UInt_t", op.rng_len(self.muonsFakeSel))
            varsToKeep["n_tightsel_mu"] = op.static_cast(
                "UInt_t", op.rng_len(self.muonsTightSel))
            varsToKeep["n_presel_ele"] = op.static_cast(
                "UInt_t", op.rng_len(self.electronsPreSel))
            varsToKeep["n_fakeablesel_ele"] = op.static_cast(
                "UInt_t", op.rng_len(self.electronsFakeSel))
            varsToKeep["n_tightsel_ele"] = op.static_cast(
                "UInt_t", op.rng_len(self.electronsTightSel))

            varsToKeep["n_ak4Jet"] = op.static_cast("UInt_t",
                                                    op.rng_len(self.ak4Jets))

            varsToKeep["n_ak8Jet"] = op.static_cast("UInt_t",
                                                    op.rng_len(self.ak8Jets))
            varsToKeep["n_presel_ak8BJet"] = op.static_cast(
                "UInt_t", op.rng_len(self.ak8BJets))
            varsToKeep["n_loose_ak4BJet"] = op.static_cast(
                "UInt_t", op.rng_len(self.ak4BJetsLoose))
            varsToKeep["n_medium_ak4BJet"] = op.static_cast(
                "UInt_t", op.rng_len(self.ak4BJets))
            varsToKeep["n_ak4JetsCleanAk8b"] = op.static_cast(
                "UInt_t", op.rng_len(self.ak4JetsCleanedFromAk8b))
            varsToKeep["n_presel_ak4JetVBF"] = op.static_cast(
                "UInt_t", op.rng_len(self.VBFJetsPreSel))

            #varsToKeep["is_SR"]             = op.static_cast("UInt_t",op.OR(op.rng_len(self.electronsTightSel)==1,
            #                                                                op.rng_len(self.muonsTightSel)==1))

            varsToKeep["is_e_SR_prompt"] = op.switch(
                op.rng_len(self.electronsTightSel) == 1, op.c_bool(True),
                op.c_bool(False))
            varsToKeep["is_m_SR_prompt"] = op.switch(
                op.rng_len(self.muonsTightSel) == 1, op.c_bool(True),
                op.c_bool(False))
            varsToKeep["is_e_FR_prompt"] = op.switch(
                op.AND(
                    op.rng_len(self.electronsFakeSel) > 0,
                    op.AND(
                        self.lambda_is_matched(self.electronsFakeSel[0]),
                        op.NOT(
                            self.lambda_electronTightSel(
                                self.electronsFakeSel[0])))), op.c_bool(True),
                op.c_bool(False))
            varsToKeep["is_m_FR_prompt"] = op.switch(
                op.AND(
                    op.rng_len(self.muonsFakeSel) > 0,
                    op.AND(
                        self.lambda_is_matched(self.muonsFakeSel[0]),
                        op.NOT(self.lambda_muonTightSel(
                            self.muonsFakeSel[0])))), op.c_bool(True),
                op.c_bool(False))

            varsToKeep["is_resolved"] = op.switch(
                op.AND(
                    op.rng_len(self.ak4Jets) >= 3,
                    op.rng_len(self.ak4BJets) >= 1,
                    op.rng_len(self.ak8BJets) == 0), op.c_bool(True),
                op.c_bool(False))
            varsToKeep["is_boosted"] = op.switch(
                op.AND(
                    op.rng_len(self.ak8BJets) >= 1,
                    op.rng_len(self.ak4JetsCleanedFromAk8b) >= 1),
                op.c_bool(True), op.c_bool(False))

            varsToKeep["is_resolved_1b"] = op.switch(
                op.AND(
                    op.rng_len(self.ak4Jets) >= 3,
                    op.rng_len(self.ak4BJets) == 1,
                    op.rng_len(self.ak8BJets) == 0), op.c_bool(True),
                op.c_bool(False))
            varsToKeep["is_resolved_2b"] = op.switch(
                op.AND(
                    op.rng_len(self.ak4Jets) >= 3,
                    op.rng_len(self.ak4BJets) >= 2,
                    op.rng_len(self.ak8BJets) == 0), op.c_bool(True),
                op.c_bool(False))

            varsToKeep["n_tau"] = op.static_cast("UInt_t",
                                                 op.rng_len(self.tauCleanSel))

            #varsToKeep['resolved_tag']  = op.static_cast("UInt_t",op.AND(op.rng_len(self.ak4Jets) >= 3,
            #                                                             op.rng_len(self.ak4BJets) >= 1,
            #                                                             op.rng_len(self.ak8BJets) == 0))
            #varsToKeep['boosted_tag']   = op.static_cast("UInt_t",op.AND(op.rng_len(self.ak8BJets) >= 1,op.rng_len(self.ak4JetsCleanedFromAk8b) >= 1))

            # Triggers #
            '''
            varsToKeep["triggers"]                  = self.triggers
            varsToKeep["triggers_SingleElectron"]   = op.OR(*self.triggersPerPrimaryDataset['SingleElectron'])
            varsToKeep["triggers_SingleMuon"]       = op.OR(*self.triggersPerPrimaryDataset['SingleMuon'])
            varsToKeep["triggers_DoubleElectron"]   = op.OR(*self.triggersPerPrimaryDataset['DoubleEGamma'])
            varsToKeep["triggers_DoubleMuon"]       = op.OR(*self.triggersPerPrimaryDataset['DoubleMuon'])
            varsToKeep["triggers_MuonElectron"]     = op.OR(*self.triggersPerPrimaryDataset['MuonEG'])
            '''
            # Muons #

            for i in range(1, 3):  # 2 leading muons
                varsToKeep["mu{}_pt".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].pt, op.c_float(-9999., "float"))
                varsToKeep["mu{}_eta".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].eta, op.c_float(-9999.))
                varsToKeep["mu{}_phi".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].phi, op.c_float(-9999.))
                varsToKeep["mu{}_E".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].p4.E(),
                    op.c_float(-9999., "float"))
                varsToKeep["mu{}_charge".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].charge, op.c_int(-9999.))
                varsToKeep["mu{}_conept".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muon_conept[self.muonsPreSel[i - 1].idx],
                    op.c_float(-9999.))
                varsToKeep["mu{}_miniRelIso".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].miniPFRelIso_all,
                    op.c_float(-9999.))
                varsToKeep["mu{}_PFRelIso04".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].pfRelIso04_all, op.c_float(-9999.))
                varsToKeep["mu{}_jetNDauChargedMVASel".format(i)] = op.c_float(
                    -9999.)
                varsToKeep["mu{}_jetPtRel".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].jetPtRelv2, op.c_float(-9999.))
                varsToKeep["mu{}_jetRelIso".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].jetRelIso, op.c_float(-9999.))
                varsToKeep["mu{}_jetDeepJet".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].jet.btagDeepFlavB,
                    op.c_float(-9999.))
                varsToKeep["mu{}_sip3D".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].sip3d, op.c_float(-9999.))
                varsToKeep["mu{}_dxy".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].dxy, op.c_float(-9999.))
                varsToKeep["mu{}_dxyAbs".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    op.abs(self.muonsPreSel[i - 1].dxy), op.c_float(-9999.))
                varsToKeep["mu{}_dz".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].dz, op.c_float(-9999.))
                varsToKeep["mu{}_segmentCompatibility".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].segmentComp, op.c_float(-9999.))
                varsToKeep["mu{}_leptonMVA".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].mvaTTH, op.c_float(-9999.))
                varsToKeep["mu{}_mediumID".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].mediumId,
                    op.c_float(-9999., "Bool_t"))
                varsToKeep["mu{}_dpt_div_pt".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].tunepRelPt,
                    op.c_float(-9999.))  # Not sure
                varsToKeep["mu{}_isfakeablesel".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    op.switch(self.lambda_muonFakeSel(self.muonsPreSel[i - 1]),
                              op.c_int(1), op.c_int(0)), op.c_int(-9999))
                varsToKeep["mu{}_ismvasel".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    op.switch(
                        op.AND(
                            self.lambda_muonTightSel(self.muonsPreSel[i - 1]),
                            self.lambda_muonFakeSel(self.muonsPreSel[i - 1])),
                        op.c_int(1), op.c_int(0)),
                    op.c_int(-9999))  # mvasel encompasses fakeablesel
                varsToKeep["mu{}_isGenMatched".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    op.switch(self.lambda_is_matched(self.muonsPreSel[i - 1]),
                              op.c_int(1), op.c_int(0)), op.c_int(-9999))
                '''
                varsToKeep["mu{}_genPartFlav".format(i)]           = op.switch(op.rng_len(self.muonsPreSel) >= i, self.muonsPreSel[i-1].genPartFlav, op.c_int(-9999))
                varsToKeep["mu{}_FR".format(i)]                    = op.switch(op.rng_len(self.muonsPreSel) >= i, self.lambda_FR_mu(self.muonsPreSel[i-1]), op.c_int(-9999))
                varsToKeep["mu{}_FRcorr".format(i)]                = op.switch(op.rng_len(self.muonsPreSel) >= i, self.lambda_FRcorr_mu(self.muonsPreSel[i-1]), op.c_int(-9999))
                varsToKeep["mu{}_FF".format(i)]                    = op.switch(op.rng_len(self.muonsPreSel) >= i, self.lambda_FF_mu(self.muonsPreSel[i-1]), op.c_int(-9999))
                varsToKeep["mu{}_looseSF".format(i)]               = op.switch(op.rng_len(self.muonsPreSel) >= i, reduce(mul,self.lambda_MuonLooseSF(self.muonsPreSel[i-1])), op.c_int(-9999))
                varsToKeep["mu{}_tightSF".format(i)]               = op.switch(op.rng_len(self.muonsPreSel) >= i, reduce(mul,self.lambda_MuonTightSF(self.muonsPreSel[i-1])), op.c_int(-9999))
                '''
            # Electrons #
            for i in range(1, 3):  # 2 leading electrons
                varsToKeep["ele{}_pt".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].pt, op.c_float(-9999.))
                varsToKeep["ele{}_eta".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].eta, op.c_float(-9999.))
                varsToKeep["ele{}_phi".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].phi, op.c_float(-9999.))
                varsToKeep["ele{}_E".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].p4.E(), op.c_float(-9999., ))
                varsToKeep["ele{}_charge".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].charge, op.c_int(-9999.))
                varsToKeep["ele{}_conept".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electron_conept[self.electronsPreSel[i - 1].idx],
                    op.c_float(-9999.))
                varsToKeep["ele{}_miniRelIso".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].miniPFRelIso_all,
                    op.c_float(-9999.))
                varsToKeep["ele{}_PFRelIso03".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].pfRelIso03_all,
                    op.c_float(-9999.))  # Iso03, Iso04 not in NanoAOD
                varsToKeep["ele{}_jetNDauChargedMVASel".format(
                    i)] = op.c_float(-9999.)
                varsToKeep["ele{}_jetPtRel".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].jetPtRelv2, op.c_float(-9999.))
                varsToKeep["ele{}_jetRelIso".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].jetRelIso, op.c_float(-9999.))
                varsToKeep["ele{}_jetDeepJet".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].jet.btagDeepFlavB,
                    op.c_float(-9999.))
                varsToKeep["ele{}_sip3D".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].sip3d, op.c_float(-9999.))

                varsToKeep["ele{}_dxy".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].dxy, op.c_float(-9999.))
                varsToKeep["ele{}_dxyAbs".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    op.abs(self.electronsPreSel[i - 1].dxy),
                    op.c_float(-9999.))
                varsToKeep["ele{}_dz".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].dz, op.c_float(-9999.))
                varsToKeep["ele{}_ntMVAeleID".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].mvaFall17V2noIso,
                    op.c_float(-9999.))
                varsToKeep["ele{}_leptonMVA".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].mvaTTH, op.c_float(-9999.))
                varsToKeep["ele{}_passesConversionVeto".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].convVeto,
                    op.c_float(-9999., "Bool_t"))
                varsToKeep["ele{}_nMissingHits".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].lostHits,
                    op.c_float(-9999., "UChar_t"))
                varsToKeep["ele{}_sigmaEtaEta".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].sieie, op.c_float(-9999.))
                varsToKeep["ele{}_HoE".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].hoe, op.c_float(-9999.))
                varsToKeep["ele{}_OoEminusOoP".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].eInvMinusPInv,
                    op.c_float(-9999.))
                varsToKeep["ele{}_isfakeablesel".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    op.switch(
                        self.lambda_electronFakeSel(self.electronsPreSel[i -
                                                                         1]),
                        op.c_int(1), op.c_int(0)), op.c_int(-9999))
                varsToKeep["ele{}_ismvasel".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    op.switch(
                        op.AND(
                            self.lambda_electronTightSel(
                                self.electronsPreSel[i - 1]),
                            self.lambda_electronFakeSel(
                                self.electronsPreSel[i - 1])), op.c_int(1),
                        op.c_int(0)),
                    op.c_int(-9999))  # mvasel encompasses fakeablesel
                varsToKeep["ele{}_isGenMatched".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    op.switch(
                        self.lambda_is_matched(self.electronsPreSel[i - 1]),
                        op.c_int(1), op.c_int(0)), op.c_int(-9999))
                '''
                varsToKeep["ele{}_genPartFlav".format(i)]           = op.switch(op.rng_len(self.electronsPreSel) >= i, self.electronsPreSel[i-1].genPartFlav, op.c_int(-9999))
                varsToKeep["ele{}_deltaEtaSC".format(i)]            = op.switch(op.rng_len(self.electronsPreSel) >= i, self.electronsPreSel[i-1].deltaEtaSC, op.c_int(-9999))
                varsToKeep["ele{}_FR".format(i)]                    = op.switch(op.rng_len(self.electronsPreSel) >= i, self.lambda_FR_el(self.electronsPreSel[i-1]), op.c_int(-9999))
                varsToKeep["ele{}_FRcorr".format(i)]                = op.switch(op.rng_len(self.electronsPreSel) >= i, self.lambda_FRcorr_el(self.electronsPreSel[i-1]), op.c_int(-9999))
                varsToKeep["ele{}_FF".format(i)]                    = op.switch(op.rng_len(self.electronsPreSel) >= i, self.lambda_FF_el(self.electronsPreSel[i-1]), op.c_int(-9999))
                varsToKeep["ele{}_looseSF".format(i)]               = op.switch(op.rng_len(self.electronsPreSel) >= i, reduce(mul,self.lambda_ElectronLooseSF(self.electronsPreSel[i-1])), op.c_int(-9999))
                varsToKeep["ele{}_tightSF".format(i)]               = op.switch(op.rng_len(self.electronsPreSel) >= i, reduce(mul,self.lambda_ElectronTightSF(self.electronsPreSel[i-1])), op.c_int(-9999))
                '''
            # AK4 Jets #
            for i in range(1, 5):  # 4 leading jets
                varsToKeep["ak4Jet{}_pt".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i, self.ak4Jets[i - 1].pt,
                    op.c_float(-9999.))
                varsToKeep["ak4Jet{}_eta".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i, self.ak4Jets[i - 1].eta,
                    op.c_float(-9999.))
                varsToKeep["ak4Jet{}_phi".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i, self.ak4Jets[i - 1].phi,
                    op.c_float(-9999.))
                varsToKeep["ak4Jet{}_E".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i, self.ak4Jets[i - 1].p4.E(),
                    op.c_float(-9999.))
                varsToKeep["ak4Jet{}_CSV".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i,
                    self.ak4Jets[i - 1].btagDeepFlavB, op.c_float(-9999.))
                #varsToKeep["ak4Jet{}_hadronFlavour".format(i)]      = op.switch(op.rng_len(self.ak4Jets) >= i, self.ak4Jets[i-1].hadronFlavour, op.c_float(-9999.))
                #varsToKeep["ak4Jet{}_btagSF".format(i)]             = op.switch(op.rng_len(self.ak4Jets) >= i, self.DeepJetDiscReshapingSF(self.ak4Jets[i-1]), op.c_float(-9999.))
                #varsToKeep["ak4Jet{}_puid_eff".format(i)]           = op.switch(op.rng_len(self.ak4Jets) >= i, self.jetpuid_mc_eff(self.ak4Jets[i-1]), op.c_float(-9999.))
                #varsToKeep["ak4Jet{}_puid_sfeff".format(i)]         = op.switch(op.rng_len(self.ak4Jets) >= i, self.jetpuid_sf_eff(self.ak4Jets[i-1]), op.c_float(-9999.))
                #varsToKeep["ak4Jet{}_puid_mis".format(i)]           = op.switch(op.rng_len(self.ak4Jets) >= i, self.jetpuid_mc_mis(self.ak4Jets[i-1]), op.c_float(-9999.))
                #varsToKeep["ak4Jet{}_puid_sfmis".format(i)]         = op.switch(op.rng_len(self.ak4Jets) >= i, self.jetpuid_sf_mis(self.ak4Jets[i-1]), op.c_float(-9999.))

            # VBF Jets #
            if not self.inclusive_sel:
                varsToKeep["ak4JetVBFPair1_pt"] = op.switch(
                    op.rng_len(VBFJetPairs) >= 1, VBFJetPairs[0][0].pt,
                    op.c_float(-9999.))
                varsToKeep["ak4JetVBFPair1_eta"] = op.switch(
                    op.rng_len(VBFJetPairs) >= 1, VBFJetPairs[0][0].eta,
                    op.c_float(-9999.))
                varsToKeep["ak4JetVBFPair1_phi"] = op.switch(
                    op.rng_len(VBFJetPairs) >= 1, VBFJetPairs[0][0].phi,
                    op.c_float(-9999.))
                varsToKeep["ak4JetVBFPair1_E"] = op.switch(
                    op.rng_len(VBFJetPairs) >= 1, VBFJetPairs[0][0].p4.E(),
                    op.c_float(-9999.))
                varsToKeep["ak4JetVBFPair2_pt"] = op.switch(
                    op.rng_len(VBFJetPairs) >= 1, VBFJetPairs[0][1].pt,
                    op.c_float(-9999.))
                varsToKeep["ak4JetVBFPair2_eta"] = op.switch(
                    op.rng_len(VBFJetPairs) >= 1, VBFJetPairs[0][1].eta,
                    op.c_float(-9999.))
                varsToKeep["ak4JetVBFPair2_phi"] = op.switch(
                    op.rng_len(VBFJetPairs) >= 1, VBFJetPairs[0][1].phi,
                    op.c_float(-9999.))
                varsToKeep["ak4JetVBFPair2_E"] = op.switch(
                    op.rng_len(VBFJetPairs) >= 1, VBFJetPairs[0][1].p4.E(),
                    op.c_float(-9999.))
                '''
                # inputs : 
                inputsLeps = mvaEvaluatorSL_nonres_DNN01.returnLeptonsMVAInputs (self  = self, lep  = lepton)
                inputsJets = mvaEvaluatorSL_nonres_DNN01.returnJetsMVAInputs    (self  = self, bjets = self.bJetsByScore, jets = self.probableWJets)
                inputsMET = mvaEvaluatorSL_nonres_DNN01.returnMETMVAInputs      (self  = self, met  = self.corrMET)
                inputsFatjet = mvaEvaluatorSL_nonres_DNN01.returnFatjetMVAInputs(self  = self, fatjets = self.ak8Jets)
                inputsHL = mvaEvaluatorSL_nonres_DNN01.returnHighLevelMVAInputs (self  = self,
                                                                                 lep   = lepton,
                                                                                 bjets = self.bJetsByScore,
                                                                                 wjets = self.wJetsByPt,
                                                                                 VBFJetPairs = VBFJetPairs,
                                                                                 channel   = self.args.Channel)
                inputsParam   = mvaEvaluatorSL_nonres_DNN01.returnParamMVAInputs    (self)
                inputsEventNr = mvaEvaluatorSL_nonres_DNN01.returnEventNrMVAInputs  (self,t)

                inputDict = {**inputsLeps, **inputsJets, **inputsMET, **inputsFatjet, **inputsHL} 

                for (varname,_,_),var in inputDict.items():
                    varsToKeep[varname] = var

                from  mvaEvaluatorSL_nonres_DNN01 import inputStaticCast

                inputs = [op.array("double",*inputStaticCast(inputsLeps,"float")),
                          op.array("double",*inputStaticCast(inputsJets,"float")),
                          op.array("double",*inputStaticCast(inputsFatjet,"float")),
                          op.array("double",*inputStaticCast(inputsMET,"float")),
                          op.array("double",*inputStaticCast(inputsHL,"float")),
                          op.array("double",*inputStaticCast(inputsParam,"float")),
                          op.array("long",*inputStaticCast(inputsEventNr,"long"))]
                
                output_01 = DNN_01(*inputs)
                
                for node, output in zip(self.nodes,output_01):
                    varsToKeep['DNN_node_'+node] = output
                '''
            # AK8 Jets #
            for i in range(1, 3):  # 2 leading fatjets
                varsToKeep["ak8Jet{}_pt".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i, self.ak8BJets[i - 1].pt,
                    op.c_float(-9999.))
                varsToKeep["ak8Jet{}_eta".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i, self.ak8BJets[i - 1].eta,
                    op.c_float(-9999.))
                varsToKeep["ak8Jet{}_phi".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i, self.ak8BJets[i - 1].phi,
                    op.c_float(-9999.))
                varsToKeep["ak8Jet{}_E".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].p4.E(), op.c_float(-9999.))
                varsToKeep["ak8Jet{}_msoftdrop".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].msoftdrop, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_tau1".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i, self.ak8BJets[i - 1].tau1,
                    op.c_float(-9999.))
                varsToKeep["ak8Jet{}_tau2".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i, self.ak8BJets[i - 1].tau2,
                    op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet0_pt".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet1.pt, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet0_eta".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet1.eta, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet0_phi".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet1.phi, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet0_CSV".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet1.btagDeepB, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet1_pt".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet2.pt, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet1_eta".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet2.eta, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet1_phi".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet2.phi, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet1_CSV".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet2.btagDeepB, op.c_float(-9999.))

            varsToKeep["PFMET"] = self.corrMET.pt
            varsToKeep["PFMETphi"] = self.corrMET.phi
            varsToKeep["met1_E"] = self.corrMET.p4.E()
            varsToKeep["met1_pt"] = self.corrMET.pt
            varsToKeep["met1_eta"] = self.corrMET.eta
            varsToKeep["met1_phi"] = self.corrMET.phi

            # SF #
            electronMuon_cont = op.combine(
                (self.electronsFakeSel, self.muonsFakeSel))
            '''
            varsToKeep["trigger_SF"] = op.multiSwitch(
                (op.AND(op.rng_len(self.electronsTightSel)==1,op.rng_len(self.muonsTightSel)==0) , self.ttH_singleElectron_trigSF(self.electronsTightSel[0])),
                (op.AND(op.rng_len(self.electronsTightSel)==0,op.rng_len(self.muonsTightSel)==1) , self.ttH_singleMuon_trigSF(self.muonsTightSel[0])),
                (op.AND(op.rng_len(self.electronsTightSel)>=2,op.rng_len(self.muonsTightSel)==0) , self.lambda_ttH_doubleElectron_trigSF(self.electronsTightSel)),
                (op.AND(op.rng_len(self.electronsTightSel)==0,op.rng_len(self.muonsTightSel)>=2) , self.lambda_ttH_doubleMuon_trigSF(self.muonsTightSel)),
                (op.AND(op.rng_len(self.electronsTightSel)>=1,op.rng_len(self.muonsTightSel)>=1) , self.lambda_ttH_electronMuon_trigSF(electronMuon_cont[0])),
                op.c_float(1.))

            if not self.inclusive_sel:
                #varsToKeep["weight_trigger_el_sf"] = op.switch(op.rng_len(self.electronsTightSel)>0, self.ttH_singleElectron_trigSF(lepton),op.c_float(1.))
                #varsToKeep["weight_trigger_mu_sf"] = op.switch(op.rng_len(self.muonsTightSel)>0, self.ttH_singleMuon_trigSF(lepton),op.c_float(1.))

                varsToKeep["lepton_IDSF"] = op.rng_product(self.electronsFakeSel, lambda el : reduce(mul,self.lambda_ElectronLooseSF(el)+self.lambda_ElectronTightSF(el))) * \
                                            op.rng_product(self.muonsFakeSel, lambda mu : reduce(mul,self.lambda_MuonLooseSF(mu)+self.lambda_MuonTightSF(mu))) 
                
                varsToKeep["lepton_IDSF_recoToLoose"]  = op.rng_product(self.electronsFakeSel, lambda el : reduce(mul,self.lambda_ElectronLooseSF(el))) * \
                                                        op.rng_product(self.muonsFakeSel, lambda mu : reduce(mul,self.lambda_MuonLooseSF(mu)))
                varsToKeep["lepton_IDSF_looseToTight"] = op.rng_product(self.electronsFakeSel, lambda el : reduce(mul,self.lambda_ElectronTightSF(el))) * \
                                                         op.rng_product(self.muonsFakeSel, lambda mu : reduce(mul,self.lambda_MuonTightSF(mu)))

                if era == "2016" or era == "2017": 
                    if self.args.Channel == "El":
                        varsToKeep["weight_electron_reco_low"]    = op.switch(op.AND(self.lambda_is_matched(lepton),lepton.pt<=20.), self.elLooseRecoPtLt20(lepton), op.c_float(1.))
                        varsToKeep["weight_electron_reco_high"]   = op.switch(op.AND(self.lambda_is_matched(lepton),lepton.pt>20.), self.elLooseRecoPtGt20(lepton), op.c_float(1.))
                        varsToKeep["weight_muon_idiso_loose"]     = op.c_float(1.)
                        varsToKeep["weight_electron_id_loose_01"] = op.switch(self.lambda_is_matched(lepton), self.elLooseEff(lepton), op.c_float(1.))
                        varsToKeep["weight_electron_id_loose_02"] = op.switch(self.lambda_is_matched(lepton), self.elLooseId(lepton),  op.c_float(1.))
                        varsToKeep["weight_electron_tth_loose"]   = self.lambda_ElectronTightSF(lepton)[0]
                        varsToKeep["weight_muon_tth_loose"]       = op.c_float(1.)

                    if self.args.Channel == "Mu":
                        varsToKeep["weight_muon_idiso_loose"]     = op.switch(self.lambda_is_matched(lepton), self.muLooseId(lepton), op.c_float(1.))
                        varsToKeep["weight_electron_reco_low"]    = op.c_float(1.)
                        varsToKeep["weight_electron_reco_high"]   = op.c_float(1.)
                        varsToKeep["weight_electron_id_loose_01"] = op.c_float(1.)
                        varsToKeep["weight_electron_id_loose_02"] = op.c_float(1.)
                        varsToKeep["weight_electron_tth_loose"]   = op.c_float(1.)
                        varsToKeep["weight_muon_tth_loose"]       = self.lambda_MuonTightSF(lepton)[0]
                else:
                    raise NotImplementedError

            # L1 Prefire #
            if era in ["2016","2017"]:
                varsToKeep["L1prefire"] = self.L1Prefiring
                varsToKeep["weight_l1_ecal_prefiring"] = self.L1Prefiring
            else:
                varsToKeep["L1prefire"] = op.c_float(-9999.)
                varsToKeep["weight_l1_ecal_prefiring"] = op.c_float(-9999.)

            # Fake rate #
            if self.args.Channel == "El":
                varsToKeep["fakeRate"]                  = op.switch(self.lambda_electronTightSel(self.electronsFakeSel[0]), self.ElFakeFactor(self.electronsFakeSel[0]), op.c_float(1.))
                varsToKeep["weight_fake_electrons"]     = op.switch(self.lambda_electronTightSel(self.electronsFakeSel[0]), op.abs(self.ElFakeFactor(self.electronsFakeSel[0])), op.c_float(1.))
                varsToKeep["weight_fake_muons"]         = op.c_float(1.)
                varsToKeep["weight_fake_two_non_tight"] = op.c_float(999.0)
            if self.args.Channel == "Mu":
                varsToKeep["fakeRate"]                  = op.switch(self.lambda_muonTightSel(self.muonsFakeSel[0]), self.MuFakeFactor(self.muonsFakeSel[0]), op.c_float(1.))
                varsToKeep["weight_fake_electrons"]     = op.c_float(1.)
                varsToKeep["weight_fake_muons"]         = op.switch(self.lambda_muonTightSel(self.muonsFakeSel[0]), op.abs(self.MuFakeFactor(self.muonsFakeSel[0])), op.c_float(1.))
                varsToKeep["weight_fake_two_non_tight"] = op.c_float(999.0)

            if self.is_MC:
                varsToKeep["weight_fake_is_mc"] = op.c_float(-1.)
            else:
                varsToKeep["weight_fake_is_mc"] = op.c_float(1.)

            # PU ID SF #
            #varsToKeep["PU_jetID_SF"]                = self.puid_reweighting
            #varsToKeep["weight_jet_PUid_efficiency"] = self.puid_reweighting_efficiency
            #varsToKeep["weight_jet_PUid_mistag"]     = self.puid_reweighting_mistag

            # Btagging SF #
            varsToKeep["btag_SF"]           = self.btagAk4SF
            varsToKeep["weight_btagWeight"] = self.btagAk4SF
            if "BtagRatioWeight" in self.__dict__.keys():
                varsToKeep["btag_ratio_SF"]   = self.BtagRatioWeight
                varsToKeep["weight_btagNorm"] = self.BtagRatioWeight

            # PS weights #
            varsToKeep["weight_PSWeight_ISR"] = self.psISRSyst
            varsToKeep["weight_PSWeight_FSR"] = self.psFSRSyst
            '''
            # ttbar PT reweighting #
            if "group" in sampleCfg and sampleCfg["group"] == 'ttbar':
                varsToKeep["topPt_wgt"] = self.ttbar_weight(
                    self.genTop[0], self.genAntitop[0])

        # Event Weight #
            if self.is_MC:
                varsToKeep["MC_weight"] = t.genWeight
                puWeightsFile = os.path.join(os.path.dirname(__file__), "data",
                                             "pileup",
                                             sample + '_%s.json' % era)
                #puWeightsFile = os.path.join(os.path.dirname(__file__), "data" , "pileup", sampleCfg["pufile"])
                varsToKeep["PU_weight"] = makePileupWeight(
                    puWeightsFile,
                    t.Pileup_nTrueInt,
                    nameHint=f"puweightFromFile{sample}".replace('-', '_'))
                varsToKeep[
                    "eventWeight"] = noSel.weight if self.inclusive_sel else selObj.sel.weight

            if self.inclusive_sel:
                return noSel, varsToKeep
            else:
                return selObj.sel, varsToKeep

        #---------------------------------------------------------------------------------------#
        #                                    Selection tree                                     #
        #---------------------------------------------------------------------------------------#
        #----- EVT variables -----#
        varsToKeep["event"] = None  # Already in tree
        varsToKeep["run"] = None  # Already in tree
        varsToKeep["ls"] = t.luminosityBlock
        '''
        inputsLeps   = mva02.returnLeptonsMVAInputs   (self  = self, lep  = lepton)
        inputsJets   = mva02.returnJetsMVAInputs      (self  = self, bjets = self.bJetsByScore, jets = self.probableWJets)
        inputsMET    = mva02.returnMETMVAInputs       (self  = self, met  = self.corrMET)
        inputsFatjet = mva02.returnFatjetMVAInputs    (self  = self, fatbjets = self.ak8BJets)
        inputNeu     = mva02.returnNuMVAInputs        (self  = self)
        inputsHL     = mva02.returnHighLevelMVAInputs (self  = self,
                                                       lep   = lepton,
                                                       bjets = self.bJetsByScore,
                                                       wjets = self.wJetsByPt,
                                                       VBFJetPairs = VBFJetPairs,
                                                       channel   = self.args.Channel)
        inputsParam   = mva02.returnParamMVAInputs    (self)
        inputsEventNr = mva02.returnEventNrMVAInputs  (self,t)
        '''

        inputsLeps = mva02.returnLeptonsMVAInputs(self=self,
                                                  lep=lepton,
                                                  conep4=lepconep4)
        inputsJets = mva02.returnJetsMVAInputs(self=self,
                                               bjets=self.bJetsByScore,
                                               jets=self.probableWJets)
        inputsMET = mva02.returnMETMVAInputs(self=self, met=self.corrMET)
        inputsFatjet = mva02.returnFatjetMVAInputs(self=self,
                                                   fatbjets=self.ak8BJets)
        inputNeu = mva02.returnNuMVAInputs(self=self)
        inputsHL = mva02.returnHighLevelMVAInputs(self=self,
                                                  lep=lepton,
                                                  conep4=lepconep4,
                                                  bjets=self.bJetsByScore,
                                                  wjets=self.wJetsByPt,
                                                  VBFJetPairs=VBFJetPairs,
                                                  channel=self.args.Channel)
        inputsParam = mva02.returnParamMVAInputs(self)
        inputsEventNr = mva02.returnEventNrMVAInputs(self, t)

        inputDict = {
            **inputsLeps,
            **inputsJets,
            **inputsFatjet,
            **inputsMET,
            **inputNeu,
            **inputsHL,
            **inputsParam,
            **inputsEventNr
        }

        for (varname, _, _), var in inputDict.items():
            varsToKeep[varname] = var

        #from  mvaEvaluatorSL_nonres_DNN01 import inputStaticCast

        inputs = [
            op.array("double", *mva02.inputStaticCast(inputsLeps, "float")),
            op.array("double", *mva02.inputStaticCast(inputsJets, "float")),
            op.array("double", *mva02.inputStaticCast(inputsFatjet, "float")),
            op.array("double", *mva02.inputStaticCast(inputsMET, "float")),
            op.array("double", *mva02.inputStaticCast(inputNeu, "float")),
            op.array("double", *mva02.inputStaticCast(inputsHL, "float")),
            op.array("double", *mva02.inputStaticCast(inputsParam, "float")),
            op.array("long", *mva02.inputStaticCast(inputsEventNr, "long"))
        ]

        output_02 = DNN_02(*inputs)

        for node, output in zip(self.nodes, output_02):
            varsToKeep['DNN_node_' + node] = output

        #----- Additional variables -----#
        varsToKeep["MC_weight"] = t.genWeight
        varsToKeep['total_weight'] = selObj.sel.weight

        #return leptonSel.sel, varsToKeep
        return selObj.sel, varsToKeep