def compare_vjets_templates( variable = 'MET', met_type = 'patType1CorrectedPFMet',
                             title = 'Untitled', channel = 'electron' ):
    ''' Compares the V+jets templates in different bins
     of the current variable'''
    global fit_variable_properties, b_tag_bin, save_as
    variable_bins = variable_bins_ROOT[variable]
    histogram_template = get_histogram_template( variable )
    
    for fit_variable in electron_fit_variables:
        all_hists = {}
        inclusive_hist = None
        save_path = 'plots/%dTeV/fit_variables/%s/%s/' % ( measurement_config.centre_of_mass_energy, variable, fit_variable )
        make_folder_if_not_exists( save_path + '/vjets/' )
        
        max_bins = len( variable_bins )
        for bin_range in variable_bins[0:max_bins]:
            
            params = {'met_type': met_type, 'bin_range':bin_range, 'fit_variable':fit_variable, 'b_tag_bin':b_tag_bin, 'variable':variable}
            fit_variable_distribution = histogram_template % params
            # format: histograms['data'][qcd_fit_variable_distribution]
            histograms = get_histograms_from_files( [fit_variable_distribution], histogram_files )
            prepare_histograms( histograms, rebin = fit_variable_properties[fit_variable]['rebin'], scale_factor = measurement_config.luminosity_scale )
            all_hists[bin_range] = histograms['V+Jets'][fit_variable_distribution]
    
        # create the inclusive distributions
        inclusive_hist = deepcopy( all_hists[variable_bins[0]] )
        for bin_range in variable_bins[1:max_bins]:
            inclusive_hist += all_hists[bin_range]
        for bin_range in variable_bins[0:max_bins]:
            if not all_hists[bin_range].Integral() == 0:
                all_hists[bin_range].Scale( 1 / all_hists[bin_range].Integral() )
        # normalise all histograms
        inclusive_hist.Scale( 1 / inclusive_hist.Integral() )
        # now compare inclusive to all bins
        histogram_properties = Histogram_properties()
        histogram_properties.x_axis_title = fit_variable_properties[fit_variable]['x-title']
        histogram_properties.y_axis_title = fit_variable_properties[fit_variable]['y-title']
        histogram_properties.y_axis_title = histogram_properties.y_axis_title.replace( 'Events', 'a.u.' )
        histogram_properties.x_limits = [fit_variable_properties[fit_variable]['min'], fit_variable_properties[fit_variable]['max']]
        histogram_properties.title = title
        histogram_properties.additional_text = channel_latex[channel] + ', ' + b_tag_bins_latex[b_tag_bin]
        histogram_properties.name = variable + '_' + fit_variable + '_' + b_tag_bin + '_VJets_template_comparison'
        histogram_properties.y_max_scale = 1.5
        measurements = {bin_range + ' GeV': histogram for bin_range, histogram in all_hists.iteritems()}
        measurements = OrderedDict( sorted( measurements.items() ) )
        fit_var = fit_variable.replace( 'electron_', '' )
        fit_var = fit_var.replace( 'muon_', '' )
        graphs = spread_x( measurements.values(), fit_variable_bin_edges[fit_var] )
        for key, graph in zip( sorted( measurements.keys() ), graphs ):
            measurements[key] = graph
        compare_measurements( models = {'inclusive' : inclusive_hist},
                             measurements = measurements,
                             show_measurement_errors = True,
                             histogram_properties = histogram_properties,
                             save_folder = save_path + '/vjets/',
                             save_as = save_as )
