def buildMuonRates(inputFiles, outputfile, outplotdir, inputFracFile=None, verbose=False, zoomIn=False) :
    """
    For each selection region, build the real eff and fake rate
    histo as a weighted sum of the corresponding fractions.
    """
    processes = fakeProcesses()
    brsit, iF, v = buildRatioAndScaleIt, inputFiles, verbose
    print "buildMuonRates: values to be fixed: ",' '.join(["%s: %s"%(_, eval(_)) for _ in ['mu_qcdSF', 'mu_realSF']])
    eff_qcd  = dict((p, brsit('muon_qcdMC_all_l_pt_coarse',  iF[p], mu_qcdSF, v))  for p in processes)
    eff_real = dict((p, brsit('muon_realMC_all_l_pt_coarse', iF[p], mu_realSF, v)) for p in processes)
    eff2d_qcd  = dict((p, brsit('muon_qcdMC_all_l_pt_eta',  iF[p], mu_qcdSF, v))  for p in processes)
    eff2d_real = dict((p, brsit('muon_realMC_all_l_pt_eta', iF[p], mu_realSF, v)) for p in processes)
    lT, lX, lY = '#varepsilon(T|L)', 'p_{T} [GeV]', '#varepsilon(T|L)'
    plot1dEfficiencies(eff_qcd,  'eff_mu_qcd',  outplotdir, lT+' qcd fake #mu'+';'+lX+';'+lY, zoomIn=zoomIn)
    plot1dEfficiencies(eff_real, 'eff_mu_real', outplotdir, lT+' real #mu'    +';'+lX+';'+lY, zoomIn=zoomIn)
    lT, lX, lY = '#varepsilon(T|L)', 'p_{T} [GeV]', '#eta'
    plot2dEfficiencies(eff2d_qcd,  'eff2d_mu_qcd', outplotdir, lT+' qcd fake #mu'+';'+lX+';'+lY)
    plot2dEfficiencies(eff2d_real, 'eff2d_mu_real', outplotdir, lT+' real #mu'   +';'+lX+';'+lY)
    mu_frac = dict()
    for sr in selectionRegions() :
        fC, bP = fetchCompositions, buildPercentages
        isf = inputFracFile
        hnTemplateQcd = '%(proc)s_muon_'+sr+'_all_flavor_pt_den_qcd'
        hnTemplateReal = '%(proc)s_muon_'+sr+'_all_flavor_pt_den_real'
        frac_qcd  = fC(isf, hnTemplateQcd,  processes) if isf else bP(inputFiles, 'muon_'+sr+'_all_flavor_den', 'qcd')
        frac_real = fC(isf, hnTemplateReal, processes) if isf else bP(inputFiles, 'muon_'+sr+'_all_flavor_den', 'real')
        if verbose : print "mu : sr ",sr,"\n frac_qcd  : ",frac2str(frac_qcd )
        if verbose : print "mu : sr ",sr,"\n frac_real : ",frac2str(frac_real)
        fake1d = buildWeightedHisto(eff_qcd,  frac_qcd, 'mu_fake_rate_'+sr, 'Muon fake rate '+sr)
        real1d = buildWeightedHisto(eff_real, frac_real, 'mu_real_eff_'+sr, 'Muon real eff ' +sr)

        c2dC = compose2Dcompositions
        hnTemplateQcd = '%(proc)s_muon_'+sr+'_all_flavor_pt_%(etabin)s_den_qcd'
        hnTemplateReal = '%(proc)s_muon_'+sr+'_all_flavor_pt_%(etabin)s_den_real'
        frac_qcd2d  = c2dC(isf, hnTemplateQcd,  processes) if isf else frac_qcd
        frac_real2d = c2dC(isf, hnTemplateReal, processes) if isf else frac_real
        fake2d = buildWeightedHisto(eff2d_qcd,  frac_qcd2d, 'mu_fake_rate2d_'+sr, 'Muon fake rate #eta vs. p_{T}'+sr)
        real2d = buildWeightedHisto(eff2d_real, frac_real2d, 'mu_real_eff2d_'+sr, 'Muon real eff  #eta vs. p_{T}'+sr)

        outputfile.cd()
        fake1d.Write()
        real1d.Write()
        fake2d.Write()
        real2d.Write()
        mu_frac[sr] = {'qcd' : frac_qcd, 'real' : frac_real}
        if isRegionToBePlotted(sr) :
            print "plotting eff2d_mu_fake:"
            fake2d.Print('all')
            print "plotting eff2d_mu_real"
            real2d.Print('all')
            lT, lX, lY = '#varepsilon(T|L)', 'p_{T} [GeV]', '#eta'
            plot2dEfficiencies({sr : fake2d}, 'eff2d_mu_fake', outplotdir, lT+' fake #mu'+';'+lX+';'+lY)
            plot2dEfficiencies({sr : real2d}, 'eff2d_mu_real', outplotdir, lT+' real #mu'+';'+lX+';'+lY)
    #json_write(mu_frac, outplotdir+/outFracFilename)
    doPlotFractions = not inputFracFile
    if doPlotFractions : plotFractions(mu_frac, outplotdir, 'frac_mu')
