Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-11-23 00:00:33

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