Ejemplo n.º 2
0
def compare( central_mc, expected_result = None, measured_result = None, results = {}, variable = 'MET',
             channel = 'electron', bin_edges = [] ):
    global input_file, plot_location, ttbar_xsection, luminosity, centre_of_mass, method, test, log_plots

    channel_label = ''
    if channel == 'electron':
        channel_label = 'e+jets, $\geq$4 jets'
    elif channel == 'muon':
        channel_label = '$\mu$+jets, $\geq$4 jets'
    else:
        channel_label = '$e, \mu$ + jets combined, $\geq$4 jets'

    if test == 'data':
        title_template = 'CMS Preliminary, $\mathcal{L} = %.1f$ fb$^{-1}$  at $\sqrt{s}$ = %d TeV \n %s'
        title = title_template % ( luminosity / 1000., centre_of_mass, channel_label )
    else:
        title_template = 'CMS Simulation at $\sqrt{s}$ = %d TeV \n %s'
        title = title_template % ( centre_of_mass, channel_label )

    models = {latex_labels.measurements_latex['MADGRAPH'] : central_mc}
    if expected_result and test == 'data':
        models.update({'fitted data' : expected_result})
        # scale central MC to lumi
        nEvents = input_file.EventFilter.EventCounter.GetBinContent( 1 )  # number of processed events 
        lumiweight = ttbar_xsection * luminosity / nEvents
        central_mc.Scale( lumiweight )
    elif expected_result:
        models.update({'expected' : expected_result})
    if measured_result and test != 'data':
        models.update({'measured' : measured_result})
    
    measurements = collections.OrderedDict()
    for key, value in results['k_value_results'].iteritems():
        measurements['k = ' + str( key )] = value
    
    # get some spread in x    
    graphs = spread_x( measurements.values(), bin_edges )
    for key, graph in zip( measurements.keys(), graphs ):
        measurements[key] = graph

    histogram_properties = Histogram_properties()
    histogram_properties.name = channel + '_' + variable + '_' + method + '_' + test
    histogram_properties.title = title + ', ' + latex_labels.b_tag_bins_latex['2orMoreBtags']
    histogram_properties.x_axis_title = '$' + latex_labels.variables_latex[variable] + '$'
    histogram_properties.y_axis_title = r'Events'
#     histogram_properties.y_limits = [0, 0.03]
    histogram_properties.x_limits = [bin_edges[0], bin_edges[-1]]

    if log_plots:
        histogram_properties.set_log_y = True
        histogram_properties.name += '_log'

    compare_measurements( models, measurements, show_measurement_errors = True,
                          histogram_properties = histogram_properties,
                          save_folder = plot_location, save_as = ['pdf'] )
def plot_fit_results(fit_results, initial_values, channel):
    global variable, output_folder

    title = electron_histogram_title if channel == 'electron' else muon_histogram_title

    histogram_properties = Histogram_properties()
    histogram_properties.title = title

    histogram_properties.x_axis_title = variable + ' [GeV]'
    histogram_properties.mc_error = 0.0
    histogram_properties.legend_location = 'upper right'
    # we will need 4 histograms: TTJet, SingleTop, QCD, V+Jets
    for sample in ['TTJet', 'SingleTop', 'QCD', 'V+Jets']:
        histograms = {}
        # absolute eta measurement as baseline
        h_absolute_eta = None
        h_before = None
        histogram_properties.y_axis_title = 'Fitted number of events for ' + samples_latex[
            sample]

        for fit_var_input in fit_results.keys():
            latex_string = create_latex_string(fit_var_input)
            fit_data = fit_results[fit_var_input][sample]
            h = value_error_tuplelist_to_hist(fit_data, bin_edges[variable])
            if fit_var_input == 'absolute_eta':
                h_absolute_eta = h
            elif fit_var_input == 'before':
                h_before = h
            else:
                histograms[latex_string] = h
        graphs = spread_x(histograms.values(), bin_edges[variable])
        for key, graph in zip(histograms.keys(), graphs):
            histograms[key] = graph
        filename = sample.replace('+', '_') + '_fit_var_comparison_' + channel
        histogram_properties.name = filename
        histogram_properties.y_limits = 0, limit_range_y(
            h_absolute_eta)[1] * 1.3
        histogram_properties.x_limits = bin_edges[variable][0], bin_edges[
            variable][-1]

        h_initial_values = value_error_tuplelist_to_hist(
            initial_values[sample], bin_edges[variable])
        h_initial_values.Scale(closure_tests['simple'][sample])

        compare_measurements(models={
            fit_variables_latex['absolute_eta']: h_absolute_eta,
            'initial values': h_initial_values,
            'before': h_before
        },
                             measurements=histograms,
                             show_measurement_errors=True,
                             histogram_properties=histogram_properties,
                             save_folder=output_folder,
                             save_as=['png', 'pdf'])
