From 46adb1ed6f15b613a0c39b858f135dd4f1737a34 Mon Sep 17 00:00:00 2001 From: Choklatier <48896806+Choklatier@users.noreply.github.com> Date: Mon, 27 Nov 2023 15:12:00 +0100 Subject: [PATCH] Adding the basic functionality of FilledHistogram class (#221) * Adding the basic functionality of FilledHistogram class * Now only one Histogram class that treats the histogram as filled depending on the specification of the 'bin_edges' input. * correct bin_edges bug for divide * Reduced line sizes and remove unused input for helper function * removed some code duplication by merging functions * bug fix * made filled argument a optional parameter to pass unit tests... * added a basic test for filled histogram * added test case for sumW2 in filled hists * reformatting to fit lines * fixed a sumW2 bug and test bug * fixed formatting with pre-commit * add changelog line * added warning upon defining sum_squared_weights but no bin_edges --------- Co-authored-by: thmaurin Co-authored-by: Sam VS --- changelog.md | 1 + puma/histogram.py | 32 +++++- .../expected_plots/test_filled_histogram.png | Bin 0 -> 52414 bytes .../test_filled_histogram_sumW2.png | Bin 0 -> 61314 bytes puma/tests/test_histogram.py | 49 +++++++++ puma/utils/histogram.py | 95 ++++++++++++------ 6 files changed, 142 insertions(+), 35 deletions(-) create mode 100644 puma/tests/expected_plots/test_filled_histogram.png create mode 100644 puma/tests/expected_plots/test_filled_histogram_sumW2.png diff --git a/changelog.md b/changelog.md index 46eba5819..a30779857 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,7 @@ - Update ratio uncertainty calculation [!225](https://github.com/umami-hep/puma/pull/225) - Add NaN filtering for HL plots. Bump atlas-ftag-tools version to 0.1.11. [!220](https://github.com/umami-hep/puma/pull/220) - Making Under- and Overflow bins default in histograms [!218](https://github.com/umami-hep/puma/pull/218) +- Adding "bin_edges" and "sum_squared_weights" parameters to the Histogram constructor to define pre-filled histograms. ### [v0.3.0] (2023/10/03) diff --git a/puma/histogram.py b/puma/histogram.py index 5306a5133..e412b9094 100644 --- a/puma/histogram.py +++ b/puma/histogram.py @@ -22,6 +22,8 @@ def __init__( self, values: np.ndarray, weights: np.ndarray = None, + bin_edges: np.ndarray = None, + sum_squared_weights: np.ndarray = None, ratio_group: str | None = None, flavour: str | Flavour = None, add_flavour_label: bool = True, @@ -34,12 +36,21 @@ def __init__( Parameters ---------- values : np.ndarray - Input data for the histogram + Input data for the histogram. If bin_edges is specified (not None) + then this array is treated as the bin heights. weights : np.ndarray, optional Weights for the input data. Has to be an array of same length as the input data with a weight for each entry. If not specified, weight 1 will be given to each entry. The uncertainties are calculated as the square root of the squared weights (for each bin separately). By default None. + bin_edges : np.ndarray, optional + If specified, the histogram is considered "filled": the array given to + values is treated as if it was the bin heights corresponding to these + bin_edges and the "weights" input is ignored. By default None. + sum_squared_weights : np.ndarray, optional + Only considered if the histogram is considered filled (i.e bin_edges + is specified). It is the sum_squared_weights per bin. + By default None. ratio_group : str, optional Name of the ratio group this histogram is compared with. The ratio group allows you to compare different groups of histograms within one plot. @@ -85,6 +96,18 @@ def __init__( raise ValueError("`values` and `weights` are not of same length.") self.values = values + self.bin_edges = bin_edges # Important to have this defined for any histogram + self.sum_squared_weights = sum_squared_weights + + if bin_edges is None and sum_squared_weights is not None: + logger.warning("""The Histogram has no bin edges defined and is thus + not considered filled. Parameter `sum_squared_weights` + is ignored. """) + + # This attribute allows to know how to handle the histogram later during + # plotting + self.filled = bin_edges is not None + self.weights = weights self.ratio_group = ratio_group self.flavour = Flavours[flavour] if isinstance(flavour, str) else flavour @@ -94,7 +117,6 @@ def __init__( # Set histogram attributes to None. They will be defined when the histograms # are plotted - self.bin_edges = None self.hist = None self.unc = None self.band = None @@ -432,12 +454,18 @@ def plot(self, **kwargs): elem.bin_edges, elem.hist, elem.unc, elem.band = hist_w_unc( elem.values, weights=elem.weights, + bin_edges=elem.bin_edges, + sum_squared_weights=elem.sum_squared_weights, bins=self.bins, + filled=elem.filled, bins_range=self.bins_range, normed=self.norm, underoverflow=self.underoverflow, ) + # MAYBE CHECK HERE THAT self.bins and elem.bin_edges are + # equivalent for plotting or throw error! + if self.discrete_vals is not None: # bins are recalculated for the discrete values bins = self.get_discrete_values(elem) diff --git a/puma/tests/expected_plots/test_filled_histogram.png b/puma/tests/expected_plots/test_filled_histogram.png new file mode 100644 index 0000000000000000000000000000000000000000..f80f4f202be20920dbd4637971828d93db936077 GIT binary patch literal 52414 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 WxlyxDNY15y+Oc(yQq(sGPW*pans;6R literal 0 HcmV?d00001 diff --git a/puma/tests/test_histogram.py b/puma/tests/test_histogram.py index f5aa6cdb6..f5682dbaf 100644 --- a/puma/tests/test_histogram.py +++ b/puma/tests/test_histogram.py @@ -768,3 +768,52 @@ def test_underoverflow_bin(self): tol=1, ) ) + + def test_plot_filled_hist(self): + bin_edges = [0, 1, 2, 3, 4, 5] + bin_counts = [5, 4, 7, 12, 2] + + vals = [0, 1, 1, 5, 4, 2, 1, 3, 3, 5, 5, 5, 5, 5] + + hist_filled = Histogram(bin_counts, bin_edges=bin_edges) + hist_notfilled = Histogram(vals) + + hist_plot = HistogramPlot(bins=bin_edges, underoverflow=False) + hist_plot.add(hist_filled) + hist_plot.add(hist_notfilled) + + hist_plot.draw() + plotname = "test_filled_histogram.png" + hist_plot.savefig(f"{self.actual_plots_dir}/{plotname}") + + self.assertIsNone( + compare_images( + f"{self.actual_plots_dir}/{plotname}", + f"{self.expected_plots_dir}/{plotname}", + tol=1, + ) + ) + + def test_plot_filled_hist_sumW2(self): + bin_edges = [0, 1, 2, 3, 4, 5] + bin_counts = [5, 4, 7, 12, 2] + sum_squared_weights = [10, 7, 12, 21, 5] + + hist_plot = HistogramPlot(bins=bin_edges, underoverflow=False) + hist_plot.add( + Histogram( + bin_counts, bin_edges=bin_edges, sum_squared_weights=sum_squared_weights + ) + ) + + hist_plot.draw() + plotname = "test_filled_histogram_sumW2.png" + hist_plot.savefig(f"{self.actual_plots_dir}/{plotname}") + + self.assertIsNone( + compare_images( + f"{self.actual_plots_dir}/{plotname}", + f"{self.expected_plots_dir}/{plotname}", + tol=1, + ) + ) diff --git a/puma/utils/histogram.py b/puma/utils/histogram.py index 884aa94c4..40de530c8 100644 --- a/puma/utils/histogram.py +++ b/puma/utils/histogram.py @@ -56,9 +56,12 @@ def save_divide( def hist_w_unc( arr, bins, + filled: bool = False, bins_range=None, normed: bool = True, weights: np.ndarray = None, + bin_edges: np.ndarray = None, + sum_squared_weights: np.ndarray = None, underoverflow: bool = False, ): """ @@ -115,42 +118,68 @@ def hist_w_unc( if np.sum(inf_mask) > 0: logger.warning("Histogram values contain %i +-inf values!", np.sum(inf_mask)) - # Calculate the counts and the bin edges - counts, bin_edges = np.histogram(arr, bins=bins, range=bins_range, weights=weights) - - # calculate the uncertainty with sum of squared weights (per bin, so we use - # np.histogram again here) - unc = np.sqrt( - np.histogram(arr, bins=bins, range=bins_range, weights=weights**2)[0] - ) + # If the histogram is not already filled we need to produce the histogram counts + # and bin edges + if not filled: + # Calculate the counts and the bin edges + counts, bin_edges = np.histogram( + arr, bins=bins, range=bins_range, weights=weights + ) - if underoverflow: - # add two dummy bins (from outermost bins to +-infinity) - bins_with_overunderflow = np.hstack( - [np.array([-np.inf]), bin_edges, np.array([np.inf])] + # calculate the uncertainty with sum of squared weights (per bin, so we use + # np.histogram again here) + unc = np.sqrt( + np.histogram(arr, bins=bins, range=bins_range, weights=weights**2)[0] ) - # recalculate the histogram with this adjusted binning - counts, _ = np.histogram(arr, bins=bins_with_overunderflow, weights=weights) - counts[1] += counts[0] # add underflow values to underflow bin - counts[-2] += counts[-1] # add overflow values to overflow bin - counts = counts[1:-1] # remove dummy bins - - # calculate the sum of squared weights - sum_squared_weights = np.histogram( - arr, bins=bins_with_overunderflow, weights=weights**2 - )[0] - # add sum of squared weights from under/overflow values to under/overflow bin - sum_squared_weights[1] += sum_squared_weights[0] - sum_squared_weights[-2] += sum_squared_weights[-1] - sum_squared_weights = sum_squared_weights[1:-1] # remove dummy bins - - unc = np.sqrt(sum_squared_weights) # uncertainty is sqrt(sum_squared_weights) - - if normed: - sum_of_weights = float(np.sum(weights)) - counts = save_divide(counts, sum_of_weights, 0) - unc = save_divide(unc, sum_of_weights, 0) + if underoverflow: + # add two dummy bins (from outermost bins to +-infinity) + bins_with_overunderflow = np.hstack( + [np.array([-np.inf]), bin_edges, np.array([np.inf])] + ) + # recalculate the histogram with this adjusted binning + counts, _ = np.histogram(arr, bins=bins_with_overunderflow, weights=weights) + counts[1] += counts[0] # add underflow values to underflow bin + counts[-2] += counts[-1] # add overflow values to overflow bin + counts = counts[1:-1] # remove dummy bins + + # calculate the sum of squared weights + sum_squared_weights = np.histogram( + arr, bins=bins_with_overunderflow, weights=weights**2 + )[0] + + # add sum of squared weights from under/overflow values + # to under/overflow bin + sum_squared_weights[1] += sum_squared_weights[0] + sum_squared_weights[-2] += sum_squared_weights[-1] + # remove dummy bins + sum_squared_weights = sum_squared_weights[1:-1] + + # uncertainty is sqrt(sum_squared_weights) + unc = np.sqrt(sum_squared_weights) + + if normed: + sum_of_weights = float(np.sum(weights)) + counts = save_divide(counts, sum_of_weights, 0) + unc = save_divide(unc, sum_of_weights, 0) + + # If the histogram is already filled then the uncertainty is computed + # differently + else: + if sum_squared_weights is not None: + sum_squared_weights = np.array(sum_squared_weights)[~nan_mask] + unc = np.sqrt(sum_squared_weights) + else: + unc = np.sqrt(arr) # treat arr as bin heights (counts) + + counts = arr + + if normed: + counts_sum = float(np.sum(counts)) + counts = save_divide(counts, counts_sum, 0) + unc = save_divide(unc, counts_sum, 0) + + # regardless of if the histogram is filled band = counts - unc hist = counts