def _access_set_of_values_associated_with_a_bin( hist: Hist, bin_of_interest: int, response_normalization: ResponseNormalization ) -> Tuple[np.ndarray, np.ndarray]: """ Access a set of bins associated with a particular bin value in the other axis. For example, if the hist looks like this graphically: a b c d e f g h i <- values (here and above) 1 2 3 <- bin number then in the case of accessing a set of y bins associated with an x bin, for example, x bin 2, it would return values h, e, and b. Args: hist: The histogram whose bins should be accessed. This must be a 2D hist. bin_of_interest: Bin which we would like to access. response_normalization: Response normalization convention, which dictates which axis to retrieve the bins from. Returns: Array of the bin contents, Array of bin errors """ # Initial setup axis, get_bin = _setup_access_bins( response_normalization=response_normalization) #logger.debug(f"Axis: {axis(hist)}, getBin: {get_bin}") set_of_bins_content = np.zeros(axis(hist).GetNbins()) set_of_bins_errors = np.zeros(axis(hist).GetNbins()) for array_index, bin_index in enumerate(range(1, axis(hist).GetNbins() + 1)): set_of_bins_content[array_index] = hist.GetBinContent( get_bin(hist, bin_of_interest, bin_index)) set_of_bins_errors[array_index] = hist.GetBinError( get_bin(hist, bin_of_interest, bin_index)) return set_of_bins_content, set_of_bins_errors
def calculate_residual_2D(efficiency_data: Hist, efficiency_function: Callable[..., float], efficiency_period: Any, centrality_bin: int) -> Tuple[np.ndarray, List[float], List[float]]: """ Calculate residual for 2D tracking efficiency. There is a separate 1D and 2D function for convenience. If there is no entries for a particular bin, we set the value to NaN so that it can be ignored later when plotting. Args: efficiency_data: 2D efficiency data. efficiency_function: Efficiency function. efficiency_period: Efficiency period. centrality_bin: Centrality bin. Returns: Calculated residual, pt values where it was evaluated, eta values where it was evaluated. """ pts = [efficiency_data.GetXaxis().GetBinCenter(x) for x in range(1, efficiency_data.GetXaxis().GetNbins() + 1)] etas = [efficiency_data.GetYaxis().GetBinCenter(y) for y in range(1, efficiency_data.GetYaxis().GetNbins() + 1)] residual = np.zeros(shape = (efficiency_data.GetXaxis().GetNbins(), efficiency_data.GetYaxis().GetNbins())) # Loop over all of the bins in the data histogram. chi_2 = [] for pt_index, pt in enumerate(pts): for eta_index, eta in enumerate(etas): x = pt_index + 1 y = eta_index + 1 # Calculate the efficiency. It's calculated again here to ensure that it's evaluated at exactly # the same location as in the data histogram. efficiency_at_value = efficiency_function(pt, eta, centrality_bin, efficiency_period, "task_name") # Determine the histogram value, setting it to NaN if there's no entries. if np.abs(efficiency_data.GetBinContent(x, y)) < epsilon: value = np.nan else: value = (efficiency_data.GetBinContent(x, y) - efficiency_at_value) / efficiency_at_value * 100. # The points around the edges aren't super reliable for calcuating chi squared if pt > 1 and np.abs(eta) < 0.8: chi_2.append(np.power(efficiency_data.GetBinContent(x, y) - efficiency_at_value, 2) / np.power(efficiency_data.GetBinError(x, y), 2)) residual[pt_index, eta_index] = value # Check max values logger.debug(f"min efficiency_data: {efficiency_data.GetMinimum()}, " f"max efficiency_data: {efficiency_data.GetMaximum()}") logger.debug(f"min residual: {np.nanmin(residual)}, max residual: {np.nanmax(residual)}") logger.debug(f"standard mean: {np.nanmean(residual)}") logger.debug(f"restricted mean: {np.nanmean(residual[:,np.abs(etas) < 0.8])}") logger.debug(f"len(pts): {len(pts)}, len(etas): {len(etas)}") # Check chi squared chi_squared = np.sum(chi_2) # 23 is the number of parameters (10 + 13) at any given point ndf = len(chi_2) - 23 logger.warning("NOTE: The restricted chi squared value calculated here may not be super reliable.") logger.info(f"Chi squared: {chi_squared}") logger.info(f"NDF: {ndf}") logger.info(f"chi2/ndf: {chi_squared / ndf}") return residual, pts, etas