def main():
    parser = optparse.OptionParser(usage=usage)
    parser.add_option('-i', '--input-dir', default='./out/fakerate')
    parser.add_option('-o', '--output-dir', default='./out/fakerate/efficiencies')
    parser.add_option('-l', '--lepton', default='el', help='either el or mu')
    parser.add_option('-m', '--mode', help='real, conv, hflf')
    parser.add_option('-t', '--tag', help='tag used to select the input files (e.g. Apr_04)')
    parser.add_option('-f', '--fill-histos', action='store_true', default=False, help='force fill (default only if needed)')
    parser.add_option('-T', '--tight-def', help='on-the-fly tight def, one of defs in fakeUtils.py: fakeu.lepIsTight_std, etc.')
    parser.add_option('-v', '--verbose', action='store_true', default=False)
    (options, args) = parser.parse_args()
    inputDir  = options.input_dir
    outputDir = options.output_dir
    lepton    = options.lepton
    mode      = options.mode
    tag       = options.tag
    verbose   = options.verbose
    if not tag : parser.error('tag is a required option')
    if lepton not in ['el', 'mu'] : parser.error("invalid lepton '%s'"%lepton)
    validModesEl = ['real', 'hflf'] + ['conv']
    validModesMu = ['real', 'hflf']
    if mode not in (validModesEl if lepton=='el' else validModesMu) : parser.error("invalid mode %s"%mode)
    tupleStem, treeName = {'conv' : ('mcconv_tuple', 'ConversionExtractionRegion'),
                           'hflf' : ('mcqcd_tuple', 'HfLfExtractionRegion'),
                           'real' : ('mcreal_tuple', 'RealExtractionRegion')
                           }[mode]
    templateInputFilename = "*_%(stem)s_%(tag)s.root" % {'tag':tag, 'stem':tupleStem}
    templateOutputFilename =  "%(stem)s_%(l)s_eff.root" % {'stem':tupleStem.replace('tuple','histos'), 'l':lepton}
    outputFileName = os.path.join(outputDir, templateOutputFilename)
    cacheFileName = outputFileName.replace('.root', '_'+mode+'_cache.root')
    doFillHistograms = options.fill_histos or not os.path.exists(cacheFileName)
    onthefly_tight_def = eval(options.tight_def) if options.tight_def else None # eval will take care of aborting on typos
    optionsToPrint = ['inputDir', 'outputDir', 'mode', 'tag', 'doFillHistograms', 'cacheFileName', 'onthefly_tight_def']
    if verbose :
        print "working from %s"%os.getcwd()
        print "being called as : %s"%' '.join(os.sys.argv)
        print "options parsed:\n"+'\n'.join(["%s : %s"%(o, eval(o)) for o in optionsToPrint])
    # collect inputs
    print 'input filenames: ',os.path.join(inputDir, templateInputFilename)

    tupleFilenames = glob.glob(os.path.join(inputDir, templateInputFilename))
    samples = setSameGroupForAllData(fastSamplesFromFilenames(tupleFilenames, verbose))
    samplesPerGroup = collections.defaultdict(list)
    filenamesPerGroup = collections.defaultdict(list)
    mkdirIfNeeded(outputDir)
    for s, f in zip(samples, tupleFilenames) :
        samplesPerGroup[s.group].append(s)
        filenamesPerGroup[s.group].append(f)
    vars = ['pt', 'pt_eta']
    groups = [g for g in samplesPerGroup.keys() if not isDataSample(g) and not g=='higgs']
    if lepton=='el' : groups = [g for g in groups if g!='heavyflavor']

    sourcesThisMode = {'real' : ['real'], # use same convention as in FakeLeptonSources.h
                       'conv' : ['conv'],
                       'hflf' : ['heavy', 'light', 'qcd']
                       }[mode]
    #fill histos
    if doFillHistograms :
        start_time = time.clock()
        num_processed_entries = 0
        histosPerGroupPerSource = bookHistosPerSamplePerSource(vars, groups, sourcesThisMode, mode=mode)
        for group in groups:
            filenames = filenamesPerGroup[group]
            histosThisGroupPerSource = dict((v, histosPerGroupPerSource[v][group]) for v in histosPerGroupPerSource.keys())
            histosAnyGroupPerSource  = dict((v, histosPerGroupPerSource[v]['anygroup']) for v in histosPerGroupPerSource.keys())

            chain = r.TChain(treeName)
            [chain.Add(fn) for fn in filenames]
            if verbose: print "%s : %d entries"%(group, chain.GetEntries())
            num_processed_entries += fillHistos(chain, histosThisGroupPerSource, histosAnyGroupPerSource,
                                                lepton, mode,
                                                onthefly_tight_def=onthefly_tight_def, verbose=verbose)
        writeHistos(cacheFileName, histosPerGroupPerSource, verbose)
        end_time = time.clock()
        delta_time = end_time - start_time
        if verbose:
            print ("processed {0:d} entries ".format(num_processed_entries)
                   +"in "+("{0:d} min ".format(int(delta_time/60)) if delta_time>60 else
                           "{0:.1f} s ".format(delta_time))
                   +"({0:.1f} kHz)".format(num_processed_entries/delta_time))
    # compute efficiencies
    histosPerGroupPerSource = fetchHistos(cacheFileName, histoNamesPerSamplePerSource(vars, groups, sourcesThisMode, mode), verbose)
    effs = computeEfficiencies(histosPerGroupPerSource) # still [var][gr][source][l/t]
    for s in sourcesThisMode:
        for v in vars:
            groups = first(effs).keys()
            varIs1D, varIs2D = v=='pt', v=='pt_eta'
            effsThisSourceThisVar = dict((g, effs[v][g][s]) for g in groups)
            densThisSourceThisVar = dict((g, histosPerGroupPerSource[v][g][s]['loose']) for g in groups if g!='anygroup')
            numsThisSourceThisVar = dict((g, histosPerGroupPerSource[v][g][s]['tight']) for g in groups if g!='anygroup')
            if varIs1D:
                cname = 'eff_'+lepton+'_'+s
                lT, lX, lY = '#varepsilon(T|L)', 'p_{T} [GeV]', '#varepsilon(T|L)'
                title = lT+' '+s+' '+lepton+';'+lX+';'+lY
                zoomIn = True
                fakeu.plot1dEfficiencies(effsThisSourceThisVar, cname, outputDir, title, zoomIn)
                cname = 'stack_loose_'+lepton+'_'+s
                lT, lY = 'loose '+lepton+', denominator to #varepsilon(T|L)', '#varepsilon(T|L)'
                title = lT+' '+s+' '+lepton+';'+lX+';'+lY
                plotParametrizedFractions.plotStackedHistos(densThisSourceThisVar, cname, outputDir, title)
                cname = 'stack_tight_'+lepton+'_'+s
                lT, lY = 'tight '+lepton+', numerator to #varepsilon(T|L)', '#varepsilon(T|L)'
                title = lT+' '+s+' '+lepton+';'+lX+';'+lY
                plotParametrizedFractions.plotStackedHistos(numsThisSourceThisVar, cname, outputDir, title)

            elif varIs2D:
                cname = 'eff_'+lepton+'_'+s
                lT, lX, lY = '#varepsilon(T|L)', 'p_{T} [GeV]', '#eta'
                title = lT+' '+s+' '+lepton+';'+lX+';'+lY
                fakeu.plot2dEfficiencies(effsThisSourceThisVar, cname, outputDir, title, zoomIn=zoomIn)
    writeHistos(outputFileName, effs, verbose)
    if verbose : print "saved scale factors to %s" % outputFileName