def plot_fit_results(fit_results, initial_values, channel):
    global variable, output_folder

    title = electron_histogram_title if channel == "electron" else muon_histogram_title

    histogram_properties = Histogram_properties()
    histogram_properties.title = title

    histogram_properties.x_axis_title = variable + " [GeV]"
    histogram_properties.mc_error = 0.0
    histogram_properties.legend_location = "upper right"
    # we will need 4 histograms: TTJet, SingleTop, QCD, V+Jets
    for sample in ["TTJet", "SingleTop", "QCD", "V+Jets"]:
        histograms = {}
        # absolute eta measurement as baseline
        h_absolute_eta = None
        h_before = None
        histogram_properties.y_axis_title = "Fitted number of events for " + samples_latex[sample]

        for fit_var_input in fit_results.keys():
            latex_string = create_latex_string(fit_var_input)
            fit_data = fit_results[fit_var_input][sample]
            h = value_error_tuplelist_to_hist(fit_data, bin_edges[variable])
            if fit_var_input == "absolute_eta":
                h_absolute_eta = h
            elif fit_var_input == "before":
                h_before = h
            else:
                histograms[latex_string] = h
        graphs = spread_x(histograms.values(), bin_edges[variable])
        for key, graph in zip(histograms.keys(), graphs):
            histograms[key] = graph
        filename = sample.replace("+", "_") + "_fit_var_comparison_" + channel
        histogram_properties.name = filename
        histogram_properties.y_limits = 0, limit_range_y(h_absolute_eta)[1] * 1.3
        histogram_properties.x_limits = bin_edges[variable][0], bin_edges[variable][-1]

        h_initial_values = value_error_tuplelist_to_hist(initial_values[sample], bin_edges[variable])
        h_initial_values.Scale(closure_tests["simple"][sample])

        compare_measurements(
            models={
                fit_variables_latex["absolute_eta"]: h_absolute_eta,
                "initial values": h_initial_values,
                "before": h_before,
            },
            measurements=histograms,
            show_measurement_errors=True,
            histogram_properties=histogram_properties,
            save_folder=output_folder,
            save_as=["png", "pdf"],
        )
def plot_fit_results( fit_results, initial_values, channel ):
    global variable, output_folder
    
    title = electron_histogram_title if channel == 'electron' else muon_histogram_title
    
    
    histogram_properties = Histogram_properties()
    histogram_properties.title = title
    
    histogram_properties.x_axis_title = variable + ' [GeV]'
    histogram_properties.mc_error = 0.0
    histogram_properties.legend_location = 'upper right'
    # we will need 4 histograms: TTJet, SingleTop, QCD, V+Jets
    for sample in ['TTJet', 'SingleTop', 'QCD', 'V+Jets']:
        histograms = {}
        # absolute eta measurement as baseline
        h_absolute_eta = None
        h_before = None
        histogram_properties.y_axis_title = 'Fitted number of events for ' + samples_latex[sample]
        
        for fit_var_input in fit_results.keys():
            latex_string = create_latex_string( fit_var_input )
            fit_data = fit_results[fit_var_input][sample]
            h = value_error_tuplelist_to_hist( fit_data,
                                              bin_edges[variable] )
            if fit_var_input == 'absolute_eta':
                h_absolute_eta = h
            elif fit_var_input == 'before':
                h_before = h
            else:
                histograms[latex_string] = h
        graphs = spread_x( histograms.values(), bin_edges[variable] )
        for key, graph in zip( histograms.keys(), graphs ):
            histograms[key] = graph
        filename = sample.replace( '+', '_' ) + '_fit_var_comparison_' + channel
        histogram_properties.name = filename
        histogram_properties.y_limits = 0, limit_range_y( h_absolute_eta )[1] * 1.3
        histogram_properties.x_limits = bin_edges[variable][0], bin_edges[variable][-1]
        
        h_initial_values = value_error_tuplelist_to_hist( initial_values[sample],
                                                         bin_edges[variable] )
        h_initial_values.Scale(closure_tests['simple'][sample])
        
        compare_measurements( models = {fit_variables_latex['absolute_eta']:h_absolute_eta,
                                        'initial values' : h_initial_values,
                                        'before': h_before},
                             measurements = histograms,
                             show_measurement_errors = True,
                             histogram_properties = histogram_properties,
                             save_folder = output_folder,
                             save_as = ['png', 'pdf'] )
