Beispiel #1
0
        for control_region in regions:
            # Fit variables (inclusive)
            for var in ['M3', 'angle_bl', 'M_bl', 'absolute_eta']:
                print channel, var
                controlTree = 'TTbar_plus_X_analysis/%s/%s/FitVariables' % (
                    channel, control_region)

                bins = fit_variable_bin_edges[var]
                xMin = bins[0]
                xMax = bins[-1]
                nBins = len(bins) - 1

                histograms = get_histograms_from_trees(
                    trees=[controlTree],
                    branch=var,
                    weightBranch='EventWeight',
                    files=histogram_files,
                    nBins=nBins,
                    xMin=xMin,
                    xMax=xMax)

                prepare_histograms(
                    histograms,
                    rebin=1,
                    scale_factor=measurement_config.luminosity_scale)

                histograms_to_draw = [
                    histograms['data'][controlTree],
                    histograms['QCD'][controlTree],
                    histograms['V+Jets'][controlTree],
                    histograms['SingleTop'][controlTree],
                    histograms['TTJet'][controlTree]
def make_ttbarReco_plot( channel, x_axis_title, y_axis_title,
              signal_region_tree,
              control_region_tree,
              branchName,
              name_prefix, x_limits, nBins,
              use_qcd_data_region = False,
              y_limits = [],
              y_max_scale = 1.2,
              rebin = 1,
              legend_location = ( 0.98, 0.78 ), cms_logo_location = 'right',
              log_y = False,
              legend_color = False,
              ratio_y_limits = [0.3, 1.7],
              normalise = False,
              ):
    global output_folder, measurement_config, category, normalise_to_fit
    global preliminary, norm_variable, sum_bins, b_tag_bin, histogram_files

    # Input files, normalisations, tree/region names
    qcd_data_region = ''
    title = title_template % ( measurement_config.new_luminosity / 1000., measurement_config.centre_of_mass_energy )
    normalisation = None
    if channel == 'electron':
        histogram_files['data'] = measurement_config.data_file_electron_trees
        histogram_files['QCD'] = measurement_config.electron_QCD_MC_category_templates_trees[category]
        if normalise_to_fit:
            normalisation = normalisations_electron[norm_variable]
        if use_qcd_data_region:
            qcd_data_region = 'QCDConversions'
    if channel == 'muon':
        histogram_files['data'] = measurement_config.data_file_muon_trees
        histogram_files['QCD'] = measurement_config.muon_QCD_MC_category_templates_trees[category]
        if normalise_to_fit:
            normalisation = normalisations_muon[norm_variable]
        if use_qcd_data_region:
            qcd_data_region = 'QCD non iso mu+jets ge3j'

    histograms = get_histograms_from_trees( trees = [signal_region_tree, control_region_tree], branch = branchName, weightBranch = '1', files = histogram_files, nBins = nBins, xMin = x_limits[0], xMax = x_limits[-1] )

    selection = 'SolutionCategory == 0'
    histogramsNoSolution = get_histograms_from_trees( trees = [signal_region_tree], branch = branchName, weightBranch = '1', selection = selection, files = histogram_files, nBins = nBins, xMin = x_limits[0], xMax = x_limits[-1] )

    selection = 'SolutionCategory == 1'
    histogramsCorrect = get_histograms_from_trees( trees = [signal_region_tree], branch = branchName, weightBranch = '1', selection = selection, files = histogram_files, nBins = nBins, xMin = x_limits[0], xMax = x_limits[-1] )

    selection = 'SolutionCategory == 2'
    histogramsNotSL = get_histograms_from_trees( trees = [signal_region_tree], branch = branchName, weightBranch = '1', selection = selection, files = histogram_files, nBins = nBins, xMin = x_limits[0], xMax = x_limits[-1] )

    selection = 'SolutionCategory == 3'
    histogramsNotReco = get_histograms_from_trees( trees = [signal_region_tree], branch = branchName, weightBranch = '1', selection = selection, files = histogram_files, nBins = nBins, xMin = x_limits[0], xMax = x_limits[-1] )

    selection = 'SolutionCategory > 3'
    histogramsWrong = get_histograms_from_trees( trees = [signal_region_tree], branch = branchName, weightBranch = '1', selection = selection, files = histogram_files, nBins = nBins, xMin = x_limits[0], xMax = x_limits[-1] )

    # Split histograms up into signal/control (?)
    signal_region_hists = {}
    inclusive_control_region_hists = {}
    for sample in histograms.keys():
        signal_region_hists[sample] = histograms[sample][signal_region_tree]
        if use_qcd_data_region:
            inclusive_control_region_hists[sample] = histograms[sample][control_region_tree]

    prepare_histograms( histograms, rebin = 1, scale_factor = measurement_config.luminosity_scale )
    prepare_histograms( histogramsNoSolution, rebin = 1, scale_factor = measurement_config.luminosity_scale )
    prepare_histograms( histogramsCorrect, rebin = 1, scale_factor = measurement_config.luminosity_scale )
    prepare_histograms( histogramsNotSL, rebin = 1, scale_factor = measurement_config.luminosity_scale )
    prepare_histograms( histogramsNotReco, rebin = 1, scale_factor = measurement_config.luminosity_scale )
    prepare_histograms( histogramsWrong, rebin = 1, scale_factor = measurement_config.luminosity_scale )

    qcd_from_data = signal_region_hists['QCD']

    # Which histograms to draw, and properties
    histograms_to_draw = [signal_region_hists['data'], qcd_from_data,
                          signal_region_hists['V+Jets'],
                          signal_region_hists['SingleTop'],
                          histogramsNoSolution['TTJet'][signal_region_tree],
                          histogramsNotSL['TTJet'][signal_region_tree],
                          histogramsNotReco['TTJet'][signal_region_tree],
                          histogramsWrong['TTJet'][signal_region_tree],
                          histogramsCorrect['TTJet'][signal_region_tree]
                          ]
    histogram_lables = ['data', 'QCD', 'V+Jets', 'Single-Top', 
                        samples_latex['TTJet'] + ' - no solution',
                        samples_latex['TTJet'] + ' - not SL',
                        samples_latex['TTJet'] + ' - not reconstructible',
                        samples_latex['TTJet'] + ' - wrong reco',
                        samples_latex['TTJet'] + ' - correct',
                        ]
    histogram_colors = ['black', 'yellow', 'green', 'magenta',
                        'black',
                        'burlywood',
                        'chartreuse',
                        'blue',
                        'red'
                        ]

    histogram_properties = Histogram_properties()
    histogram_properties.name = name_prefix + b_tag_bin
    if category != 'central':
        histogram_properties.name += '_' + category
    histogram_properties.title = title
    histogram_properties.x_axis_title = x_axis_title
    histogram_properties.y_axis_title = y_axis_title
    histogram_properties.x_limits = x_limits
    histogram_properties.y_limits = y_limits
    histogram_properties.y_max_scale = y_max_scale
    histogram_properties.xerr = None
    # workaround for rootpy issue #638
    histogram_properties.emptybins = True
    if b_tag_bin:
        histogram_properties.additional_text = channel_latex[channel] + ', ' + b_tag_bins_latex[b_tag_bin]
    else:
        histogram_properties.additional_text = channel_latex[channel]
    histogram_properties.legend_location = legend_location
    histogram_properties.cms_logo_location = cms_logo_location
    histogram_properties.preliminary = preliminary
    histogram_properties.set_log_y = log_y
    histogram_properties.legend_color = legend_color
    if ratio_y_limits:
        histogram_properties.ratio_y_limits = ratio_y_limits

    if normalise_to_fit:
        histogram_properties.mc_error = get_normalisation_error( normalisation )
        histogram_properties.mc_errors_label = 'fit uncertainty'
    else:
        histogram_properties.mc_error = mc_uncertainty
        histogram_properties.mc_errors_label = 'MC unc.'

    # Actually draw histograms
    make_data_mc_comparison_plot( histograms_to_draw, histogram_lables, histogram_colors,
                                 histogram_properties, save_folder = output_folder,
                                 show_ratio = False, normalise = normalise,
                                 )
    histogram_properties.name += '_with_ratio'
    loc = histogram_properties.legend_location
    # adjust legend location as it is relative to canvas!
    histogram_properties.legend_location = ( loc[0], loc[1] + 0.05 )
    make_data_mc_comparison_plot( histograms_to_draw, histogram_lables, histogram_colors,
                                 histogram_properties, save_folder = output_folder,
                                 show_ratio = True, normalise = normalise,
                                 )
def make_plot(
    channel,
    x_axis_title,
    y_axis_title,
    signal_region_tree,
    control_region_tree,
    branchName,
    name_prefix,
    x_limits,
    nBins,
    use_qcd_data_region=False,
    compare_qcd_signal_with_data_control=False,
    y_limits=[],
    y_max_scale=1.3,
    rebin=1,
    legend_location=(0.98, 0.78),
    cms_logo_location='right',
    log_y=False,
    legend_color=False,
    ratio_y_limits=[0.3, 2.5],
    normalise=False,
):
    global output_folder, measurement_config, category, normalise_to_fit
    global preliminary, norm_variable, sum_bins, b_tag_bin, histogram_files

    controlToCompare = []
    if 'electron' in channel:
        controlToCompare = ['QCDConversions', 'QCD non iso e+jets']
    elif 'muon' in channel:
        controlToCompare = ['QCD iso > 0.3', 'QCD 0.12 < iso <= 0.3']

    histogramsToCompare = {}
    for qcd_data_region in controlToCompare:
        print 'Doing ', qcd_data_region
        # Input files, normalisations, tree/region names
        title = title_template % (measurement_config.new_luminosity,
                                  measurement_config.centre_of_mass_energy)
        normalisation = None
        weightBranchSignalRegion = 'EventWeight'
        if 'electron' in channel:
            histogram_files[
                'data'] = measurement_config.data_file_electron_trees
            histogram_files[
                'QCD'] = measurement_config.electron_QCD_MC_category_templates_trees[
                    category]
            if normalise_to_fit:
                normalisation = normalisations_electron[norm_variable]
            # if use_qcd_data_region:
            #     qcd_data_region = 'QCDConversions'
            #     # qcd_data_region = 'QCD non iso e+jets'
            if not 'QCD' in channel and not 'NPU' in branchName:
                weightBranchSignalRegion += ' * ElectronEfficiencyCorrection'
        if 'muon' in channel:
            histogram_files['data'] = measurement_config.data_file_muon_trees
            histogram_files[
                'QCD'] = measurement_config.muon_QCD_MC_category_templates_trees[
                    category]
            if normalise_to_fit:
                normalisation = normalisations_muon[norm_variable]
            # if use_qcd_data_region:
            #     qcd_data_region = 'QCD iso > 0.3'
            if not 'QCD' in channel and not 'NPU' in branchName:
                weightBranchSignalRegion += ' * MuonEfficiencyCorrection'

        if not "_NPUNoWeight" in name_prefix:
            weightBranchSignalRegion += ' * PUWeight'

        if not "_NBJetsNoWeight" in name_prefix:
            weightBranchSignalRegion += ' * BJetWeight'

        selection = '1'
        if branchName == 'abs(lepton_eta)':
            selection = 'lepton_eta > -10'
        else:
            selection = '%s >= 0' % branchName
        # if 'QCDConversions' in signal_region_tree:
        #     selection += '&& isTightElectron'
        # print selection
        histograms = get_histograms_from_trees(
            trees=[signal_region_tree, control_region_tree],
            branch=branchName,
            weightBranch=weightBranchSignalRegion,
            files=histogram_files,
            nBins=nBins,
            xMin=x_limits[0],
            xMax=x_limits[-1],
            selection=selection)
        histograms_QCDControlRegion = None
        if use_qcd_data_region:
            qcd_control_region = signal_region_tree.replace(
                'Ref selection', qcd_data_region)
            histograms_QCDControlRegion = get_histograms_from_trees(
                trees=[qcd_control_region],
                branch=branchName,
                weightBranch='EventWeight',
                files=histogram_files,
                nBins=nBins,
                xMin=x_limits[0],
                xMax=x_limits[-1],
                selection=selection)

        # Split histograms up into signal/control (?)
        signal_region_hists = {}
        control_region_hists = {}
        for sample in histograms.keys():
            signal_region_hists[sample] = histograms[sample][
                signal_region_tree]

            if compare_qcd_signal_with_data_control:
                if sample is 'data':
                    signal_region_hists[sample] = histograms[sample][
                        control_region_tree]
                elif sample is 'QCD':
                    signal_region_hists[sample] = histograms[sample][
                        signal_region_tree]
                else:
                    del signal_region_hists[sample]

            if use_qcd_data_region:
                control_region_hists[sample] = histograms_QCDControlRegion[
                    sample][qcd_control_region]

        # Prepare histograms
        if normalise_to_fit:
            # only scale signal region to fit (results are invalid for control region)
            prepare_histograms(
                signal_region_hists,
                rebin=rebin,
                scale_factor=measurement_config.luminosity_scale,
                normalisation=normalisation)
        elif normalise_to_data:
            totalMC = 0
            for sample in signal_region_hists:
                if sample is 'data': continue
                totalMC += signal_region_hists[sample].Integral()
            newScale = signal_region_hists['data'].Integral() / totalMC

            prepare_histograms(
                signal_region_hists,
                rebin=rebin,
                scale_factor=newScale,
            )
        else:
            print measurement_config.luminosity_scale
            prepare_histograms(
                signal_region_hists,
                rebin=rebin,
                scale_factor=measurement_config.luminosity_scale)
            prepare_histograms(
                control_region_hists,
                rebin=rebin,
                scale_factor=measurement_config.luminosity_scale)

        # Use qcd from data control region or not
        qcd_from_data = None
        if use_qcd_data_region:
            qcd_from_data = clean_control_region(
                control_region_hists,
                subtract=['TTJet', 'V+Jets', 'SingleTop'])
            # Normalise control region correctly
            nBins = signal_region_hists['QCD'].GetNbinsX()
            n, error = signal_region_hists['QCD'].integral(0,
                                                           nBins + 1,
                                                           error=True)
            n_qcd_predicted_mc_signal = ufloat(n, error)

            n, error = control_region_hists['QCD'].integral(0,
                                                            nBins + 1,
                                                            error=True)
            n_qcd_predicted_mc_control = ufloat(n, error)

            n, error = qcd_from_data.integral(0, nBins + 1, error=True)
            n_qcd_control_region = ufloat(n, error)

            if not n_qcd_control_region == 0:
                dataDrivenQCDScale = n_qcd_predicted_mc_signal / n_qcd_predicted_mc_control
                print 'Overall scale : ', dataDrivenQCDScale
                qcd_from_data.Scale(dataDrivenQCDScale.nominal_value)
                signalToControlScale = n_qcd_predicted_mc_signal / n_qcd_control_region
                dataToMCscale = n_qcd_control_region / n_qcd_predicted_mc_control
                print "Signal to control :", signalToControlScale
                print "QCD scale : ", dataToMCscale
        else:
            qcd_from_data = signal_region_hists['QCD']

        # Which histograms to draw, and properties
        histograms_to_draw = []
        histogram_lables = []
        histogram_colors = []

        if compare_qcd_signal_with_data_control:
            histograms_to_draw = [signal_region_hists['data'], qcd_from_data]
            histogram_lables = ['data', 'QCD']
            histogram_colors = ['black', 'yellow']
        else:
            histograms_to_draw = [
                signal_region_hists['data'], qcd_from_data,
                signal_region_hists['V+Jets'],
                signal_region_hists['SingleTop'], signal_region_hists['TTJet']
            ]
            histogram_lables = [
                'data', 'QCD', 'V+Jets', 'Single-Top', samples_latex['TTJet']
            ]
            histogram_colors = [
                colours['data'], colours['QCD'], colours['V+Jets'],
                colours['Single-Top'], colours['TTJet']
            ]

        print list(qcd_from_data.y())
        histogramsToCompare[qcd_data_region] = qcd_from_data

    print histogramsToCompare
    histogram_properties = Histogram_properties()
    histogram_properties.name = 'QCD_control_region_comparison_' + channel + '_' + branchName
    histogram_properties.title = title
    histogram_properties.x_axis_title = x_axis_title
    histogram_properties.y_axis_title = y_axis_title
    histogram_properties.x_limits = x_limits
    histogram_properties.y_limits = y_limits
    histogram_properties.mc_error = 0.0
    histogram_properties.legend_location = (0.98, 0.78)
    histogram_properties.ratio_y_limits = ratio_y_limits
    if 'electron' in channel:
        make_control_region_comparison(
            histogramsToCompare['QCDConversions'],
            histogramsToCompare['QCD non iso e+jets'],
            name_region_1='Conversions',
            name_region_2='Non Iso',
            histogram_properties=histogram_properties,
            save_folder=output_folder)
    elif 'muon' in channel:
        make_control_region_comparison(
            histogramsToCompare['QCD iso > 0.3'],
            histogramsToCompare['QCD 0.12 < iso <= 0.3'],
            name_region_1='QCD iso > 0.3',
            name_region_2='QCD 0.12 < iso <= 0.3',
            histogram_properties=histogram_properties,
            save_folder=output_folder)
def make_plot( channel, x_axis_title, y_axis_title,
              signal_region_tree,
              control_region_tree,
              branchName,
              name_prefix, x_limits, nBins,
              use_qcd_data_region = False,
              compare_qcd_signal_with_data_control = False,
              y_limits = [],
              y_max_scale = 1.3,
              rebin = 1,
              legend_location = ( 0.98, 0.78 ), cms_logo_location = 'right',
              log_y = False,
              legend_color = False,
              ratio_y_limits = [0.3, 2.5],
              normalise = False,
              ):
    global output_folder, measurement_config, category, normalise_to_fit
    global preliminary, norm_variable, sum_bins, b_tag_bin, histogram_files

    controlToCompare = []
    if 'electron' in channel :
        controlToCompare =  ['QCDConversions', 'QCD non iso e+jets']
    elif 'muon' in channel :
        controlToCompare =  ['QCD iso > 0.3', 'QCD 0.12 < iso <= 0.3']

    histogramsToCompare = {}
    for qcd_data_region in controlToCompare:
        print 'Doing ',qcd_data_region
        # Input files, normalisations, tree/region names
        title = title_template % ( measurement_config.new_luminosity, measurement_config.centre_of_mass_energy )
        normalisation = None
        weightBranchSignalRegion = 'EventWeight'
        if 'electron' in channel:
            histogram_files['data'] = measurement_config.data_file_electron_trees
            histogram_files['QCD'] = measurement_config.electron_QCD_MC_category_templates_trees[category]
            if normalise_to_fit:
                normalisation = normalisations_electron[norm_variable]
            # if use_qcd_data_region:
            #     qcd_data_region = 'QCDConversions'
            #     # qcd_data_region = 'QCD non iso e+jets'
            if not 'QCD' in channel and not 'NPU' in branchName:
                weightBranchSignalRegion += ' * ElectronEfficiencyCorrection'
        if 'muon' in channel:
            histogram_files['data'] = measurement_config.data_file_muon_trees
            histogram_files['QCD'] = measurement_config.muon_QCD_MC_category_templates_trees[category]
            if normalise_to_fit:
                normalisation = normalisations_muon[norm_variable]
            # if use_qcd_data_region:
            #     qcd_data_region = 'QCD iso > 0.3'
            if not 'QCD' in channel and not 'NPU' in branchName:
                weightBranchSignalRegion += ' * MuonEfficiencyCorrection'

        if not "_NPUNoWeight" in name_prefix:
            weightBranchSignalRegion += ' * PUWeight'

        if not "_NBJetsNoWeight" in name_prefix:
            weightBranchSignalRegion += ' * BJetWeight'

        selection = '1'
        if branchName == 'abs(lepton_eta)' :
            selection = 'lepton_eta > -10'
        else:
            selection = '%s >= 0' % branchName
        # if 'QCDConversions' in signal_region_tree:
        #     selection += '&& isTightElectron'
        # print selection
        histograms = get_histograms_from_trees( trees = [signal_region_tree, control_region_tree], branch = branchName, weightBranch = weightBranchSignalRegion, files = histogram_files, nBins = nBins, xMin = x_limits[0], xMax = x_limits[-1], selection = selection )
        histograms_QCDControlRegion = None
        if use_qcd_data_region:
            qcd_control_region = signal_region_tree.replace( 'Ref selection', qcd_data_region )
            histograms_QCDControlRegion = get_histograms_from_trees( trees = [qcd_control_region], branch = branchName, weightBranch = 'EventWeight', files = histogram_files, nBins = nBins, xMin = x_limits[0], xMax = x_limits[-1], selection = selection )

        # Split histograms up into signal/control (?)
        signal_region_hists = {}
        control_region_hists = {}
        for sample in histograms.keys():
            signal_region_hists[sample] = histograms[sample][signal_region_tree]

            if compare_qcd_signal_with_data_control:
                if sample is 'data':
                    signal_region_hists[sample] = histograms[sample][control_region_tree]
                elif sample is 'QCD' :
                    signal_region_hists[sample] = histograms[sample][signal_region_tree]
                else:
                    del signal_region_hists[sample]

            if use_qcd_data_region:
                control_region_hists[sample] = histograms_QCDControlRegion[sample][qcd_control_region]

        # Prepare histograms
        if normalise_to_fit:
            # only scale signal region to fit (results are invalid for control region)
            prepare_histograms( signal_region_hists, rebin = rebin,
                                scale_factor = measurement_config.luminosity_scale,
                                normalisation = normalisation )
        elif normalise_to_data:
            totalMC = 0
            for sample in signal_region_hists:
                if sample is 'data' : continue
                totalMC += signal_region_hists[sample].Integral()
            newScale = signal_region_hists['data'].Integral() / totalMC

            prepare_histograms( signal_region_hists, rebin = rebin,
                                scale_factor = newScale,
                               )
        else:
            print measurement_config.luminosity_scale
            prepare_histograms( signal_region_hists, rebin = rebin,
                                scale_factor = measurement_config.luminosity_scale )
            prepare_histograms( control_region_hists, rebin = rebin,
                                scale_factor = measurement_config.luminosity_scale )

        # Use qcd from data control region or not
        qcd_from_data = None
        if use_qcd_data_region:
            qcd_from_data = clean_control_region( control_region_hists,

                              subtract = ['TTJet', 'V+Jets', 'SingleTop'] )
            # Normalise control region correctly
            nBins = signal_region_hists['QCD'].GetNbinsX()
            n, error = signal_region_hists['QCD'].integral(0,nBins+1,error=True)
            n_qcd_predicted_mc_signal = ufloat( n, error)

            n, error = control_region_hists['QCD'].integral(0,nBins+1,error=True)
            n_qcd_predicted_mc_control = ufloat( n, error)

            n, error = qcd_from_data.integral(0,nBins+1,error=True)
            n_qcd_control_region = ufloat( n, error)

            if not n_qcd_control_region == 0:
                dataDrivenQCDScale = n_qcd_predicted_mc_signal / n_qcd_predicted_mc_control
                print 'Overall scale : ',dataDrivenQCDScale
                qcd_from_data.Scale( dataDrivenQCDScale.nominal_value )
                signalToControlScale = n_qcd_predicted_mc_signal / n_qcd_control_region
                dataToMCscale = n_qcd_control_region / n_qcd_predicted_mc_control
                print "Signal to control :",signalToControlScale
                print "QCD scale : ",dataToMCscale
        else:
            qcd_from_data = signal_region_hists['QCD']

        # Which histograms to draw, and properties
        histograms_to_draw = []
        histogram_lables = []
        histogram_colors = []

        if compare_qcd_signal_with_data_control :
            histograms_to_draw = [signal_region_hists['data'], qcd_from_data ]
            histogram_lables = ['data', 'QCD']
            histogram_colors = ['black', 'yellow']
        else :
            histograms_to_draw = [signal_region_hists['data'], qcd_from_data,
                                  signal_region_hists['V+Jets'],
                                  signal_region_hists['SingleTop'],
                                  signal_region_hists['TTJet']]
            histogram_lables = ['data', 'QCD', 'V+Jets', 'Single-Top', samples_latex['TTJet']]
            histogram_colors = [colours['data'], colours['QCD'], colours['V+Jets'], colours['Single-Top'], colours['TTJet'] ]

        
        print list(qcd_from_data.y())
        histogramsToCompare[qcd_data_region] = qcd_from_data

    print histogramsToCompare
    histogram_properties = Histogram_properties()
    histogram_properties.name = 'QCD_control_region_comparison_' + channel + '_' + branchName
    histogram_properties.title = title
    histogram_properties.x_axis_title = x_axis_title
    histogram_properties.y_axis_title = y_axis_title
    histogram_properties.x_limits = x_limits
    histogram_properties.y_limits = y_limits
    histogram_properties.mc_error = 0.0
    histogram_properties.legend_location = ( 0.98, 0.78 )
    histogram_properties.ratio_y_limits = ratio_y_limits
    if 'electron' in channel:
        make_control_region_comparison(histogramsToCompare['QCDConversions'], histogramsToCompare['QCD non iso e+jets'],
                                       name_region_1='Conversions', name_region_2='Non Iso',
                                       histogram_properties=histogram_properties, save_folder=output_folder)
    elif 'muon' in channel:
        make_control_region_comparison(histogramsToCompare['QCD iso > 0.3'], histogramsToCompare['QCD 0.12 < iso <= 0.3'],
                                       name_region_1='QCD iso > 0.3', name_region_2='QCD 0.12 < iso <= 0.3',
                                       histogram_properties=histogram_properties, save_folder=output_folder)
            regions = ['QCD non iso mu+jets']
        elif channel == 'EPlusJets':
            regions = ['QCD non iso e+jets', 'QCDConversions']

        for control_region in regions :
            # Fit variables (inclusive)
            for var in ['M3', 'angle_bl', 'M_bl', 'absolute_eta']:
                print channel,var
                controlTree = 'TTbar_plus_X_analysis/%s/%s/FitVariables' % ( channel, control_region )

                bins = fit_variable_bin_edges[var]
                xMin = bins[0]
                xMax = bins[-1]
                nBins = len(bins) -1
                
                histograms = get_histograms_from_trees( trees = [controlTree], branch = var, weightBranch = 'EventWeight', files = histogram_files, nBins = nBins, xMin = xMin, xMax = xMax )

                prepare_histograms( histograms, rebin = 1, scale_factor = measurement_config.luminosity_scale )
                
                histograms_to_draw = [histograms['data'][controlTree], histograms['QCD'][controlTree],
                                      histograms['V+Jets'][controlTree],
                                      histograms['SingleTop'][controlTree], histograms['TTJet'][controlTree]]
                histogram_lables = ['data', 'QCD', 'V+Jets', 'Single-Top', samples_latex['TTJet']]
                histogram_colors = ['black', 'yellow', 'green', 'magenta', 'red']
                
                histogram_properties = Histogram_properties()
                histogram_properties.name = 'QCD_nonIso_%s_%s' % (channel, var)
                if control_region == 'QCDConversions' :
                    histogram_properties.name = 'QCD_Conversions_%s_%s' % (channel, var)
                if category != 'central':
                    histogram_properties.name += '_' + category
Beispiel #6
0
def get_histograms(channel,
                   input_files,
                   variable,
                   met_systematic,
                   met_type,
                   variable_bin,
                   b_tag_bin,
                   treePrefix,
                   weightBranch,
                   rebin=1,
                   fit_variable='absolute_eta',
                   scale_factors=None):
    global b_tag_bin_VJets, fit_variables
    global electron_control_region, muon_control_region

    boundaries = measurement_config.fit_boundaries[fit_variable]
    histograms = {}

    tree = measurement_config.tree_path_templates[channel]
    control_tree = measurement_config.tree_path_control_templates[channel]

    # Put together weight
    fullWeight = 'EventWeight'
    if weightBranch != '':
        fullWeight += ' * %s' % weightBranch

    # Work out bin of variable
    variableForSelection = variable
    minVar = variable_bin.split('-')[0]
    maxVar = variable_bin.split('-')[-1]
    selection = ''
    if maxVar != 'inf':
        selection = '%s >= %s && %s < %s' % (variableForSelection, minVar,
                                             variableForSelection, maxVar)
    else:
        selection = '%s >= %s' % (variableForSelection, minVar)

    bins = fit_variable_bin_edges[fit_variable]
    xMin = bins[0]
    xMax = bins[-1]
    nBins = len(bins) - 1

    # Get data files here, without any systematic variations
    data_files = {sample: input_files[sample] for sample in ['data']}
    histograms_data = get_histograms_from_trees(trees=[tree],
                                                branch=fit_variable,
                                                selection=selection,
                                                weightBranch=fullWeight,
                                                files=data_files,
                                                nBins=nBins,
                                                xMin=xMin,
                                                xMax=xMax)

    # Now work out tree/variable for MC
    # Identical for data if central, different for systematics
    tree = tree + treePrefix

    if met_systematic:
        if variable == 'MET':
            variableForSelection = 'MET_METUncertainties[%i]' % met_systematics[
                met_systematic]
        elif variable == 'ST':
            variableForSelection = 'ST_METUncertainties[%i]' % met_systematics[
                met_systematic]

    # Work out selection again for MC, as variable (e.g. MET) could be different after systematic variation
    if maxVar != 'inf':
        selection = '%s >= %s && %s < %s' % (variableForSelection, minVar,
                                             variableForSelection, maxVar)
    else:
        selection = '%s >= %s' % (variableForSelection, minVar)

    # Get exclusive templates for MC
    input_files_exclusive = {
        sample: input_files[sample]
        for sample in ['TTJet', 'SingleTop', 'V+Jets', 'QCD']
    }
    # Get inclusive template for these (i.e. don't split up fit variable in bins of MET or whatever)
    input_files_inclusive = {
        sample: input_files[sample]
        for sample in ['V+Jets']
    }
    # # Get control templates for QCD only, and inclusive
    # input_files_control = input_files

    # Get necessary histograms
    # Signal, binned by e.g. MET, HT etc.
    histograms_exclusive = get_histograms_from_trees(
        trees=[tree],
        branch=fit_variable,
        selection=selection,
        weightBranch=fullWeight,
        files=input_files_exclusive,
        nBins=nBins,
        xMin=xMin,
        xMax=xMax)
    # Signal, not binned.  For V+Jets template
    histograms_inclusive = get_histograms_from_trees(
        trees=[tree],
        branch=fit_variable,
        weightBranch=fullWeight,
        files=input_files_inclusive,
        nBins=nBins,
        xMin=xMin,
        xMax=xMax)
    # Control, not binned.  For QCD template
    histograms_control_inclusive = get_histograms_from_trees(
        trees=[control_tree],
        branch=fit_variable,
        weightBranch=fullWeight,
        files=input_files,
        nBins=nBins,
        xMin=xMin,
        xMax=xMax)

    # Currently needed, as get_histograms_from_trees returns the histograms as part of a more complicated structure
    for histogram in histograms_data:
        for d in histograms_data[histogram]:
            histograms_data[histogram] = histograms_data[histogram][d].Clone()

    for histogram in histograms_exclusive:
        for d in histograms_exclusive[histogram]:
            histograms_exclusive[histogram] = histograms_exclusive[histogram][
                d].Clone()

    for histogram in histograms_inclusive:
        for d in histograms_inclusive[histogram]:
            histograms_inclusive[histogram] = histograms_inclusive[histogram][
                d].Clone()

    for histogram in histograms_control_inclusive:
        for d in histograms_control_inclusive[histogram]:
            histograms_control_inclusive[
                histogram] = histograms_control_inclusive[histogram][d].Clone(
                )

    # Put all histograms into one dictionary
    histograms = {}
    histograms.update(histograms_exclusive)

    # Always use central data sample
    histograms['data'] = histograms_data['data']

    # Get QCD distribution from data
    # histograms['QCD'] = get_data_derived_qcd(histograms_control_inclusive, histograms_exclusive['QCD'])
    # histograms['V+Jets'] = get_inclusive_histogram( histograms_inclusive['V+Jets'], histograms['V+Jets'] )

    # normalise histograms
    if not measurement_config.luminosity_scale == 1.0:
        for sample, histogram in histograms.iteritems():
            if sample == 'data':
                continue
            histogram.Scale(measurement_config.luminosity_scale)

    # # apply normalisation scale factors for rate-changing systematics
    if scale_factors:
        for source, factor in scale_factors.iteritems():
            for sample, histogram in histograms.iteritems():
                if 'luminosity' in source:
                    if sample is 'data':
                        # Skip data for luminosity systematic
                        continue
                    else:
                        histogram.Scale(factor)
                # For cross section systematics, only change normalisation of relevant sample
                elif sample in source:
                    histogram.Scale(factor)

    return histograms
def get_histograms( channel, input_files, variable, met_type, variable_bin,
                   b_tag_bin, rebin = 1, fit_variable = 'absolute_eta',
                   scale_factors = None ):
    global b_tag_bin_VJets, fit_variables
    global electron_control_region, muon_control_region

    boundaries = measurement_config.fit_boundaries[fit_variable]
    histograms = {}

    tree = measurement_config.tree_path_templates[channel]
    control_tree = measurement_config.tree_path_control_templates[channel]
    print variable, fit_variable

    # fit_variable_name = ''
    # fit_variable_name_data = ''
    # ht_fill_list, other_fill_list = None, None
    # if fit_variable == 'absolute_eta':
    #     ht_fill_list = ( analysis_type[channel], variable_bin, channel + '_' + fit_variable )
    #     other_fill_list = ( analysis_type[channel], met_type, variable_bin, channel + '_' + fit_variable )
    # else:
    #     ht_fill_list = ( analysis_type[channel], variable_bin, fit_variable )
    #     other_fill_list = ( analysis_type[channel], met_type, variable_bin, fit_variable )
    # if variable == 'HT':
    #     fit_variable_name = fit_variable_template % ht_fill_list
    #     fit_variable_name_data = fit_variable_name
    # else:
    #     fit_variable_name = fit_variable_template % other_fill_list

        # if 'JetRes' in met_type:
        #     fit_variable_name_data = fit_variable_name.replace( 'JetResDown', '' )
        #     fit_variable_name_data = fit_variable_name_data.replace( 'JetResUp', '' )
        #     if 'patPFMet' in met_type:
        #         fit_variable_name = fit_variable_name.replace( 'patPFMet', 'PFMET' )
        # else:
        #     fit_variable_name_data = fit_variable_name

    # Work out bin of variable
    minVar = variable_bin.split('-')[0]
    maxVar = variable_bin.split('-')[-1]
    if maxVar != 'inf' :
        selection = '%s >= %s && %s < %s' % ( variable, minVar, variable, maxVar)
    else :
        selection = '%s >= %s' % ( variable, minVar )


    # Get inclusive template for these (i.e. don't split up fit variable in bins of MET or whatever)
    input_files_inclusive = { sample : input_files[sample] for sample in ['V+Jets'] }
    # # Get control templates for QCD only, and inclusive
    # input_files_control = input_files

    print selection, fit_variable

    bins = fit_variable_bin_edges[fit_variable]
    xMin = bins[0]
    xMax = bins[-1]
    nBins = len(bins) -1   
 
    # Get necessary histograms
    # Signal, binned by e.g. MET, HT etc.
    histograms_exclusive = get_histograms_from_trees( trees = [tree], branch = fit_variable, selection = selection, weightBranch = 'EventWeight', files = input_files, nBins = nBins, xMin = xMin, xMax = xMax )
    # Signal, not binned.  For V+Jets template
    histograms_inclusive = get_histograms_from_trees( trees = [tree], branch = fit_variable, weightBranch = 'EventWeight', files = input_files_inclusive, nBins = nBins, xMin = xMin, xMax = xMax )
    # Control, not binned.  For QCD template
    histograms_control_inclusive = get_histograms_from_trees( trees = [control_tree], branch = fit_variable, weightBranch = 'EventWeight', files = input_files, nBins = nBins, xMin = xMin, xMax = xMax )

    # Currently needed, as get_histograms_from_trees returns the histograms as part of a more complicated structure
    for histogram in histograms_exclusive:
        for d in histograms_exclusive[histogram]:
            histograms_exclusive[histogram] = histograms_exclusive[histogram][d].Clone()

    for histogram in histograms_inclusive:
        for d in histograms_inclusive[histogram]:
            histograms_inclusive[histogram] = histograms_inclusive[histogram][d].Clone()

    for histogram in histograms_control_inclusive:
        for d in histograms_control_inclusive[histogram]:
            histograms_control_inclusive[histogram] = histograms_control_inclusive[histogram][d].Clone()

    # Put all histograms into one dictionary
    histograms = {}
    histograms.update(histograms_exclusive)

    # Get QCD distribution from data
    histograms['QCD'] = get_data_derived_qcd(histograms_control_inclusive, histograms_exclusive['QCD'])
    histograms['V+Jets'] = get_inclusive_histogram( histograms_inclusive['V+Jets'], histograms['V+Jets'] )
    
    # normalise histograms
    if not measurement_config.luminosity_scale == 1.0:
        for sample, histogram in histograms.iteritems():
            if sample == 'data':
                continue
            histogram.Scale( measurement_config.luminosity_scale )

    # # apply normalisation scale factors for rate-changing systematics
    # if scale_factors:
    #     for source, factor in scale_factors.iteritems():
    #         if 'luminosity' in source:
    #             for sample, histogram in histograms.iteritems():
    #                 if sample == 'data':
    #                     continue
    #                 histogram.Scale( factor )
    #         for sample, histogram in histograms.iteritems():
    #             if sample in source:
    #                 histogram.Scale( factor )
    return histograms
def get_histograms( channel, input_files, variable, met_systematic, met_type, variable_bin,
                   b_tag_bin, 
                   treePrefix, weightBranch,
                   rebin = 1, fit_variable = 'absolute_eta',
                   scale_factors = None ):
    global b_tag_bin_VJets, fit_variables
    global electron_control_region, muon_control_region

    boundaries = measurement_config.fit_boundaries[fit_variable]
    histograms = {}

    tree = measurement_config.tree_path_templates[channel]
    control_tree = measurement_config.tree_path_control_templates[channel]

    # Put together weight
    fullWeight = 'EventWeight'
    if weightBranch != '' :
        fullWeight += ' * %s' % weightBranch

    # Work out bin of variable
    variableForSelection = variable
    minVar = variable_bin.split('-')[0]
    maxVar = variable_bin.split('-')[-1]
    selection = ''
    if maxVar != 'inf' :
        selection = '%s >= %s && %s < %s' % ( variableForSelection, minVar, variableForSelection, maxVar)
    else :
        selection = '%s >= %s' % ( variableForSelection, minVar )

    bins = fit_variable_bin_edges[fit_variable]
    xMin = bins[0]
    xMax = bins[-1]
    nBins = len(bins) -1

    # Get data files here, without any systematic variations
    data_files = { sample : input_files[sample] for sample in ['data'] }
    histograms_data = get_histograms_from_trees( trees = [tree], branch = fit_variable, selection = selection, weightBranch = fullWeight, files = data_files, nBins = nBins, xMin = xMin, xMax = xMax )

    # Now work out tree/variable for MC
    # Identical for data if central, different for systematics
    tree = tree + treePrefix

    if met_systematic:
        if variable == 'MET':
            variableForSelection = 'MET_METUncertainties[%i]' % met_systematics[met_systematic]
        elif variable == 'ST':
            variableForSelection = 'ST_METUncertainties[%i]' % met_systematics[met_systematic]

    # Work out selection again for MC, as variable (e.g. MET) could be different after systematic variation
    if maxVar != 'inf' :
        selection = '%s >= %s && %s < %s' % ( variableForSelection, minVar, variableForSelection, maxVar)
    else :
        selection = '%s >= %s' % ( variableForSelection, minVar )

    # Get exclusive templates for MC
    input_files_exclusive = { sample : input_files[sample] for sample in ['TTJet', 'SingleTop', 'V+Jets', 'QCD'] }
    # Get inclusive template for these (i.e. don't split up fit variable in bins of MET or whatever)
    input_files_inclusive = { sample : input_files[sample] for sample in ['V+Jets'] }
    # # Get control templates for QCD only, and inclusive
    # input_files_control = input_files

    # Get necessary histograms
    # Signal, binned by e.g. MET, HT etc.
    histograms_exclusive = get_histograms_from_trees( trees = [tree], branch = fit_variable, selection = selection, weightBranch = fullWeight, files = input_files_exclusive, nBins = nBins, xMin = xMin, xMax = xMax )
    # Signal, not binned.  For V+Jets template
    histograms_inclusive = get_histograms_from_trees( trees = [tree], branch = fit_variable, weightBranch = fullWeight, files = input_files_inclusive, nBins = nBins, xMin = xMin, xMax = xMax )
    # Control, not binned.  For QCD template
    histograms_control_inclusive = get_histograms_from_trees( trees = [control_tree], branch = fit_variable, weightBranch = fullWeight, files = input_files, nBins = nBins, xMin = xMin, xMax = xMax )

    # Currently needed, as get_histograms_from_trees returns the histograms as part of a more complicated structure
    for histogram in histograms_data:
        for d in histograms_data[histogram]:
            histograms_data[histogram] = histograms_data[histogram][d].Clone()

    for histogram in histograms_exclusive:
        for d in histograms_exclusive[histogram]:
            histograms_exclusive[histogram] = histograms_exclusive[histogram][d].Clone()

    for histogram in histograms_inclusive:
        for d in histograms_inclusive[histogram]:
            histograms_inclusive[histogram] = histograms_inclusive[histogram][d].Clone()

    for histogram in histograms_control_inclusive:
        for d in histograms_control_inclusive[histogram]:
            histograms_control_inclusive[histogram] = histograms_control_inclusive[histogram][d].Clone()

    # Put all histograms into one dictionary
    histograms = {}
    histograms.update(histograms_exclusive)

    # Always use central data sample
    histograms['data'] = histograms_data['data']

    # Get QCD distribution from data
    # histograms['QCD'] = get_data_derived_qcd(histograms_control_inclusive, histograms_exclusive['QCD'])
    # histograms['V+Jets'] = get_inclusive_histogram( histograms_inclusive['V+Jets'], histograms['V+Jets'] )
    
    # normalise histograms
    if not measurement_config.luminosity_scale == 1.0:
        for sample, histogram in histograms.iteritems():
            if sample == 'data':
                continue
            histogram.Scale( measurement_config.luminosity_scale )

    # # apply normalisation scale factors for rate-changing systematics
    if scale_factors:
        for source, factor in scale_factors.iteritems():
            for sample, histogram in histograms.iteritems():
                if 'luminosity' in source:
                    if sample is 'data':
                        # Skip data for luminosity systematic
                        continue
                    else:
                        histogram.Scale( factor )
                # For cross section systematics, only change normalisation of relevant sample
                elif sample in source :
                    histogram.Scale( factor )

    return histograms
def make_ttbarReco_plot(
    channel,
    x_axis_title,
    y_axis_title,
    signal_region_tree,
    control_region_tree,
    branchName,
    name_prefix,
    x_limits,
    nBins,
    use_qcd_data_region=False,
    y_limits=[],
    y_max_scale=1.2,
    rebin=1,
    legend_location=(0.98, 0.78),
    cms_logo_location='right',
    log_y=False,
    legend_color=False,
    ratio_y_limits=[0.3, 1.7],
    normalise=False,
):
    global output_folder, measurement_config, category, normalise_to_fit
    global preliminary, norm_variable, sum_bins, b_tag_bin, histogram_files

    # Input files, normalisations, tree/region names
    qcd_data_region = ''
    title = title_template % (measurement_config.new_luminosity / 1000.,
                              measurement_config.centre_of_mass_energy)
    normalisation = None
    if channel == 'electron':
        histogram_files['data'] = measurement_config.data_file_electron_trees
        histogram_files[
            'QCD'] = measurement_config.electron_QCD_MC_category_templates_trees[
                category]
        if normalise_to_fit:
            normalisation = normalisations_electron[norm_variable]
        if use_qcd_data_region:
            qcd_data_region = 'QCDConversions'
    if channel == 'muon':
        histogram_files['data'] = measurement_config.data_file_muon_trees
        histogram_files[
            'QCD'] = measurement_config.muon_QCD_MC_category_templates_trees[
                category]
        if normalise_to_fit:
            normalisation = normalisations_muon[norm_variable]
        if use_qcd_data_region:
            qcd_data_region = 'QCD non iso mu+jets ge3j'

    histograms = get_histograms_from_trees(
        trees=[signal_region_tree, control_region_tree],
        branch=branchName,
        weightBranch='1',
        files=histogram_files,
        nBins=nBins,
        xMin=x_limits[0],
        xMax=x_limits[-1])

    selection = 'SolutionCategory == 0'
    histogramsNoSolution = get_histograms_from_trees(
        trees=[signal_region_tree],
        branch=branchName,
        weightBranch='1',
        selection=selection,
        files=histogram_files,
        nBins=nBins,
        xMin=x_limits[0],
        xMax=x_limits[-1])

    selection = 'SolutionCategory == 1'
    histogramsCorrect = get_histograms_from_trees(trees=[signal_region_tree],
                                                  branch=branchName,
                                                  weightBranch='1',
                                                  selection=selection,
                                                  files=histogram_files,
                                                  nBins=nBins,
                                                  xMin=x_limits[0],
                                                  xMax=x_limits[-1])

    selection = 'SolutionCategory == 2'
    histogramsNotSL = get_histograms_from_trees(trees=[signal_region_tree],
                                                branch=branchName,
                                                weightBranch='1',
                                                selection=selection,
                                                files=histogram_files,
                                                nBins=nBins,
                                                xMin=x_limits[0],
                                                xMax=x_limits[-1])

    selection = 'SolutionCategory == 3'
    histogramsNotReco = get_histograms_from_trees(trees=[signal_region_tree],
                                                  branch=branchName,
                                                  weightBranch='1',
                                                  selection=selection,
                                                  files=histogram_files,
                                                  nBins=nBins,
                                                  xMin=x_limits[0],
                                                  xMax=x_limits[-1])

    selection = 'SolutionCategory > 3'
    histogramsWrong = get_histograms_from_trees(trees=[signal_region_tree],
                                                branch=branchName,
                                                weightBranch='1',
                                                selection=selection,
                                                files=histogram_files,
                                                nBins=nBins,
                                                xMin=x_limits[0],
                                                xMax=x_limits[-1])

    # Split histograms up into signal/control (?)
    signal_region_hists = {}
    inclusive_control_region_hists = {}
    for sample in histograms.keys():
        signal_region_hists[sample] = histograms[sample][signal_region_tree]
        if use_qcd_data_region:
            inclusive_control_region_hists[sample] = histograms[sample][
                control_region_tree]

    prepare_histograms(histograms,
                       rebin=1,
                       scale_factor=measurement_config.luminosity_scale)
    prepare_histograms(histogramsNoSolution,
                       rebin=1,
                       scale_factor=measurement_config.luminosity_scale)
    prepare_histograms(histogramsCorrect,
                       rebin=1,
                       scale_factor=measurement_config.luminosity_scale)
    prepare_histograms(histogramsNotSL,
                       rebin=1,
                       scale_factor=measurement_config.luminosity_scale)
    prepare_histograms(histogramsNotReco,
                       rebin=1,
                       scale_factor=measurement_config.luminosity_scale)
    prepare_histograms(histogramsWrong,
                       rebin=1,
                       scale_factor=measurement_config.luminosity_scale)

    qcd_from_data = signal_region_hists['QCD']

    # Which histograms to draw, and properties
    histograms_to_draw = [
        signal_region_hists['data'], qcd_from_data,
        signal_region_hists['V+Jets'], signal_region_hists['SingleTop'],
        histogramsNoSolution['TTJet'][signal_region_tree],
        histogramsNotSL['TTJet'][signal_region_tree],
        histogramsNotReco['TTJet'][signal_region_tree],
        histogramsWrong['TTJet'][signal_region_tree],
        histogramsCorrect['TTJet'][signal_region_tree]
    ]
    histogram_lables = [
        'data',
        'QCD',
        'V+Jets',
        'Single-Top',
        samples_latex['TTJet'] + ' - no solution',
        samples_latex['TTJet'] + ' - not SL',
        samples_latex['TTJet'] + ' - not reconstructible',
        samples_latex['TTJet'] + ' - wrong reco',
        samples_latex['TTJet'] + ' - correct',
    ]
    histogram_colors = [
        'black', 'yellow', 'green', 'magenta', 'black', 'burlywood',
        'chartreuse', 'blue', 'red'
    ]

    histogram_properties = Histogram_properties()
    histogram_properties.name = name_prefix + b_tag_bin
    if category != 'central':
        histogram_properties.name += '_' + category
    histogram_properties.title = title
    histogram_properties.x_axis_title = x_axis_title
    histogram_properties.y_axis_title = y_axis_title
    histogram_properties.x_limits = x_limits
    histogram_properties.y_limits = y_limits
    histogram_properties.y_max_scale = y_max_scale
    histogram_properties.xerr = None
    # workaround for rootpy issue #638
    histogram_properties.emptybins = True
    if b_tag_bin:
        histogram_properties.additional_text = channel_latex[
            channel] + ', ' + b_tag_bins_latex[b_tag_bin]
    else:
        histogram_properties.additional_text = channel_latex[channel]
    histogram_properties.legend_location = legend_location
    histogram_properties.cms_logo_location = cms_logo_location
    histogram_properties.preliminary = preliminary
    histogram_properties.set_log_y = log_y
    histogram_properties.legend_color = legend_color
    if ratio_y_limits:
        histogram_properties.ratio_y_limits = ratio_y_limits

    if normalise_to_fit:
        histogram_properties.mc_error = get_normalisation_error(normalisation)
        histogram_properties.mc_errors_label = 'fit uncertainty'
    else:
        histogram_properties.mc_error = mc_uncertainty
        histogram_properties.mc_errors_label = 'MC unc.'

    # Actually draw histograms
    make_data_mc_comparison_plot(
        histograms_to_draw,
        histogram_lables,
        histogram_colors,
        histogram_properties,
        save_folder=output_folder,
        show_ratio=False,
        normalise=normalise,
    )
    histogram_properties.name += '_with_ratio'
    loc = histogram_properties.legend_location
    # adjust legend location as it is relative to canvas!
    histogram_properties.legend_location = (loc[0], loc[1] + 0.05)
    make_data_mc_comparison_plot(
        histograms_to_draw,
        histogram_lables,
        histogram_colors,
        histogram_properties,
        save_folder=output_folder,
        show_ratio=True,
        normalise=normalise,
    )