def main():
    parser = optparse.OptionParser(usage=usage)
    parser.add_option('-i', '--input-dir', default='./out/fakerate')
    parser.add_option('-c', '--comp-histos', help='output from compute_fake_compositions.py')
    parser.add_option('-e', '--eff-histos', default=[], action='append', help='output files from compute_eff_from_ntuple.py')
    parser.add_option('-r', '--region', help='where we have the compositions, and want the fake matrix, e.g. ssinc1j, emu')
    parser.add_option('-s', '--scale-factors', default=[], action='append', help='bin-by-bin data/mc from compute_fake_scale_factor')
    parser.add_option('-o', '--output-dir', default='./out/fake_weighted_average', help='dir for plots')
    parser.add_option('-l', '--lepton', default='el', help='either el or mu')
    parser.add_option('-f', '--fill-histos', action='store_true', default=False, help='force fill (default only if needed)')
    parser.add_option('--also-anygroup', action='store_true', help='also build matrix without compositions,'                      ' to evaluate the systematic uncertainty on the composition')
    parser.add_option('-v', '--verbose', action='store_true', default=False)
    (options, args) = parser.parse_args()
    inputDir  = options.input_dir
    compFname = options.comp_histos
    effFnames = options.eff_histos
    region    = options.region
    sfFnames  = options.scale_factors
    outputDir = options.output_dir
    lepton    = options.lepton
    verbose   = options.verbose
    if lepton not in ['el', 'mu'] : parser.error("invalid lepton '%s'"%lepton)
    if region not in ['emu', 'ssinc', 'ssinc1j','razor0j'] : parser.error("invalid region '%s'"%region)
    if not compFname or not os.path.exists(compFname) : parser.error("invalid composition file '%s'"%compFname)
    if not effFnames or not all(os.path.exists(f) for f in effFnames) : parser.error("invalid efficiency file '%s'"%str(effFnames))
    if not sfFnames  or not all(os.path.exists(f) for f in sfFnames) :
        # parser.error("invalid electron sf file(s) %s"%str(sfFnames))
        print "missing sf files, using flat scale factors"# do not crash, fall back on flat scale factors
    optionsToPrint = ['inputDir', 'outputDir']
    if verbose :
        print "working from %s"%os.getcwd()
        print "being called as : %s"%' '.join(os.sys.argv)
        print "options parsed:\n"+'\n'.join(["%s : %s"%(o, eval(o)) for o in optionsToPrint])
    mkdirIfNeeded(outputDir)
    # collect inputs
    regions = [region, ]
    groups=['diboson', 'heavyflavor', 'ttbar', 'wjets', 'zjets']
    if lepton=='el' : groups = filter(lambda _ : _!='heavyflavor', groups) # note this must be in sync with compute_fake_compositions; TODO: implement a way to get the groups from the available histos
    compositions = fetchCompositionHistos(compFname, lepton, groups, regions, verbose) # [var][group][reg][orig], note here orig=[conv,heavy,light]
    # pprint.pprint(compositions)
    efficiencies = fetchEffienciesHistos(effFnames, lepton, groups, verbose) # [var][group][orig], note here orig=[conv,heavy,light,qcd]
    # pprint.pprint(efficiencies)
    scale_factor_histos = fetchSfHistos(sfFnames, lepton, verbose)
    convSF_vs_eta = scale_factor_histos['conv'] if lepton=='el' else None
    qcdSF_vs_eta  = scale_factor_histos['hflf'] if 'hflf' in scale_factor_histos else None
    # if verbose:
    #     print "convSF: "+("vs. eta {0}".format(getBinContents(convSF_vs_eta)) if convSF_vs_eta else el_convSF)
    #     print "qcdSF: "+("vs. eta {0}".format(getBinContents(qcdSF_vs_eta)) if qcdSF_vs_eta else el_qcdSF)
    def scale_factor_to_str(sf):
        if 'vs_eta' in sf: return '['+', '.join("%.3f" % _ for _ in sf['vs_eta'])+']'
        else : return "%.3f" % sf['flat']
    if lepton=='el':
        scaleFactors = {'conv' : {'flat' : el_convSF, 'vs_eta' : convSF_vs_eta},
                        'heavy' : {'flat' : el_qcdSF, 'vs_eta' : qcdSF_vs_eta} }
        if verbose : print_scale_factor_dict(scaleFactors)
        scaleFakeEfficiencies(efficiencies, scaleFactors)
    elif lepton=='mu':
        scaleFactors = {'heavy' : {'flat' : mu_qcdSF, 'vs_eta' : qcdSF_vs_eta} }
        if verbose : print_scale_factor_dict(scaleFactors)
        scaleFakeEfficiencies(efficiencies, scaleFactors)

    # for now compute the weighted avg only for 'ssinc1j'
    avgEfficiencies = dict()
    for reg in first(first(compositions)).keys():
        avgEfficiencies[reg] = dict()
        for var in ['pt', 'pt_eta']:
            is1D = var=='pt'
            lT = "%s #varepsilon(T|L) fake %s"%(reg, lepton)
            lX = 'p_{T} [GeV]'
            lY = '#varepsilon(T|L)' if is1D else '#eta'
            hname = "%(lep)s_fake_%(var)s_%(reg)s"%{'lep':lepton, 'var':var, 'reg':reg}
            htitle = lT+';'+lX+';'+lY
            groups  = first(compositions).keys()
            origins = first(first(first(compositions))).keys()
            if verbose : print 'origins :',origins,'\n' + 'groups :',groups
            histosEff  = dict((group+'_'+orig, efficiencies[var][group]     [orig]) for group in groups for orig in origins)
            histosComp = dict((group+'_'+orig, compositions[var][group][reg][orig]) for group in groups for orig in origins)
            avgEff =  weightedAverage(histosEff, histosComp, hname, htitle, verbose)
            avgEfficiencies[reg][var] = avgEff
            if is1D:
                fakeu.plot1dEfficiencies({reg : avgEff}, 'eff1d_'+lepton+'_fake_'+reg, outputDir, htitle, zoomIn=True)
            else:
                fakeu.plot2dEfficiencies({reg : avgEff}, 'eff2d_'+lepton+'_fake_'+reg, outputDir, htitle, zoomIn=True)
    writeHistos(os.path.join(outputDir,'fake_matrices_'+lepton+'.root'), avgEfficiencies, verbose)
    if options.also_anygroup:# test with the group-independent efficiencies
	print 'fetchCompositionHistos ',compFname
	compositions = fetchCompositionHistos(compFname, lepton, ['anygroup'], verbose)
	pprint.pprint(compositions)
	print 'fetchEffienciesHistos ',effFnames
	efficiencies = fetchEffienciesHistos(effFnames, lepton, ['anygroup'], verbose)
	avgEfficiencies = dict()
	for reg in first(first(compositions)).keys():
	    avgEfficiencies[reg] = dict()
	    for var in ['pt', 'pt_eta']:
	        is1D = var=='pt'
	        lT = "%s #varepsilon(T|L) fake %s"%(reg, lepton)
	        lX = 'p_{T} [GeV]'
	        lY = '#varepsilon(T|L)' if is1D else '#eta'
	        hname = "%(lep)s_fake_%(var)s_%(reg)s"%{'lep':lepton, 'var':var, 'reg':reg}
	        htitle = lT+';'+lX+';'+lY
	        groups  = first(compositions).keys()
	        origins = first(first(first(compositions))).keys()
	        if verbose : print 'origins :',origins,'\n' + 'groups :',groups
	        histosEff  = dict((group+'_'+orig, efficiencies[var][group]     [orig])
                                  for group in groups for orig in origins)
	        histosComp = dict((group+'_'+orig, compositions[var][group][reg][orig])
                                  for group in groups for orig in origins)
	        avgEff =  weightedAverage(histosEff, histosComp, hname, htitle, verbose)
	        avgEfficiencies[reg][var] = avgEff
	        if is1D:
	            fakeu.plot1dEfficiencies({reg : avgEff}, 'eff1d_'+lepton+'_fake_'+reg+'_anygroup',
                                             outputDir, htitle, zoomIn=True)
	        else:
	            fakeu.plot2dEfficiencies({reg : avgEff}, 'eff2d_'+lepton+'_fake_'+reg+'_anygroup',
                                             outputDir, htitle, zoomIn=True)
	writeHistos(os.path.join(outputDir,'fake_matrices_'+lepton+'_anygroup.root'),
                    avgEfficiencies, verbose)