def compare_vjets_templates(variable='MET',
                            met_type='patType1CorrectedPFMet',
                            title='Untitled',
                            channel='electron'):
    ''' Compares the V+jets templates in different bins
     of the current variable'''
    global fit_variable_properties, b_tag_bin, save_as
    variable_bins = variable_bins_ROOT[variable]
    histogram_template = get_histogram_template(variable)

    for fit_variable in electron_fit_variables:
        all_hists = {}
        inclusive_hist = None
        save_path = 'plots/%dTeV/fit_variables/%s/%s/' % (
            measurement_config.centre_of_mass_energy, variable, fit_variable)
        make_folder_if_not_exists(save_path + '/vjets/')

        max_bins = len(variable_bins)
        for bin_range in variable_bins[0:max_bins]:

            params = {
                'met_type': met_type,
                'bin_range': bin_range,
                'fit_variable': fit_variable,
                'b_tag_bin': b_tag_bin,
                'variable': variable
            }
            fit_variable_distribution = histogram_template % params
            # format: histograms['data'][qcd_fit_variable_distribution]
            histograms = get_histograms_from_files([fit_variable_distribution],
                                                   histogram_files)
            prepare_histograms(
                histograms,
                rebin=fit_variable_properties[fit_variable]['rebin'],
                scale_factor=measurement_config.luminosity_scale)
            all_hists[bin_range] = histograms['V+Jets'][
                fit_variable_distribution]

        # create the inclusive distributions
        inclusive_hist = deepcopy(all_hists[variable_bins[0]])
        for bin_range in variable_bins[1:max_bins]:
            inclusive_hist += all_hists[bin_range]
        for bin_range in variable_bins[0:max_bins]:
            if not all_hists[bin_range].Integral() == 0:
                all_hists[bin_range].Scale(1 / all_hists[bin_range].Integral())
        # normalise all histograms
        inclusive_hist.Scale(1 / inclusive_hist.Integral())
        # now compare inclusive to all bins
        histogram_properties = Histogram_properties()
        histogram_properties.x_axis_title = fit_variable_properties[
            fit_variable]['x-title']
        histogram_properties.y_axis_title = fit_variable_properties[
            fit_variable]['y-title']
        histogram_properties.y_axis_title = histogram_properties.y_axis_title.replace(
            'Events', 'a.u.')
        histogram_properties.x_limits = [
            fit_variable_properties[fit_variable]['min'],
            fit_variable_properties[fit_variable]['max']
        ]
        histogram_properties.title = title
        histogram_properties.additional_text = channel_latex[
            channel] + ', ' + b_tag_bins_latex[b_tag_bin]
        histogram_properties.name = variable + '_' + fit_variable + '_' + b_tag_bin + '_VJets_template_comparison'
        histogram_properties.y_max_scale = 1.5
        measurements = {
            bin_range + ' GeV': histogram
            for bin_range, histogram in all_hists.iteritems()
        }
        measurements = OrderedDict(sorted(measurements.items()))
        fit_var = fit_variable.replace('electron_', '')
        fit_var = fit_var.replace('muon_', '')
        graphs = spread_x(measurements.values(),
                          fit_variable_bin_edges[fit_var])
        for key, graph in zip(sorted(measurements.keys()), graphs):
            measurements[key] = graph
        compare_measurements(models={'inclusive': inclusive_hist},
                             measurements=measurements,
                             show_measurement_errors=True,
                             histogram_properties=histogram_properties,
                             save_folder=save_path + '/vjets/',
                             save_as=save_as)
