示例#1
0
def fit_subtracted_signal_dominated(
        analysis: "correlations.Correlations") -> None:
    """ Plot the subtracted signal dominated hist. """
    # Setup
    fig, ax = plt.subplots(figsize=(8, 6))
    hists = analysis.correlation_hists_delta_phi_subtracted
    h = hists.signal_dominated.hist

    # Plot the subtracted hist
    ax.errorbar(
        h.x,
        h.y,
        yerr=h.errors,
        label=f"Subtracted {hists.signal_dominated.type.display_str()}",
        marker="o",
        linestyle="",
    )
    # Plot the background uncertainty separately.
    background_error = analysis.fit_object.calculate_background_function_errors(
        h.x)
    ax.fill_between(
        h.x,
        h.y - background_error,
        h.y + background_error,
        label="RP background uncertainty",
        color=plot_base.AnalysisColors.fit,
    )
    # Line for comparison
    ax.axhline(y=0, color="black", linestyle="dashed", zorder=1)

    # Labels.
    ax.set_xlabel(
        labels.make_valid_latex_string(
            hists.signal_dominated.axis.display_str()))
    ax.set_ylabel(labels.make_valid_latex_string(
        labels.delta_phi_axis_label()))
    jet_pt_label = labels.jet_pt_range_string(analysis.jet_pt)
    track_pt_label = labels.track_pt_range_string(analysis.track_pt)
    ax.set_title(
        fr"Subtracted 1D ${hists.signal_dominated.axis.display_str()}$,"
        f" {analysis.reaction_plane_orientation.display_str()} event plane orient.,"
        f" {jet_pt_label}, {track_pt_label}")
    ax.legend(loc="upper right", frameon=False)

    # Final adjustments
    fig.tight_layout()
    # Save plot and cleanup
    plot_base.save_plot(analysis.output_info, fig,
                        f"jetH_delta_phi_{analysis.identifier}_subtracted")
    plt.close(fig)
示例#2
0
def test_delta_phi_axis_label(logging_mixin, include_normalized_by_n_trig,
                              expected):
    """ Test for the delta phi axis label. """
    label = labels.delta_phi_axis_label(
        normalized_by_n_trig=include_normalized_by_n_trig)
    assert label == expected
示例#3
0
def plot_RP_fit(rp_fit: reaction_plane_fit.fit.ReactionPlaneFit,
                inclusive_analysis: "correlations.Correlations",
                ep_analyses: List[Tuple[Any, "correlations.Correlations"]],
                output_info: analysis_objects.PlottingOutputWrapper,
                output_name: str) -> None:
    """ Basic plot of the reaction plane fit.

    Args:
        rp_fit: Reaction plane fit object.
        inclusive_analysis: Inclusive analysis object. Mainly used for labeling.
        ep_analyses: Event plane dependent correlation analysis objects.
        output_info: Output information.
        output_name: Name of the output plot.
    Returns:
        None. The plot will be saved.
    """
    # Setup
    n_components = len(rp_fit.components)
    fig, axes = plt.subplots(2,
                             n_components,
                             sharey="row",
                             sharex=True,
                             gridspec_kw={"height_ratios": [3, 1]},
                             figsize=(3 * n_components, 6))
    flat_axes = axes.flatten()

    # Plot the fits on the upper panels.
    _plot_rp_fit_components(rp_fit=rp_fit,
                            ep_analyses=ep_analyses,
                            axes=flat_axes[:n_components])
    # Plot the residuals on the lower panels.
    _plot_rp_fit_residuals(rp_fit=rp_fit,
                           ep_analyses=ep_analyses,
                           axes=flat_axes[n_components:])

    # Define upper panel labels.
    # In-plane
    text = labels.track_pt_range_string(inclusive_analysis.track_pt)
    text += "\n" + labels.constituent_cuts()
    text += "\n" + labels.make_valid_latex_string(
        inclusive_analysis.leading_hadron_bias.display_str())
    _add_label_to_rpf_plot_axis(ax=flat_axes[0], label=text)
    # Mid-plane
    text = labels.make_valid_latex_string(
        inclusive_analysis.alice_label.display_str())
    text += "\n" + labels.system_label(
        energy=inclusive_analysis.collision_energy,
        system=inclusive_analysis.collision_system,
        activity=inclusive_analysis.event_activity)
    text += "\n" + labels.jet_pt_range_string(inclusive_analysis.jet_pt)
    text += "\n" + labels.jet_finding()
    _add_label_to_rpf_plot_axis(ax=flat_axes[1], label=text)
    # Out-of-plane
    #text = "Background: $0.8<|\Delta\eta|<1.2$"
    #text += "\nSignal + Background: $|\Delta\eta|<0.6$"
    #_add_label_to_rpf_plot_axis(ax = flat_axes[2], label = text)
    # Inclusive
    text = (r"\chi^{2}/\mathrm{NDF} = "
            f"{rp_fit.fit_result.minimum_val:.1f}/{rp_fit.fit_result.nDOF} = "
            f"{rp_fit.fit_result.minimum_val / rp_fit.fit_result.nDOF:.3f}")
    _add_label_to_rpf_plot_axis(ax=flat_axes[2],
                                label=labels.make_valid_latex_string(text))

    # Define lower panel labels.
    for ax in flat_axes[n_components:]:
        # Increase the frequency of major ticks to once every integer.
        ax.xaxis.set_major_locator(matplotlib.ticker.MultipleLocator(base=1.0))
        # Add axis labels
        ax.set_xlabel(
            labels.make_valid_latex_string(
                inclusive_analysis.correlation_hists_delta_phi.
                signal_dominated.axis.display_str()))
    # Improve the viewable range for the lower panels.
    # This value is somewhat arbitrarily selected, but seems to work well enough.
    flat_axes[n_components].set_ylim(-0.2, 0.2)

    # Specify shared y axis label
    # Delta phi correlations first
    flat_axes[0].set_ylabel(labels.delta_phi_axis_label())
    # Then label the residual
    flat_axes[n_components].set_ylabel("data - fit / fit")

    # Final adjustments
    fig.tight_layout()
    # Reduce spacing between subplots
    fig.subplots_adjust(hspace=0, wspace=0)
    # Save plot and cleanup
    plot_base.save_plot(output_info, fig, output_name)
    plt.close(fig)
