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)
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
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)
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)
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)