Ejemplo n.º 7
0
def make_shape_comparison_plot( shapes = [],
                                   names = [],
                                   colours = [],
                                   histogram_properties = Histogram_properties(),
                                   fill_area = True,
                                   make_ratio = False,
                                   alpha = 0.5,
                                   save_folder = 'plots/',
                                   save_as = ['pdf', 'png'],
                                   normalise_ratio_to_errors = False ):
    save_folder = check_save_folder(save_folder)
    # make copies in order not to mess with existing histograms
    shapes_ = deepcopy(shapes)
    # normalise as we are comparing shapes
    for shape, colour, label in zip(shapes_, colours, names):
        shape.SetTitle(label)
        integral = shape.Integral()
        if integral > 0:
            shape.Sumw2()
            shape.Scale( 1 / integral )
        if fill_area:
            shape.fillcolor = colour
            shape.fillstyle = 'solid'
            shape.legendstyle = 'F'
        else:
            shape.linecolor = colour
            shape.legendstyle = 'F'
            shape.linewidth = 5
            
    if not histogram_properties.y_limits:
        histogram_properties.y_limits = [0, get_best_max_y(shapes_, False)]
    # plot with matplotlib
    plt.figure( figsize = CMS.figsize, dpi = CMS.dpi, facecolor = CMS.facecolor )
    gs = gridspec.GridSpec( 2, 1, height_ratios = [5, 1] )
    axes = None
    if make_ratio: 
        axes = plt.subplot( gs[0] )
    else:
        axes = plt.axes()
    axes.minorticks_on()
    
    for shape in shapes_:
        rplt.hist( shape, axes = axes, alpha = alpha )
    
    set_labels( plt, histogram_properties, show_x_label = not make_ratio, axes = axes )
    handles, labels = axes.get_legend_handles_labels()
    for i,name in enumerate(names):
        labels.insert(i, name)

    # always fill legends
    if not fill_area:
        for handle in handles:
            handle.set_fill(True)
            handle.set_facecolor(handle.get_edgecolor())

    l1 = axes.legend( handles, labels, numpoints = 1,
                     frameon = histogram_properties.legend_color,
                bbox_to_anchor = histogram_properties.legend_location,
                bbox_transform=plt.gcf().transFigure,
                prop = CMS.legend_properties,
                ncol = histogram_properties.legend_columns )
    l1.set_zorder(102)
    #add error bars
    graphs = spread_x(shapes_, list(shapes_[0].xedges()))
    for graph in graphs:
        rplt.errorbar( graph, axes = axes )

    adjust_axis_limits(axes, histogram_properties, shapes_)
    if make_ratio:
        plt.setp( axes.get_xticklabels(), visible = False )
        ratios = get_histogram_ratios(shapes_[0], shapes_[1:], normalise_ratio_to_errors)
        ax1 = plt.subplot( gs[1] )
        ax1.minorticks_on()
        ax1.grid( True, 'major', linewidth = 1 )
        set_labels( plt, histogram_properties, show_x_label = True, show_title = False )
        if normalise_ratio_to_errors:
            plt.ylabel( r'$\frac{1-2}{\sqrt{(\sigma_1)^2 + (\sigma_2)^2}}$', CMS.y_axis_title )
        else:
            plt.ylabel( '(1)/(2)', CMS.y_axis_title )
        for ratio in ratios:
            ratio.SetMarkerSize( 2 )
            rplt.errorbar( ratio, xerr = True,
                           emptybins = histogram_properties.emptybins,
                           axes = ax1 )
        if len( histogram_properties.x_limits ) == 2:
            ax1.set_xlim( xmin = histogram_properties.x_limits[0], 
                          xmax = histogram_properties.x_limits[1] )
        if len( histogram_properties.ratio_y_limits ) == 2:
            ax1.set_ylim( ymin = histogram_properties.ratio_y_limits[0],
                      ymax = histogram_properties.ratio_y_limits[1] )
        # dynamic tick placement
        adjust_ratio_ticks(ax1.yaxis, n_ticks = 3)
    
    if CMS.tight_layout:
        plt.tight_layout()
    
    for save in save_as:
        plt.savefig( save_folder + histogram_properties.name + '.' + save ) 
    plt.close()