示例#4
0
def rp_fit_subtracted(ep_analyses: List[Tuple[Any,
                                              "correlations.Correlations"]],
                      inclusive_analysis: "correlations.Correlations",
                      output_info: analysis_objects.PlottingOutputWrapper,
                      output_name: str) -> None:
    """ Basic plot of the reaction plane fit subtracted hists.

    Args:
        ep_analyses: Event plane dependent correlation analysis objects.
        inclusive_analysis: Inclusive analysis object. Mainly used for labeling.
        output_info: Output information.
        output_name: Name of the output plot.
    Returns:
        None. The plot will be saved.
    """
    # Setup
    n_components = len(ep_analyses)
    fig, axes = plt.subplots(
        1,
        n_components,
        sharey="row",
        sharex=True,
        #gridspec_kw = {"height_ratios": [3, 1]},
        figsize=(3 * n_components, 6))
    flat_axes = axes.flatten()

    # Plot the fits on the upper panels.
    _plot_rp_fit_subtracted(ep_analyses=ep_analyses,
                            axes=flat_axes[:n_components])

    # Define upper panel labels.
    # In-plane
    text = labels.track_pt_range_string(inclusive_analysis.track_pt)
    text += "\n" + labels.constituent_cuts()
    text += "\n" + labels.make_valid_latex_string(
        inclusive_analysis.leading_hadron_bias.display_str())
    _add_label_to_rpf_plot_axis(ax=flat_axes[0], label=text)
    # Mid-plane
    text = labels.make_valid_latex_string(
        inclusive_analysis.alice_label.display_str())
    text += "\n" + labels.system_label(
        energy=inclusive_analysis.collision_energy,
        system=inclusive_analysis.collision_system,
        activity=inclusive_analysis.event_activity)
    text += "\n" + labels.jet_pt_range_string(inclusive_analysis.jet_pt)
    text += "\n" + labels.jet_finding()
    _add_label_to_rpf_plot_axis(ax=flat_axes[1], label=text)
    # Out-of-plane
    #text = "Background: $0.8<|\Delta\eta|<1.2$"
    #text += "\nSignal + Background: $|\Delta\eta|<0.6$"
    #_add_label_to_rpf_plot_axis(ax = flat_axes[2], label = text)
    _add_label_to_rpf_plot_axis(ax=flat_axes[2],
                                label=labels.make_valid_latex_string(text))

    for ax in flat_axes:
        # Increase the frequency of major ticks to once every integer.
        ax.xaxis.set_major_locator(matplotlib.ticker.MultipleLocator(base=1.0))
        # Set label
        ax.set_xlabel(labels.make_valid_latex_string(r"\Delta\varphi"))

    flat_axes[0].set_ylabel(
        labels.make_valid_latex_string(labels.delta_phi_axis_label()))
    #jet_pt_label = labels.jet_pt_range_string(inclusive_analysis.jet_pt)
    #track_pt_label = labels.track_pt_range_string(inclusive_analysis.track_pt)
    #ax.set_title(fr"Subtracted 1D ${inclusive_analysis.correlation_hists_delta_phi_subtracted.signal_dominated.axis.display_str()}$,"
    #             f" {inclusive_analysis.reaction_plane_orientation.display_str()} event plane orient.,"
    #             f" {jet_pt_label}, {track_pt_label}")
    ax.legend(loc="upper right")

    # Final adjustments
    fig.tight_layout()
    # Reduce spacing between subplots
    fig.subplots_adjust(hspace=0, wspace=0)
    # Save plot and cleanup
    plot_base.save_plot(
        output_info, fig,
        f"jetH_delta_phi_{inclusive_analysis.identifier}_rp_subtracted")
    plt.close(fig)
