Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:24:06

0001 from __future__ import print_function
0002 import FWCore.ParameterSet.Config as cms
0003 
0004 from PhysicsTools.PatAlgos.tools.ConfigToolBase import *
0005 import PhysicsTools.PatAlgos.tools.helpers as configtools
0006 from PhysicsTools.PatAlgos.tools.helpers import getPatAlgosToolsTask, addToProcessAndTask, addTaskToProcess
0007 from PhysicsTools.PatAlgos.tools.jetTools import switchJetCollection
0008 import CommonTools.CandAlgos.candPtrProjector_cfi as _mod
0009 from PhysicsTools.PatUtils.tools.pfforTrkMET_cff import *
0010 import JetMETCorrections.Type1MET.BadPFCandidateJetsEEnoiseProducer_cfi as _modbad
0011 import JetMETCorrections.Type1MET.UnclusteredBlobProducer_cfi as _modunc
0012 
0013 # function to determine whether a valid input tag was given
0014 def isValidInputTag(input):
0015     input_str = input
0016     if isinstance(input, cms.InputTag):
0017         input_str = input.value()
0018     if input is None or input_str == '""':
0019         return False
0020     else:
0021         return True
0022 
0023 # class to manage the (re-)calculation of MET, its corrections, and its uncertainties
0024 class RunMETCorrectionsAndUncertainties(ConfigToolBase):
0025 
0026     _label='RunMETCorrectionsAndUncertainties'
0027     _defaultParameters=dicttypes.SortedKeysDict()
0028 
0029     def __init__(self):
0030         ConfigToolBase.__init__(self)
0031         # MET type, correctionlevel, and uncertainties
0032         self.addParameter(self._defaultParameters, 'metType', "PF",
0033                           "Type of considered MET (only PF and Puppi supported so far)", Type=str, allowedValues = ["PF","Puppi"])
0034         self.addParameter(self._defaultParameters, 'correctionLevel', [""],
0035                           "level of correction : available corrections for pfMet are T0, T1, T2, Txy and Smear)",
0036                           allowedValues=["T0","T1","T2","Txy","Smear",""])
0037         self.addParameter(self._defaultParameters, 'computeUncertainties', True,
0038                           "enable/disable the uncertainty computation", Type=bool)
0039         self.addParameter(self._defaultParameters, 'produceIntermediateCorrections', False,
0040                           "enable/disable the production of all correction schemes (only for the most common)", Type=bool)
0041 
0042         # high-level object collections used e.g. for MET uncertainties or jet cleaning
0043         self.addParameter(self._defaultParameters, 'electronCollection', cms.InputTag('selectedPatElectrons'),
0044                           "Input electron collection", Type=cms.InputTag, acceptNoneValue=True)
0045         self.addParameter(self._defaultParameters, 'photonCollection', cms.InputTag('selectedPatPhotons'),
0046                           "Input photon collection", Type=cms.InputTag, acceptNoneValue=True)
0047         self.addParameter(self._defaultParameters, 'muonCollection', cms.InputTag('selectedPatMuons'),
0048                           "Input muon collection", Type=cms.InputTag, acceptNoneValue=True)
0049         self.addParameter(self._defaultParameters, 'tauCollection', cms.InputTag('selectedPatTaus'),
0050                           "Input tau collection", Type=cms.InputTag, acceptNoneValue=True)
0051         self.addParameter(self._defaultParameters, 'jetCollectionUnskimmed', cms.InputTag('patJets'),
0052                           "Input unskimmed jet collection for T1 MET computation", Type=cms.InputTag, acceptNoneValue=True)
0053 
0054         # pf candidate collection used for recalculation of MET from pf candidates
0055         self.addParameter(self._defaultParameters, 'pfCandCollection', cms.InputTag('particleFlow'),
0056                           "pf Candidate collection", Type=cms.InputTag, acceptNoneValue=True)
0057 
0058         # some options influencing MET corrections and uncertainties calculation
0059         self.addParameter(self._defaultParameters, 'autoJetCleaning', 'LepClean',
0060                           "Enable the jet cleaning for the uncertainty computation: Full for tau/photons/jet cleaning, Partial for jet cleaning, LepClean for jet cleaning with muon and electrons only, None or Manual for no cleaning",
0061                           allowedValues = ["Full","Partial","LepClean","None"])
0062         self.addParameter(self._defaultParameters, 'jetFlavor', 'AK4PFchs',
0063                           "Use AK4PF/AK4PFchs for PFJets,AK4Calo for CaloJets", Type=str, allowedValues = ["AK4PF","AK4PFchs","AK4PFPuppi","CaloJets"])
0064         self.addParameter(self._defaultParameters, 'jetCorrectionType', 'L1L2L3-L1',
0065                           "Use L1L2L3-L1 for the standard L1 removal / L1L2L3-RC for the random-cone correction", Type=str, allowedValues = ["L1L2L3-L1","L1L2L3-RC"])
0066 
0067         # technical options determining which JES corrections are used
0068         self.addParameter(self._defaultParameters, 'jetCorLabelUpToL3', "ak4PFCHSL1FastL2L3Corrector", "Use ak4PFL1FastL2L3Corrector (ak4PFCHSL1FastL2L3Corrector) for PFJets with (without) charged hadron subtraction, ak4CaloL1FastL2L3Corrector for CaloJets", Type=str)
0069         self.addParameter(self._defaultParameters, 'jetCorLabelL3Res', "ak4PFCHSL1FastL2L3ResidualCorrector", "Use ak4PFL1FastL2L3ResidualCorrector (ak4PFCHSL1FastL2L3ResidualCorrector) for PFJets with (without) charged hadron subtraction, ak4CaloL1FastL2L3ResidualCorrector for CaloJets", Type=str)
0070         # the file is used only for local running
0071         self.addParameter(self._defaultParameters, 'jecUncertaintyFile', '',
0072                           "Extra JES uncertainty file", Type=str)
0073         self.addParameter(self._defaultParameters, 'jecUncertaintyTag', None,
0074                           "JES uncertainty Tag", acceptNoneValue=True) # Type=str,
0075 
0076         # options to apply selections to the considered jets
0077         self.addParameter(self._defaultParameters, 'manualJetConfig', False,
0078                   "Enable jet configuration options", Type=bool)
0079         self.addParameter(self._defaultParameters, 'jetSelection', 'pt>15 && abs(eta)<9.9',
0080                           "Advanced jet kinematic selection", Type=str)
0081 
0082         # flags to influence how the MET is (re-)calculated, e.g. completely from scratch or just propagating new JECs
0083         self.addParameter(self._defaultParameters, 'recoMetFromPFCs', False,
0084                   "Recompute the MET from scratch using the pfCandidate collection", Type=bool)
0085         self.addParameter(self._defaultParameters, 'reapplyJEC', True,
0086                   "Flag to enable/disable JEC update", Type=bool)
0087         self.addParameter(self._defaultParameters, 'reclusterJets', False,
0088                   "Flag to enable/disable the jet reclustering", Type=bool)
0089         self.addParameter(self._defaultParameters, 'computeMETSignificance', True,
0090                   "Flag to enable/disable the MET significance computation", Type=bool)
0091         self.addParameter(self._defaultParameters, 'CHS', False,
0092                   "Flag to enable/disable the CHS jets", Type=bool)
0093 
0094         # information on what dataformat or datatype we are running on
0095         self.addParameter(self._defaultParameters, 'runOnData', False,
0096                           "Switch for data/MC processing", Type=bool)
0097         self.addParameter(self._defaultParameters, 'onMiniAOD', False,
0098                           "Switch on miniAOD configuration", Type=bool)
0099 
0100         # special input parameters when running over 2017 data
0101         self.addParameter(self._defaultParameters,'fixEE2017', False,
0102                           "Exclude jets and PF candidates with EE noise characteristics (fix for 2017 run)", Type=bool)
0103         self.addParameter(self._defaultParameters,'fixEE2017Params', {'userawPt': True, 'ptThreshold': 50.0, 'minEtaThreshold': 2.65, 'maxEtaThreshold': 3.139},
0104                           "Parameters dict for fixEE2017: userawPt, ptThreshold, minEtaThreshold, maxEtaThreshold", Type=dict)
0105         self.addParameter(self._defaultParameters, 'extractDeepMETs', False,
0106                           "Extract DeepMETs from miniAOD, instead of recomputing them.", Type=bool)
0107 
0108         # technical parameters
0109         self.addParameter(self._defaultParameters, 'Puppi', False,
0110                           "Puppi algorithm (private)", Type=bool)
0111         self.addParameter(self._defaultParameters, 'puppiProducerLabel', 'puppi',
0112                           "PuppiProducer module for jet clustering label name", Type=str)
0113         self.addParameter(self._defaultParameters, 'puppiProducerForMETLabel', 'puppiNoLep',
0114                           "PuppiProducer module for MET clustering label name", Type=str)
0115         self.addParameter(self._defaultParameters, 'addToPatDefaultSequence', False,
0116                           "Flag to enable/disable that metUncertaintySequence is inserted into patDefaultSequence", Type=bool)
0117         self.addParameter(self._defaultParameters, 'postfix', '',
0118                           "Technical parameter to identify the resulting sequences/tasks and its corresponding modules (allows multiple calls in a job)", Type=str)
0119 
0120         self.addParameter(self._defaultParameters, 'campaign', '', 'Production campaign', Type=str)
0121         self.addParameter(self._defaultParameters, 'era', '', 'Era e.g. 2018, 2017B, ...', Type=str)
0122         # make another parameter collection by copying the default parameters collection
0123         # later adapt the newly created parameter collection to always have a copy of the default parameters
0124         self._parameters = copy.deepcopy(self._defaultParameters)
0125         self._comment = ""
0126 
0127     # function to return the saved default parameters of the class
0128     def getDefaultParameters(self):
0129         return self._defaultParameters
0130 
0131 #=========================================================================================
0132 # implement __call__ function to be able to use class instances like functions
0133 # reads the given parameters and saves them
0134 # runs the toolCode function in the end
0135     def __call__(self, process,
0136                  metType                 =None,
0137                  correctionLevel         =None,
0138                  computeUncertainties    =None,
0139                  produceIntermediateCorrections = None,
0140                  electronCollection      =None,
0141                  photonCollection        =None,
0142                  muonCollection          =None,
0143                  tauCollection           =None,
0144                  jetCollectionUnskimmed  =None,
0145                  pfCandCollection        =None,
0146                  autoJetCleaning         =None,
0147                  jetFlavor               =None,
0148                  jetCorr                 =None,
0149                  jetCorLabelUpToL3       =None,
0150                  jetCorLabelL3Res        =None,
0151                  jecUncertaintyFile      =None,
0152                  jecUncertaintyTag       =None,
0153                  addToPatDefaultSequence =None,
0154                  manualJetConfig         =None,
0155                  jetSelection            =None,
0156                  recoMetFromPFCs         =None,
0157                  reapplyJEC              =None,
0158                  reclusterJets           =None,
0159                  computeMETSignificance  =None,
0160                  CHS                     =None,
0161                  puppiProducerLabel      =None,
0162                  puppiProducerForMETLabel = None,
0163                  runOnData               =None,
0164                  onMiniAOD               =None,
0165                  fixEE2017               =None,
0166                  fixEE2017Params         =None,
0167                  extractDeepMETs         =None,
0168                  campaign                =None,
0169                  era                     =None,
0170                  postfix                 =None):
0171         electronCollection = self.initializeInputTag(electronCollection, 'electronCollection')
0172         photonCollection = self.initializeInputTag(photonCollection, 'photonCollection')
0173         muonCollection = self.initializeInputTag(muonCollection, 'muonCollection')
0174         tauCollection = self.initializeInputTag(tauCollection, 'tauCollection')
0175         jetCollectionUnskimmed = self.initializeInputTag(jetCollectionUnskimmed, 'jetCollectionUnskimmed')
0176         pfCandCollection = self.initializeInputTag(pfCandCollection, 'pfCandCollection')
0177         if metType is None :
0178             metType =  self._defaultParameters['metType'].value
0179         if correctionLevel is None :
0180             correctionLevel = self._defaultParameters['correctionLevel'].value
0181         if computeUncertainties is None :
0182             computeUncertainties = self._defaultParameters['computeUncertainties'].value
0183         if produceIntermediateCorrections is None :
0184             produceIntermediateCorrections = self._defaultParameters['produceIntermediateCorrections'].value
0185         if electronCollection is None :
0186             electronCollection = self._defaultParameters['electronCollection'].value
0187         if photonCollection is None :
0188             photonCollection = self._defaultParameters['photonCollection'].value
0189         if muonCollection is None :
0190             muonCollection = self._defaultParameters['muonCollection'].value
0191         if tauCollection is None :
0192             tauCollection = self._defaultParameters['tauCollection'].value
0193         if jetCollectionUnskimmed is None :
0194             jetCollectionUnskimmed = self._defaultParameters['jetCollectionUnskimmed'].value
0195         if pfCandCollection is None :
0196             pfCandCollection = self._defaultParameters['pfCandCollection'].value
0197         if autoJetCleaning is None :
0198             autoJetCleaning = self._defaultParameters['autoJetCleaning'].value
0199         if jetFlavor is None :
0200             jetFlavor = self._defaultParameters['jetFlavor'].value
0201         if jetCorr is None :
0202             jetCorr = self._defaultParameters['jetCorrectionType'].value
0203         if jetCorLabelUpToL3  is None:
0204             jetCorLabelUpToL3 = self._defaultParameters['jetCorLabelUpToL3'].value
0205         if jetCorLabelL3Res   is None:
0206             jetCorLabelL3Res = self._defaultParameters['jetCorLabelL3Res'].value
0207         if jecUncertaintyFile is None:
0208             jecUncertaintyFile = self._defaultParameters['jecUncertaintyFile'].value
0209         if jecUncertaintyTag  is None:
0210             jecUncertaintyTag = self._defaultParameters['jecUncertaintyTag'].value
0211         if addToPatDefaultSequence is None :
0212             addToPatDefaultSequence = self._defaultParameters['addToPatDefaultSequence'].value
0213         if manualJetConfig is None :
0214             manualJetConfig =  self._defaultParameters['manualJetConfig'].value
0215         if jetSelection is None :
0216             jetSelection = self._defaultParameters['jetSelection'].value
0217         recoMetFromPFCsIsNone = (recoMetFromPFCs is None)
0218         if recoMetFromPFCs is None :
0219             recoMetFromPFCs =  self._defaultParameters['recoMetFromPFCs'].value
0220         if reapplyJEC is None :
0221             reapplyJEC = self._defaultParameters['reapplyJEC'].value
0222         reclusterJetsIsNone = (reclusterJets is None)
0223         if reclusterJets is None :
0224             reclusterJets = self._defaultParameters['reclusterJets'].value
0225         if computeMETSignificance is None :
0226             computeMETSignificance = self._defaultParameters['computeMETSignificance'].value
0227         if CHS is None :
0228             CHS = self._defaultParameters['CHS'].value
0229         if puppiProducerLabel is None:
0230             puppiProducerLabel = self._defaultParameters['puppiProducerLabel'].value
0231         if puppiProducerForMETLabel is None:
0232             puppiProducerForMETLabel = self._defaultParameters['puppiProducerForMETLabel'].value
0233         if runOnData is None :
0234             runOnData = self._defaultParameters['runOnData'].value
0235         if onMiniAOD is None :
0236             onMiniAOD = self._defaultParameters['onMiniAOD'].value
0237         if postfix is None :
0238             postfix = self._defaultParameters['postfix'].value
0239         if fixEE2017 is None :
0240             fixEE2017 = self._defaultParameters['fixEE2017'].value
0241         if fixEE2017Params is None :
0242             fixEE2017Params = self._defaultParameters['fixEE2017Params'].value
0243         if extractDeepMETs is None :
0244             extractDeepMETs = self._defaultParameters['extractDeepMETs'].value
0245         if campaign is None :
0246             campaign = self._defaultParameters['campaign'].value
0247         if era is None :
0248             era = self._defaultParameters['era'].value
0249 
0250         self.setParameter('metType',metType),
0251         self.setParameter('correctionLevel',correctionLevel),
0252         self.setParameter('computeUncertainties',computeUncertainties),
0253         self.setParameter('produceIntermediateCorrections',produceIntermediateCorrections),
0254         self.setParameter('electronCollection',electronCollection),
0255         self.setParameter('photonCollection',photonCollection),
0256         self.setParameter('muonCollection',muonCollection),
0257         self.setParameter('tauCollection',tauCollection),
0258         self.setParameter('jetCollectionUnskimmed',jetCollectionUnskimmed),
0259         self.setParameter('pfCandCollection',pfCandCollection),
0260 
0261         self.setParameter('autoJetCleaning',autoJetCleaning),
0262         self.setParameter('jetFlavor',jetFlavor),
0263 
0264         #optional
0265         self.setParameter('jecUncertaintyFile',jecUncertaintyFile),
0266         self.setParameter('jecUncertaintyTag',jecUncertaintyTag),
0267 
0268         self.setParameter('addToPatDefaultSequence',addToPatDefaultSequence),
0269         self.setParameter('jetSelection',jetSelection),
0270         self.setParameter('recoMetFromPFCs',recoMetFromPFCs),
0271         self.setParameter('reclusterJets',reclusterJets),
0272         self.setParameter('computeMETSignificance',computeMETSignificance),
0273         self.setParameter('reapplyJEC',reapplyJEC),
0274         self.setParameter('CHS',CHS),
0275         self.setParameter('puppiProducerLabel',puppiProducerLabel),
0276         self.setParameter('puppiProducerForMETLabel',puppiProducerForMETLabel),
0277         self.setParameter('runOnData',runOnData),
0278         self.setParameter('onMiniAOD',onMiniAOD),
0279         self.setParameter('postfix',postfix),
0280         self.setParameter('fixEE2017',fixEE2017),
0281         self.setParameter('fixEE2017Params',fixEE2017Params),
0282         self.setParameter('extractDeepMETs',extractDeepMETs),
0283         self.setParameter('campaign',campaign),
0284         self.setParameter('era',era),
0285 
0286         # if puppi MET, autoswitch to std jets
0287         if metType == "Puppi":
0288             self.setParameter('CHS',False),
0289 
0290         # enabling puppi flag
0291         # metType is set back to PF because the necessary adaptions are handled via a postfix and directly changing parameters when Puppi parameter is true
0292         self.setParameter('Puppi',self._defaultParameters['Puppi'].value)
0293         if metType == "Puppi":
0294             self.setParameter('metType',"PF")
0295             self.setParameter('Puppi',True)
0296 
0297         # jet energy scale uncertainty needs
0298         if manualJetConfig:
0299             self.setParameter('CHS',CHS)
0300             self.setParameter('jetCorLabelUpToL3',jetCorLabelUpToL3)
0301             self.setParameter('jetCorLabelL3Res',jetCorLabelL3Res)
0302             self.setParameter('reclusterJets',reclusterJets)
0303         else:
0304             # internal jet configuration
0305             self.jetConfiguration()
0306 
0307         # defaults for 2017 fix
0308         # (don't need to recluster, just uses a subset of the input jet coll)
0309         if fixEE2017:
0310             if recoMetFromPFCsIsNone: self.setParameter('recoMetFromPFCs',True)
0311             if reclusterJetsIsNone: self.setParameter('reclusterJets',False)
0312 
0313         # met reprocessing and jet reclustering
0314         if recoMetFromPFCs and reclusterJetsIsNone and not fixEE2017:
0315             self.setParameter('reclusterJets',True)
0316 
0317         self.apply(process)
0318 
0319 
0320     def toolCode(self, process):
0321         ################################
0322         ### 1. read given parameters ###
0323         ################################
0324 
0325         # MET type, corrections, and uncertainties
0326         metType                 = self._parameters['metType'].value
0327         correctionLevel         = self._parameters['correctionLevel'].value
0328         computeUncertainties    = self._parameters['computeUncertainties'].value
0329         produceIntermediateCorrections = self._parameters['produceIntermediateCorrections'].value
0330         # physics object collections to consider when recalculating MET
0331         electronCollection      = self._parameters['electronCollection'].value
0332         photonCollection        = self._parameters['photonCollection'].value
0333         muonCollection          = self._parameters['muonCollection'].value
0334         tauCollection           = self._parameters['tauCollection'].value
0335         jetCollectionUnskimmed  = self._parameters['jetCollectionUnskimmed'].value
0336         pfCandCollection        = self._parameters['pfCandCollection'].value
0337         # jet specific options: jet corrections/uncertainties as well as jet selection/cleaning options
0338         jetSelection            = self._parameters['jetSelection'].value
0339         autoJetCleaning         = self._parameters['autoJetCleaning'].value
0340         jetFlavor               = self._parameters['jetFlavor'].value
0341         jetCorLabelUpToL3       = self._parameters['jetCorLabelUpToL3'].value
0342         jetCorLabelL3Res        = self._parameters['jetCorLabelL3Res'].value
0343         jecUncertaintyFile      = self._parameters['jecUncertaintyFile'].value
0344         jecUncertaintyTag       = self._parameters['jecUncertaintyTag'].value
0345         # additional MET calculation/extraction options
0346         recoMetFromPFCs         = self._parameters['recoMetFromPFCs'].value
0347         reapplyJEC              = self._parameters['reapplyJEC'].value
0348         reclusterJets           = self._parameters['reclusterJets'].value
0349         computeMETSignificance  = self._parameters['computeMETSignificance'].value
0350         extractDeepMETs         = self._parameters['extractDeepMETs'].value
0351         # specific option for 2017 EE noise mitigation
0352         fixEE2017               = self._parameters['fixEE2017'].value
0353         fixEE2017Params         = self._parameters['fixEE2017Params'].value
0354         campaign                = self._parameters['campaign'].value
0355         era                     = self._parameters['era'].value
0356         # additional runtime options
0357         onMiniAOD               = self._parameters['onMiniAOD'].value
0358         addToPatDefaultSequence = self._parameters['addToPatDefaultSequence'].value
0359         postfix                 = self._parameters['postfix'].value
0360 
0361         # prepare jet configuration used during MET (re-)calculation
0362         jetUncInfos = {
0363                         "jCorrPayload":jetFlavor,
0364                         "jCorLabelUpToL3":jetCorLabelUpToL3,
0365                         "jCorLabelL3Res":jetCorLabelL3Res,
0366                         "jecUncFile":jecUncertaintyFile,
0367                         "jecUncTag":"Uncertainty"
0368         }
0369 
0370         # get jet uncertainties from file
0371         if (jecUncertaintyFile!="" and jecUncertaintyTag==None):
0372             jetUncInfos[ "jecUncTag" ] = ""
0373         # get jet uncertainties from tag
0374         elif (jecUncertaintyTag!=None):
0375             jetUncInfos[ "jecUncTag" ] = jecUncertaintyTag
0376 
0377         #############################
0378         ### 2. (re-)construct MET ###
0379         #############################
0380 
0381         # task for main MET construction modules
0382         patMetModuleTask = cms.Task()
0383 
0384         # 2017 EE fix will modify pf cand and jet collections used downstream
0385         if fixEE2017:
0386             pfCandCollection, jetCollectionUnskimmed = self.runFixEE2017(process,
0387                 fixEE2017Params,
0388                 jetCollectionUnskimmed,
0389                 pfCandCollection,
0390                 [electronCollection,muonCollection,tauCollection,photonCollection],
0391                 patMetModuleTask,
0392                 postfix,
0393             )
0394 
0395         # recompute the MET (and thus the jets as well for correction) from scratch i.e. from pfcandidates
0396         if recoMetFromPFCs:
0397             self.recomputeRawMetFromPfcs(process,
0398                                          pfCandCollection,
0399                                          onMiniAOD,
0400                                          patMetModuleTask,
0401                                          postfix)
0402         # if not using pfcandidates, you also can extract the raw MET from MiniAOD
0403         elif onMiniAOD:
0404             self.extractMET(process, "raw", patMetModuleTask, postfix)
0405 
0406         # jet AK4 reclustering if needed for JECs ...
0407         if reclusterJets:
0408             jetCollectionUnskimmed = self.ak4JetReclustering(process, pfCandCollection,
0409                                                              patMetModuleTask, postfix)
0410 
0411         # ... or reapplication of JECs to already existing jets in MiniAOD
0412         if onMiniAOD:
0413             if not reclusterJets and reapplyJEC:
0414                 jetCollectionUnskimmed = self.updateJECs(process, jetCollectionUnskimmed, patMetModuleTask, postfix)
0415 
0416 
0417         # getting the jet collection that will be used for corrections and uncertainty computation
0418         # starts with the unskimmed jet collection and applies some selection and cleaning criteria
0419         jetCollection = self.getJetCollectionForCorsAndUncs(process,
0420                                                             jetCollectionUnskimmed,
0421                                                             jetSelection,
0422                                                             autoJetCleaning,
0423                                                             patMetModuleTask,
0424                                                             postfix)
0425 
0426         if onMiniAOD:
0427             # obtain specific METs (caloMET, DeepMET, PFCHS MET, TRKMET) from MiniAOD
0428             self.miniAODConfigurationPre(process, patMetModuleTask, pfCandCollection, postfix)
0429         else:
0430             from PhysicsTools.PatUtils.pfeGammaToCandidate_cfi import pfeGammaToCandidate
0431             addToProcessAndTask("pfeGammaToCandidate", pfeGammaToCandidate.clone(
0432                                   electrons = copy.copy(electronCollection),
0433                                   photons = copy.copy(photonCollection)),
0434                                 process, patMetModuleTask)
0435             if hasattr(process,"patElectrons") and process.patElectrons.electronSource == cms.InputTag("reducedEgamma","reducedGedGsfElectrons"):
0436                 process.pfeGammaToCandidate.electron2pf = "reducedEgamma:reducedGsfElectronPfCandMap"
0437             if hasattr(process,"patPhotons") and process.patPhotons.photonSource == cms.InputTag("reducedEgamma","reducedGedPhotons"):
0438                 process.pfeGammaToCandidate.photon2pf = "reducedEgamma:reducedPhotonPfCandMap"
0439 
0440         # default MET production
0441         self.produceMET(process, metType, patMetModuleTask, postfix)
0442 
0443 
0444 
0445         # preparation to run over miniAOD (met reproduction)
0446         if onMiniAOD:
0447             self.miniAODConfiguration(process,
0448                                       pfCandCollection,
0449                                       jetCollection,
0450                                       patMetModuleTask,
0451                                       postfix
0452                                       )
0453 
0454         ###########################
0455         ### 3. (re-)correct MET ###
0456         ###########################
0457 
0458         patMetCorrectionTask = cms.Task()
0459         metModName = self.getCorrectedMET(process, metType, correctionLevel,
0460                                                                     produceIntermediateCorrections,
0461                                                                     jetCollection,
0462                                                                     patMetCorrectionTask, postfix )
0463         # fix the default jets for the type1 computation to those used to compute the uncertainties
0464         # in order to be consistent with what is done in the correction and uncertainty step
0465         # particularly true for miniAODs
0466         if "T1" in metModName:
0467             getattr(process,"patPFMetT1T2Corr"+postfix).src = jetCollection
0468             getattr(process,"patPFMetT2Corr"+postfix).src = jetCollection
0469             #ZD:puppi currently doesn't have the L1 corrections in the GT
0470             if self._parameters["Puppi"].value:
0471                 getattr(process,"patPFMetT1T2Corr"+postfix).offsetCorrLabel = cms.InputTag("")
0472                 getattr(process,"patPFMetT2Corr"+postfix).offsetCorrLabel = cms.InputTag("")
0473         if "Smear" in metModName:
0474             getattr(process,"patSmearedJets"+postfix).src = jetCollection
0475             if self._parameters["Puppi"].value:
0476                 getattr(process,"patPFMetT1T2SmearCorr"+postfix).offsetCorrLabel = cms.InputTag("")
0477 
0478 
0479         ####################################
0480         ### 4. compute MET uncertainties ###
0481         ####################################
0482 
0483         patMetUncertaintyTask = cms.Task()
0484         if not hasattr(process, "patMetUncertaintyTask"+postfix):
0485             if self._parameters["Puppi"].value:
0486                 patMetUncertaintyTask.add(cms.Task(getattr(process, "ak4PFPuppiL1FastL2L3CorrectorTask"),getattr(process, "ak4PFPuppiL1FastL2L3ResidualCorrectorTask")))
0487             else:
0488                 patMetUncertaintyTask.add(cms.Task(getattr(process, "ak4PFCHSL1FastL2L3CorrectorTask"),getattr(process, "ak4PFCHSL1FastL2L3ResidualCorrectorTask")))
0489         patShiftedModuleTask = cms.Task()
0490         if computeUncertainties:
0491             self.getMETUncertainties(process, metType, metModName,
0492                                         electronCollection,
0493                                         photonCollection,
0494                                         muonCollection,
0495                                         tauCollection,
0496                                         pfCandCollection,
0497                                         jetCollection,
0498                                         jetUncInfos,
0499                                         patMetUncertaintyTask,
0500                                         postfix)
0501 
0502         ####################################
0503         ### 5. Bring everything together ###
0504         ####################################
0505 
0506         # add main MET tasks to process
0507         addTaskToProcess(process, "patMetCorrectionTask"+postfix, patMetCorrectionTask)
0508         addTaskToProcess(process, "patMetUncertaintyTask"+postfix, patMetUncertaintyTask)
0509         addTaskToProcess(process, "patShiftedModuleTask"+postfix, patShiftedModuleTask)
0510         addTaskToProcess(process, "patMetModuleTask"+postfix, patMetModuleTask)
0511 
0512         # prepare and fill the final task containing all the sub-tasks
0513         fullPatMetTask = cms.Task()
0514         fullPatMetTask.add(getattr(process, "patMetModuleTask"+postfix))
0515         fullPatMetTask.add(getattr(process, "patMetCorrectionTask"+postfix))
0516         fullPatMetTask.add(getattr(process, "patMetUncertaintyTask"+postfix))
0517         fullPatMetTask.add(getattr(process, "patShiftedModuleTask"+postfix))
0518 
0519         # include calo MET in final MET task
0520         if hasattr(process, "patCaloMet"):
0521             fullPatMetTask.add(getattr(process, "patCaloMet"))
0522         # include deepMETsResolutionTune and deepMETsResponseTune into final MET task
0523         if hasattr(process, "deepMETsResolutionTune"):
0524             fullPatMetTask.add(getattr(process, "deepMETsResolutionTune"))
0525         if hasattr(process, "deepMETsResponseTune"):
0526             fullPatMetTask.add(getattr(process, "deepMETsResponseTune"))
0527         # adding the slimmed MET module to final MET task
0528         if hasattr(process, "slimmedMETs"+postfix):
0529             fullPatMetTask.add(getattr(process, "slimmedMETs"+postfix))
0530 
0531         # add final MET task to the process
0532         addTaskToProcess(process, "fullPatMetTask"+postfix, fullPatMetTask)
0533 
0534         # add final MET task to the complete PatAlgosTools task
0535         task = getPatAlgosToolsTask(process)
0536         task.add(getattr(process,"fullPatMetTask"+postfix))
0537 
0538         #removing the non used jet selectors
0539         #configtools.removeIfInSequence(process, "selectedPatJetsForMetT1T2Corr", "patPFMetT1T2CorrSequence", postfix )
0540 
0541         #last modification for miniAODs
0542         self.miniAODConfigurationPost(process, postfix)
0543 
0544         # insert the fullPatMetSequence into patDefaultSequence if needed
0545         if addToPatDefaultSequence:
0546             if not hasattr(process, "patDefaultSequence"):
0547                 raise ValueError("PAT default sequence is not defined !!")
0548             process.patDefaultSequence += getattr(process, "fullPatMetSequence"+postfix)
0549 
0550 #====================================================================================================
0551     def produceMET(self, process,  metType, patMetModuleTask, postfix):
0552         # create a local task and a corresponding label to collect all the modules added in this function
0553         produceMET_task, produceMET_label = cms.Task(), "produceMET_task{}".format(postfix)
0554 
0555         # if PF MET is requested and not already part of the process object, then load the necessary configs and add them to the subtask
0556         if metType == "PF" and not hasattr(process, 'pat'+metType+'Met'):
0557             process.load("PhysicsTools.PatUtils.patPFMETCorrections_cff")
0558             produceMET_task.add(process.producePatPFMETCorrectionsTask)
0559             produceMET_task.add(process.patPFMetT2SmearCorrTask)
0560             produceMET_task.add(process.patPFMetTxyCorrTask)
0561             produceMET_task.add(process.jetCorrectorsTask)
0562 
0563         # account for a possible postfix
0564         _myPatMet = 'pat'+metType+'Met'+postfix
0565         # if a postfix is requested, the MET type is PF MET, and there is not already an associated object in the process object, then add the needed modules
0566         if postfix != "" and metType == "PF" and not hasattr(process, _myPatMet):
0567             noClonesTmp = [ "particleFlowDisplacedVertex", "pfCandidateToVertexAssociation" ]
0568             # clone the PF MET correction task, add it to the process with a postfix, and add it to the patAlgosToolsTask but exclude the modules above
0569             # QUESTION: is it possible to add this directly to the subtask?
0570             configtools.cloneProcessingSnippetTask(process, getattr(process,"producePatPFMETCorrectionsTask"), postfix, noClones = noClonesTmp)
0571             produceMET_task.add(getattr(process,"producePatPFMETCorrectionsTask"+postfix))
0572             # add a clone of the patPFMet producer to the process and the subtask
0573             addToProcessAndTask(_myPatMet,  getattr(process,'patPFMet').clone(), process, produceMET_task)
0574             # adapt some inputs of the patPFMet producer to account e.g. for the postfix
0575             getattr(process, _myPatMet).metSource = cms.InputTag("pfMet"+postfix)
0576             getattr(process, _myPatMet).srcPFCands = copy.copy(self.getvalue("pfCandCollection"))
0577             # account for possibility of Puppi
0578             if self.getvalue("Puppi"):
0579                 getattr(process, _myPatMet).srcWeights = self._parameters['puppiProducerForMETLabel'].value
0580         # set considered electrons, muons, and photons depending on data tier
0581         if metType == "PF":
0582             getattr(process, _myPatMet).srcLeptons = \
0583               cms.VInputTag(copy.copy(self.getvalue("electronCollection")) if self.getvalue("onMiniAOD") else
0584                               cms.InputTag("pfeGammaToCandidate","electrons"),
0585                             copy.copy(self.getvalue("muonCollection")),
0586                             copy.copy(self.getvalue("photonCollection")) if self.getvalue("onMiniAOD") else
0587                               cms.InputTag("pfeGammaToCandidate","photons"))
0588         # if running on data, remove generator quantities
0589         if self.getvalue("runOnData"):
0590             getattr(process, _myPatMet).addGenMET  = False
0591 
0592         # add PAT MET producer to subtask
0593         produceMET_task.add(getattr(process, _myPatMet ))
0594 
0595         # add the local task to the process
0596         addTaskToProcess(process, produceMET_label, produceMET_task)
0597 
0598         # add the task to the patMetModuleTask of the toolCode function
0599         patMetModuleTask.add(getattr(process, produceMET_label))
0600 
0601 #====================================================================================================
0602     def getCorrectedMET(self, process, metType, correctionLevel, produceIntermediateCorrections,
0603                         jetCollection, metModuleTask, postfix):
0604 
0605         # default outputs
0606         getCorrectedMET_task, getCorrectedMET_label = cms.Task(), "getCorrectedMET_task{}".format(postfix)
0607         # metModName -> metModuleName
0608         metModName = "pat"+metType+"Met"+postfix
0609 
0610         # names of correction types
0611         # not really needed but in case we have changes in the future ...
0612         corTypeNames = {
0613             "T0":"T0pc",
0614             "T1":"T1",
0615             "T2":"T2",
0616             "Txy":"Txy",
0617             "Smear":"Smear",
0618             }
0619 
0620 
0621         # if empty correction level, no need to try something or stop if an unknown correction type is used
0622         for corType in correctionLevel:
0623             if corType not in corTypeNames.keys():
0624                 if corType != "":
0625                     raise ValueError(corType+" is not a proper MET correction name! Aborting the MET correction production")
0626                 else:
0627                     return metModName
0628 
0629         # names of the tasks implementing a specific corretion type, see PatUtils/python/patPFMETCorrections_cff.py
0630         corTypeTaskNames = {
0631             "T0": "patPFMetT0CorrTask"+postfix,
0632             "T1": "patPFMetT1T2CorrTask"+postfix,
0633             "T2": "patPFMetT2CorrTask"+postfix,
0634             "Txy": "patPFMetTxyCorrTask"+postfix,
0635             "Smear": "patPFMetSmearCorrTask"+postfix,
0636             "T2Smear": "patPFMetT2SmearCorrTask"+postfix
0637             }
0638 
0639         # if a postfix is requested, clone the needed correction task to the configs and a add a postfix
0640         # this adds all the correction tasks for all the other METs e.g. PuppiMET due to the postfix
0641         if postfix != "":
0642             noClonesTmp = [ "particleFlowDisplacedVertex", "pfCandidateToVertexAssociation" ]
0643             if not hasattr(process, "patPFMetT0CorrTask"+postfix):
0644                 configtools.cloneProcessingSnippetTask(process, getattr(process,"patPFMetT0CorrTask"), postfix, noClones = noClonesTmp)
0645                 getCorrectedMET_task.add(getattr(process,"patPFMetT0CorrTask"+postfix))
0646             if not hasattr(process, "patPFMetT1T2CorrTask"+postfix):
0647                 configtools.cloneProcessingSnippetTask(process, getattr(process,"patPFMetT1T2CorrTask"), postfix)
0648                 getCorrectedMET_task.add(getattr(process,"patPFMetT1T2CorrTask"+postfix))
0649             if not hasattr(process, "patPFMetT2CorrTask"+postfix):
0650                 configtools.cloneProcessingSnippetTask(process, getattr(process,"patPFMetT2CorrTask"), postfix)
0651                 getCorrectedMET_task.add(getattr(process,"patPFMetT2CorrTask"+postfix))
0652             if not hasattr(process, "patPFMetTxyCorrTask"+postfix):
0653                 configtools.cloneProcessingSnippetTask(process, getattr(process,"patPFMetTxyCorrTask"), postfix)
0654                 getCorrectedMET_task.add(getattr(process,"patPFMetTxyCorrTask"+postfix))
0655             if not hasattr(process, "patPFMetSmearCorrTask"+postfix):
0656                 configtools.cloneProcessingSnippetTask(process, getattr(process,"patPFMetSmearCorrTask"), postfix)
0657                 getCorrectedMET_task.add(getattr(process,"patPFMetSmearCorrTask"+postfix))
0658             if not hasattr(process, "patPFMetT2SmearCorrTask"+postfix):
0659                 configtools.cloneProcessingSnippetTask(process, getattr(process,"patPFMetT2SmearCorrTask"), postfix)
0660                 getCorrectedMET_task.add(getattr(process,"patPFMetT2SmearCorrTask"+postfix))
0661 
0662         # collect the MET correction tasks, which have been added to the process, in a dict
0663         corTypeTasks = {}
0664         for corType in corTypeTaskNames.keys():
0665             corTypeTasks[corType] = getattr(process, corTypeTaskNames[corType] )
0666 
0667         # the names of the products which are created by the MET correction tasks and added to the event
0668         corTypeTags = {
0669             "T0":['patPFMetT0Corr'+postfix,''],
0670             "T1":['patPFMetT1T2Corr'+postfix, 'type1'],
0671             "T2":['patPFMetT2Corr'+postfix,   'type2'],
0672             "Txy": ['patPFMetTxyCorr'+postfix,''],
0673             "Smear":['patPFMetT1T2SmearCorr'+postfix, 'type1'],
0674             "T2Smear":['patPFMetT2SmearCorr'+postfix, 'type2']
0675             }
0676 
0677         # build the correction string (== correction level), collect the corresponding corrections, and collect the needed tasks
0678         correctionScheme=""
0679         correctionProducts = []
0680         correctionTasks = []
0681         for corType in correctionLevel:
0682             correctionScheme += corTypeNames[corType]
0683             correctionProducts.append(cms.InputTag(corTypeTags[corType][0],corTypeTags[corType][1]))
0684             correctionTasks.append(corTypeTasks[corType])
0685 
0686         # T2 and smearing corModuleTag switch, specific case
0687         if "T2" in correctionLevel and "Smear" in correctionLevel:
0688             correctionProducts.append(cms.InputTag(corTypeTags["T2Smear"][0],corTypeTags["T2Smear"][1]))
0689             correctionTasks.append(corTypeTasks["T2Smear"])
0690 
0691         # if both are here, consider smeared corJets for the full T1+Smear correction
0692         if "T1" in correctionLevel and "Smear" in correctionLevel:
0693             correctionProducts.remove(cms.InputTag(corTypeTags["T1"][0],corTypeTags["T1"][1]))
0694 
0695         # Txy parameter tuning
0696         if "Txy" in correctionLevel:
0697             datamc = "DATA" if self.getvalue("runOnData") else "MC"
0698             self.tuneTxyParameters(process, correctionScheme, postfix, datamc, self.getvalue("campaign"), self.getvalue("era"))
0699             getattr(process, "patPFMetTxyCorr"+postfix).srcPFlow = self._parameters["pfCandCollection"].value
0700             if self.getvalue("Puppi"):
0701                 getattr(process, "patPFMetTxyCorr"+postfix).srcWeights = self._parameters['puppiProducerForMETLabel'].value
0702 
0703 
0704         # Enable MET significance if the type1 MET is computed
0705         if "T1" in correctionLevel:
0706             _myPatMet = "pat"+metType+"Met"+postfix
0707             getattr(process, _myPatMet).computeMETSignificance = cms.bool(self.getvalue("computeMETSignificance"))
0708             getattr(process, _myPatMet).srcPFCands = copy.copy(self.getvalue("pfCandCollection"))
0709             getattr(process, _myPatMet).srcLeptons = \
0710               cms.VInputTag(copy.copy(self.getvalue("electronCollection")) if self.getvalue("onMiniAOD") else
0711                               cms.InputTag("pfeGammaToCandidate","electrons"),
0712                             copy.copy(self.getvalue("muonCollection")),
0713                             copy.copy(self.getvalue("photonCollection")) if self.getvalue("onMiniAOD") else
0714                               cms.InputTag("pfeGammaToCandidate","photons"))
0715             if postfix=="NoHF":
0716                 getattr(process, _myPatMet).computeMETSignificance = cms.bool(False)
0717             if self.getvalue("runOnData"):
0718                 from RecoMET.METProducers.METSignificanceParams_cfi import METSignificanceParams_Data
0719                 getattr(process, _myPatMet).parameters = METSignificanceParams_Data
0720             if self.getvalue("Puppi"):
0721                 getattr(process, _myPatMet).srcWeights = self._parameters['puppiProducerForMETLabel'].value
0722                 getattr(process, _myPatMet).srcJets = cms.InputTag('cleanedPatJets'+postfix)
0723                 getattr(process, _myPatMet).srcJetSF = 'AK4PFPuppi'
0724                 getattr(process, _myPatMet).srcJetResPt = 'AK4PFPuppi_pt'
0725                 getattr(process, _myPatMet).srcJetResPhi = 'AK4PFPuppi_phi'
0726 
0727         # MET significance bypass for the patMETs from AOD
0728         if not self._parameters["onMiniAOD"].value and not postfix=="NoHF":
0729             _myPatMet = "patMETs"+postfix
0730             getattr(process, _myPatMet).computeMETSignificance = cms.bool(self.getvalue("computeMETSignificance"))
0731             getattr(process, _myPatMet).srcPFCands=copy.copy(self.getvalue("pfCandCollection"))
0732             getattr(process, _myPatMet).srcLeptons = \
0733               cms.VInputTag(copy.copy(self.getvalue("electronCollection")) if self.getvalue("onMiniAOD") else
0734                               cms.InputTag("pfeGammaToCandidate","electrons"),
0735                             copy.copy(self.getvalue("muonCollection")),
0736                             copy.copy(self.getvalue("photonCollection")) if self.getvalue("onMiniAOD") else
0737                               cms.InputTag("pfeGammaToCandidate","photons"))
0738             if self.getvalue("Puppi"):
0739                 getattr(process, _myPatMet).srcWeights = self._parameters['puppiProducerForMETLabel'].value
0740 
0741         if hasattr(process, "patCaloMet"):
0742             getattr(process, "patCaloMet").computeMETSignificance = cms.bool(False)
0743 
0744         # T1 parameter tuning when CHS jets are not used
0745         if "T1" in correctionLevel and not self._parameters["CHS"].value and not self._parameters["Puppi"].value:
0746             addToProcessAndTask("corrPfMetType1"+postfix, getattr(process, "corrPfMetType1" ).clone(), process, getCorrectedMET_task)
0747             getattr(process, "corrPfMetType1"+postfix).src =  cms.InputTag("ak4PFJets"+postfix)
0748             getattr(process, "corrPfMetType1"+postfix).jetCorrLabel = cms.InputTag("ak4PFL1FastL2L3Corrector")
0749             getattr(process, "corrPfMetType1"+postfix).jetCorrLabelRes = cms.InputTag("ak4PFL1FastL2L3ResidualCorrector")
0750             getattr(process, "corrPfMetType1"+postfix).offsetCorrLabel = cms.InputTag("ak4PFL1FastjetCorrector")
0751             getattr(process, "basicJetsForMet"+postfix).offsetCorrLabel = cms.InputTag("ak4PFL1FastjetCorrector")
0752 
0753         if "T1" in correctionLevel and self._parameters["Puppi"].value:
0754             addToProcessAndTask("corrPfMetType1"+postfix, getattr(process, "corrPfMetType1" ).clone(), process, getCorrectedMET_task)
0755             getattr(process, "corrPfMetType1"+postfix).src =  cms.InputTag("ak4PFJets"+postfix)
0756             getattr(process, "corrPfMetType1"+postfix).jetCorrLabel = cms.InputTag("ak4PFPuppiL1FastL2L3Corrector")
0757             getattr(process, "corrPfMetType1"+postfix).jetCorrLabelRes = cms.InputTag("ak4PFPuppiL1FastL2L3ResidualCorrector")
0758             getattr(process, "corrPfMetType1"+postfix).offsetCorrLabel = cms.InputTag("ak4PFPuppiL1FastjetCorrector")
0759             getattr(process, "basicJetsForMet"+postfix).offsetCorrLabel = cms.InputTag("L1FastJet")
0760 
0761         if "T1" in correctionLevel and self._parameters["CHS"].value and self._parameters["reclusterJets"].value:
0762             getattr(process, "corrPfMetType1"+postfix).src =  cms.InputTag("ak4PFJetsCHS"+postfix)
0763 
0764         # create the main MET producer with the applied correction scheme
0765         metModName = "pat"+metType+"Met"+correctionScheme+postfix
0766 
0767         taskName=""
0768         corMetProducer=None
0769         
0770         # this should always be true due to the way e.g. PuppiMET is handled (metType is set back to PF and the puppi flag is set to true instead)
0771         if metType == "PF":
0772             corMetProducer = cms.EDProducer("CorrectedPATMETProducer",
0773                        src = cms.InputTag('pat'+metType+'Met' + postfix),
0774                        srcCorrections = cms.VInputTag(correctionProducts)
0775                      )
0776             taskName="getCorrectedMET_task"
0777 
0778         addToProcessAndTask(metModName, corMetProducer, process, getCorrectedMET_task)
0779 
0780         # adding the full sequence only if it does not exist
0781         if not hasattr(process, getCorrectedMET_label):
0782             for corTask in correctionTasks:
0783                 getCorrectedMET_task.add(corTask)
0784         # if it exists, only add the missing correction modules, no need to redo everything
0785         else:
0786             for corType in corTypeTaskNames.keys():
0787                 if not configtools.contains(getCorrectedMET_task, corTypeTags[corType][0]) and corType in correctionLevel:
0788                     getCorrectedMET_task.add(corTypeTasks[corType])
0789 
0790         # plug the main patMetproducer
0791         getCorrectedMET_task.add(getattr(process, metModName))
0792         
0793         addTaskToProcess(process, getCorrectedMET_label, getCorrectedMET_task)
0794         metModuleTask.add(getattr(process, getCorrectedMET_label))
0795 
0796         # create the intermediate MET steps
0797         # and finally add the met producers in the sequence for scheduled mode
0798         if produceIntermediateCorrections:
0799             interMets = self.addIntermediateMETs(process, metType, correctionLevel, correctionScheme, corTypeTags,corTypeNames, postfix)
0800             for met in interMets.keys():
0801                 addToProcessAndTask(met, interMets[met], process, getCorrectedMET_task)
0802 
0803         return metModName
0804 
0805 
0806 #====================================================================================================
0807     def addIntermediateMETs(self, process, metType, correctionLevel, corScheme, corTags, corNames, postfix):
0808         interMets = {}
0809 
0810         # we don't want to duplicate an exisiting module if we ask for a simple 1-corr scheme
0811         if len(correctionLevel) == 1:
0812             return interMets
0813 
0814         #ugly, but it works
0815         nCor=len(correctionLevel)+1
0816         ids = [0]*nCor
0817         for i in range(nCor**nCor):
0818             tmp=i
0819             exists=False
0820             corName=""
0821             corrections = []
0822             for j in range(nCor):
0823                 ids[j] = tmp%nCor
0824                 tmp = tmp//nCor
0825 
0826                 if j != 0 and ids[j-1] < ids[j]:
0827                     exists=True
0828                 for k in range(0,j):
0829                     if ids[k] == ids[j] and ids[k]!=0:
0830                         exists=True
0831 
0832             if exists or sum(ids[j] for j in range(nCor))==0:
0833                 continue
0834 
0835             for cor in range(nCor):
0836                 cid = ids[nCor-cor-1]
0837                 cKey = correctionLevel[cid-1]
0838                 if cid ==0:#empty correction
0839                     continue
0840                 else :
0841                     corName += corNames[cKey]
0842                     corrections.append( cms.InputTag(corTags[ cKey ][0], corTags[ cKey ][1]) )
0843 
0844             if corName == corScheme:
0845                 continue
0846 
0847             corName='pat'+metType+'Met' + corName + postfix
0848             if configtools.contains(getattr(process,"getCorrectedMET_task"+postfix), corName ) and hasattr(process, corName):
0849                 continue
0850 
0851             interMets[corName] =  cms.EDProducer("CorrectedPATMETProducer",
0852                  src = cms.InputTag('pat'+metType+'Met' + postfix),
0853                  srcCorrections = cms.VInputTag(corrections)
0854                )
0855 
0856 
0857         return interMets
0858 
0859 
0860 #====================================================================================================
0861     def getMETUncertainties(self, process, metType, metModName, electronCollection,
0862                             photonCollection, muonCollection, tauCollection,
0863                             pfCandCollection, jetCollection, jetUncInfos,
0864                             patMetUncertaintyTask,
0865                             postfix):
0866         # create a local task and a corresponding label to collect all the modules added in this function
0867         getMETUncertainties_task, getMETUncertainties_label = cms.Task(), "getMETUncertainties_task{}".format(postfix)
0868 
0869         #===================================================================================
0870         # jet energy resolution shifts
0871         #===================================================================================
0872         if not isValidInputTag(jetCollection): #or jetCollection=="":
0873             print("INFO : jet collection %s does not exists, no energy resolution shifting will be performed in MET uncertainty tools" % jetCollection)
0874         else:
0875             preId=""
0876             if "Smear" in metModName:
0877                 preId="Smeared"
0878 
0879             metJERUncModules = self.getVariations(process, metModName, "Jet",preId, jetCollection, "Res", patMetUncertaintyTask, postfix=postfix )
0880 
0881             for mod in metJERUncModules.keys():
0882                 addToProcessAndTask(mod, metJERUncModules[mod], process, getMETUncertainties_task)
0883 
0884         #===================================================================================
0885         # Unclustered energy candidates
0886         #===================================================================================
0887         if not hasattr(process, "pfCandsForUnclusteredUnc"+postfix):
0888 
0889             #Jet projection ==
0890             pfCandsNoJets = _mod.candPtrProjector.clone( 
0891                                            src = pfCandCollection,
0892                                            veto = jetCollection,
0893                                            )
0894             addToProcessAndTask("pfCandsNoJets"+postfix, pfCandsNoJets, process, getMETUncertainties_task)
0895 
0896             #electron projection ==
0897             pfCandsNoJetsNoEle = _mod.candPtrProjector.clone(
0898                                                 src = "pfCandsNoJets"+postfix,
0899                                                 veto = electronCollection,
0900                                                 )
0901             if not self.getvalue("onMiniAOD"):
0902               pfCandsNoJetsNoEle.veto = "pfeGammaToCandidate:electrons"
0903             addToProcessAndTask("pfCandsNoJetsNoEle"+postfix, pfCandsNoJetsNoEle, process, getMETUncertainties_task)
0904 
0905             #muon projection ==
0906             pfCandsNoJetsNoEleNoMu = _mod.candPtrProjector.clone(
0907                                               src = "pfCandsNoJetsNoEle"+postfix,
0908                                               veto = muonCollection,
0909                                               )
0910             addToProcessAndTask("pfCandsNoJetsNoEleNoMu"+postfix, pfCandsNoJetsNoEleNoMu, process, getMETUncertainties_task)
0911 
0912             #tau projection ==
0913             pfCandsNoJetsNoEleNoMuNoTau = _mod.candPtrProjector.clone(
0914                                               src = "pfCandsNoJetsNoEleNoMu"+postfix,
0915                                               veto = tauCollection,
0916                                               )
0917             addToProcessAndTask("pfCandsNoJetsNoEleNoMuNoTau"+postfix, pfCandsNoJetsNoEleNoMuNoTau, process, getMETUncertainties_task)
0918 
0919             #photon projection ==
0920             pfCandsForUnclusteredUnc = _mod.candPtrProjector.clone(
0921                                               src = "pfCandsNoJetsNoEleNoMuNoTau"+postfix,
0922                                               veto = photonCollection,
0923                                               )
0924             if not self.getvalue("onMiniAOD"):
0925               pfCandsForUnclusteredUnc.veto = "pfeGammaToCandidate:photons"
0926             addToProcessAndTask("pfCandsForUnclusteredUnc"+postfix, pfCandsForUnclusteredUnc, process, getMETUncertainties_task)
0927 
0928         #===================================================================================
0929         # energy shifts
0930         #===================================================================================
0931         # PFMuons, PFElectrons, PFPhotons, and PFTaus will be used
0932         # to calculate MET Uncertainties.
0933         #===================================================================================
0934         #--------------
0935         # PFElectrons :
0936         #--------------
0937         pfElectrons = cms.EDFilter("CandPtrSelector",
0938                                    src = electronCollection,
0939                                    cut = cms.string("pt > 5 && isPF && gsfTrack.isAvailable() && gsfTrack.hitPattern().numberOfLostHits(\'MISSING_INNER_HITS\') < 2")
0940                                    )
0941         addToProcessAndTask("pfElectrons"+postfix, pfElectrons, process, getMETUncertainties_task)
0942         #--------------------------------------------------------------------
0943         # PFTaus :
0944         #---------
0945         pfTaus = cms.EDFilter("PATTauRefSelector",
0946                               src = tauCollection,
0947                               cut = cms.string('pt > 18.0 & abs(eta) < 2.6 & tauID("decayModeFinding") > 0.5 & isPFTau')
0948                               )
0949         addToProcessAndTask("pfTaus"+postfix, pfTaus, process, getMETUncertainties_task)
0950         #---------------------------------------------------------------------
0951         # PFMuons :
0952         #----------
0953         pfMuons = cms.EDFilter("CandPtrSelector",
0954                                src = muonCollection,
0955                                cut = cms.string("pt > 5.0 && isPFMuon && abs(eta) < 2.4")
0956                                )
0957         addToProcessAndTask("pfMuons"+postfix, pfMuons, process, getMETUncertainties_task)
0958         #---------------------------------------------------------------------
0959         # PFPhotons :
0960         #------------
0961         if self._parameters["Puppi"].value or not self._parameters["onMiniAOD"].value:
0962             cutforpfNoPileUp = cms.string("")
0963         else:
0964             cutforpfNoPileUp = cms.string("fromPV > 1")
0965 
0966         pfNoPileUp = cms.EDFilter("CandPtrSelector",
0967                                   src = pfCandCollection,
0968                                   cut = cutforpfNoPileUp
0969                                   )
0970         addToProcessAndTask("pfNoPileUp"+postfix, pfNoPileUp, process, getMETUncertainties_task)
0971 
0972         pfPhotons = cms.EDFilter("CandPtrSelector",
0973                                  src = pfCandCollection if self._parameters["Puppi"].value or not self._parameters["onMiniAOD"].value else cms.InputTag("pfCHS"),
0974                                  cut = cms.string("abs(pdgId) = 22")
0975                                  )
0976         addToProcessAndTask("pfPhotons"+postfix, pfPhotons, process, getMETUncertainties_task)
0977         #-------------------------------------------------------------------------
0978         # Collections which have only PF Objects for calculating MET uncertainties
0979         #-------------------------------------------------------------------------
0980         electronCollection = cms.InputTag("pfElectrons"+postfix)
0981         muonCollection     = cms.InputTag("pfMuons"+postfix)
0982         tauCollection      = cms.InputTag("pfTaus"+postfix)
0983         photonCollection   = cms.InputTag("pfPhotons"+postfix)
0984 
0985 
0986         objectCollections = { "Jet":jetCollection,
0987                               "Electron":electronCollection,
0988                               "Photon":photonCollection,
0989                               "Muon":muonCollection,
0990                               "Unclustered":cms.InputTag("pfCandsForUnclusteredUnc"+postfix),
0991                               "Tau":tauCollection,
0992                               }
0993 
0994         for obj in objectCollections.keys():
0995             if not isValidInputTag(objectCollections[obj]): # or objectCollections[obj]=="":
0996                 print("INFO : %s collection %s does not exists, no energy scale shifting will be performed in MET uncertainty tools" %(obj, objectCollections[obj]))
0997             else:
0998                 metObjUncModules = self.getVariations(process, metModName, obj,"", objectCollections[obj], "En", patMetUncertaintyTask, jetUncInfos, postfix )
0999 
1000                 #adding the shifted MET produced to the proper patMetModuleSequence
1001                 for mod in metObjUncModules.keys():
1002                     addToProcessAndTask(mod, metObjUncModules[mod], process, getMETUncertainties_task)
1003 
1004         # add the local task to the process
1005         addTaskToProcess(process, getMETUncertainties_label, getMETUncertainties_task)
1006         patMetUncertaintyTask.add(getattr(process, getMETUncertainties_label))
1007 
1008 #====================================================================================================
1009     def createEnergyScaleShiftedUpModule(self, process,identifier, objectCollection,
1010                                          varyByNsigmas, jetUncInfos=None, postfix=""):
1011 
1012         shiftedModuleUp = None
1013 
1014         if identifier == "Electron":
1015             shiftedModuleUp = cms.EDProducer("ShiftedParticleProducer",
1016                                              src = objectCollection,
1017                                              uncertainty = cms.string('((abs(y)<1.479)?(0.006+0*x):(0.015+0*x))'),
1018                                              shiftBy = cms.double(+1.*varyByNsigmas),
1019                                              srcWeights = cms.InputTag("")
1020                                              )
1021 
1022         if identifier == "Photon":
1023             shiftedModuleUp = cms.EDProducer("ShiftedParticleProducer",
1024                                              src = objectCollection,
1025                                              uncertainty = cms.string('((abs(y)<1.479)?(0.01+0*x):(0.025+0*x))'),
1026                                              shiftBy = cms.double(+1.*varyByNsigmas),
1027                                              srcWeights = cms.InputTag("")
1028                                              )
1029 
1030         if identifier == "Muon":
1031             shiftedModuleUp = cms.EDProducer("ShiftedParticleProducer",
1032                                              src = objectCollection,
1033                                              uncertainty = cms.string('((x<100)?(0.002+0*y):(0.05+0*y))'),
1034                                              shiftBy = cms.double(+1.*varyByNsigmas),
1035                                              srcWeights = cms.InputTag("")
1036                                              )
1037 
1038         if identifier == "Tau":
1039             shiftedModuleUp = cms.EDProducer("ShiftedParticleProducer",
1040                                              src = objectCollection,
1041                                              uncertainty = cms.string('0.03+0*x*y'),
1042                                              shiftBy = cms.double(+1.*varyByNsigmas),
1043                                              srcWeights = cms.InputTag("")
1044                                              )
1045 
1046         if identifier == "Unclustered":
1047             shiftedModuleUp = cms.EDProducer("ShiftedParticleProducer",
1048                                              src = objectCollection,
1049                                              binning = cms.VPSet(
1050                     # charged PF hadrons - tracker resolution
1051                     cms.PSet(
1052                         binSelection = cms.string('charge!=0'),
1053                         binUncertainty = cms.string('sqrt(pow(0.00009*x,2)+pow(0.0085/sqrt(sin(2*atan(exp(-y)))),2))')
1054                         ),
1055                     # neutral PF hadrons - HCAL resolution
1056                     cms.PSet(
1057                         binSelection = cms.string('pdgId==130'),
1058                         energyDependency = cms.bool(True),
1059                         binUncertainty = cms.string('((abs(y)<1.3)?(min(0.25,sqrt(0.64/x+0.0025))):(min(0.30,sqrt(1.0/x+0.0016))))')
1060                         ),
1061                     # photon - ECAL resolution
1062                     cms.PSet(
1063                         binSelection = cms.string('pdgId==22'),
1064                         energyDependency = cms.bool(True),
1065                         binUncertainty = cms.string('sqrt(0.0009/x+0.000001)+0*y')
1066                         ),
1067                     # HF particules - HF resolution
1068                     cms.PSet(
1069                         binSelection = cms.string('pdgId==1 || pdgId==2'),
1070                         energyDependency = cms.bool(True),
1071                         binUncertainty = cms.string('sqrt(1./x+0.0025)+0*y')
1072                         ),
1073                     ),
1074                                              shiftBy = cms.double(+1.*varyByNsigmas),
1075                                              srcWeights = cms.InputTag("")
1076                                              )
1077 
1078         if identifier == "Jet":
1079             moduleType="ShiftedPATJetProducer"
1080 
1081             if jetUncInfos["jecUncFile"] == "":
1082                 shiftedModuleUp = cms.EDProducer(moduleType,
1083                                                  src = objectCollection,
1084                                                  jetCorrUncertaintyTag = cms.string(jetUncInfos["jecUncTag"] ),
1085                                                  addResidualJES = cms.bool(True),
1086                                                  jetCorrLabelUpToL3 = cms.InputTag(jetUncInfos["jCorLabelUpToL3"] ),
1087                                                  jetCorrLabelUpToL3Res = cms.InputTag(jetUncInfos["jCorLabelL3Res"] ),
1088                                                  jetCorrPayloadName =  cms.string(jetUncInfos["jCorrPayload"] ),
1089                                                  shiftBy = cms.double(+1.*varyByNsigmas),
1090                                                  )
1091             else:
1092                 shiftedModuleUp = cms.EDProducer(moduleType,
1093                                                  src = objectCollection,
1094                                                  jetCorrInputFileName = cms.FileInPath(jetUncInfos["jecUncFile"] ),
1095                                                  jetCorrUncertaintyTag = cms.string(jetUncInfos["jecUncTag"] ),
1096                                                  addResidualJES = cms.bool(True),
1097                                                  jetCorrLabelUpToL3 = cms.InputTag(jetUncInfos["jCorLabelUpToL3"] ),
1098                                                  jetCorrLabelUpToL3Res = cms.InputTag(jetUncInfos["jCorLabelL3Res"] ),
1099                                                  jetCorrPayloadName =  cms.string(jetUncInfos["jCorrPayload"] ),
1100                                                  shiftBy = cms.double(+1.*varyByNsigmas),
1101                                                  )
1102 
1103 
1104         return shiftedModuleUp
1105 
1106 
1107 #====================================================================================================
1108 
1109 
1110 #====================================================================================================
1111     def removePostfix(self, name, postfix):
1112 
1113         if postfix=="":
1114             return name
1115 
1116         baseName = name
1117         if baseName[-len(postfix):] == postfix:
1118             baseName = baseName[0:-len(postfix)]
1119         else:
1120             raise Exception("Tried to remove postfix %s from %s, but it wasn't there" % (postfix, baseName))
1121 
1122         return baseName
1123 
1124 #====================================================================================================
1125     def tuneTxyParameters(self, process, corScheme, postfix, datamc="", campaign="", era="" ):
1126         corSchemes = ["Txy", "T1Txy", "T0pcTxy", "T0pcT1Txy", "T1T2Txy", "T0pcT1T2Txy", "T1SmearTxy", "T1T2SmearTxy", "T0pcT1SmearTxy", "T0pcT1T2SmearTxy"]
1127         import PhysicsTools.PatUtils.patPFMETCorrections_cff as metCors
1128         xyTags = {}
1129         for corScheme_ in corSchemes:
1130             xyTags["{}_{}".format(corScheme_,"50ns")]=getattr(metCors,"{}_{}_{}".format("patMultPhiCorrParams",corScheme_,"50ns"))
1131             xyTags["{}_{}".format(corScheme_,"25ns")]=getattr(metCors,"{}_{}_{}".format("patMultPhiCorrParams",corScheme_,"25ns"))
1132             if datamc!="" and campaign!="" and era!="":
1133                 if not self.getvalue("Puppi"):
1134                     xyTags["{}_{}_{}_{}".format(corScheme_,campaign,datamc,era)]=getattr(metCors,"{}_{}{}{}".format("patMultPhiCorrParams",campaign,datamc,era))
1135                 else:
1136                     xyTags["{}_{}_{}_{}".format(corScheme_,campaign,datamc,era)]=getattr(metCors,"{}_{}{}{}".format("patMultPhiCorrParams_Puppi",campaign,datamc,era))
1137 
1138         if datamc!="" and campaign!="" and era!="":
1139             getattr(process, "patPFMetTxyCorr"+postfix).parameters = xyTags["{}_{}_{}_{}".format(corScheme,campaign,datamc,era)]
1140         else:
1141             getattr(process, "patPFMetTxyCorr"+postfix).parameters = xyTags[corScheme+"_25ns"]
1142 
1143 
1144 #====================================================================================================
1145     def getVariations(self, process, metModName, identifier,preId, objectCollection, varType,
1146                       patMetUncertaintyTask, jetUncInfos=None, postfix="" ):
1147 
1148         # temporary hardcoded varyByNSigma value
1149         varyByNsigmas=1
1150 
1151         # remove the postfix to put it at the end
1152         baseName = self.removePostfix(metModName, postfix)
1153 
1154         #default shifted MET producers
1155         shiftedMetProducers = {preId+identifier+varType+'Up':None, preId+identifier+varType+'Down':None}
1156 
1157         #create the shifted collection producers=========================================
1158         shiftedCollModules = {'Up':None, 'Down':None}
1159 
1160         if identifier=="Jet" and varType=="Res":
1161             smear=False
1162             if "Smear" in metModName:
1163                 smear=True
1164             else:
1165                 smear=True
1166                 varyByNsigmas=101
1167 
1168             shiftedCollModules['Up'] = self.createShiftedJetResModule(process, smear, objectCollection, +1.*varyByNsigmas,
1169                                                                       "Up", postfix)
1170             shiftedCollModules['Down'] = self.createShiftedJetResModule(process, smear, objectCollection, -1.*varyByNsigmas,
1171                                                                         "Down", postfix)
1172         else:
1173             shiftedCollModules['Up'] = self.createEnergyScaleShiftedUpModule(process, identifier, objectCollection, varyByNsigmas, jetUncInfos, postfix)
1174             shiftedCollModules['Down'] = shiftedCollModules['Up'].clone( shiftBy = cms.double(-1.*varyByNsigmas) )
1175 
1176         if identifier=="Jet" and varType=="Res":
1177             smear=False
1178             if "Smear" in metModName:
1179                 objectCollection=cms.InputTag("selectedPatJetsForMetT1T2SmearCorr"+postfix)
1180 
1181 
1182 
1183         #and the MET producers
1184         if identifier=="Jet" and varType=="Res" and self._parameters["runOnData"].value:
1185             shiftedMetProducers = self.copyCentralMETProducer(process, shiftedCollModules, identifier, metModName, varType, postfix)
1186         else:
1187             shiftedMetProducers = self.createShiftedModules(process, shiftedCollModules, identifier, preId, objectCollection,
1188                                                             metModName, varType, patMetUncertaintyTask, postfix)
1189 
1190         return shiftedMetProducers
1191 
1192 
1193 #========================================================================================
1194     def copyCentralMETProducer(self, process, shiftedCollModules, identifier, metModName, varType, postfix):
1195 
1196         # remove the postfix to put it at the end
1197         shiftedMetProducers = {}
1198         baseName = self.removePostfix(metModName, postfix)
1199         for mod in shiftedCollModules.keys():
1200             modName = baseName+identifier+varType+mod+postfix
1201             shiftedMETModule = getattr(process, metModName).clone()
1202             shiftedMetProducers[ modName ] = shiftedMETModule
1203 
1204         return shiftedMetProducers
1205 
1206 
1207 #========================================================================================
1208     def createShiftedJetResModule(self, process, smear, objectCollection, varyByNsigmas, varDir, postfix ):
1209 
1210         smearedJetModule = self.createSmearedJetModule(process, objectCollection, smear, varyByNsigmas, varDir, postfix)
1211 
1212         return smearedJetModule
1213 
1214 
1215 #========================================================================================
1216     def createShiftedModules(self, process, shiftedCollModules, identifier, preId, objectCollection,
1217                              metModName, varType, patMetUncertaintyTask, postfix):
1218         # create a local task and a corresponding label to collect all the modules added in this function
1219         createShiftedModules_task, createShiftedModules_label = cms.Task(), "createShiftedModules_task{}".format(postfix)
1220 
1221         shiftedMetProducers = {}
1222 
1223         # remove the postfix to put it at the end
1224         baseName = self.removePostfix(metModName, postfix)
1225 
1226         #adding the shifted collection producers to the sequence, create the shifted MET correction Modules and add them as well
1227         for mod in shiftedCollModules.keys():
1228             modName = "shiftedPat"+preId+identifier+varType+mod+postfix
1229             if (identifier=="Photon" or identifier=="Unclustered") and self.getvalue("Puppi"):
1230                 shiftedCollModules[mod].srcWeights = self._parameters['puppiProducerForMETLabel'].value
1231             if not hasattr(process, modName):
1232                 addToProcessAndTask(modName, shiftedCollModules[mod], process, createShiftedModules_task)
1233 
1234             #removing the uncorrected
1235             modName = "shiftedPat"+preId+identifier+varType+mod+postfix
1236 
1237             #PF MET =================================================================================
1238             if "PF" in metModName:
1239                 #create the MET shifts and add them to the sequence
1240                 shiftedMETCorrModule = self.createShiftedMETModule(process, objectCollection, modName)
1241                 if (identifier=="Photon" or identifier=="Unclustered") and self.getvalue("Puppi"):
1242                    shiftedMETCorrModule.srcWeights = self._parameters['puppiProducerForMETLabel'].value
1243                 modMETShiftName = "shiftedPatMETCorr"+preId+identifier+varType+mod+postfix
1244                 if not hasattr(process, modMETShiftName):
1245                     addToProcessAndTask(modMETShiftName, shiftedMETCorrModule, process, createShiftedModules_task)
1246 
1247                 #and finally prepare the shifted MET producers
1248                 modName = baseName+identifier+varType+mod+postfix
1249                 shiftedMETModule = getattr(process, metModName).clone(
1250                     src = cms.InputTag( metModName ),
1251                     srcCorrections = cms.VInputTag( cms.InputTag(modMETShiftName) )
1252                     )
1253                 shiftedMetProducers[ modName ] = shiftedMETModule
1254 
1255            #==========================================================================================
1256 
1257         addTaskToProcess(process, createShiftedModules_label, createShiftedModules_task)
1258         patMetUncertaintyTask.add(getattr(process, createShiftedModules_label))
1259 
1260         return shiftedMetProducers
1261 
1262 
1263 #========================================================================================
1264     def createShiftedMETModule(self, process, originCollection, shiftedCollection):
1265 
1266         shiftedModule = cms.EDProducer("ShiftedParticleMETcorrInputProducer",
1267                                        srcOriginal = originCollection,
1268                                        srcShifted = cms.InputTag(shiftedCollection),
1269                                        srcWeights = cms.InputTag("")
1270                                        )
1271 
1272         return shiftedModule
1273 
1274 #========================================================================================
1275     def createSmearedJetModule(self, process, jetCollection, smear, varyByNsigmas, varDir, postfix):
1276 
1277         smearedJetModule = None
1278 
1279         modName = "pat"
1280         selJetModName= "selectedPatJetsForMetT1T2"
1281         if smear:
1282             modName += "SmearedJets"
1283             selJetModName += "SmearCorr"
1284         else:
1285             modName += "Jets"
1286 
1287 
1288         if varDir != "":
1289             modName += "Res"+varDir
1290             selJetModName += "Res"+varDir
1291 
1292         modName += postfix
1293         selJetModName += postfix
1294 
1295         genJetsCollection=cms.InputTag('ak4GenJetsNoNu')
1296         if self._parameters["onMiniAOD"].value:
1297             genJetsCollection=cms.InputTag("slimmedGenJets")
1298 
1299         if self._parameters["Puppi"].value:
1300             getattr(process, "patSmearedJets"+postfix).algo = 'AK4PFPuppi'
1301             getattr(process, "patSmearedJets"+postfix).algopt = 'AK4PFPuppi_pt'
1302 
1303         if "PF" == self._parameters["metType"].value:
1304             smearedJetModule = getattr(process, "patSmearedJets"+postfix).clone(
1305                 src = jetCollection,
1306                 enabled = cms.bool(smear),
1307                 variation = cms.int32( int(varyByNsigmas) ),
1308                 genJets = genJetsCollection,
1309                 )
1310 
1311         return smearedJetModule
1312 
1313 
1314 ### Utilities ====================================================================
1315     def labelsInSequence(process, sequenceLabel, postfix=""):
1316         result = [ m.label()[:-len(postfix)] for m in listModules( getattr(process,sequenceLabel+postfix))]
1317         result.extend([ m.label()[:-len(postfix)] for m in listSequences( getattr(process,sequenceLabel+postfix))]  )
1318         if postfix == "":
1319             result = [ m.label() for m in listModules( getattr(process,sequenceLabel+postfix))]
1320             result.extend([ m.label() for m in listSequences( getattr(process,sequenceLabel+postfix))]  )
1321         return result
1322 
1323     def initializeInputTag(self, input, default):
1324         retVal = None
1325         if input is None:
1326             retVal = self._defaultParameters[default].value
1327         elif isinstance(input, str):
1328             retVal = cms.InputTag(input)
1329         else:
1330             retVal = input
1331         return retVal
1332 
1333 
1334     def recomputeRawMetFromPfcs(self, process, pfCandCollection, onMiniAOD, patMetModuleTask, postfix):
1335         # create a local task and a corresponding label to collect all the modules added in this function
1336         recomputeRawMetFromPfcs_task, recomputeRawMetFromPfcs_label = cms.Task(), "recomputeRawMetFromPfcs_task{}".format(postfix)
1337 
1338         # RECO MET
1339         if not hasattr(process, "pfMet"+postfix) and self._parameters["metType"].value == "PF":
1340             # common to AOD/mAOD processing
1341             # raw MET
1342             # clone the standard pfMet module, add it to the relevant task, and adapt the input collection to the desired PF candidate collection
1343             from RecoMET.METProducers.pfMet_cfi import pfMet
1344             addToProcessAndTask("pfMet"+postfix, pfMet.clone(), process, recomputeRawMetFromPfcs_task)
1345             getattr(process, "pfMet"+postfix).src = pfCandCollection
1346             getattr(process, "pfMet"+postfix).calculateSignificance = False
1347             # if Puppi MET is requested, apply the Puppi weights
1348             if self.getvalue("Puppi"):
1349                 getattr(process, "pfMet"+postfix).applyWeight = True
1350                 getattr(process, "pfMet"+postfix).srcWeights = self._parameters['puppiProducerForMETLabel'].value
1351 
1352         # PAT MET
1353         if not hasattr(process, "patMETs"+postfix) and self._parameters["metType"].value == "PF":
1354             process.load("PhysicsTools.PatAlgos.producersLayer1.metProducer_cff")
1355             recomputeRawMetFromPfcs_task.add(process.makePatMETsTask)
1356             configtools.cloneProcessingSnippetTask(process, getattr(process,"patMETCorrectionsTask"), postfix)
1357             recomputeRawMetFromPfcs_task.add(getattr(process,"patMETCorrectionsTask"+postfix))
1358 
1359             # T1 pfMet for AOD to mAOD only
1360             if not onMiniAOD: #or self._parameters["Puppi"].value:
1361                 #correction duplication needed
1362                 getattr(process, "pfMetT1"+postfix).src = cms.InputTag("pfMet"+postfix)
1363                 recomputeRawMetFromPfcs_task.add(getattr(process, "pfMetT1"+postfix))
1364                 _myPatMet = 'patMETs'+postfix
1365                 addToProcessAndTask(_myPatMet, getattr(process,'patMETs' ).clone(), process, recomputeRawMetFromPfcs_task)
1366                 getattr(process, _myPatMet).metSource = cms.InputTag("pfMetT1"+postfix)
1367                 getattr(process, _myPatMet).computeMETSignificance = cms.bool(self.getvalue("computeMETSignificance"))
1368                 getattr(process, _myPatMet).srcLeptons = \
1369                   cms.VInputTag(copy.copy(self.getvalue("electronCollection")) if self.getvalue("onMiniAOD") else
1370                                   cms.InputTag("pfeGammaToCandidate","electrons"),
1371                                 copy.copy(self.getvalue("muonCollection")),
1372                                 copy.copy(self.getvalue("photonCollection")) if self.getvalue("onMiniAOD") else
1373                                   cms.InputTag("pfeGammaToCandidate","photons"))
1374                 if postfix=="NoHF":
1375                     getattr(process, _myPatMet).computeMETSignificance = cms.bool(False)
1376 
1377                 if self.getvalue("Puppi"):
1378                     getattr(process, _myPatMet).srcWeights = self._parameters['puppiProducerForMETLabel'].value
1379                     getattr(process, _myPatMet).srcJets = cms.InputTag('cleanedPatJets'+postfix)
1380                     getattr(process, _myPatMet).srcJetSF = cms.string('AK4PFPuppi')
1381                     getattr(process, _myPatMet).srcJetResPt = cms.string('AK4PFPuppi_pt')
1382                     getattr(process, _myPatMet).srcJetResPhi = cms.string('AK4PFPuppi_phi')
1383 
1384         # add the local task to the process
1385         addTaskToProcess(process, recomputeRawMetFromPfcs_label, recomputeRawMetFromPfcs_task)
1386 
1387         # add the task to the patMetModuleTask of the toolCode function
1388         patMetModuleTask.add(getattr(process, recomputeRawMetFromPfcs_label))
1389 
1390     # function to extract specific MET from the slimmedMETs(Puppi) collection in MiniAOD and then put it into the event as a new reco::MET collection
1391     def extractMET(self, process, correctionLevel, patMetModuleTask, postfix):
1392         # create a local task and a corresponding label to collect all the modules added in this function
1393         extractMET_task, extractMET_label = cms.Task(), "extractMET_task{}".format(postfix)
1394 
1395         # module to extract a MET from the slimmedMETs(Puppi) collection
1396         pfMet = cms.EDProducer("RecoMETExtractor",
1397                                metSource= cms.InputTag("slimmedMETs" if not self._parameters["Puppi"].value else "slimmedMETsPuppi",processName=cms.InputTag.skipCurrentProcess()),
1398                                correctionLevel = cms.string(correctionLevel)
1399                                )
1400         if(correctionLevel=="raw"):
1401             addToProcessAndTask("pfMet"+postfix, pfMet, process, extractMET_task)
1402         else:
1403             addToProcessAndTask("met"+correctionLevel+postfix, pfMet, process, extractMET_task)
1404 
1405         if not hasattr(process, "genMetExtractor"+postfix) and not self._parameters["runOnData"].value:
1406             genMetExtractor = cms.EDProducer("GenMETExtractor",
1407                                              metSource= cms.InputTag("slimmedMETs",processName=cms.InputTag.skipCurrentProcess())
1408                                              )
1409             addToProcessAndTask("genMetExtractor"+postfix, genMetExtractor, process, extractMET_task)
1410 
1411         # add the local task to the process
1412         addTaskToProcess(process, extractMET_label, extractMET_task)
1413 
1414         # add the task to the patMetModuleTask of the toolCode function
1415         patMetModuleTask.add(getattr(process, extractMET_label))
1416 
1417 
1418     def updateJECs(self,process,jetCollection, patMetModuleTask, postfix):
1419         from PhysicsTools.PatAlgos.producersLayer1.jetUpdater_cff import updatedPatJetCorrFactors
1420 
1421         patJetCorrFactorsReapplyJEC = updatedPatJetCorrFactors.clone(
1422             src = jetCollection if not self._parameters["Puppi"].value else cms.InputTag("slimmedJetsPuppi"),
1423             levels = ['L1FastJet',
1424                       'L2Relative',
1425                       'L3Absolute'],
1426             payload = 'AK4PFchs' if not self._parameters["Puppi"].value else 'AK4PFPuppi' ) # always CHS from miniAODs, except for puppi
1427 
1428         if self._parameters["runOnData"].value:
1429             patJetCorrFactorsReapplyJEC.levels.append("L2L3Residual")
1430 
1431         from PhysicsTools.PatAlgos.producersLayer1.jetUpdater_cff import updatedPatJets
1432         patJetsReapplyJEC = updatedPatJets.clone(
1433             jetSource = jetCollection if not self._parameters["Puppi"].value else cms.InputTag("slimmedJetsPuppi"),
1434             jetCorrFactorsSource = cms.VInputTag(cms.InputTag("patJetCorrFactorsReapplyJEC"+postfix))
1435             )
1436 
1437         # create a local task and a corresponding label to collect all the modules added in this function
1438         updateJECs_task, updateJECs_label = cms.Task(), "updateJECs_task{}".format(postfix)
1439         addToProcessAndTask("patJetCorrFactorsReapplyJEC"+postfix, patJetCorrFactorsReapplyJEC, process, updateJECs_task)
1440         addToProcessAndTask("patJetsReapplyJEC"+postfix, patJetsReapplyJEC.clone(), process, updateJECs_task)
1441 
1442         # add the local task to the process
1443         addTaskToProcess(process, updateJECs_label, updateJECs_task)
1444 
1445         # add the task to the patMetModuleTask of the toolCode function
1446         patMetModuleTask.add(getattr(process, updateJECs_label))
1447 
1448         return  cms.InputTag("patJetsReapplyJEC"+postfix)
1449 
1450 
1451     def getJetCollectionForCorsAndUncs(self, process, jetCollectionUnskimmed,
1452                                        jetSelection, autoJetCleaning,patMetModuleTask, postfix):
1453         # create a local task and a corresponding label to collect all the modules added in this function
1454         getJetCollectionForCorsAndUncs_task, getJetCollectionForCorsAndUncs_label = cms.Task(), "getJetCollectionForCorsAndUncs_task{}".format(postfix)
1455 
1456         basicJetsForMet = cms.EDProducer("PATJetCleanerForType1MET",
1457                                          src = jetCollectionUnskimmed,
1458                                          jetCorrEtaMax = cms.double(9.9),
1459                                          jetCorrLabel = cms.InputTag("L3Absolute"),
1460                                          jetCorrLabelRes = cms.InputTag("L2L3Residual"),
1461                                          offsetCorrLabel = cms.InputTag("L1FastJet"),
1462                                          skipEM = cms.bool(True),
1463                                          skipEMfractionThreshold = cms.double(0.9),
1464                                          skipMuonSelection = cms.string('isGlobalMuon | isStandAloneMuon'),
1465                                          skipMuons = cms.bool(True),
1466                                          type1JetPtThreshold = cms.double(15.0)
1467                                          )
1468         addToProcessAndTask("basicJetsForMet"+postfix, basicJetsForMet, process, getJetCollectionForCorsAndUncs_task)
1469 
1470         from PhysicsTools.PatAlgos.selectionLayer1.jetSelector_cfi import selectedPatJets
1471         jetSelector = selectedPatJets.clone(
1472             src = cms.InputTag("basicJetsForMet"+postfix),
1473             cut = cms.string(jetSelection)
1474             )
1475         addToProcessAndTask("jetSelectorForMet"+postfix, jetSelector, process, getJetCollectionForCorsAndUncs_task)
1476 
1477         jetCollection = self.jetCleaning(process, "jetSelectorForMet"+postfix, autoJetCleaning, patMetModuleTask, postfix)
1478         addTaskToProcess(process, getJetCollectionForCorsAndUncs_label, getJetCollectionForCorsAndUncs_task)
1479         patMetModuleTask.add(getattr(process, getJetCollectionForCorsAndUncs_label))
1480 
1481         return jetCollection
1482 
1483 
1484     def ak4JetReclustering(self,process, pfCandCollection, patMetModuleTask, postfix):
1485         # create a local task and a corresponding label to collect all the modules added in this function
1486         ak4JetReclustering_task, ak4JetReclustering_label = cms.Task(), "ak4JetReclustering_task{}".format(postfix)
1487 
1488         chs = self._parameters["CHS"].value
1489         jetColName="ak4PFJets"
1490         CHSname=""
1491         pfCandColl=pfCandCollection
1492         if chs:
1493             CHSname="chs"
1494             jetColName="ak4PFJetsCHS"
1495             if self._parameters["onMiniAOD"].value: 
1496                 pfCandColl = cms.InputTag("pfCHS")
1497             else:
1498                 addToProcessAndTask("tmpPFCandCollPtr"+postfix,
1499                                     cms.EDProducer("PFCandidateFwdPtrProducer",
1500                                                    src = pfCandCollection ),
1501                                     process, ak4JetReclustering_task)
1502                 process.load("CommonTools.ParticleFlow.pfNoPileUpJME_cff")
1503                 ak4JetReclustering_task.add(process.pfNoPileUpJMETask)
1504                 configtools.cloneProcessingSnippetTask(process, getattr(process,"pfNoPileUpJMETask"), postfix)
1505                 ak4JetReclustering_task.add(getattr(process,"pfNoPileUpJMETask"+postfix))
1506                 getattr(process, "pfPileUpJME"+postfix).PFCandidates = "tmpPFCandCollPtr"+postfix
1507                 getattr(process, "pfNoPileUpJME"+postfix).bottomCollection = "tmpPFCandCollPtr"+postfix
1508                 pfCandColl = "pfNoPileUpJME"+postfix
1509 
1510         jetColName+=postfix
1511         if not hasattr(process, jetColName):
1512             from RecoJets.JetProducers.ak4PFJets_cfi import ak4PFJets
1513             #if chs:
1514             addToProcessAndTask(jetColName, ak4PFJets.clone(), process, ak4JetReclustering_task)
1515             getattr(process, jetColName).src = pfCandColl
1516             getattr(process, jetColName).doAreaFastjet = True
1517 
1518             #puppi
1519             if self._parameters["Puppi"].value:
1520                 getattr(process, jetColName).srcWeights = cms.InputTag(self._parameters['puppiProducerLabel'].value)
1521                 getattr(process, jetColName).applyWeight = True
1522 
1523             corLevels=['L1FastJet', 'L2Relative', 'L3Absolute']
1524             if self._parameters["runOnData"].value:
1525                 corLevels.append("L2L3Residual")
1526 
1527             switchJetCollection(process,
1528                                 jetSource = cms.InputTag(jetColName),
1529                                 jetCorrections = ('AK4PF'+CHSname, corLevels , ''),
1530                                 postfix=postfix
1531                                 )
1532 
1533             getattr(process,"patJets"+postfix).addGenJetMatch = False
1534             getattr(process,"patJets"+postfix).addGenPartonMatch = False
1535             getattr(process,"patJets"+postfix).addPartonJetMatch = False
1536             getattr(process,"patJets"+postfix).embedGenPartonMatch = False
1537             getattr(process,"patJets"+postfix).embedGenJetMatch = False
1538             if self._parameters['onMiniAOD'].value:
1539                 del getattr(process,"patJets"+postfix).JetFlavourInfoSource
1540                 del getattr(process,"patJets"+postfix).JetPartonMapSource
1541                 del getattr(process,"patJets"+postfix).genPartonMatch
1542                 del getattr(process,"patJets"+postfix).genJetMatch
1543             getattr(process,"patJets"+postfix).getJetMCFlavour = False
1544 
1545             getattr(process,"patJetCorrFactors"+postfix).src=cms.InputTag(jetColName)
1546             getattr(process,"patJetCorrFactors"+postfix).primaryVertices= cms.InputTag("offlineSlimmedPrimaryVertices")
1547             if self._parameters["Puppi"].value:
1548                 getattr(process,"patJetCorrFactors"+postfix).payload=cms.string('AK4PFPuppi')
1549 
1550         # add the local task to the process
1551         addTaskToProcess(process, ak4JetReclustering_label, ak4JetReclustering_task)
1552 
1553         # add the task to the patMetModuleTask of the toolCode function
1554         patMetModuleTask.add(getattr(process, ak4JetReclustering_label))
1555 
1556         return cms.InputTag("patJets"+postfix)
1557 
1558 
1559     # function to add different METs to event starting from slimmedMET collections in MiniAOD
1560     def miniAODConfigurationPre(self, process, patMetModuleTask, pfCandCollection, postfix):
1561         # create a local task and a corresponding label to collect all the modules added in this function
1562         miniAODConfigurationPre_task, miniAODConfigurationPre_label = cms.Task(), "miniAODConfigurationPre_task{}".format(postfix)
1563 
1564         # extract caloMET from MiniAOD
1565         # "rawCalo" -> hardcoded in PhysicsTools/PatAlgos/plugins/RecoMETExtractor.cc
1566         self.extractMET(process, "rawCalo", miniAODConfigurationPre_task, postfix)
1567         caloMetName="metrawCalo" if hasattr(process,"metrawCalo") else "metrawCalo"+postfix
1568         from PhysicsTools.PatAlgos.tools.metTools import addMETCollection
1569         addMETCollection(process,
1570                          labelName = "patCaloMet",
1571                          metSource = caloMetName
1572                          )
1573         getattr(process,"patCaloMet").addGenMET = False
1574         miniAODConfigurationPre_task.add(getattr(process,"patCaloMet"))
1575 
1576         # extract DeepMETs (ResponseTune and ResolutionTune) from MiniAOD
1577         # "rawDeepResponseTune" and "rawDeepResolutionTune" hardcoded in PhysicsTools/PatAlgos/plugins/RecoMETExtractor.cc
1578         if self._parameters["extractDeepMETs"].value:
1579             self.extractMET(process, "rawDeepResponseTune", miniAODConfigurationPre_task, postfix)
1580             deepMetResponseTuneName = "metrawDeepResponseTune" if hasattr(process, "metrawDeepResponseTune") else "metrawDeepResponseTune"+postfix
1581             addMETCollection(process,
1582                              labelName = "deepMETsResponseTune",
1583                              metSource = deepMetResponseTuneName
1584                             )
1585             getattr(process, "deepMETsResponseTune").addGenMET = False
1586             getattr(process, "deepMETsResponseTune").computeMETSignificance = cms.bool(False)
1587             miniAODConfigurationPre_task.add(getattr(process, "deepMETsResponseTune"))
1588 
1589             self.extractMET(process, "rawDeepResolutionTune", miniAODConfigurationPre_task, postfix)
1590             deepMetResolutionTuneName = "metrawDeepResolutionTune" if hasattr(process, "metrawDeepResolutionTune") else "metrawDeepResolutionTune"+postfix
1591             addMETCollection(process,
1592                              labelName = "deepMETsResolutionTune",
1593                              metSource = deepMetResolutionTuneName
1594                             )
1595             getattr(process, "deepMETsResolutionTune").addGenMET = False
1596             getattr(process, "deepMETsResolutionTune").computeMETSignificance = cms.bool(False)
1597             miniAODConfigurationPre_task.add(getattr(process, "deepMETsResolutionTune"))
1598 
1599 
1600         # obtain PFCHS MET and TRK MET
1601         # adding the necessary chs and track met configuration
1602 
1603         from CommonTools.ParticleFlow.pfCHS_cff import pfCHS
1604         addToProcessAndTask("pfCHS", pfCHS.clone(), process, miniAODConfigurationPre_task)
1605         from RecoMET.METProducers.pfMet_cfi import pfMet
1606         pfMetCHS = pfMet.clone(src = "pfCHS")
1607         addToProcessAndTask("pfMetCHS", pfMetCHS, process, miniAODConfigurationPre_task)
1608 
1609         addMETCollection(process,
1610                          labelName = "patCHSMet",
1611                          metSource = "pfMetCHS"
1612                          )
1613 
1614         process.patCHSMet.computeMETSignificant = cms.bool(False)
1615         process.patCHSMet.addGenMET = cms.bool(False)
1616         miniAODConfigurationPre_task.add(process.patCHSMet)
1617 
1618         # get pf met only considering charged particles matched to primary vertex -> TRK MET
1619         pfTrk = chargedPackedCandsForTkMet.clone()
1620         addToProcessAndTask("pfTrk", pfTrk, process, miniAODConfigurationPre_task)
1621         pfMetTrk = pfMet.clone(src = 'pfTrk')
1622         addToProcessAndTask("pfMetTrk", pfMetTrk, process, miniAODConfigurationPre_task)
1623 
1624         addMETCollection(process,
1625                          labelName = "patTrkMet",
1626                          metSource = "pfMetTrk"
1627                          )
1628 
1629         process.patTrkMet.computeMETSignificant = cms.bool(False)
1630         process.patTrkMet.addGenMET = cms.bool(False)
1631         miniAODConfigurationPre_task.add(process.patTrkMet)
1632 
1633         addTaskToProcess(process, miniAODConfigurationPre_label, miniAODConfigurationPre_task)
1634 
1635         patMetModuleTask.add(getattr(process, miniAODConfigurationPre_label))
1636 
1637     def miniAODConfigurationPost(self, process, postfix):
1638 
1639         if self._parameters["metType"].value == "PF":
1640             if hasattr(process, "patPFMetTxyCorr"+postfix):
1641                 getattr(process, "patPFMetTxyCorr"+postfix).vertexCollection = cms.InputTag("offlineSlimmedPrimaryVertices")
1642 
1643         if self._parameters['computeUncertainties'].value and not self._parameters["runOnData"]:
1644             getattr(process, "shiftedPatJetResDown"+postfix).genJets = cms.InputTag("slimmedGenJets")
1645             getattr(process, "shiftedPatJetResUp"+postfix).genJets = cms.InputTag("slimmedGenJets")
1646 
1647 
1648     def miniAODConfiguration(self, process, pfCandCollection, jetCollection,
1649                              patMetModuleTask, postfix ):
1650         # specify options for regular pat PFMET
1651         if self._parameters["metType"].value == "PF": # not hasattr(process, "pfMet"+postfix)
1652             if "T1" in self._parameters['correctionLevel'].value:
1653                 getattr(process, "patPFMet"+postfix).srcJets = jetCollection
1654             getattr(process, "patPFMet"+postfix).addGenMET  = False
1655             if not self._parameters["runOnData"].value:
1656                 getattr(process, "patPFMet"+postfix).addGenMET  = True
1657                 getattr(process, "patPFMet"+postfix).genMETSource = cms.InputTag("genMetExtractor"+postfix)
1658 
1659         # if smeared PFMET is needed, use the ak4 gen jets saved in MiniAOD
1660         if "Smear" in self._parameters['correctionLevel'].value:
1661             getattr(process, "patSmearedJets"+postfix).genJets = cms.InputTag("slimmedGenJets")
1662 
1663         # add a new slimmedMETs collection and configure it properly
1664         if not hasattr(process, "slimmedMETs"+postfix) and self._parameters["metType"].value == "PF":
1665 
1666             # create a local task and a corresponding label to collect all the modules added in this function
1667             miniAODConfiguration_task, miniAODConfiguration_label = cms.Task(), "miniAODConfiguration_task{}".format(postfix)
1668 
1669             from PhysicsTools.PatAlgos.slimming.slimmedMETs_cfi import slimmedMETs
1670             addToProcessAndTask("slimmedMETs"+postfix, slimmedMETs.clone(), process, miniAODConfiguration_task)
1671             getattr(process,"slimmedMETs"+postfix).src = cms.InputTag("patPFMetT1"+postfix)
1672             getattr(process,"slimmedMETs"+postfix).rawVariation = cms.InputTag("patPFMet"+postfix)
1673             getattr(process,"slimmedMETs"+postfix).t1Uncertainties = cms.InputTag("patPFMetT1%s"+postfix)
1674             getattr(process,"slimmedMETs"+postfix).t01Variation = cms.InputTag("patPFMetT0pcT1"+postfix)
1675             getattr(process,"slimmedMETs"+postfix).t1SmearedVarsAndUncs = cms.InputTag("patPFMetT1Smear%s"+postfix)
1676 
1677             getattr(process,"slimmedMETs"+postfix).tXYUncForRaw = cms.InputTag("patPFMetTxy"+postfix)
1678             getattr(process,"slimmedMETs"+postfix).tXYUncForT1 = cms.InputTag("patPFMetT1Txy"+postfix)
1679             getattr(process,"slimmedMETs"+postfix).tXYUncForT01 = cms.InputTag("patPFMetT0pcT1Txy"+postfix)
1680             getattr(process,"slimmedMETs"+postfix).tXYUncForT1Smear = cms.InputTag("patPFMetT1SmearTxy"+postfix)
1681             getattr(process,"slimmedMETs"+postfix).tXYUncForT01Smear = cms.InputTag("patPFMetT0pcT1SmearTxy"+postfix)
1682 
1683             getattr(process,"slimmedMETs"+postfix).runningOnMiniAOD = True
1684             getattr(process,"slimmedMETs"+postfix).t01Variation = cms.InputTag("slimmedMETs" if not self._parameters["Puppi"].value else "slimmedMETsPuppi",processName=cms.InputTag.skipCurrentProcess())
1685 
1686             if hasattr(process, "deepMETsResolutionTune") and hasattr(process, "deepMETsResponseTune"):
1687                 # process includes producing/extracting deepMETsResolutionTune and deepMETsResponseTune
1688                 # add them to the slimmedMETs
1689                 getattr(process,"slimmedMETs"+postfix).addDeepMETs = True
1690 
1691             # smearing and type0 variations not yet supported in reprocessing
1692             #del getattr(process,"slimmedMETs"+postfix).t1SmearedVarsAndUncs
1693             del getattr(process,"slimmedMETs"+postfix).tXYUncForRaw
1694             del getattr(process,"slimmedMETs"+postfix).tXYUncForT01
1695             del getattr(process,"slimmedMETs"+postfix).tXYUncForT1Smear
1696             del getattr(process,"slimmedMETs"+postfix).tXYUncForT01Smear
1697             #del getattr(process,"slimmedMETs"+postfix).caloMET
1698 
1699             # add the local task to the process
1700             addTaskToProcess(process, miniAODConfiguration_label, miniAODConfiguration_task)
1701 
1702             # add the task to the patMetModuleTask of the toolCode function
1703             patMetModuleTask.add(getattr(process, miniAODConfiguration_label))
1704 
1705     def jetConfiguration(self):
1706 
1707         jetFlavor = self._parameters["jetFlavor"].value
1708         jetCorr = self._parameters["jetCorrectionType"].value
1709 
1710         jetCorLabelUpToL3Name="ak4PF"
1711         jetCorLabelL3ResName="ak4PF"
1712 
1713         # normal or CHS jets =============================
1714         if "chs" in jetFlavor:
1715             self.setParameter("CHS",True)
1716             jetCorLabelUpToL3Name += "CHS" #chs
1717             jetCorLabelL3ResName += "CHS"
1718         elif "Puppi" in jetFlavor:
1719             self.setParameter("CHS",False)
1720             jetCorLabelUpToL3Name += "Puppi"
1721             jetCorLabelL3ResName += "Puppi"
1722 
1723         else:
1724             self.setParameter("CHS",False)
1725 
1726         # change the correction type =====================
1727         if jetCorr == "L1L2L3-L1":
1728             jetCorLabelUpToL3Name += "L1FastL2L3Corrector"
1729             jetCorLabelL3ResName  += "L1FastL2L3ResidualCorrector"
1730         elif jetCorr == "L1L2L3-RC": #to be fixed
1731             jetCorLabelUpToL3Name += "L1FastL2L3Corrector"
1732             jetCorLabelL3ResName  += "L1FastL2L3ResidualCorrector"
1733 
1734         self.setParameter("jetCorLabelUpToL3",jetCorLabelUpToL3Name )
1735         self.setParameter("jetCorLabelL3Res",jetCorLabelL3ResName )
1736 
1737     # function enabling the auto jet cleaning for uncertainties ===============
1738     def jetCleaning(self, process, jetCollectionName, autoJetCleaning, jetProductionTask, postfix ):
1739 
1740         if autoJetCleaning == "None" or autoJetCleaning == "Manual" :
1741             return cms.InputTag(jetCollectionName)
1742 
1743         #retrieve collections
1744         electronCollection = self._parameters["electronCollection"].value
1745         muonCollection = self._parameters["muonCollection"].value
1746         photonCollection = self._parameters["photonCollection"].value
1747         tauCollection = self._parameters["tauCollection"].value
1748 
1749         jetCleaning_task, jetCleaning_label = cms.Task(), "jetCleaning_task{}".format(postfix)
1750 
1751         if autoJetCleaning == "Full" : # auto clean taus, photons and jets
1752             if isValidInputTag(tauCollection):
1753                 process.load("PhysicsTools.PatAlgos.cleaningLayer1.tauCleaner_cfi")
1754                 jetCleaning_task.add(process.cleanPatTaus)
1755                 cleanPatTauProducer = getattr(process, "cleanPatTaus").clone(
1756                     src = tauCollection
1757                     )
1758                 cleanPatTauProducer.checkOverlaps.electrons.src = electronCollection
1759                 cleanPatTauProducer.checkOverlaps.muons.src = muonCollection
1760                 addToProcessAndTask("cleanedPatTaus"+postfix, cleanPatTauProducer, process, jetCleaning_task)
1761                 tauCollection = cms.InputTag("cleanedPatTaus"+postfix)
1762 
1763             if isValidInputTag(photonCollection):
1764                 process.load("PhysicsTools.PatAlgos.cleaningLayer1.photonCleaner_cfi")
1765                 jetCleaning_task.add(process.cleanPatPhotons)
1766                 cleanPatPhotonProducer = getattr(process, "cleanPatPhotons").clone(
1767                     src = photonCollection
1768                     )
1769                 cleanPatPhotonProducer.checkOverlaps.electrons.src = electronCollection
1770                 addToProcessAndTask("cleanedPatPhotons"+postfix, cleanPatPhotonProducer, process, jetCleaning_task)
1771                 photonCollection = cms.InputTag("cleanedPatPhotons"+postfix)
1772 
1773         #jet cleaning
1774         have_cleanPatJets = hasattr(process, "cleanPatJets")
1775         process.load("PhysicsTools.PatAlgos.cleaningLayer1.jetCleaner_cfi")
1776         cleanPatJetProducer = getattr(process, "cleanPatJets").clone(
1777                      src = cms.InputTag(jetCollectionName)
1778             )
1779         #do not leave it hanging
1780         if not have_cleanPatJets:
1781             del process.cleanPatJets
1782         cleanPatJetProducer.checkOverlaps.muons.src = muonCollection
1783         cleanPatJetProducer.checkOverlaps.electrons.src = electronCollection
1784         if isValidInputTag(photonCollection) and autoJetCleaning != "LepClean":
1785             cleanPatJetProducer.checkOverlaps.photons.src = photonCollection
1786         else:
1787             del cleanPatJetProducer.checkOverlaps.photons
1788 
1789         if isValidInputTag(tauCollection) and autoJetCleaning != "LepClean":
1790             cleanPatJetProducer.checkOverlaps.taus.src = tauCollection
1791         else:
1792             del cleanPatJetProducer.checkOverlaps.taus
1793 
1794         # not used at all and electrons are already cleaned
1795         del cleanPatJetProducer.checkOverlaps.tkIsoElectrons
1796 
1797         addToProcessAndTask("cleanedPatJets"+postfix, cleanPatJetProducer, process, jetCleaning_task)
1798 
1799         addTaskToProcess(process, jetCleaning_label, jetCleaning_task)
1800         jetProductionTask.add(getattr(process, jetCleaning_label))
1801         return cms.InputTag("cleanedPatJets"+postfix)
1802 
1803     # function to implement the 2017 EE noise mitigation fix
1804     def runFixEE2017(self, process, params, jets, cands, goodcolls, patMetModuleTask, postfix):
1805         # create a local task and a corresponding label to collect all the modules added in this function
1806         runFixEE2017_task, runFixEE2017_label = cms.Task(), "runFixEE2017_task{}".format(postfix)
1807 
1808         pfCandidateJetsWithEEnoise = _modbad.BadPFCandidateJetsEEnoiseProducer.clone(
1809             jetsrc = jets,
1810             userawPt = params["userawPt"],
1811             ptThreshold = params["ptThreshold"],
1812             minEtaThreshold = params["minEtaThreshold"],
1813             maxEtaThreshold = params["maxEtaThreshold"],
1814         )
1815         addToProcessAndTask("pfCandidateJetsWithEEnoise"+postfix, pfCandidateJetsWithEEnoise, process, runFixEE2017_task)
1816 
1817         pfcandidateClustered = cms.EDProducer("CandViewMerger",
1818             src = cms.VInputTag(goodcolls+[jets])
1819         )
1820         addToProcessAndTask("pfcandidateClustered"+postfix, pfcandidateClustered, process, runFixEE2017_task)
1821 
1822         pfcandidateForUnclusteredUnc = _mod.candPtrProjector.clone(
1823             src  = cands,
1824             veto = "pfcandidateClustered"+postfix,
1825         )
1826         addToProcessAndTask("pfcandidateForUnclusteredUnc"+postfix, pfcandidateForUnclusteredUnc, process, runFixEE2017_task)
1827 
1828         badUnclustered = cms.EDFilter("CandPtrSelector",
1829             src = cms.InputTag("pfcandidateForUnclusteredUnc"+postfix),
1830             cut = cms.string("abs(eta) > "+str(params["minEtaThreshold"])+" && abs(eta) < "+str(params["maxEtaThreshold"])),
1831         )
1832         addToProcessAndTask("badUnclustered"+postfix, badUnclustered, process, runFixEE2017_task)
1833 
1834         blobUnclustered = cms.EDProducer("UnclusteredBlobProducer",
1835             candsrc = cms.InputTag("badUnclustered"+postfix),
1836         )
1837         addToProcessAndTask("blobUnclustered"+postfix, blobUnclustered, process, runFixEE2017_task)
1838 
1839         superbad = cms.EDProducer("CandViewMerger",
1840             src = cms.VInputTag(
1841                 cms.InputTag("blobUnclustered"+postfix),
1842                 cms.InputTag("pfCandidateJetsWithEEnoise"+postfix,"bad"),
1843             )
1844         )
1845         addToProcessAndTask("superbad"+postfix, superbad, process, runFixEE2017_task)
1846 
1847         pfCandidatesGoodEE2017 = _mod.candPtrProjector.clone(
1848             src  = cands,
1849             veto = "superbad"+postfix,
1850         )
1851         addToProcessAndTask("pfCandidatesGoodEE2017"+postfix, pfCandidatesGoodEE2017, process, runFixEE2017_task)
1852 
1853         # add the local task to the process
1854         addTaskToProcess(process, runFixEE2017_label, runFixEE2017_task)
1855 
1856         # add the task to the patMetModuleTask of the toolCode function
1857         patMetModuleTask.add(getattr(process, runFixEE2017_label))
1858 
1859         # return good cands and jets
1860         return (cms.InputTag("pfCandidatesGoodEE2017"+postfix), cms.InputTag("pfCandidateJetsWithEEnoise"+postfix,"good"))
1861 
1862 #========================================================================================
1863 runMETCorrectionsAndUncertainties = RunMETCorrectionsAndUncertainties()
1864 
1865 
1866 
1867 #predefined functions for miniAOD production and reproduction
1868 # miniAOD production ===========================
1869 def runMetCorAndUncForMiniAODProduction(process, metType="PF",
1870                                         jetCollUnskimmed="patJets",
1871                                         photonColl="selectedPatPhotons",
1872                                         electronColl="selectedPatElectrons",
1873                                         muonColl="selectedPatMuons",
1874                                         tauColl="selectedPatTaus",
1875                                         pfCandColl = "particleFlow",
1876                                         jetCleaning="LepClean",
1877                                         jetSelection="pt>15 && abs(eta)<9.9",
1878                                         jecUnFile="",
1879                                         jetFlavor="AK4PFchs",
1880                                         recoMetFromPFCs=False,
1881                                         postfix=""):
1882 
1883     runMETCorrectionsAndUncertainties = RunMETCorrectionsAndUncertainties()
1884 
1885     #MET flavors
1886     runMETCorrectionsAndUncertainties(process, metType=metType,
1887                                       correctionLevel=["T0","T1","T2","Smear","Txy"],
1888                                       computeUncertainties=False,
1889                                       produceIntermediateCorrections=True,
1890                                       addToPatDefaultSequence=False,
1891                                       jetCollectionUnskimmed=jetCollUnskimmed,
1892                                       photonCollection=photonColl,
1893                                       electronCollection=electronColl,
1894                                       muonCollection=muonColl,
1895                                       tauCollection=tauColl,
1896                                       pfCandCollection =pfCandColl,
1897                                       autoJetCleaning=jetCleaning,
1898                                       jecUncertaintyFile=jecUnFile,
1899                                       jetSelection=jetSelection,
1900                                       jetFlavor=jetFlavor,
1901                                       recoMetFromPFCs=recoMetFromPFCs,
1902                                       postfix=postfix
1903                                       )
1904 
1905     #MET T1 uncertainties
1906     runMETCorrectionsAndUncertainties(process, metType=metType,
1907                                       correctionLevel=["T1"],
1908                                       computeUncertainties=True,
1909                                       produceIntermediateCorrections=False,
1910                                       addToPatDefaultSequence=False,
1911                                       jetCollectionUnskimmed=jetCollUnskimmed,
1912                                       photonCollection=photonColl,
1913                                       electronCollection=electronColl,
1914                                       muonCollection=muonColl,
1915                                       tauCollection=tauColl,
1916                                       pfCandCollection =pfCandColl,
1917                                       autoJetCleaning=jetCleaning,
1918                                       jecUncertaintyFile=jecUnFile,
1919                                       jetSelection=jetSelection,
1920                                       jetFlavor=jetFlavor,
1921                                       recoMetFromPFCs=recoMetFromPFCs,
1922                                       postfix=postfix
1923                                       )
1924 
1925     #MET T1 Smeared JER uncertainties
1926     runMETCorrectionsAndUncertainties(process, metType=metType,
1927                                       correctionLevel=["T1","Smear"],
1928                                       computeUncertainties=True,
1929                                       produceIntermediateCorrections=False,
1930                                       addToPatDefaultSequence=False,
1931                                       jetCollectionUnskimmed=jetCollUnskimmed,
1932                                       photonCollection=photonColl,
1933                                       electronCollection=electronColl,
1934                                       muonCollection=muonColl,
1935                                       tauCollection=tauColl,
1936                                       pfCandCollection =pfCandColl,
1937                                       autoJetCleaning=jetCleaning,
1938                                       jecUncertaintyFile=jecUnFile,
1939                                       jetSelection=jetSelection,
1940                                       jetFlavor=jetFlavor,
1941                                       recoMetFromPFCs=recoMetFromPFCs,
1942                                       postfix=postfix,
1943                                       )
1944 
1945 
1946 
1947 
1948 # miniAOD reproduction ===========================
1949 def runMetCorAndUncFromMiniAOD(process, metType="PF",
1950                                jetCollUnskimmed="slimmedJets",
1951                                photonColl="slimmedPhotons",
1952                                electronColl="slimmedElectrons",
1953                                muonColl="slimmedMuons",
1954                                tauColl="slimmedTaus",
1955                                pfCandColl = "packedPFCandidates",
1956                                jetFlavor="AK4PFchs",
1957                                jetCleaning="LepClean",
1958                                isData=False,
1959                                manualJetConfig=False,
1960                                reclusterJets=None,
1961                                jetSelection="pt>15 && abs(eta)<9.9",
1962                                recoMetFromPFCs=None,
1963                                jetCorLabelL3="ak4PFCHSL1FastL2L3Corrector",
1964                                jetCorLabelRes="ak4PFCHSL1FastL2L3ResidualCorrector",
1965 ##                               jecUncFile="CondFormats/JetMETObjects/data/Summer15_50nsV5_DATA_UncertaintySources_AK4PFchs.txt",
1966                                CHS=False,
1967                                puppiProducerLabel="puppi",
1968                                puppiProducerForMETLabel="puppiNoLep",
1969                                reapplyJEC=True,
1970                                jecUncFile="",
1971                                computeMETSignificance=True,
1972                                fixEE2017=False,
1973                                fixEE2017Params=None,
1974                                extractDeepMETs=False,
1975                                campaign="",
1976                                era="",
1977                                postfix=""):
1978 
1979     runMETCorrectionsAndUncertainties = RunMETCorrectionsAndUncertainties()
1980 
1981     #MET T1 uncertainties
1982     runMETCorrectionsAndUncertainties(process, metType=metType,
1983                                       correctionLevel=["T1"],
1984                                       computeUncertainties=True,
1985                                       produceIntermediateCorrections=False,
1986                                       addToPatDefaultSequence=False,
1987                                       jetCollectionUnskimmed=jetCollUnskimmed,
1988                                       electronCollection=electronColl,
1989                                       muonCollection=muonColl,
1990                                       tauCollection=tauColl,
1991                                       photonCollection=photonColl,
1992                                       pfCandCollection =pfCandColl,
1993                                       runOnData=isData,
1994                                       onMiniAOD=True,
1995                                       reapplyJEC=reapplyJEC,
1996                                       reclusterJets=reclusterJets,
1997                                       jetSelection=jetSelection,
1998                                       recoMetFromPFCs=recoMetFromPFCs,
1999                                       autoJetCleaning=jetCleaning,
2000                                       manualJetConfig=manualJetConfig,
2001                                       jetFlavor=jetFlavor,
2002                                       jetCorLabelUpToL3=jetCorLabelL3,
2003                                       jetCorLabelL3Res=jetCorLabelRes,
2004                                       jecUncertaintyFile=jecUncFile,
2005                                       computeMETSignificance=computeMETSignificance,
2006                                       CHS=CHS,
2007                                       puppiProducerLabel=puppiProducerLabel,
2008                                       puppiProducerForMETLabel=puppiProducerForMETLabel,
2009                                       postfix=postfix,
2010                                       fixEE2017=fixEE2017,
2011                                       fixEE2017Params=fixEE2017Params,
2012                                       extractDeepMETs=extractDeepMETs,
2013                                       campaign=campaign,
2014                                       era=era,
2015                                       )
2016 
2017     #MET T1+Txy / Smear
2018     runMETCorrectionsAndUncertainties(process, metType=metType,
2019                                       correctionLevel=["T1","Txy"],
2020                                       computeUncertainties=False,
2021                                       produceIntermediateCorrections=True,
2022                                       addToPatDefaultSequence=False,
2023                                       jetCollectionUnskimmed=jetCollUnskimmed,
2024                                       electronCollection=electronColl,
2025                                       muonCollection=muonColl,
2026                                       tauCollection=tauColl,
2027                                       photonCollection=photonColl,
2028                                       pfCandCollection =pfCandColl,
2029                                       runOnData=isData,
2030                                       onMiniAOD=True,
2031                                       reapplyJEC=reapplyJEC,
2032                                       reclusterJets=reclusterJets,
2033                                       jetSelection=jetSelection,
2034                                       recoMetFromPFCs=recoMetFromPFCs,
2035                                       autoJetCleaning=jetCleaning,
2036                                       manualJetConfig=manualJetConfig,
2037                                       jetFlavor=jetFlavor,
2038                                       jetCorLabelUpToL3=jetCorLabelL3,
2039                                       jetCorLabelL3Res=jetCorLabelRes,
2040                                       jecUncertaintyFile=jecUncFile,
2041                                       computeMETSignificance=computeMETSignificance,
2042                                       CHS=CHS,
2043                                       puppiProducerLabel=puppiProducerLabel,
2044                                       puppiProducerForMETLabel=puppiProducerForMETLabel,
2045                                       postfix=postfix,
2046                                       fixEE2017=fixEE2017,
2047                                       fixEE2017Params=fixEE2017Params,
2048                                       extractDeepMETs=extractDeepMETs,
2049                                       campaign=campaign,
2050                                       era=era,
2051                                       )
2052     #MET T1+Smear + uncertainties
2053     runMETCorrectionsAndUncertainties(process, metType=metType,
2054                                       correctionLevel=["T1","Smear"],
2055                                       computeUncertainties=True,
2056                                       produceIntermediateCorrections=False,
2057                                       addToPatDefaultSequence=False,
2058                                       jetCollectionUnskimmed=jetCollUnskimmed,
2059                                       electronCollection=electronColl,
2060                                       muonCollection=muonColl,
2061                                       tauCollection=tauColl,
2062                                       photonCollection=photonColl,
2063                                       pfCandCollection =pfCandColl,
2064                                       runOnData=isData,
2065                                       onMiniAOD=True,
2066                                       reapplyJEC=reapplyJEC,
2067                                       reclusterJets=reclusterJets,
2068                                       jetSelection=jetSelection,
2069                                       recoMetFromPFCs=recoMetFromPFCs,
2070                                       autoJetCleaning=jetCleaning,
2071                                       manualJetConfig=manualJetConfig,
2072                                       jetFlavor=jetFlavor,
2073                                       jetCorLabelUpToL3=jetCorLabelL3,
2074                                       jetCorLabelL3Res=jetCorLabelRes,
2075                                       jecUncertaintyFile=jecUncFile,
2076                                       computeMETSignificance=computeMETSignificance,
2077                                       CHS=CHS,
2078                                       puppiProducerLabel=puppiProducerLabel,
2079                                       puppiProducerForMETLabel=puppiProducerForMETLabel,
2080                                       postfix=postfix,
2081                                       fixEE2017=fixEE2017,
2082                                       fixEE2017Params=fixEE2017Params,
2083                                       extractDeepMETs=extractDeepMETs,
2084                                       campaign=campaign,
2085                                       era=era,
2086                                       )