def debug_last_bin():
    '''
        For debugging why the last bin in the problematic variables deviates a
        lot in _one_ of the channels only.
    '''
    file_template = '/hdfs/TopQuarkGroup/run2/dpsData/'
    file_template += 'data/normalisation/background_subtraction/13TeV/'
    file_template += '{variable}/VisiblePS/central/'
    file_template += 'normalised_xsection_{channel}_RooUnfoldSvd{suffix}.txt'
    problematic_variables = ['HT', 'MET', 'NJets', 'lepton_pt']

    for variable in problematic_variables:
        results = {}
        Result = namedtuple('Result',
                            ['before_unfolding', 'after_unfolding', 'model'])
        for channel in ['electron', 'muon', 'combined']:
            input_file_data = file_template.format(
                variable=variable,
                channel=channel,
                suffix='_with_errors',
            )
            input_file_model = file_template.format(
                variable=variable,
                channel=channel,
                suffix='',
            )
            data = read_data_from_JSON(input_file_data)
            data_model = read_data_from_JSON(input_file_model)
            before_unfolding = data['TTJet_measured_withoutFakes']
            after_unfolding = data['TTJet_unfolded']

            model = data_model['powhegPythia8']

            # only use the last bin
            h_before_unfolding = value_errors_tuplelist_to_graph(
                [before_unfolding[-1]], bin_edges_vis[variable][-2:])
            h_after_unfolding = value_errors_tuplelist_to_graph(
                [after_unfolding[-1]], bin_edges_vis[variable][-2:])
            h_model = value_error_tuplelist_to_hist(
                [model[-1]], bin_edges_vis[variable][-2:])

            r = Result(before_unfolding, after_unfolding, model)
            h = Result(h_before_unfolding, h_after_unfolding, h_model)
            results[channel] = (r, h)

        models = {'POWHEG+PYTHIA': results['combined'][1].model}
        h_unfolded = [
            results[channel][1].after_unfolding
            for channel in ['electron', 'muon', 'combined']
        ]
        tmp_hists = spread_x(h_unfolded, bin_edges_vis[variable][-2:])
        measurements = {}
        for channel, hist in zip(['electron', 'muon', 'combined'], tmp_hists):
            value = results[channel][0].after_unfolding[-1][0]
            error = results[channel][0].after_unfolding[-1][1]
            label = '{c_label} ({value:1.2g} $\pm$ {error:1.2g})'.format(
                c_label=channel,
                value=value,
                error=error,
            )
            measurements[label] = hist

        properties = Histogram_properties()
        properties.name = 'normalised_xsection_compare_channels_{0}_{1}_last_bin'.format(
            variable, channel)
        properties.title = 'Comparison of channels'
        properties.path = 'plots'
        properties.has_ratio = True
        properties.xerr = False
        properties.x_limits = (bin_edges_vis[variable][-2],
                               bin_edges_vis[variable][-1])
        properties.x_axis_title = variables_latex[variable]
        properties.y_axis_title = r'$\frac{1}{\sigma}  \frac{d\sigma}{d' + \
            variables_latex[variable] + '}$'
        properties.legend_location = (0.95, 0.40)
        if variable == 'NJets':
            properties.legend_location = (0.97, 0.80)
        properties.formats = ['png']

        compare_measurements(models=models,
                             measurements=measurements,
                             show_measurement_errors=True,
                             histogram_properties=properties,
                             save_folder='plots/',
                             save_as=properties.formats)
