def create_toy_mc(input_files, sample, output_folder, n_toy, centre_of_mass, config): from dps.utils.file_utilities import make_folder_if_not_exists from dps.utils.toy_mc import generate_toy_MC_from_distribution, generate_toy_MC_from_2Ddistribution from dps.utils.Unfolding import get_unfold_histogram_tuple make_folder_if_not_exists(output_folder) output_file_name = get_output_file_name(output_folder, sample, n_toy, centre_of_mass) variable_bins = bin_edges_vis.copy() with root_open(output_file_name, 'recreate') as f_out: input_file_index = 0 for input_file in input_files: input_file_hists = File(input_file) for channel in config.analysis_types.keys(): if channel is 'combined':continue for variable in variable_bins: output_dir = f_out.mkdir(str(input_file_index) + '/' + channel + '/' + variable, recurse=True) cd = output_dir.cd mkdir = output_dir.mkdir h_truth, h_measured, h_response, _ = get_unfold_histogram_tuple(input_file_hists, variable, channel, centre_of_mass = centre_of_mass, visiblePS = True, load_fakes=False) cd() mkdir('Original') cd ('Original') h_truth.Write('truth') h_measured.Write('measured') h_response.Write('response') for i in range(1, n_toy+1): toy_id = 'toy_{0}'.format(i) mkdir(toy_id) cd(toy_id) # create histograms # add tuples (truth, measured, response) of histograms truth = generate_toy_MC_from_distribution(h_truth) measured = generate_toy_MC_from_distribution(h_measured) response = generate_toy_MC_from_2Ddistribution(h_response) truth.SetName('truth') measured.SetName('measured') response.SetName('response') truth.Write() measured.Write() response.Write() input_file_index += 1
def main(): parser = OptionParser() parser.add_option('--topPtReweighting', dest='applyTopPtReweighting', type='int', default=0 ) parser.add_option('--topEtaReweighting', dest='applyTopEtaReweighting', type='int', default=0 ) parser.add_option('-c', '--centreOfMassEnergy', dest='centreOfMassEnergy', type='int', default=13 ) parser.add_option('--pdfWeight', type='int', dest='pdfWeight', default=-1 ) parser.add_option('--muFmuRWeight', type='int', dest='muFmuRWeight', default=-1 ) parser.add_option('--alphaSWeight', type='int', dest='alphaSWeight', default=-1 ) parser.add_option('--nGeneratorWeights', type='int', dest='nGeneratorWeights', default=1 ) parser.add_option('-s', '--sample', dest='sample', default='central') parser.add_option('-d', '--debug', action='store_true', dest='debug', default=False) parser.add_option('-n', action='store_true', dest='donothing', default=False) parser.add_option('-e', action='store_true', dest='extraHists', default=False) parser.add_option('-f',action='store_true', dest='fineBinned', default=False) (options, _) = parser.parse_args() measurement_config = XSectionConfig( options.centreOfMassEnergy ) # Input file name file_name = 'crap.root' if int(options.centreOfMassEnergy) == 13: # file_name = fileNames['13TeV'][options.sample] file_name = getFileName('13TeV', options.sample, measurement_config) # if options.generatorWeight >= 0: # file_name = 'localInputFile.root' else: print "Error: Unrecognised centre of mass energy." pdfWeight = options.pdfWeight muFmuRWeight = options.muFmuRWeight alphaSWeight = options.alphaSWeight # Output file name outputFileName = 'crap.root' outputFileDir = 'unfolding/%sTeV/' % options.centreOfMassEnergy make_folder_if_not_exists(outputFileDir) energySuffix = '%sTeV' % ( options.centreOfMassEnergy ) if options.applyTopEtaReweighting != 0: if options.applyTopEtaReweighting == 1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_withTopEtaReweighting_up.root' % energySuffix elif options.applyTopEtaReweighting == -1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_withTopEtaReweighting_down.root' % energySuffix elif options.applyTopPtReweighting != 0: if options.applyTopPtReweighting == 1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_withTopPtReweighting_up.root' % energySuffix elif options.applyTopPtReweighting == -1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_withTopPtReweighting_down.root' % energySuffix elif alphaSWeight == 0: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_alphaSDown.root' % ( energySuffix ) elif alphaSWeight == 1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_alphaSUp.root' % ( energySuffix ) elif muFmuRWeight == 1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_1muR2muF.root' % ( energySuffix ) elif muFmuRWeight == 2: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_1muR05muF.root' % ( energySuffix ) elif muFmuRWeight == 3: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_2muR1muF.root' % ( energySuffix ) elif muFmuRWeight == 4: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_2muR2muF.root' % ( energySuffix ) elif muFmuRWeight == 6: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_05muR1muF.root' % ( energySuffix ) elif muFmuRWeight == 8: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_05muR05muF.root' % ( energySuffix ) elif pdfWeight >= 0 and pdfWeight <= 99: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_pdfWeight_%i.root' % ( energySuffix, pdfWeight ) elif options.sample != 'central': outputFileName = outputFileDir+'/unfolding_TTJets_%s_%s_asymmetric.root' % ( energySuffix, options.sample ) elif options.fineBinned : outputFileName = outputFileDir+'/unfolding_TTJets_%s.root' % ( energySuffix ) else: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric.root' % energySuffix with root_open( file_name, 'read' ) as f, root_open( outputFileName, 'recreate') as out: # Get the tree treeName = "TTbar_plus_X_analysis/Unfolding/Unfolding" if options.sample == "jesup": treeName += "_JESUp" elif options.sample == "jesdown": treeName += "_JESDown" elif options.sample == "jerup": treeName += "_JERUp" elif options.sample == "jerdown": treeName += "_JERDown" tree = f.Get(treeName) nEntries = tree.GetEntries() # weightTree = f.Get('TTbar_plus_X_analysis/Unfolding/GeneratorSystematicWeights') # if meWeight >= 0 : # tree.AddFriend('TTbar_plus_X_analysis/Unfolding/GeneratorSystematicWeights') # tree.SetBranchStatus('genWeight_*',1) # tree.SetBranchStatus('genWeight_%i' % meWeight, 1) # For variables where you want bins to be symmetric about 0, use abs(variable) (but also make plots for signed variable) allVariablesBins = bin_edges_vis.copy() for variable in bin_edges_vis: if 'Rap' in variable: allVariablesBins['abs_%s' % variable] = [0,bin_edges_vis[variable][-1]] recoVariableNames = {} genVariable_particle_names = {} genVariable_parton_names = {} histograms = {} outputDirs = {} for variable in allVariablesBins: if options.debug and variable != 'HT' : continue if options.sample in measurement_config.met_systematics and variable not in ['MET', 'ST', 'WPT']: continue outputDirs[variable] = {} histograms[variable] = {} # # Variable names # recoVariableName = branchNames[variable] sysIndex = None if variable in ['MET', 'ST', 'WPT']: if options.sample == "jesup": recoVariableName += '_METUncertainties' sysIndex = 2 elif options.sample == "jesdown": recoVariableName += '_METUncertainties' sysIndex = 3 elif options.sample == "jerup": recoVariableName += '_METUncertainties' sysIndex = 0 elif options.sample == "jerdown": recoVariableName+= '_METUncertainties' sysIndex = 1 elif options.sample in measurement_config.met_systematics: recoVariableName += '_METUncertainties' sysIndex = measurement_config.met_systematics[options.sample] genVariable_particle_name = None genVariable_parton_name = None if variable in genBranchNames_particle: genVariable_particle_name = genBranchNames_particle[variable] if variable in genBranchNames_parton: genVariable_parton_name = genBranchNames_parton[variable] recoVariableNames[variable] = recoVariableName genVariable_particle_names[variable] = genVariable_particle_name genVariable_parton_names[variable] = genVariable_parton_name for channel in channels: # Make dir in output file outputDirName = variable+'_'+channel.outputDirName outputDir = out.mkdir(outputDirName) outputDirs[variable][channel.channelName] = outputDir # # Book histograms # # 1D histograms histograms[variable][channel.channelName] = {} h = histograms[variable][channel.channelName] h['truth'] = Hist( allVariablesBins[variable], name='truth') h['truthVis'] = Hist( allVariablesBins[variable], name='truthVis') h['truth_parton'] = Hist( allVariablesBins[variable], name='truth_parton') h['measured'] = Hist( reco_bin_edges_vis[variable], name='measured') h['measuredVis'] = Hist( reco_bin_edges_vis[variable], name='measuredVis') h['measured_without_fakes'] = Hist( reco_bin_edges_vis[variable], name='measured_without_fakes') h['measuredVis_without_fakes'] = Hist( reco_bin_edges_vis[variable], name='measuredVis_without_fakes') h['fake'] = Hist( reco_bin_edges_vis[variable], name='fake') h['fakeVis'] = Hist( reco_bin_edges_vis[variable], name='fakeVis') # 2D histograms h['response'] = Hist2D( reco_bin_edges_vis[variable], allVariablesBins[variable], name='response') h['response_without_fakes'] = Hist2D( reco_bin_edges_vis[variable], allVariablesBins[variable], name='response_without_fakes') h['responseVis_without_fakes'] = Hist2D( reco_bin_edges_vis[variable], allVariablesBins[variable], name='responseVis_without_fakes') h['response_parton'] = Hist2D( reco_bin_edges_vis[variable], allVariablesBins[variable], name='response_parton') h['response_without_fakes_parton'] = Hist2D( reco_bin_edges_vis[variable], allVariablesBins[variable], name='response_without_fakes_parton') if options.fineBinned: minVar = trunc( allVariablesBins[variable][0] ) maxVar = trunc( max( tree.GetMaximum(genVariable_particle_names[variable]), tree.GetMaximum( recoVariableNames[variable] ) ) * 1.2 ) nBins = int(maxVar - minVar) if variable is 'lepton_eta' or variable is 'bjets_eta': maxVar = 2.5 minVar = -2.5 nBins = 1000 elif 'abs' in variable and 'eta' in variable: maxVar = 3.0 minVar = 0. nBins = 1000 elif 'Rap' in variable: maxVar = 3.0 minVar = -3.0 nBins = 1000 elif 'NJets' in variable: maxVar = 20.5 minVar = 3.5 nBins = 17 h['truth'] = Hist( nBins, minVar, maxVar, name='truth') h['truthVis'] = Hist( nBins, minVar, maxVar, name='truthVis') h['truth_parton'] = Hist( nBins, minVar, maxVar, name='truth_parton') h['measured'] = Hist( nBins, minVar, maxVar, name='measured') h['measuredVis'] = Hist( nBins, minVar, maxVar, name='measuredVis') h['measured_without_fakes'] = Hist( nBins, minVar, maxVar, name='measured_without_fakes') h['measuredVis_without_fakes'] = Hist( nBins, minVar, maxVar, name='measuredVis_without_fakes') h['fake'] = Hist( nBins, minVar, maxVar, name='fake') h['fakeVis'] = Hist( nBins, minVar, maxVar, name='fakeVis') h['response'] = Hist2D( nBins, minVar, maxVar, nBins, minVar, maxVar, name='response') h['response_without_fakes'] = Hist2D( nBins, minVar, maxVar, nBins, minVar, maxVar, name='response_without_fakes') h['responseVis_without_fakes'] = Hist2D( nBins, minVar, maxVar, nBins, minVar, maxVar, name='responseVis_without_fakes') h['response_parton'] = Hist2D( nBins, minVar, maxVar, nBins, minVar, maxVar, name='response_parton') h['response_without_fakes_parton'] = Hist2D( nBins, minVar, maxVar, nBins, minVar, maxVar, name='response_without_fakes_parton') # Some interesting histograms h['puOffline'] = Hist( 20, 0, 2, name='puWeights_offline') h['eventWeightHist'] = Hist( 100, -2, 2, name='eventWeightHist') h['genWeightHist'] = Hist( 100, -2, 2, name='genWeightHist') h['offlineWeightHist'] = Hist( 100, -2, 2, name='offlineWeightHist') h['phaseSpaceInfoHist'] = Hist( 10, 0, 1, name='phaseSpaceInfoHist') # Counters for studying phase space nVis = {c.channelName : 0 for c in channels} nVisNotOffline = {c.channelName : 0 for c in channels} nOffline = {c.channelName : 0 for c in channels} nOfflineNotVis = {c.channelName : 0 for c in channels} nFull = {c.channelName : 0 for c in channels} nOfflineSL = {c.channelName : 0 for c in channels} n=0 # Event Loop # for event, weight in zip(tree,weightTree): for event in tree: branch = event.__getattr__ n+=1 if not n%100000: print 'Processing event %.0f Progress : %.2g %%' % ( n, float(n)/nEntries*100 ) # if n == 10000: break # # # # # # Weights and selection # # # # Pileup weight # Don't apply if calculating systematic pileupWeight = event.PUWeight # print event.PUWeight,event.PUWeight_up,event.PUWeight_down if options.sample == "pileupUp": pileupWeight = event.PUWeight_up elif options.sample == "pileupDown": pileupWeight = event.PUWeight_down # Generator level weight genWeight = event.EventWeight * measurement_config.luminosity_scale # Offline level weights offlineWeight = pileupWeight # Lepton weight leptonWeight = event.LeptonEfficiencyCorrection if options.sample == 'leptonup': leptonWeight = event.LeptonEfficiencyCorrectionUp elif options.sample == 'leptondown': leptonWeight == event.LeptonEfficiencyCorrectionDown # B Jet Weight bjetWeight = event.BJetWeight if options.sample == "bjetup": bjetWeight = event.BJetUpWeight elif options.sample == "bjetdown": bjetWeight = event.BJetDownWeight elif options.sample == "lightjetup": bjetWeight = event.LightJetUpWeight elif options.sample == "lightjetdown": bjetWeight = event.LightJetDownWeight offlineWeight = event.EventWeight * measurement_config.luminosity_scale offlineWeight *= pileupWeight offlineWeight *= bjetWeight offlineWeight *= leptonWeight # Generator weight # Scale up/down, pdf if pdfWeight >= 0: genWeight *= branch('pdfWeight_%i' % pdfWeight) offlineWeight *= branch('pdfWeight_%i' % pdfWeight) pass if muFmuRWeight >= 0: genWeight *= branch('muFmuRWeight_%i' % muFmuRWeight) offlineWeight *= branch('muFmuRWeight_%i' % muFmuRWeight) pass if alphaSWeight >= 0: genWeight *= branch('alphaSWeight_%i' % alphaSWeight) offlineWeight *= branch('alphaSWeight_%i' % alphaSWeight) pass if options.applyTopPtReweighting != 0: ptWeight = calculateTopPtWeight( branch('lepTopPt_parton'), branch('hadTopPt_parton'), options.applyTopPtReweighting) offlineWeight *= ptWeight genWeight *= ptWeight if options.applyTopEtaReweighting != 0: etaWeight = calculateTopEtaWeight( branch('lepTopRap_parton'), branch('hadTopRap_parton'), options.applyTopEtaReweighting) offlineWeight *= etaWeight genWeight *= etaWeight for channel in channels: # Generator level selection genSelection = '' genSelectionVis = '' if channel.channelName is 'muPlusJets' : genSelection = event.isSemiLeptonicMuon == 1 genSelectionVis = event.isSemiLeptonicMuon == 1 and event.passesGenEventSelection == 1 elif channel.channelName is 'ePlusJets' : genSelection = event.isSemiLeptonicElectron == 1 genSelectionVis = event.isSemiLeptonicElectron == 1 and event.passesGenEventSelection == 1 # Offline level selection offlineSelection = 0 if channel.channelName is 'muPlusJets' : offlineSelection = int(event.passSelection) == 1 elif channel.channelName is 'ePlusJets' : offlineSelection = int(event.passSelection) == 2 # Fake selection fakeSelection = offlineSelection and not genSelection fakeSelectionVis = offlineSelection and not genSelectionVis # Phase space info if genSelection: nFull[channel.channelName] += genWeight if offlineSelection: nOfflineSL[channel.channelName] += genWeight if genSelectionVis: nVis[channel.channelName] += genWeight if not offlineSelection: nVisNotOffline[channel.channelName] += genWeight if offlineSelection: nOffline[channel.channelName] += offlineWeight if not genSelectionVis: nOfflineNotVis[channel.channelName] += offlineWeight for variable in allVariablesBins: if options.sample in measurement_config.met_systematics and variable not in ['MET', 'ST', 'WPT']: continue # # # # # # Variable to plot # # # recoVariable = branch(recoVariableNames[variable]) if variable in ['MET', 'ST', 'WPT'] and \ sysIndex != None and ( offlineSelection or fakeSelection or fakeSelectionVis ) : recoVariable = recoVariable[sysIndex] if 'abs' in variable: recoVariable = abs(recoVariable) # With TUnfold, reco variable never goes in the overflow (or underflow) # if recoVariable > allVariablesBins[variable][-1]: # print 'Big reco variable : ',recoVariable # print 'Setting to :',min( recoVariable, allVariablesBins[variable][-1] - 0.000001 ) if not options.fineBinned: recoVariable = min( recoVariable, allVariablesBins[variable][-1] - 0.000001 ) genVariable_particle = branch(genVariable_particle_names[variable]) if 'abs' in variable: genVariable_particle = abs(genVariable_particle) # # # # Fill histograms # # histogramsToFill = histograms[variable][channel.channelName] if not options.donothing: if genSelection: histogramsToFill['truth'].Fill( genVariable_particle, genWeight) if genSelectionVis: histogramsToFill['truthVis'].Fill( genVariable_particle, genWeight) if offlineSelection: histogramsToFill['measured'].Fill( recoVariable, offlineWeight) histogramsToFill['measuredVis'].Fill( recoVariable, offlineWeight) if genSelectionVis : histogramsToFill['measuredVis_without_fakes'].Fill( recoVariable, offlineWeight) if genSelection: histogramsToFill['measured_without_fakes'].Fill( recoVariable, offlineWeight) histogramsToFill['response'].Fill( recoVariable, genVariable_particle, offlineWeight ) if offlineSelection and genSelection: histogramsToFill['response_without_fakes'].Fill( recoVariable, genVariable_particle, offlineWeight ) elif genSelection: histogramsToFill['response_without_fakes'].Fill( allVariablesBins[variable][0]-1, genVariable_particle, genWeight ) # if genVariable_particle < 0 : print recoVariable, genVariable_particle # if genVariable_particle < 0 : print genVariable_particle if offlineSelection and genSelectionVis: histogramsToFill['responseVis_without_fakes'].Fill( recoVariable, genVariable_particle, offlineWeight ) elif genSelectionVis: histogramsToFill['responseVis_without_fakes'].Fill( allVariablesBins[variable][0]-1, genVariable_particle, genWeight ) if fakeSelection: histogramsToFill['fake'].Fill( recoVariable, offlineWeight) if fakeSelectionVis: histogramsToFill['fakeVis'].Fill( recoVariable, offlineWeight) if options.extraHists: if genSelection: histogramsToFill['eventWeightHist'].Fill(event.EventWeight) histogramsToFill['genWeightHist'].Fill(genWeight) histogramsToFill['offlineWeightHist'].Fill(offlineWeight) # # Output histgorams to file # for variable in allVariablesBins: if options.sample in measurement_config.met_systematics and variable not in ['MET', 'ST', 'WPT']: continue for channel in channels: # Fill phase space info h = histograms[variable][channel.channelName]['phaseSpaceInfoHist'] h.SetBinContent(1, nVisNotOffline[channel.channelName] / nVis[channel.channelName]) h.SetBinContent(2, nOfflineNotVis[channel.channelName] / nOffline[channel.channelName]) h.SetBinContent(3, nVis[channel.channelName] / nFull[channel.channelName]) # Selection efficiency for SL ttbar h.SetBinContent(4, nOfflineSL[channel.channelName] / nFull[channel.channelName]) # Fraction of offline that are SL h.SetBinContent(5, nOfflineSL[channel.channelName] / nOffline[channel.channelName]) outputDirs[variable][channel.channelName].cd() for h in histograms[variable][channel.channelName]: histograms[variable][channel.channelName][h].Write() with root_open( outputFileName, 'update') as out: # Done all channels, now combine the two channels, and output to the same file for path, dirs, objects in out.walk(): if 'electron' in path: outputDir = out.mkdir(path.replace('electron','combined')) outputDir.cd() for h in objects: h_e = out.Get(path+'/'+h) h_mu = out.Get(path.replace('electron','muon')+'/'+h) h_comb = (h_e + h_mu).Clone(h) h_comb.Write() pass pass pass
def main(): args = parse_arguments() measurement_config = XSectionConfig( args.centreOfMassEnergy ) # Input file name file_name = 'crap.root' if int(args.centreOfMassEnergy) == 13: file_name = getFileName('13TeV', args.sample, measurement_config) else: print "Error: Unrecognised centre of mass energy." pdfWeight = args.pdfWeight CT14Weight = args.CT14Weight MMHT14Weight = args.MMHT14Weight muFmuRWeight = args.muFmuRWeight alphaSWeight = args.alphaSWeight semiLepBrWeight = args.semiLepBrWeight fragWeight = args.fragWeight # Output file name outputFileName = 'crap.root' outputFileDir = 'unfolding/%sTeV/' % args.centreOfMassEnergy make_folder_if_not_exists(outputFileDir) energySuffix = '%sTeV' % ( args.centreOfMassEnergy ) if args.applyTopEtaReweighting != 0: if args.applyTopEtaReweighting == 1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_withTopEtaReweighting_up.root' % energySuffix elif args.applyTopEtaReweighting == -1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_withTopEtaReweighting_down.root' % energySuffix elif args.applyTopPtReweighting: if args.applyTopPtReweighting == 1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_withTopPtReweighting_up.root' % energySuffix elif args.applyTopPtReweighting == -1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_withTopPtReweighting_down.root' % energySuffix elif muFmuRWeight == 1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_1muR2muF.root' % ( energySuffix ) elif muFmuRWeight == 2: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_1muR05muF.root' % ( energySuffix ) elif muFmuRWeight == 3: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_2muR1muF.root' % ( energySuffix ) elif muFmuRWeight == 4: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_2muR2muF.root' % ( energySuffix ) elif muFmuRWeight == 6: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_05muR1muF.root' % ( energySuffix ) elif muFmuRWeight == 8: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_05muR05muF.root' % ( energySuffix ) elif alphaSWeight == 0: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_alphaS_down.root' % ( energySuffix ) elif alphaSWeight == 1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_alphaS_up.root' % ( energySuffix ) elif semiLepBrWeight == -1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_semiLepBr_down.root' % ( energySuffix ) elif semiLepBrWeight == 1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_semiLepBr_up.root' % ( energySuffix ) elif fragWeight == 1: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_frag_down.root' % ( energySuffix ) elif fragWeight == 2: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_frag_central.root' % ( energySuffix ) elif fragWeight == 3: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_frag_up.root' % ( energySuffix ) elif fragWeight == 4: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_frag_peterson.root' % ( energySuffix ) elif pdfWeight >= 0 and pdfWeight <= 99: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_pdfWeight_%i.root' % ( energySuffix, pdfWeight ) elif CT14Weight >= 0 and CT14Weight <= 54: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_CT14Weight_%i.root' % ( energySuffix, CT14Weight ) elif MMHT14Weight >= 0 and MMHT14Weight <= 55: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric_MMHT14Weight_%i.root' % ( energySuffix, MMHT14Weight ) elif 'central' not in args.sample: outputFileName = outputFileDir+'/unfolding_TTJets_%s_%s_asymmetric.root' % ( energySuffix, args.sample ) elif args.fineBinned : outputFileName = outputFileDir+'/unfolding_TTJets_%s.root' % ( energySuffix ) else: outputFileName = outputFileDir+'/unfolding_TTJets_%s_asymmetric.root' % energySuffix if '70pc' in args.sample or '30pc' in args.sample: outputFileName.replace('asymmetric','asymmetric_'+args.sample.split('_')[1]) if 'firstHalf' in args.sample: outputFileName = outputFileName.replace('asymmetric','asymmetric_firstHalf') elif 'secondHalf' in args.sample: outputFileName = outputFileName.replace('asymmetric','asymmetric_secondHalf') if args.newPS : outputFileName = outputFileName.replace('asymmetric','asymmetric_newPS') # Get the tree/chain treeName = "TTbar_plus_X_analysis/Unfolding/Unfolding" print file_name file_name = getUnmergedDirectory(file_name) print file_name tree = ROOT.TChain(treeName); filenames = glob.glob( file_name ) for f in filenames: tree.Add(f) with root_open( outputFileName, 'recreate') as out: nEntries = tree.GetEntries() print 'Number of entries:',nEntries # For variables where you want bins to be symmetric about 0, use abs(variable) (but also make plots for signed variable) allVariablesBins = bin_edges_vis.copy() for variable in bin_edges_vis: if 'Rap' in variable: allVariablesBins['abs_%s' % variable] = [0,bin_edges_vis[variable][-1]] recoVariableNames = {} genVariable_particle_names = {} genVariable_parton_names = {} histograms = {} residuals = {} residual_options= {} outputDirs = {} outputDirsRes = {} for variable in allVariablesBins: if args.debug and variable != 'HT' : continue if args.sample in measurement_config.met_specific_systematics \ and variable in measurement_config.variables_no_met: continue outputDirs[variable] = {} outputDirsRes[variable] = {} histograms[variable] = {} residuals[variable] = {} residual_options[variable] = {} # # Variable names # recoVariableName = branchNames[variable] sysIndex = None if variable in ['MET', 'ST', 'WPT']: if args.sample == "jerup": recoVariableName += '_METUncertainties' sysIndex = 0 elif args.sample == "jerdown": recoVariableName+= '_METUncertainties' sysIndex = 1 elif args.sample == "jesup": recoVariableName += '_METUncertainties' sysIndex = 2 elif args.sample == "jesdown": recoVariableName += '_METUncertainties' sysIndex = 3 # Dont need this? elif args.sample in measurement_config.met_systematics: recoVariableName += '_METUncertainties' sysIndex = measurement_config.met_systematics[args.sample] genVariable_particle_name = None genVariable_parton_name = None if variable in genBranchNames_particle: genVariable_particle_name = genBranchNames_particle[variable] if args.newPS and variable in ['HT', 'ST', 'NJets']: genVariable_particle_name += '_20GeVLastJet' if variable in genBranchNames_parton: genVariable_parton_name = genBranchNames_parton[variable] recoVariableNames[variable] = recoVariableName genVariable_particle_names[variable] = genVariable_particle_name genVariable_parton_names[variable] = genVariable_parton_name reco_bin_edges_vis_to_use = reco_bin_edges_vis[variable] for channel in channels: # Make dir in output file outputDirName = variable+'_'+channel.outputDirName outputDir = out.mkdir(outputDirName) outputDirs[variable][channel.channelName] = outputDir if args.fineBinned: outputDirResName = outputDirName + '/residuals/' outputDirRes = out.mkdir(outputDirResName) outputDirsRes[variable][channel.channelName] = outputDirRes # # Book histograms # # 1D histograms histograms[variable][channel.channelName] = {} h = histograms[variable][channel.channelName] h['truth'] = Hist( allVariablesBins[variable], name='truth', type='D') h['truthVis'] = Hist( allVariablesBins[variable], name='truthVis', type='D') h['truthVis_noWeight'] = Hist( allVariablesBins[variable], name='truthVis_noWeight', type='D') h['truth_parton'] = Hist( allVariablesBins[variable], name='truth_parton', type='D') h['measured'] = Hist( reco_bin_edges_vis_to_use, name='measured', type='D') h['measuredVis'] = Hist( reco_bin_edges_vis_to_use, name='measuredVis', type='D') h['measured_without_fakes'] = Hist( reco_bin_edges_vis_to_use, name='measured_without_fakes', type='D') h['measuredVis_without_fakes'] = Hist( reco_bin_edges_vis_to_use, name='measuredVis_without_fakes', type='D') h['fake'] = Hist( reco_bin_edges_vis_to_use, name='fake', type='D') h['fakeVis'] = Hist( reco_bin_edges_vis_to_use, name='fakeVis', type='D') # 2D histograms h['response'] = Hist2D( reco_bin_edges_vis_to_use, allVariablesBins[variable], name='response', type='D') h['response_without_fakes'] = Hist2D( reco_bin_edges_vis_to_use, allVariablesBins[variable], name='response_without_fakes', type='D') h['responseVis_without_fakes'] = Hist2D( reco_bin_edges_vis_to_use, allVariablesBins[variable], name='responseVis_without_fakes', type='D') h['response_parton'] = Hist2D( reco_bin_edges_vis_to_use, allVariablesBins[variable], name='response_parton', type='D') h['response_without_fakes_parton'] = Hist2D( reco_bin_edges_vis_to_use, allVariablesBins[variable], name='response_without_fakes_parton', type='D') if args.fineBinned: minVar = trunc( allVariablesBins[variable][0] ) maxVar = trunc( max( tree.GetMaximum(genVariable_particle_names[variable]), tree.GetMaximum( reco_bin_edges_vis_to_use ) ) * 1.2 ) nBins = int(maxVar - minVar) if variable is 'lepton_eta' or variable is 'bjets_eta': maxVar = 2.4 minVar = -2.4 nBins = 1000 # nBins = 960 so that small bin width is usable in 00. [0.0025] elif 'abs' in variable and 'eta' in variable: maxVar = 2.4 minVar = 0. nBins = 960 elif 'Rap' in variable: maxVar = 2.4 minVar = -2.4 nBins = 1000 elif 'NJets' in variable: maxVar = 20.5 minVar = 3.5 nBins = 17 h['truth'] = Hist( nBins, minVar, maxVar, name='truth') h['truthVis'] = Hist( nBins, minVar, maxVar, name='truthVis') h['truthVis_noWeight'] = Hist( nBins, minVar, maxVar, name='truthVis_noWeight') h['truth_parton'] = Hist( nBins, minVar, maxVar, name='truth_parton') h['measured'] = Hist( nBins, minVar, maxVar, name='measured') h['measuredVis'] = Hist( nBins, minVar, maxVar, name='measuredVis') h['measured_without_fakes'] = Hist( nBins, minVar, maxVar, name='measured_without_fakes') h['measuredVis_without_fakes'] = Hist( nBins, minVar, maxVar, name='measuredVis_without_fakes') h['fake'] = Hist( nBins, minVar, maxVar, name='fake') h['fakeVis'] = Hist( nBins, minVar, maxVar, name='fakeVis') h['response'] = Hist2D( nBins, minVar, maxVar, nBins, minVar, maxVar, name='response') h['response_without_fakes'] = Hist2D( nBins, minVar, maxVar, nBins, minVar, maxVar, name='response_without_fakes') h['responseVis_without_fakes'] = Hist2D( nBins, minVar, maxVar, nBins, minVar, maxVar, name='responseVis_without_fakes') h['response_parton'] = Hist2D( nBins, minVar, maxVar, nBins, minVar, maxVar, name='response_parton') h['response_without_fakes_parton'] = Hist2D( nBins, minVar, maxVar, nBins, minVar, maxVar, name='response_without_fakes_parton') residuals[variable][channel.channelName] = {} r = residuals[variable][channel.channelName] for i in range (1, nBins+1): r[i] = Hist(100, 0, maxVar*0.1, name='Residuals_Bin_'+str(i)) residual_options[variable][channel.channelName] = {} o = residual_options[variable][channel.channelName] o['min'] = minVar o['max'] = maxVar o['nbins'] = nBins o['step'] = (maxVar-minVar)/nBins o['bin_edges'] = np.arange(minVar, maxVar, (maxVar-minVar)/nBins) # Some interesting histograms h['puOffline'] = Hist( 20, 0, 2, name='puWeights_offline') h['eventWeightHist'] = Hist( 100, -2, 2, name='eventWeightHist') h['genWeightHist'] = Hist( 1000, 0, 1, name='genWeightHist') h['offlineWeightHist'] = Hist( 100, -2, 2, name='offlineWeightHist') h['phaseSpaceInfoHist'] = Hist( 10, 0, 1, name='phaseSpaceInfoHist') print("Initialisation of Histograms Complete") # Counters for studying phase space nPassGenSelection = 0 nVis = {c.channelName : 0 for c in channels} nVisNotOffline = {c.channelName : 0 for c in channels} nOffline = {c.channelName : 0 for c in channels} nOfflineNotVis = {c.channelName : 0 for c in channels} nFull = {c.channelName : 0 for c in channels} nOfflineSL = {c.channelName : 0 for c in channels} n=0 maxEvents = -1 halfOfEvents = 0 if '70pc' in args.sample or '30pc' in args.sample: print 'Only processing fraction of total events for sample :',args.sample totalEvents = tree.GetEntries() if '70pc' in args.sample: maxEvents = int( totalEvents * 0.7 ) elif '30pc' in args.sample: maxEvents = int( totalEvents * 0.3 ) print 'Will process ',maxEvents,'out of',totalEvents,'events' if 'firstHalf' in args.sample or 'secondHalf' in args.sample: totalEvents = tree.GetEntries() halfOfEvents = int( totalEvents / 2 ) # Event Loop # for event, weight in zip(tree,weightTree): for event in tree: branch = event.__getattr__ n+=1 if not n%100000: print 'Processing event %.0f Progress : %.2g %%' % ( n, float(n)/nEntries*100 ) # if n > 100000: break if maxEvents > 0 and n > maxEvents: break if 'firstHalf' in args.sample and n >= halfOfEvents: break elif 'secondHalf' in args.sample and n < halfOfEvents: continue # # # # # # Weights and selection # # # # Pileup weight # Don't apply if calculating systematic pileupWeight = event.PUWeight # print event.PUWeight,event.PUWeight_up,event.PUWeight_down if args.sample == "pileupUp": pileupWeight = event.PUWeight_up elif args.sample == "pileupDown": pileupWeight = event.PUWeight_down # Generator level weight genWeight = event.EventWeight * measurement_config.luminosity_scale # B Jet Weight # bjetWeight = event.BJetWeight bjetWeight = event.BJetAlternativeWeight if 'fsr' in args.sample: # bjetWeight = event.BJetAlternativeWeight * event.BJetEfficiencyCorrectionWeight bjetWeight = event.BJetWeight * event.BJetEfficiencyCorrectionWeight if args.sample == "bjetup": bjetWeight = event.BJetUpWeight elif args.sample == "bjetdown": bjetWeight = event.BJetDownWeight elif args.sample == "lightjetup": bjetWeight = event.LightJetUpWeight elif args.sample == "lightjetdown": bjetWeight = event.LightJetDownWeight # Top pt systematic weight topPtSystematicWeight = 1 if args.sample == 'topPtSystematic': topPtSystematicWeight = calculateTopPtSystematicWeight( branch('lepTopPt_parton'), branch('hadTopPt_parton')) # Offline level weights offlineWeight = 1 offlineWeight *= pileupWeight offlineWeight *= bjetWeight offlineWeight_forLeptonEta = offlineWeight genWeight *= topPtSystematicWeight # Generator weight # Scale up/down, pdf if pdfWeight >= 0: genWeight *= branch('pdfWeight_%i' % pdfWeight) pass if MMHT14Weight >= 0: genWeight *= branch('MMHT14Weight_%i' % MMHT14Weight) pass if CT14Weight >= 0: genWeight *= branch('CT14Weight_%i' % CT14Weight) pass if muFmuRWeight >= 0: genWeight *= branch('muFmuRWeight_%i' % muFmuRWeight) pass if alphaSWeight == 0 or alphaSWeight == 1: genWeight *= branch('alphaSWeight_%i' % alphaSWeight) pass if semiLepBrWeight == -1: genWeight *= branch('semilepbrDown') elif semiLepBrWeight == 1: genWeight *= branch('semilepbrUp') pass if fragWeight == 1: genWeight *= branch('downFrag') elif fragWeight == 2: genWeight *= branch('centralFrag') elif fragWeight == 3: genWeight *= branch('upFrag') elif fragWeight == 4: genWeight *= branch('petersonFrag') pass if args.applyTopPtReweighting != 0: ptWeight = calculateTopPtWeight( branch('lepTopPt_parton'), branch('hadTopPt_parton'), args.applyTopPtReweighting) genWeight *= ptWeight if args.applyTopEtaReweighting != 0: etaWeight = calculateTopEtaWeight( branch('lepTopRap_parton'), branch('hadTopRap_parton'), args.applyTopEtaReweighting) genWeight *= etaWeight for channel in channels: # Generator level selection genSelection = '' genSelectionVis = '' if channel.channelName is 'muPlusJets' : genSelection = event.isSemiLeptonicMuon == 1 genSelectionVis = event.passesGenEventSelection == 1 and event.pseudoLepton_pdgId == 13 if args.newPS: genSelectionVis = event.passesGenEventSelection_20GeVLastJet == 1 and event.pseudoLepton_pdgId == 13 elif channel.channelName is 'ePlusJets' : genSelection = event.isSemiLeptonicElectron == 1 genSelectionVis = event.passesGenEventSelection == 1 and event.pseudoLepton_pdgId == 11 if args.newPS: genSelectionVis = event.passesGenEventSelection_20GeVLastJet == 1 and event.pseudoLepton_pdgId == 11 # Lepton weight # Channel specific leptonWeight = 1 leptonWeight_forLeptonEta = 1 if channel.channelName is 'muPlusJets' : leptonWeight = event.MuonEfficiencyCorrection leptonWeight_forLeptonEta = event.MuonEfficiencyCorrection_etaBins if args.sample == 'muonup': leptonWeight = event.MuonEfficiencyCorrectionUp leptonWeight_forLeptonEta = event.MuonEfficiencyCorrectionUp_etaBins elif args.sample == 'muondown': leptonWeight = event.MuonEfficiencyCorrectionDown leptonWeight_forLeptonEta = event.MuonEfficiencyCorrectionDown_etaBins elif channel.channelName is 'ePlusJets' : leptonWeight = event.ElectronEfficiencyCorrection leptonWeight_forLeptonEta = event.ElectronEfficiencyCorrection_etaBins if args.sample == 'electronup': leptonWeight = event.ElectronEfficiencyCorrectionUp leptonWeight_forLeptonEta = event.ElectronEfficiencyCorrectionUp_etaBins elif args.sample == 'electrondown': leptonWeight = event.ElectronEfficiencyCorrectionDown leptonWeight_forLeptonEta = event.ElectronEfficiencyCorrectionDown_etaBins offlineWeight_withLeptonWeight = offlineWeight * leptonWeight offlineWeight_withLeptonWeight_forLeptonEta = offlineWeight_forLeptonEta * leptonWeight_forLeptonEta # Offline level selection offlineSelection = 0 if channel.channelName is 'muPlusJets' : offlineSelection = int(event.passSelection) == 1 elif channel.channelName is 'ePlusJets' : offlineSelection = int(event.passSelection) == 2 # Fake selection fakeSelection = offlineSelection and not genSelection fakeSelectionVis = offlineSelection and not genSelectionVis # Phase space info if genSelection: nFull[channel.channelName] += genWeight if offlineSelection: nOfflineSL[channel.channelName] += genWeight if genSelectionVis: nPassGenSelection += 1 nVis[channel.channelName] += genWeight if not offlineSelection: nVisNotOffline[channel.channelName] += genWeight if offlineSelection: nOffline[channel.channelName] += offlineWeight * genWeight if not genSelectionVis: nOfflineNotVis[channel.channelName] += offlineWeight * genWeight for variable in allVariablesBins: if args.debug and variable != 'HT' : continue if args.sample in measurement_config.met_specific_systematics and \ variable in measurement_config.variables_no_met: continue offlineWeight_toUse = offlineWeight_withLeptonWeight if 'abs_lepton_eta' in variable: offlineWeight_toUse = offlineWeight_withLeptonWeight_forLeptonEta # # # # # # Variable to plot # # # recoVariable = branch(recoVariableNames[variable]) if variable in ['MET', 'ST', 'WPT'] and \ sysIndex != None and ( offlineSelection or fakeSelection or fakeSelectionVis ) : recoVariable = recoVariable[sysIndex] if 'abs' in variable: recoVariable = abs(recoVariable) # With TUnfold, reco variable never goes in the overflow (or underflow) if not args.fineBinned: recoVariable = min( recoVariable, allVariablesBins[variable][-1] - 0.000001 ) genVariable_particle = branch(genVariable_particle_names[variable]) if 'abs' in variable: genVariable_particle = abs(genVariable_particle) # # # # Fill histograms # # histogramsToFill = histograms[variable][channel.channelName] if not args.donothing: if genSelection: histogramsToFill['truth'].Fill( genVariable_particle, genWeight) if genSelectionVis: filledTruth = True histogramsToFill['truthVis'].Fill( genVariable_particle, genWeight) histogramsToFill['truthVis_noWeight'].Fill( genVariable_particle, 1) if offlineSelection: histogramsToFill['measured'].Fill( recoVariable, offlineWeight_toUse * genWeight ) histogramsToFill['measuredVis'].Fill( recoVariable, offlineWeight_toUse * genWeight ) if genSelectionVis : histogramsToFill['measuredVis_without_fakes'].Fill( recoVariable, offlineWeight_toUse * genWeight ) if genSelection: histogramsToFill['measured_without_fakes'].Fill( recoVariable, offlineWeight_toUse * genWeight ) histogramsToFill['response'].Fill( recoVariable, genVariable_particle, offlineWeight_toUse * genWeight ) if offlineSelection and genSelection: histogramsToFill['response_without_fakes'].Fill( recoVariable, genVariable_particle, offlineWeight_toUse * genWeight ) histogramsToFill['response_without_fakes'].Fill( allVariablesBins[variable][0]-1, genVariable_particle, ( 1 - offlineWeight_toUse ) * genWeight ) elif genSelection: histogramsToFill['response_without_fakes'].Fill( allVariablesBins[variable][0]-1, genVariable_particle, genWeight ) if offlineSelection and genSelectionVis: histogramsToFill['responseVis_without_fakes'].Fill( recoVariable, genVariable_particle, offlineWeight_toUse * genWeight ) histogramsToFill['responseVis_without_fakes'].Fill( allVariablesBins[variable][0]-1, genVariable_particle, ( 1 - offlineWeight_toUse ) * genWeight ) filledResponse = True elif genSelectionVis: histogramsToFill['responseVis_without_fakes'].Fill( allVariablesBins[variable][0]-1, genVariable_particle, genWeight ) filledResponse = True if fakeSelection: histogramsToFill['fake'].Fill( recoVariable, offlineWeight_toUse * genWeight ) if fakeSelectionVis: histogramsToFill['fakeVis'].Fill( recoVariable, offlineWeight_toUse * genWeight ) if args.extraHists: if genSelectionVis: histogramsToFill['eventWeightHist'].Fill(event.EventWeight) histogramsToFill['genWeightHist'].Fill(genWeight) histogramsToFill['offlineWeightHist'].Fill(offlineWeight_toUse ) if args.fineBinned: # Bin reco var is in options = residual_options[variable][channel.channelName] if offlineSelection and genSelection: # i will be fine bin number the reco var resides in for i, edge in enumerate(options['bin_edges']): if recoVariable > edge: continue else: break residual = abs(recoVariable - genVariable_particle) if not residual > options['max']*0.1: residuals[variable][channel.channelName][i].Fill(residual, offlineWeight_toUse*genWeight) # # Output histgorams to file # for variable in allVariablesBins: if args.debug and variable != 'HT' : continue if args.sample in measurement_config.met_systematics and variable not in ['MET', 'ST', 'WPT']: continue for channel in channels: if nOffline[channel.channelName] != 0 : # Fill phase space info h = histograms[variable][channel.channelName]['phaseSpaceInfoHist'] h.SetBinContent(1, nVisNotOffline[channel.channelName] / nVis[channel.channelName]) # h.GetXaxis().SetBinLabel(1, "nVisNotOffline/nVis") h.SetBinContent(2, nOfflineNotVis[channel.channelName] / nOffline[channel.channelName]) # h.GetXaxis().SetBinLabel(2, "nOfflineNotVis/nOffline") h.SetBinContent(3, nVis[channel.channelName] / nFull[channel.channelName]) # h.GetXaxis().SetBinLabel(3, "nVis/nFull") # Selection efficiency for SL ttbar h.SetBinContent(4, nOfflineSL[channel.channelName] / nFull[channel.channelName]) # h.GetXaxis().SetBinLabel(4, "nOfflineSL/nFull") # Fraction of offline that are SL h.SetBinContent(5, nOfflineSL[channel.channelName] / nOffline[channel.channelName]) # h.GetXaxis().SetBinLabel(5, "nOfflineSL/nOffline") outputDirs[variable][channel.channelName].cd() for h in histograms[variable][channel.channelName]: histograms[variable][channel.channelName][h].Write() if args.fineBinned: outputDirsRes[variable][channel.channelName].cd() for r in residuals[variable][channel.channelName]: residuals[variable][channel.channelName][r].Write() print 'N events passing gen selection : ',nPassGenSelection with root_open( outputFileName, 'update') as out: # Done all channels, now combine the two channels, and output to the same file for path, dirs, objects in out.walk(): if 'electron' in path: if 'coarse' in path: continue outputDir = out.mkdir(path.replace('electron','combined')) outputDir.cd() for h in objects: h_e = out.Get(path+'/'+h) h_mu = out.Get(path.replace('electron','muon')+'/'+h) h_comb = (h_e + h_mu).Clone(h) h_comb.Write() pass pass pass
def main(): args = parse_arguments() measurement_config = XSectionConfig(args.centreOfMassEnergy) # Input file name file_name = 'crap.root' if int(args.centreOfMassEnergy) == 13: file_name = getFileName('13TeV', args.sample, measurement_config) else: print "Error: Unrecognised centre of mass energy." pdfWeight = args.pdfWeight CT14Weight = args.CT14Weight MMHT14Weight = args.MMHT14Weight muFmuRWeight = args.muFmuRWeight alphaSWeight = args.alphaSWeight semiLepBrWeight = args.semiLepBrWeight fragWeight = args.fragWeight # Output file name outputFileName = 'crap.root' outputFileDir = 'unfolding/%sTeV/' % args.centreOfMassEnergy make_folder_if_not_exists(outputFileDir) energySuffix = '%sTeV' % (args.centreOfMassEnergy) if args.applyTopEtaReweighting != 0: if args.applyTopEtaReweighting == 1: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_withTopEtaReweighting_up.root' % energySuffix elif args.applyTopEtaReweighting == -1: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_withTopEtaReweighting_down.root' % energySuffix elif args.applyTopPtReweighting: if args.applyTopPtReweighting == 1: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_withTopPtReweighting_up.root' % energySuffix elif args.applyTopPtReweighting == -1: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_withTopPtReweighting_down.root' % energySuffix elif muFmuRWeight == 1: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_1muR2muF.root' % ( energySuffix) elif muFmuRWeight == 2: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_1muR05muF.root' % ( energySuffix) elif muFmuRWeight == 3: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_2muR1muF.root' % ( energySuffix) elif muFmuRWeight == 4: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_2muR2muF.root' % ( energySuffix) elif muFmuRWeight == 6: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_05muR1muF.root' % ( energySuffix) elif muFmuRWeight == 8: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_05muR05muF.root' % ( energySuffix) elif alphaSWeight == 0: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_alphaS_down.root' % ( energySuffix) elif alphaSWeight == 1: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_alphaS_up.root' % ( energySuffix) elif semiLepBrWeight == -1: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_semiLepBr_down.root' % ( energySuffix) elif semiLepBrWeight == 1: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_semiLepBr_up.root' % ( energySuffix) elif fragWeight == 1: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_frag_down.root' % ( energySuffix) elif fragWeight == 2: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_frag_central.root' % ( energySuffix) elif fragWeight == 3: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_frag_up.root' % ( energySuffix) elif fragWeight == 4: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_frag_peterson.root' % ( energySuffix) elif pdfWeight >= 0 and pdfWeight <= 99: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_pdfWeight_%i.root' % ( energySuffix, pdfWeight) elif CT14Weight >= 0 and CT14Weight <= 54: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_CT14Weight_%i.root' % ( energySuffix, CT14Weight) elif MMHT14Weight >= 0 and MMHT14Weight <= 55: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric_MMHT14Weight_%i.root' % ( energySuffix, MMHT14Weight) elif 'central' not in args.sample: outputFileName = outputFileDir + '/unfolding_TTJets_%s_%s_asymmetric.root' % ( energySuffix, args.sample) elif args.fineBinned: outputFileName = outputFileDir + '/unfolding_TTJets_%s.root' % ( energySuffix) else: outputFileName = outputFileDir + '/unfolding_TTJets_%s_asymmetric.root' % energySuffix if '70pc' in args.sample or '30pc' in args.sample: outputFileName.replace('asymmetric', 'asymmetric_' + args.sample.split('_')[1]) if 'firstHalf' in args.sample: outputFileName = outputFileName.replace('asymmetric', 'asymmetric_firstHalf') elif 'secondHalf' in args.sample: outputFileName = outputFileName.replace('asymmetric', 'asymmetric_secondHalf') if args.newPS: outputFileName = outputFileName.replace('asymmetric', 'asymmetric_newPS') # Get the tree/chain treeName = "TTbar_plus_X_analysis/Unfolding/Unfolding" print file_name file_name = getUnmergedDirectory(file_name) print file_name tree = ROOT.TChain(treeName) filenames = glob.glob(file_name) for f in filenames: tree.Add(f) with root_open(outputFileName, 'recreate') as out: nEntries = tree.GetEntries() print 'Number of entries:', nEntries # For variables where you want bins to be symmetric about 0, use abs(variable) (but also make plots for signed variable) allVariablesBins = bin_edges_vis.copy() for variable in bin_edges_vis: if 'Rap' in variable: allVariablesBins['abs_%s' % variable] = [0, bin_edges_vis[variable][-1]] recoVariableNames = {} genVariable_particle_names = {} genVariable_parton_names = {} histograms = {} residuals = {} residual_options = {} outputDirs = {} outputDirsRes = {} for variable in allVariablesBins: if args.debug and variable != 'HT': continue if args.sample in measurement_config.met_specific_systematics \ and variable in measurement_config.variables_no_met: continue outputDirs[variable] = {} outputDirsRes[variable] = {} histograms[variable] = {} residuals[variable] = {} residual_options[variable] = {} # # Variable names # recoVariableName = branchNames[variable] sysIndex = None if variable in ['MET', 'ST', 'WPT']: if args.sample == "jerup": recoVariableName += '_METUncertainties' sysIndex = 0 elif args.sample == "jerdown": recoVariableName += '_METUncertainties' sysIndex = 1 elif args.sample == "jesup": recoVariableName += '_METUncertainties' sysIndex = 2 elif args.sample == "jesdown": recoVariableName += '_METUncertainties' sysIndex = 3 # Dont need this? elif args.sample in measurement_config.met_systematics: recoVariableName += '_METUncertainties' sysIndex = measurement_config.met_systematics[args.sample] genVariable_particle_name = None genVariable_parton_name = None if variable in genBranchNames_particle: genVariable_particle_name = genBranchNames_particle[variable] if args.newPS and variable in ['HT', 'ST', 'NJets']: genVariable_particle_name += '_20GeVLastJet' if variable in genBranchNames_parton: genVariable_parton_name = genBranchNames_parton[variable] recoVariableNames[variable] = recoVariableName genVariable_particle_names[variable] = genVariable_particle_name genVariable_parton_names[variable] = genVariable_parton_name reco_bin_edges_vis_to_use = reco_bin_edges_vis[variable] for channel in channels: # Make dir in output file outputDirName = variable + '_' + channel.outputDirName outputDir = out.mkdir(outputDirName) outputDirs[variable][channel.channelName] = outputDir if args.fineBinned: outputDirResName = outputDirName + '/residuals/' outputDirRes = out.mkdir(outputDirResName) outputDirsRes[variable][channel.channelName] = outputDirRes # # Book histograms # # 1D histograms histograms[variable][channel.channelName] = {} h = histograms[variable][channel.channelName] h['truth'] = Hist(allVariablesBins[variable], name='truth', type='D') h['truthVis'] = Hist(allVariablesBins[variable], name='truthVis', type='D') h['truthVis_noWeight'] = Hist(allVariablesBins[variable], name='truthVis_noWeight', type='D') h['truth_parton'] = Hist(allVariablesBins[variable], name='truth_parton', type='D') h['measured'] = Hist(reco_bin_edges_vis_to_use, name='measured', type='D') h['measuredVis'] = Hist(reco_bin_edges_vis_to_use, name='measuredVis', type='D') h['measured_without_fakes'] = Hist( reco_bin_edges_vis_to_use, name='measured_without_fakes', type='D') h['measuredVis_without_fakes'] = Hist( reco_bin_edges_vis_to_use, name='measuredVis_without_fakes', type='D') h['fake'] = Hist(reco_bin_edges_vis_to_use, name='fake', type='D') h['fakeVis'] = Hist(reco_bin_edges_vis_to_use, name='fakeVis', type='D') # 2D histograms h['response'] = Hist2D(reco_bin_edges_vis_to_use, allVariablesBins[variable], name='response', type='D') h['response_without_fakes'] = Hist2D( reco_bin_edges_vis_to_use, allVariablesBins[variable], name='response_without_fakes', type='D') h['responseVis_without_fakes'] = Hist2D( reco_bin_edges_vis_to_use, allVariablesBins[variable], name='responseVis_without_fakes', type='D') h['response_parton'] = Hist2D(reco_bin_edges_vis_to_use, allVariablesBins[variable], name='response_parton', type='D') h['response_without_fakes_parton'] = Hist2D( reco_bin_edges_vis_to_use, allVariablesBins[variable], name='response_without_fakes_parton', type='D') if args.fineBinned: minVar = trunc(allVariablesBins[variable][0]) maxVar = trunc( max( tree.GetMaximum( genVariable_particle_names[variable]), tree.GetMaximum(reco_bin_edges_vis_to_use)) * 1.2) nBins = int(maxVar - minVar) if variable is 'lepton_eta' or variable is 'bjets_eta': maxVar = 2.4 minVar = -2.4 nBins = 1000 # nBins = 960 so that small bin width is usable in 00. [0.0025] elif 'abs' in variable and 'eta' in variable: maxVar = 2.4 minVar = 0. nBins = 960 elif 'Rap' in variable: maxVar = 2.4 minVar = -2.4 nBins = 1000 elif 'NJets' in variable: maxVar = 20.5 minVar = 3.5 nBins = 17 h['truth'] = Hist(nBins, minVar, maxVar, name='truth') h['truthVis'] = Hist(nBins, minVar, maxVar, name='truthVis') h['truthVis_noWeight'] = Hist(nBins, minVar, maxVar, name='truthVis_noWeight') h['truth_parton'] = Hist(nBins, minVar, maxVar, name='truth_parton') h['measured'] = Hist(nBins, minVar, maxVar, name='measured') h['measuredVis'] = Hist(nBins, minVar, maxVar, name='measuredVis') h['measured_without_fakes'] = Hist( nBins, minVar, maxVar, name='measured_without_fakes') h['measuredVis_without_fakes'] = Hist( nBins, minVar, maxVar, name='measuredVis_without_fakes') h['fake'] = Hist(nBins, minVar, maxVar, name='fake') h['fakeVis'] = Hist(nBins, minVar, maxVar, name='fakeVis') h['response'] = Hist2D(nBins, minVar, maxVar, nBins, minVar, maxVar, name='response') h['response_without_fakes'] = Hist2D( nBins, minVar, maxVar, nBins, minVar, maxVar, name='response_without_fakes') h['responseVis_without_fakes'] = Hist2D( nBins, minVar, maxVar, nBins, minVar, maxVar, name='responseVis_without_fakes') h['response_parton'] = Hist2D(nBins, minVar, maxVar, nBins, minVar, maxVar, name='response_parton') h['response_without_fakes_parton'] = Hist2D( nBins, minVar, maxVar, nBins, minVar, maxVar, name='response_without_fakes_parton') residuals[variable][channel.channelName] = {} r = residuals[variable][channel.channelName] for i in range(1, nBins + 1): r[i] = Hist(100, 0, maxVar * 0.1, name='Residuals_Bin_' + str(i)) residual_options[variable][channel.channelName] = {} o = residual_options[variable][channel.channelName] o['min'] = minVar o['max'] = maxVar o['nbins'] = nBins o['step'] = (maxVar - minVar) / nBins o['bin_edges'] = np.arange(minVar, maxVar, (maxVar - minVar) / nBins) # Some interesting histograms h['puOffline'] = Hist(20, 0, 2, name='puWeights_offline') h['eventWeightHist'] = Hist(100, -2, 2, name='eventWeightHist') h['genWeightHist'] = Hist(1000, 0, 1, name='genWeightHist') h['offlineWeightHist'] = Hist(100, -2, 2, name='offlineWeightHist') h['phaseSpaceInfoHist'] = Hist(10, 0, 1, name='phaseSpaceInfoHist') print("Initialisation of Histograms Complete") # Counters for studying phase space nPassGenSelection = 0 nVis = {c.channelName: 0 for c in channels} nVisNotOffline = {c.channelName: 0 for c in channels} nOffline = {c.channelName: 0 for c in channels} nOfflineNotVis = {c.channelName: 0 for c in channels} nFull = {c.channelName: 0 for c in channels} nOfflineSL = {c.channelName: 0 for c in channels} n = 0 maxEvents = -1 halfOfEvents = 0 if '70pc' in args.sample or '30pc' in args.sample: print 'Only processing fraction of total events for sample :', args.sample totalEvents = tree.GetEntries() if '70pc' in args.sample: maxEvents = int(totalEvents * 0.7) elif '30pc' in args.sample: maxEvents = int(totalEvents * 0.3) print 'Will process ', maxEvents, 'out of', totalEvents, 'events' if 'firstHalf' in args.sample or 'secondHalf' in args.sample: totalEvents = tree.GetEntries() halfOfEvents = int(totalEvents / 2) # Event Loop # for event, weight in zip(tree,weightTree): for event in tree: branch = event.__getattr__ n += 1 if not n % 100000: print 'Processing event %.0f Progress : %.2g %%' % ( n, float(n) / nEntries * 100) # if n > 100000: break if maxEvents > 0 and n > maxEvents: break if 'firstHalf' in args.sample and n >= halfOfEvents: break elif 'secondHalf' in args.sample and n < halfOfEvents: continue # # # # # # Weights and selection # # # # Pileup weight # Don't apply if calculating systematic pileupWeight = event.PUWeight # print event.PUWeight,event.PUWeight_up,event.PUWeight_down if args.sample == "pileupUp": pileupWeight = event.PUWeight_up elif args.sample == "pileupDown": pileupWeight = event.PUWeight_down # Generator level weight genWeight = event.EventWeight * measurement_config.luminosity_scale # B Jet Weight # bjetWeight = event.BJetWeight bjetWeight = event.BJetAlternativeWeight if 'fsr' in args.sample: # bjetWeight = event.BJetAlternativeWeight * event.BJetEfficiencyCorrectionWeight bjetWeight = event.BJetWeight * event.BJetEfficiencyCorrectionWeight if args.sample == "bjetup": bjetWeight = event.BJetUpWeight elif args.sample == "bjetdown": bjetWeight = event.BJetDownWeight elif args.sample == "lightjetup": bjetWeight = event.LightJetUpWeight elif args.sample == "lightjetdown": bjetWeight = event.LightJetDownWeight # Top pt systematic weight topPtSystematicWeight = 1 if args.sample == 'topPtSystematic': topPtSystematicWeight = calculateTopPtSystematicWeight( branch('lepTopPt_parton'), branch('hadTopPt_parton')) # Offline level weights offlineWeight = 1 offlineWeight *= pileupWeight offlineWeight *= bjetWeight offlineWeight_forLeptonEta = offlineWeight genWeight *= topPtSystematicWeight # Generator weight # Scale up/down, pdf if pdfWeight >= 0: genWeight *= branch('pdfWeight_%i' % pdfWeight) pass if MMHT14Weight >= 0: genWeight *= branch('MMHT14Weight_%i' % MMHT14Weight) pass if CT14Weight >= 0: genWeight *= branch('CT14Weight_%i' % CT14Weight) pass if muFmuRWeight >= 0: genWeight *= branch('muFmuRWeight_%i' % muFmuRWeight) pass if alphaSWeight == 0 or alphaSWeight == 1: genWeight *= branch('alphaSWeight_%i' % alphaSWeight) pass if semiLepBrWeight == -1: genWeight *= branch('semilepbrDown') elif semiLepBrWeight == 1: genWeight *= branch('semilepbrUp') pass if fragWeight == 1: genWeight *= branch('downFrag') elif fragWeight == 2: genWeight *= branch('centralFrag') elif fragWeight == 3: genWeight *= branch('upFrag') elif fragWeight == 4: genWeight *= branch('petersonFrag') pass if args.applyTopPtReweighting != 0: ptWeight = calculateTopPtWeight(branch('lepTopPt_parton'), branch('hadTopPt_parton'), args.applyTopPtReweighting) genWeight *= ptWeight if args.applyTopEtaReweighting != 0: etaWeight = calculateTopEtaWeight(branch('lepTopRap_parton'), branch('hadTopRap_parton'), args.applyTopEtaReweighting) genWeight *= etaWeight for channel in channels: # Generator level selection genSelection = '' genSelectionVis = '' if channel.channelName is 'muPlusJets': genSelection = event.isSemiLeptonicMuon == 1 genSelectionVis = event.passesGenEventSelection == 1 and event.pseudoLepton_pdgId == 13 if args.newPS: genSelectionVis = event.passesGenEventSelection_20GeVLastJet == 1 and event.pseudoLepton_pdgId == 13 elif channel.channelName is 'ePlusJets': genSelection = event.isSemiLeptonicElectron == 1 genSelectionVis = event.passesGenEventSelection == 1 and event.pseudoLepton_pdgId == 11 if args.newPS: genSelectionVis = event.passesGenEventSelection_20GeVLastJet == 1 and event.pseudoLepton_pdgId == 11 # Lepton weight # Channel specific leptonWeight = 1 leptonWeight_forLeptonEta = 1 if channel.channelName is 'muPlusJets': leptonWeight = event.MuonEfficiencyCorrection leptonWeight_forLeptonEta = event.MuonEfficiencyCorrection_etaBins if args.sample == 'muonup': leptonWeight = event.MuonEfficiencyCorrectionUp leptonWeight_forLeptonEta = event.MuonEfficiencyCorrectionUp_etaBins elif args.sample == 'muondown': leptonWeight = event.MuonEfficiencyCorrectionDown leptonWeight_forLeptonEta = event.MuonEfficiencyCorrectionDown_etaBins elif channel.channelName is 'ePlusJets': leptonWeight = event.ElectronEfficiencyCorrection leptonWeight_forLeptonEta = event.ElectronEfficiencyCorrection_etaBins if args.sample == 'electronup': leptonWeight = event.ElectronEfficiencyCorrectionUp leptonWeight_forLeptonEta = event.ElectronEfficiencyCorrectionUp_etaBins elif args.sample == 'electrondown': leptonWeight = event.ElectronEfficiencyCorrectionDown leptonWeight_forLeptonEta = event.ElectronEfficiencyCorrectionDown_etaBins offlineWeight_withLeptonWeight = offlineWeight * leptonWeight offlineWeight_withLeptonWeight_forLeptonEta = offlineWeight_forLeptonEta * leptonWeight_forLeptonEta # Offline level selection offlineSelection = 0 if channel.channelName is 'muPlusJets': offlineSelection = int(event.passSelection) == 1 elif channel.channelName is 'ePlusJets': offlineSelection = int(event.passSelection) == 2 # Fake selection fakeSelection = offlineSelection and not genSelection fakeSelectionVis = offlineSelection and not genSelectionVis # Phase space info if genSelection: nFull[channel.channelName] += genWeight if offlineSelection: nOfflineSL[channel.channelName] += genWeight if genSelectionVis: nPassGenSelection += 1 nVis[channel.channelName] += genWeight if not offlineSelection: nVisNotOffline[channel.channelName] += genWeight if offlineSelection: nOffline[channel.channelName] += offlineWeight * genWeight if not genSelectionVis: nOfflineNotVis[ channel.channelName] += offlineWeight * genWeight for variable in allVariablesBins: if args.debug and variable != 'HT': continue if args.sample in measurement_config.met_specific_systematics and \ variable in measurement_config.variables_no_met: continue offlineWeight_toUse = offlineWeight_withLeptonWeight if 'abs_lepton_eta' in variable: offlineWeight_toUse = offlineWeight_withLeptonWeight_forLeptonEta # # # # # # Variable to plot # # # recoVariable = branch(recoVariableNames[variable]) if variable in ['MET', 'ST', 'WPT'] and \ sysIndex != None and ( offlineSelection or fakeSelection or fakeSelectionVis ) : recoVariable = recoVariable[sysIndex] if 'abs' in variable: recoVariable = abs(recoVariable) # With TUnfold, reco variable never goes in the overflow (or underflow) if not args.fineBinned: recoVariable = min( recoVariable, allVariablesBins[variable][-1] - 0.000001) genVariable_particle = branch( genVariable_particle_names[variable]) if 'abs' in variable: genVariable_particle = abs(genVariable_particle) # # # # Fill histograms # # histogramsToFill = histograms[variable][ channel.channelName] if not args.donothing: if genSelection: histogramsToFill['truth'].Fill( genVariable_particle, genWeight) if genSelectionVis: filledTruth = True histogramsToFill['truthVis'].Fill( genVariable_particle, genWeight) histogramsToFill['truthVis_noWeight'].Fill( genVariable_particle, 1) if offlineSelection: histogramsToFill['measured'].Fill( recoVariable, offlineWeight_toUse * genWeight) histogramsToFill['measuredVis'].Fill( recoVariable, offlineWeight_toUse * genWeight) if genSelectionVis: histogramsToFill[ 'measuredVis_without_fakes'].Fill( recoVariable, offlineWeight_toUse * genWeight) if genSelection: histogramsToFill[ 'measured_without_fakes'].Fill( recoVariable, offlineWeight_toUse * genWeight) histogramsToFill['response'].Fill( recoVariable, genVariable_particle, offlineWeight_toUse * genWeight) if offlineSelection and genSelection: histogramsToFill['response_without_fakes'].Fill( recoVariable, genVariable_particle, offlineWeight_toUse * genWeight) histogramsToFill['response_without_fakes'].Fill( allVariablesBins[variable][0] - 1, genVariable_particle, (1 - offlineWeight_toUse) * genWeight) elif genSelection: histogramsToFill['response_without_fakes'].Fill( allVariablesBins[variable][0] - 1, genVariable_particle, genWeight) if offlineSelection and genSelectionVis: histogramsToFill['responseVis_without_fakes'].Fill( recoVariable, genVariable_particle, offlineWeight_toUse * genWeight) histogramsToFill['responseVis_without_fakes'].Fill( allVariablesBins[variable][0] - 1, genVariable_particle, (1 - offlineWeight_toUse) * genWeight) filledResponse = True elif genSelectionVis: histogramsToFill['responseVis_without_fakes'].Fill( allVariablesBins[variable][0] - 1, genVariable_particle, genWeight) filledResponse = True if fakeSelection: histogramsToFill['fake'].Fill( recoVariable, offlineWeight_toUse * genWeight) if fakeSelectionVis: histogramsToFill['fakeVis'].Fill( recoVariable, offlineWeight_toUse * genWeight) if args.extraHists: if genSelectionVis: histogramsToFill['eventWeightHist'].Fill( event.EventWeight) histogramsToFill['genWeightHist'].Fill( genWeight) histogramsToFill['offlineWeightHist'].Fill( offlineWeight_toUse) if args.fineBinned: # Bin reco var is in options = residual_options[variable][ channel.channelName] if offlineSelection and genSelection: # i will be fine bin number the reco var resides in for i, edge in enumerate(options['bin_edges']): if recoVariable > edge: continue else: break residual = abs(recoVariable - genVariable_particle) if not residual > options['max'] * 0.1: residuals[variable][ channel.channelName][i].Fill( residual, offlineWeight_toUse * genWeight) # # Output histgorams to file # for variable in allVariablesBins: if args.debug and variable != 'HT': continue if args.sample in measurement_config.met_systematics and variable not in [ 'MET', 'ST', 'WPT' ]: continue for channel in channels: if nOffline[channel.channelName] != 0: # Fill phase space info h = histograms[variable][ channel.channelName]['phaseSpaceInfoHist'] h.SetBinContent( 1, nVisNotOffline[channel.channelName] / nVis[channel.channelName]) # h.GetXaxis().SetBinLabel(1, "nVisNotOffline/nVis") h.SetBinContent( 2, nOfflineNotVis[channel.channelName] / nOffline[channel.channelName]) # h.GetXaxis().SetBinLabel(2, "nOfflineNotVis/nOffline") h.SetBinContent( 3, nVis[channel.channelName] / nFull[channel.channelName]) # h.GetXaxis().SetBinLabel(3, "nVis/nFull") # Selection efficiency for SL ttbar h.SetBinContent( 4, nOfflineSL[channel.channelName] / nFull[channel.channelName]) # h.GetXaxis().SetBinLabel(4, "nOfflineSL/nFull") # Fraction of offline that are SL h.SetBinContent( 5, nOfflineSL[channel.channelName] / nOffline[channel.channelName]) # h.GetXaxis().SetBinLabel(5, "nOfflineSL/nOffline") outputDirs[variable][channel.channelName].cd() for h in histograms[variable][channel.channelName]: histograms[variable][channel.channelName][h].Write() if args.fineBinned: outputDirsRes[variable][channel.channelName].cd() for r in residuals[variable][channel.channelName]: residuals[variable][channel.channelName][r].Write() print 'N events passing gen selection : ', nPassGenSelection with root_open(outputFileName, 'update') as out: # Done all channels, now combine the two channels, and output to the same file for path, dirs, objects in out.walk(): if 'electron' in path: if 'coarse' in path: continue outputDir = out.mkdir(path.replace('electron', 'combined')) outputDir.cd() for h in objects: h_e = out.Get(path + '/' + h) h_mu = out.Get(path.replace('electron', 'muon') + '/' + h) h_comb = (h_e + h_mu).Clone(h) h_comb.Write() pass pass pass