def simplified_mixed_event_comparison(output_info: analysis_objects.PlottingOutputWrapper,
                                      # For labeling purposes
                                      output_name: str, eta_limits: Sequence[float],
                                      jet_pt_title: str, track_pt_title: str,
                                      # Mixed event 1D hist
                                      mixed_event_1D: histogram.Histogram1D,
                                      max_moving_avg: float,
                                      fit_1D: float, fit_2D: float) -> None:
    """ Simplified mixed event comparison.

    Args:
        output_info: Standard information needed to store the output.
        output_name: Output name.
        eta_limits: Eta limits.
        jet_pt_title: Jet pt title for labeling.
        track_pt_title: Track pt title for labeling.
        mixed_event_1D: 1D mixed event.
        max_moving_avg: Maximum of the moving average (nominal value).
        fit_1D: Max value from a 1D fit.
        fit_2D: Max value from a 2D fit.
    Returns:
        None. The comparison is plotted.
    """
    # Setup
    fig, ax = plt.subplots(figsize = (8, 6))
    hist = histogram.Histogram1D.from_existing_hist(mixed_event_1D)

    # Plot the data
    ax.errorbar(
        hist.x, hist.y, yerr = hist.errors, linestyle = "", marker = "o",
        label = "Mixed event",
    )
    # Plot the lines
    ax.axhline(
        max_moving_avg, xmin = 0.4, xmax = 1,
        label = r"Moving avg. (size $\pi$)", color = "tab:orange"
    )
    ax.axhline(
        fit_1D, xmin = 0.5, xmax = 1,
        label = r"1D fit ($\pi/2-3\pi/2$)", color = "tab:purple"
    )
    ax.axhline(
        fit_2D, xmin = 0.5, xmax = 1,
        label = r"2D fit ($\pi/2-3\pi/2$)", linestyle = "--", color = "tab:purple"
    )

    # Label delta eta range.
    ax.text(
        0.05, 0.95, fr"$|\Delta\eta| < {eta_limits[1]}$", horizontalalignment = "left",
        verticalalignment = "top", multialignment = "left",
        transform = ax.transAxes
    )

    # Legend and Labels for the plot
    ax.legend(loc = "lower right", frameon = False)
    ax.set_title(f"ME norm. for {jet_pt_title}, {track_pt_title}")
    ax.set_ylabel(labels.delta_phi_axis_label())
    ax.set_xlabel(r"$\Delta\varphi$")

    # Final adjustments
    plt.tight_layout()
    # Cleanup and save
    plot_base.save_plot(output_info, fig, output_name)
    plt.close(fig)