def debug_last_bin():
    '''
        For debugging why the last bin in the problematic variables deviates a
        lot in _one_ of the channels only.
    '''
    file_template = '/hdfs/TopQuarkGroup/run2/dpsData/'
    file_template += 'data/normalisation/background_subtraction/13TeV/'
    file_template += '{variable}/VisiblePS/central/'
    file_template += 'normalised_xsection_{channel}_RooUnfoldSvd{suffix}.txt'
    problematic_variables = ['HT', 'MET', 'NJets', 'lepton_pt']

    for variable in problematic_variables:
        results = {}
        Result = namedtuple(
            'Result', ['before_unfolding', 'after_unfolding', 'model'])
        for channel in ['electron', 'muon', 'combined']:
            input_file_data = file_template.format(
                variable=variable,
                channel=channel,
                suffix='_with_errors',
            )
            input_file_model = file_template.format(
                variable=variable,
                channel=channel,
                suffix='',
            )
            data = read_data_from_JSON(input_file_data)
            data_model = read_data_from_JSON(input_file_model)
            before_unfolding = data['TTJet_measured_withoutFakes']
            after_unfolding = data['TTJet_unfolded']

            model = data_model['powhegPythia8']

            # only use the last bin
            h_before_unfolding = value_errors_tuplelist_to_graph(
                [before_unfolding[-1]], bin_edges_vis[variable][-2:])
            h_after_unfolding = value_errors_tuplelist_to_graph(
                [after_unfolding[-1]], bin_edges_vis[variable][-2:])
            h_model = value_error_tuplelist_to_hist(
                [model[-1]], bin_edges_vis[variable][-2:])

            r = Result(before_unfolding, after_unfolding, model)
            h = Result(h_before_unfolding, h_after_unfolding, h_model)
            results[channel] = (r, h)

        models = {'POWHEG+PYTHIA': results['combined'][1].model}
        h_unfolded = [results[channel][1].after_unfolding for channel in [
            'electron', 'muon', 'combined']]
        tmp_hists = spread_x(h_unfolded, bin_edges_vis[variable][-2:])
        measurements = {}
        for channel, hist in zip(['electron', 'muon', 'combined'], tmp_hists):
            value = results[channel][0].after_unfolding[-1][0]
            error = results[channel][0].after_unfolding[-1][1]
            label = '{c_label} ({value:1.2g} $\pm$ {error:1.2g})'.format(
                    c_label=channel,
                    value=value,
                    error=error,
            )
            measurements[label] = hist

        properties = Histogram_properties()
        properties.name = 'normalised_xsection_compare_channels_{0}_{1}_last_bin'.format(
            variable, channel)
        properties.title = 'Comparison of channels'
        properties.path = 'plots'
        properties.has_ratio = True
        properties.xerr = False
        properties.x_limits = (
            bin_edges_vis[variable][-2], bin_edges_vis[variable][-1])
        properties.x_axis_title = variables_latex[variable]
        properties.y_axis_title = r'$\frac{1}{\sigma}  \frac{d\sigma}{d' + \
            variables_latex[variable] + '}$'
        properties.legend_location = (0.95, 0.40)
        if variable == 'NJets':
            properties.legend_location = (0.97, 0.80)
        properties.formats = ['png']

        compare_measurements(models=models, measurements=measurements, show_measurement_errors=True,
                             histogram_properties=properties, save_folder='plots/', save_as=properties.formats)
