def test_apply_range_set(self, logging_mixin, min_val, max_val, min_val_func, max_val_func, expected_func, test_sparse): """ Test apply a range set to an axis via a HistAxisRange object. This is intentionally tested against SetRangeUser, so we can be certain that it reproduces that selection as expected. Note: It doens't matter whether we operate on TH1 or THn, since they both set ranges on TAxis. Note: This implicity tests apply_func_to_find_bin, which is fine given how often the two are used together (almost always). """ import ROOT # Setup functions function_map = { None: lambda x: projectors.HistAxisRange.apply_func_to_find_bin(None, x), "find_bin_min": lambda x: projectors.HistAxisRange.apply_func_to_find_bin( ROOT.TAxis.FindBin, x + utils.epsilon), "find_bin_max": lambda x: projectors.HistAxisRange.apply_func_to_find_bin( ROOT.TAxis.FindBin, x - utils.epsilon), "n_bins": lambda x: projectors.HistAxisRange.apply_func_to_find_bin( ROOT.TAxis.GetNbins), } min_val_func = function_map[min_val_func] max_val_func = function_map[max_val_func] selected_axis = SparseAxisLabels.axis_two sparse, _ = test_sparse expected_axis = sparse.GetAxis(selected_axis.value).Clone("axis2") expected_func(expected_axis, min_val, max_val) obj = projectors.HistAxisRange(axis_range_name="axis_two_test", axis_type=selected_axis, min_val=min_val_func(min_val), max_val=max_val_func(max_val)) # Applys the restriction to the sparse. obj.apply_range_set(sparse) ax = sparse.GetAxis(selected_axis.value) # Unfortunately, equality comparison doesn't work for TAxis... # GetXmin() and GetXmax() aren't restircted by SetRange(), so instead use GetFirst() and GetLast() assert ax.GetFirst() == expected_axis.GetFirst() assert ax.GetLast() == expected_axis.GetLast() # Sanity check that the overall axis still agrees assert ax.GetNbins() == expected_axis.GetNbins() assert ax.GetName() == expected_axis.GetName()
def create_hist_axis_range(): """ Create a HistAxisRange object to use for testing. """ object_args = { "axis_range_name": "z_axis_test_projector", "axis_type": projectors.TH1AxisType.y_axis, "min_val": lambda x: x, "max_val": lambda y: y } obj = projectors.HistAxisRange(**object_args) # axis_range_name is referred to as name internally, so we rename to that object_args["name"] = object_args.pop("axis_range_name") return (obj, object_args)
def _project_to_part_level(hist: Hist, outliers_removal_axis: OutliersRemovalAxis) -> Hist: """Project the input histogram to the particle level axis. Args: hist: Histogram to check for outliers. outliers_removal_axis: Axis along which outliers removal will be performed. Usually the particle level aixs. Returns: The histogram to check for outliers. """ # Setup the projector import ROOT if isinstance(hist, (ROOT.TH2, ROOT.TH3)): projection_information: Dict[str, Any] = {} output_object = _OutputObject(None) projector = projectors.HistProjector( observable_to_project_from=hist, output_observable=output_object, output_attribute_name="output", projection_name_format="outliers_removal_hist", projection_information=projection_information, ) # No additional_axis_cuts or projection_dependent_cut_axes # Projection axis projector.projection_axes.append( projectors.HistAxisRange( axis_type=outliers_removal_axis, axis_range_name="outliers_removal_axis", min_val=projectors.HistAxisRange.apply_func_to_find_bin( None, 1), max_val=projectors.HistAxisRange.apply_func_to_find_bin( ROOT.TAxis.GetNbins), )) # Perform the actual projection and return the output. projector.project() return output_object.output # If we already have a 1D hist, just return that existing hist. return hist
def test_disagreement_with_set_range_user(self, logging_mixin, test_sparse): """ Test the disagreement between SetRange and SetRangeUser when the epsilon shift is not included. """ import ROOT # Setup values selected_axis = SparseAxisLabels.axis_two min_val = 2 max_val = 8 sparse, _ = test_sparse # Detemine expected value (must be first to avoid interfering with applying the axis range) expected_axis = sparse.GetAxis(selected_axis.value).Clone("axis2") expected_axis.SetRangeUser(min_val, max_val) obj = projectors.HistAxisRange( axis_range_name="axis_two_test", axis_type=selected_axis, min_val=projectors.HistAxisRange.apply_func_to_find_bin( ROOT.TAxis.FindBin, min_val), max_val=projectors.HistAxisRange.apply_func_to_find_bin( ROOT.TAxis.FindBin, max_val)) # Applys the restriction to the sparse. obj.apply_range_set(sparse) ax = sparse.GetAxis(selected_axis.value) # Unfortunately, equality comparison doesn't work for TAxis... # GetXmin() and GetXmax() aren't restircted by SetRange(), so instead use GetFirst() and GetLast() # The lower bin will still agree. assert ax.GetFirst() == expected_axis.GetFirst() # The upper bin will not. assert ax.GetLast() != expected_axis.GetLast() # If we subtract a bin (equivalent to including - epsilon), it will agree. assert ax.GetLast() - 1 == expected_axis.GetLast() # Sanity check that the overall axis still agrees assert ax.GetNbins() == expected_axis.GetNbins() assert ax.GetName() == expected_axis.GetName()
ROOT.TAxis.FindBin, hist_range.max_val - utils.epsilon # type: ignore ) return hist_range # Convenient access to hist axis ranges. HistAxisRanges = dataclasses.make_dataclass("HistAxisRanges", ["x_axis", "y_axis", "z_axis"]) # Hist axis ranges # NOTE: We don't define these in the class because we won't be able to access these variables when # defining the tests restricted ranges, but with entries. hist_axis_ranges = HistAxisRanges( projectors.HistAxisRange(axis_type=projectors.TH1AxisType.x_axis, axis_range_name="an_x_axis", min_val=0.1, max_val=0.8), projectors.HistAxisRange(axis_type=projectors.TH1AxisType.y_axis, axis_range_name="an_y_axis", min_val=0, max_val=12), projectors.HistAxisRange(axis_type=projectors.TH1AxisType.z_axis, axis_range_name="an_z_axis", min_val=10, max_val=60)) # Restricted ranges with no counts hist_axis_ranges_without_entries = HistAxisRanges( projectors.HistAxisRange(axis_type=projectors.TH1AxisType.x_axis, axis_range_name="an_x_axis_no_entries", min_val=0.2, max_val=0.8),