def mixed_event_normalization(output_info: analysis_objects.PlottingOutputWrapper,
                              # For labeling purposes
                              output_name: str, eta_limits: Sequence[float], jet_pt_title: str, track_pt_title: str,
                              # Basic data
                              lin_space: np.ndarray,       peak_finding_hist_array: np.ndarray,  # noqa: E241
                              lin_space_rebin: np.ndarray, peak_finding_hist_array_rebin: np.ndarray,
                              # CWT
                              peak_locations: np.ndarray, peak_locations_rebin: np.ndarray,
                              # Moving Average
                              max_moving_avg: float, max_moving_avg_rebin: float,
                              # Smoothed gaussian
                              lin_space_resample: np.ndarray, smoothed_array: np.ndarray, max_smoothed_moving_avg: float,
                              # Linear fits
                              max_linear_fit_1d: float, max_linear_fit_1d_rebin: float,
                              max_linear_fit_2d: float, max_linear_fit_2d_rebin: float) -> None:
    # Make the actual plot
    fig, ax = plt.subplots(figsize = (8, 6))
    # Add additional y margin at the bottom so the legend will fit a bit better
    # Cannot do asymmetric padding via `ax.set_ymargin()`, so we'll do it by hand
    # See: https://stackoverflow.com/a/42804403
    data_min = min(peak_finding_hist_array.min(), peak_finding_hist_array_rebin.min())
    data_max = max(peak_finding_hist_array.max(), peak_finding_hist_array_rebin.max())
    y_min = data_min - 0.5 * (data_max - data_min)
    y_max = data_max + 0.12 * (data_max - data_min)
    ax.set_ylim(y_min, y_max)

    # Can either plot the hist or the array
    # Hist based on: https://stackoverflow.com/a/8553614
    #ax.hist(lin_space, weights=peak_finding_hist_array, bins=len(peak_finding_hist_array))
    # If plotting the hist, it's best to set the y axis limits to make it easier to view
    #ax.set_ylim(ymin=.95*min(peak_finding_hist_array), ymax=1.05*max(peak_finding_hist_array))
    # Plot array
    ax.plot(lin_space, peak_finding_hist_array, label = "ME")
    ax.plot(lin_space_rebin, peak_finding_hist_array_rebin, label = "ME rebin")
    # Peak finding
    # Set zorder of 10 to ensure that the stars are always visible
    plot_array_peak = ax.plot(
        lin_space[peak_locations],
        peak_finding_hist_array[peak_locations],
        marker = "*", markersize = 10, linestyle = "None",
        label = "CWT", zorder = 10
    )
    plot_array_rebin_peak = ax.plot(
        lin_space_rebin[peak_locations_rebin],
        peak_finding_hist_array_rebin[peak_locations_rebin],
        marker = "*", markersize = 10, linestyle = "None",
        label = "CWT rebin", zorder = 10
    )
    # Moving average
    ax.axhline(max_moving_avg, color = plot_array_peak[0].get_color(), label = r"Mov. avg. (size $\pi$)")
    ax.axhline(max_moving_avg_rebin, color = plot_array_rebin_peak[0].get_color(), linestyle = "--", label = "Mov. avg. rebin")
    # Gaussian
    # Use a mask so the range doesn't get extremely distorted when the interpolation drops around the edges
    mask = np.where(np.logical_and(lin_space_resample > -0.3 * np.pi, lin_space_resample < 1.3 * np.pi))
    plot_gaussian = ax.plot(lin_space_resample[mask], smoothed_array[mask], label = "Gauss. smooth")
    ax.axhline(max_smoothed_moving_avg, color = plot_gaussian[0].get_color(), linestyle = "--", label ="Gauss. mov. avg")
    #ax.axhline(max_smoothed, color = plot_gaussian[0].get_color(), linestyle = ":", label = "Gauss. max")

    # Linear fits
    ax.axhline(max_linear_fit_1d, color = "g", label = "1D fit")
    ax.axhline(max_linear_fit_1d_rebin, color = "g", linestyle = "--", label = "1D fit rebin")
    ax.axhline(max_linear_fit_2d, color = "b", label = "2D fit")
    ax.axhline(max_linear_fit_2d_rebin, color = "b", linestyle = "--", label = "2D fit rebin")

    ax.text(
        0.05, 0.95, fr"$|\Delta\eta| < {eta_limits[1]}$", horizontalalignment = "left",
        verticalalignment = "top", multialignment = "left",
        transform = ax.transAxes
    )

    # Legend and Labels for the plot
    #ax.set_ymargin = 0.01
    ax.legend(loc = "lower left", ncol = 3, frameon = False)
    #ax.legend(bbox_to_anchor=(0,1.02,1,0.2), loc="lower left",
    #          ncol=3, mode="expand", borderaxespad=0)
    ax.set_title(f"ME norm. for {jet_pt_title}, {track_pt_title}")
    ax.set_ylabel(labels.delta_phi_axis_label())
    ax.set_xlabel(r"$\Delta\varphi$")

    # Final adjustments
    plt.tight_layout()
    # Cleanup and save
    plot_base.save_plot(output_info, fig, output_name)
    plt.close(fig)