Ejemplo n.º 10
0
def make_shape_comparison_plot(shapes=[],
                               names=[],
                               colours=[],
                               histogram_properties=Histogram_properties(),
                               fill_area=True,
                               make_ratio=False,
                               alpha=0.5,
                               save_folder='plots/',
                               save_as=['pdf', 'png'],
                               normalise_ratio_to_errors=False):
    save_folder = check_save_folder(save_folder)
    # make copies in order not to mess with existing histograms
    shapes_ = deepcopy(shapes)
    # normalise as we are comparing shapes
    for shape, colour, label in zip(shapes_, colours, names):
        shape.SetTitle(label)
        integral = shape.Integral()
        if integral > 0:
            shape.Sumw2()
            shape.Scale(1 / integral)
        if fill_area:
            shape.fillcolor = colour
            shape.fillstyle = 'solid'
            shape.legendstyle = 'F'
        else:
            shape.linecolor = colour
            shape.legendstyle = 'F'
            shape.linewidth = 5

    if not histogram_properties.y_limits:
        histogram_properties.y_limits = [0, get_best_max_y(shapes_, False)]
    # plot with matplotlib
    plt.figure(figsize=CMS.figsize, dpi=CMS.dpi, facecolor=CMS.facecolor)
    gs = gridspec.GridSpec(2, 1, height_ratios=[5, 1])
    axes = None
    if make_ratio:
        axes = plt.subplot(gs[0])
    else:
        axes = plt.axes()
    axes.minorticks_on()

    for shape in shapes_:
        rplt.hist(shape, axes=axes, alpha=alpha)

    set_labels(plt,
               histogram_properties,
               show_x_label=not make_ratio,
               axes=axes)
    handles, labels = axes.get_legend_handles_labels()
    for i, name in enumerate(names):
        labels.insert(i, name)

    # always fill legends
    if not fill_area:
        for handle in handles:
            handle.set_fill(True)
            handle.set_facecolor(handle.get_edgecolor())

    l1 = axes.legend(handles,
                     labels,
                     numpoints=1,
                     frameon=histogram_properties.legend_color,
                     bbox_to_anchor=histogram_properties.legend_location,
                     bbox_transform=plt.gcf().transFigure,
                     prop=CMS.legend_properties,
                     ncol=histogram_properties.legend_columns)
    l1.set_zorder(102)
    #add error bars
    graphs = spread_x(shapes_, list(shapes_[0].xedges()))
    for graph in graphs:
        rplt.errorbar(graph, axes=axes)

    adjust_axis_limits(axes, histogram_properties, shapes_)
    if make_ratio:
        plt.setp(axes.get_xticklabels(), visible=False)
        ratios = get_histogram_ratios(shapes_[0], shapes_[1:],
                                      normalise_ratio_to_errors)
        ax1 = plt.subplot(gs[1])
        ax1.minorticks_on()
        ax1.grid(True, 'major', linewidth=1)
        set_labels(plt,
                   histogram_properties,
                   show_x_label=True,
                   show_title=False)
        if normalise_ratio_to_errors:
            plt.ylabel(r'$\frac{1-2}{\sqrt{(\sigma_1)^2 + (\sigma_2)^2}}$',
                       CMS.y_axis_title)
        else:
            plt.ylabel('(1)/(2)', CMS.y_axis_title)
        for ratio in ratios:
            ratio.SetMarkerSize(2)
            rplt.errorbar(ratio,
                          xerr=True,
                          emptybins=histogram_properties.emptybins,
                          axes=ax1)
        if len(histogram_properties.x_limits) == 2:
            ax1.set_xlim(xmin=histogram_properties.x_limits[0],
                         xmax=histogram_properties.x_limits[1])
        if len(histogram_properties.ratio_y_limits) == 2:
            ax1.set_ylim(ymin=histogram_properties.ratio_y_limits[0],
                         ymax=histogram_properties.ratio_y_limits[1])
        # dynamic tick placement
        adjust_ratio_ticks(ax1.yaxis, n_ticks=3)

    if CMS.tight_layout:
        plt.tight_layout()

    for save in save_as:
        plt.savefig(save_folder + histogram_properties.name + '.' + save)
    plt.close()