def buildElectronRates(inputFiles, outputfile, outplotdir, inputFracFile=None, inputElecSfFiles=[], verbose=False, zoomIn=False) :
    """
    For each selection region, build the real eff and fake rate
    histo as a weighted sum of the corresponding fractions.
    Note that the fake has two components (conversion and qcd).
    """
    processes = fakeProcesses()
    brsit, iF, v = buildRatioAndScaleIt, inputFiles, verbose
    # if we have the sf vs eta, use it in the 2d parametrization
    lepton = 'el'
    el_convSF_vs_eta = el_convSF if not inputElecSfFiles else fetchSfHistos(inputElecSfFiles, lepton, verbose)['conv']
    el_qcdSF_vs_eta  = el_qcdSF if not inputElecSfFiles else fetchSfHistos(inputElecSfFiles,  lepton, verbose)['hflf']
    if inputElecSfFiles : el_convSF_vs_eta.Print("all")
    if inputElecSfFiles : el_qcdSF_vs_eta.Print("all")

    eff_conv = dict((p, brsit('elec_convMC_all_l_pt_coarse', iF[p], el_convSF, v)) for p in processes)
    eff_qcd  = dict((p, brsit('elec_qcdMC_all_l_pt_coarse',  iF[p], el_qcdSF, v))  for p in processes)
    eff_real = dict((p, brsit('elec_realMC_all_l_pt_coarse', iF[p], el_realSF, v)) for p in processes)
    eff2d_conv = dict((p, brsit('elec_convMC_all_l_pt_eta', iF[p], el_convSF_vs_eta, v)) for p in processes)
    eff2d_qcd  = dict((p, brsit('elec_qcdMC_all_l_pt_eta',  iF[p], el_qcdSF_vs_eta, v))  for p in processes)
    eff2d_real = dict((p, brsit('elec_realMC_all_l_pt_eta', iF[p], el_realSF, v)) for p in processes)

    lT, lX, lY = '#varepsilon(T|L)', 'p_{T} [GeV]', '#varepsilon(T|L)'
    plot1dEfficiencies(eff_conv, 'eff_el_conv', outplotdir, lT+' conv fake el'+';'+lX+';'+lY, zoomIn=zoomIn)
    plot1dEfficiencies(eff_qcd,  'eff_el_qcd',  outplotdir, lT+' qcd fake el' +';'+lX+';'+lY, zoomIn=zoomIn)
    plot1dEfficiencies(eff_real, 'eff_el_real', outplotdir, lT+' real el'     +';'+lX+';'+lY, zoomIn=zoomIn)
    lT, lX, lY = '#varepsilon(T|L)', 'p_{T} [GeV]', '#eta'
    plot2dEfficiencies(eff2d_conv, 'eff2d_el_conv', outplotdir, lT+' conv fake el'+';'+lX+';'+lY)
    plot2dEfficiencies(eff2d_qcd,  'eff2d_el_qcd',  outplotdir, lT+' qcd fake el' +';'+lX+';'+lY)
    plot2dEfficiencies(eff2d_real, 'eff2d_el_real', outplotdir, lT+' real el'     +';'+lX+';'+lY)

    el_frac = dict()
    for sr in selectionRegions() :
        fC, bPt = fetchCompositions, buildPercentagesTwice
        isf = inputFracFile
        hnTemplateQcd  = '%(proc)s_elec_'+sr+'_all_flavor_pt_den_qcd'
        hnTemplateConv = '%(proc)s_elec_'+sr+'_all_flavor_pt_den_conv'
        hnTemplateReal = '%(proc)s_elec_'+sr+'_all_flavor_pt_den_real'
        frac_conv, frac_qcd= (fC(isf, hnTemplateConv,  processes), fC(isf, hnTemplateQcd,  processes)) if isf else bPt(inputFiles, 'elec_'+sr+'_all_flavor_den', 'conv', 'qcd')
        frac_real = fC(isf, hnTemplateReal, processes) if isf else buildPercentages(inputFiles, 'elec_'+sr+'_all_flavor_den', 'real')
        if verbose : print "el : sr ",sr,"\n frac_conv : ",frac2str(frac_conv)
        if verbose : print "el : sr ",sr,"\n frac_qcd  : ",frac2str(frac_qcd )
        if verbose : print "el : sr ",sr,"\n frac_real : ",frac2str(frac_real)
        real1d = buildWeightedHisto     (eff_real, frac_real,                     'el_real_eff_'+sr, 'Electron real eff '+sr)
        fake1d = buildWeightedHistoTwice(eff_conv, frac_conv, eff_qcd,  frac_qcd, 'el_fake_rate_'+sr, 'Electron fake rate '+sr)

        c2dC = compose2Dcompositions
        hnTemplateQcd  = '%(proc)s_elec_'+sr+'_all_flavor_pt_%(etabin)s_den_qcd'
        hnTemplateConv = '%(proc)s_elec_'+sr+'_all_flavor_pt_%(etabin)s_den_conv'
        hnTemplateReal = '%(proc)s_elec_'+sr+'_all_flavor_pt_%(etabin)s_den_real'
        frac_qcd2d  = c2dC(isf, hnTemplateQcd,  processes) if isf else frac_qcd
        frac_conv2d = c2dC(isf, hnTemplateConv, processes) if isf else frac_conv
        frac_real2d = c2dC(isf, hnTemplateReal, processes) if isf else frac_real
        real2d = buildWeightedHisto     (eff2d_real, frac_real2d,                     'el_real_eff2d_'+sr, 'Electron real eff  #eta vs. p_{T}'+sr)
        fake2d = buildWeightedHistoTwice(eff2d_conv, frac_conv2d, eff2d_qcd,  frac_qcd2d, 'el_fake_rate2d_'+sr, 'Electron fake rate  #eta vs. p_{T}'+sr)

        outputfile.cd()
        fake1d.Write()
        real1d.Write()
        fake2d.Write()
        real2d.Write()
        el_frac[sr] = {'conv' : frac_conv, 'qcd' : frac_qcd, 'real' : frac_real}
        if isRegionToBePlotted(sr) :
            lT, lX, lY = '#varepsilon(T|L)', 'p_{T} [GeV]', '#eta'
            plot2dEfficiencies({sr : fake2d}, 'eff2d_el_fake', outplotdir, lT+' fake e'+';'+lX+';'+lY)
            plot2dEfficiencies({sr : real2d}, 'eff2d_el_real', outplotdir, lT+' real e'+';'+lX+';'+lY)
    #json_write(el_frac, outFracFilename)
    doPlotFractions = not inputFracFile
    if doPlotFractions : plotFractions(el_frac, outplotdir, 'frac_el')