示例#7
0
def delta_phi_with_gaussians(analysis: "correlations.Correlations") -> None:
    """ Plot the subtracted delta phi correlation with gaussian fits to the near and away side. """
    # Setup
    fig, ax = plt.subplots(figsize=(8, 6))
    correlation = analysis.correlation_hists_delta_phi_subtracted.signal_dominated
    h = correlation.hist

    # First we plot the data
    ax.errorbar(
        h.x,
        h.y,
        yerr=h.errors,
        marker="o",
        linestyle="",
        label=f"{correlation.type.display_str()}",
    )

    # Plot the fit.
    for attribute_name, width_obj in analysis.widths_delta_phi:
        # Setup
        # Convert the attribute name to display better. Ex: "near_side" -> "Near side"
        attribute_display_name = attribute_name.replace("_", " ").capitalize()
        # We only want to plot the fit over the range that it was fit.
        restricted_range = (h.x > width_obj.fit_object.fit_range.min) & (
            h.x < width_obj.fit_object.fit_range.max)
        x = h.x[restricted_range]

        # Plot the fit
        gauss = width_obj.fit_object(x,
                                     **width_obj.fit_result.values_at_minimum)
        fit_plot = ax.plot(
            x,
            gauss,
            label=
            fr"{attribute_display_name} gaussian fit: $\mu = $ {width_obj.mean:.2f}"
            fr", $\sigma = $ {width_obj.width:.2f}",
        )
        # Fill in the error band.
        error = width_obj.fit_object.calculate_errors(x=x)
        ax.fill_between(
            x,
            gauss - error,
            gauss + error,
            facecolor=fit_plot[0].get_color(),
            alpha=0.5,
        )

        # This means that we extracted values from the RP fit. Let's also plot them for comparison
        if width_obj.fit_args != {}:
            args = dict(width_obj.fit_result.values_at_minimum)
            args.update({
                # Help out mypy...
                k: cast(float, v)
                for k, v in width_obj.fit_args.items() if "error_" not in k
            })
            rpf_gauss = width_obj.fit_object(x, **args)
            rp_fit_plot = ax.plot(
                x,
                rpf_gauss,
                label=
                fr"RPF {attribute_display_name} gaussian fit: $\mu = $ {width_obj.mean:.2f}"
                fr", $\sigma = $ {width_obj.fit_args['width']:.2f}",
            )
            # Fill in the error band.
            # NOTE: Strictly speaking, this error band isn't quite right (since it is dependent on the fit result
            # of the actual width fit), but I think it's fine for these purposes.
            error = width_obj.fit_object.calculate_errors(x=x)
            ax.fill_between(
                x,
                rpf_gauss - error,
                rpf_gauss + error,
                facecolor=rp_fit_plot[0].get_color(),
                alpha=0.5,
            )

    # Labels.
    ax.set_xlabel(
        labels.make_valid_latex_string(correlation.axis.display_str()))
    ax.set_ylabel(labels.make_valid_latex_string(
        labels.delta_phi_axis_label()))
    jet_pt_label = labels.jet_pt_range_string(analysis.jet_pt)
    track_pt_label = labels.track_pt_range_string(analysis.track_pt)
    ax.set_title(
        fr"Subtracted 1D ${correlation.axis.display_str()}$,"
        f" {analysis.reaction_plane_orientation.display_str()} event plane orient.,"
        f" {jet_pt_label}, {track_pt_label}")
    ax.legend(loc="upper right")

    # Final adjustments
    fig.tight_layout()
    # Save plot and cleanup
    plot_base.save_plot(
        analysis.output_info, fig,
        f"jetH_delta_phi_{analysis.identifier}_width_signal_dominated_fit")
    plt.close(fig)