diff --git a/docs/advanced/hep_examples.rst b/docs/advanced/hep_examples.rst
index ef1384f4..074b68aa 100644
--- a/docs/advanced/hep_examples.rst
+++ b/docs/advanced/hep_examples.rst
@@ -171,7 +171,128 @@ If you do not want to show and take into account the MC uncertainties, setting `
-For other type of comparisons, see :ref:`basics-1d_hist_comparison-label`.
+Other comparisons
+-----------------
+
+Every type of comparisons available with ``plot_comparison()`` are available for ``compare_data_mc()`` (see :ref:`basics-1d_hist_comparison-label`).
+
+Example plot with all comparisons, using the same histograms as above:
+
+.. code-block:: python
+ from plothist import (
+ create_comparison_figure,
+ compare_data_mc,
+ add_text,
+ set_fitting_ylabel_fontsize
+ )
+ import matplotlib.pyplot as plt
+
+ fig, axes = create_comparison_figure(
+ figsize=(6, 11),
+ nrows=5,
+ gridspec_kw={"height_ratios": [3.3, 1, 1, 1, 1]},
+ hspace=0.3,
+ )
+
+ fig_temp, ax_temp = plt.subplots()
+
+ for k_comp, comparison in enumerate(["ratio", "pull", "relative_difference", "difference"], 1):
+
+ fig_comp, ax_main, ax_comparison = compare_data_mc(
+ data_hist=data_hist,
+ mc_hist_list=background_hists,
+ signal_hist=signal_hist,
+ xlabel=key,
+ ylabel="Entries",
+ mc_labels=background_categories_labels,
+ mc_colors=background_categories_colors,
+ comparison=comparison,
+ fig=fig,
+ ax_main=axes[0] if k_comp == 1 else ax_temp,
+ ax_comparison=axes[k_comp],
+ )
+
+ axes[k_comp].set_xlabel("")
+ add_text(f' $\mathbf{{→}}$ comparison = "{comparison}"', ax=ax_comparison, fontsize=13)
+ set_fitting_ylabel_fontsize(ax_comparison)
+
+ fig.savefig("hep_all_comparisons.svg", bbox_inches="tight")
+
+
+.. image:: ../img/hep_all_comparisons.svg
+ :alt: Data/MC comparison with all comparisons, stacked plot
+ :width: 500
+
+
+
+Same example plot but we remove the MC statistical uncertainties by adding ``mc_uncertainty=False`` in ``compare_data_mc()``:
+
+
+.. image:: ../img/hep_all_comparisons_no_stat_MC_unc.svg
+ :alt: Data/MC comparison with all comparisons, no mc uncertainties, stacked plot
+ :width: 500
+
+
+
+For ``ratio`` or ``relative_difference``, the uncertainties can be split between MC and data (default option) or both can be added to the ratio uncertainty (``ratio_uncertainty="uncorrelated"``). Here are all the possible options:
+
+.. code-block:: python
+
+ from plothist import (
+ compare_data_mc,
+ add_luminosity,
+ create_comparison_figure,
+ set_fitting_ylabel_fontsize,
+ add_text,
+ compare_two_hist,
+ )
+ import matplotlib.pyplot as plt
+
+ fig, axes = create_comparison_figure(
+ figsize=(6, 11),
+ nrows=5,
+ gridspec_kw={"height_ratios": [3.3, 1, 1, 1, 1]},
+ hspace=0.3,
+ )
+
+ fig_temp, ax_temp = plt.subplots()
+
+ for k_comp in [1, 2, 3, 4]:
+ ratio_uncertainty = "uncorrelated" if k_comp % 2 == 0 else "split"
+ mc_uncertainty = False if k_comp > 2 else True
+
+ fig_comp, ax_main, ax_comparison = compare_data_mc(
+ data_hist=data_hist,
+ mc_hist_list=background_hists,
+ signal_hist=signal_hist,
+ xlabel=key,
+ ylabel="Entries",
+ mc_labels=background_categories_labels,
+ mc_colors=background_categories_colors,
+ comparison="ratio",
+ fig=fig,
+ ax_main=axes[0] if k_comp == 1 else ax_temp,
+ ax_comparison=axes[k_comp],
+ ratio_uncertainty=ratio_uncertainty,
+ mc_uncertainty=mc_uncertainty,
+ )
+ axes[k_comp].set_xlabel("")
+ add_text(
+ f' $\mathbf{{→}}$ comparison = "ratio", \n $\mathbf{{→}}$ ratio_uncertainty="{ratio_uncertainty}", mc_uncertainty = {mc_uncertainty}',
+ ax=ax_comparison,
+ fontsize=10,
+ )
+
+ fig.savefig("hep_comparisons_ratio_options.svg", bbox_inches="tight")
+
+
+
+.. image:: ../img/hep_comparisons_ratio_options.svg
+ :alt: Data/MC comparison with all comparisons option for ratio
+ :width: 500
+
+
+
Advanced
========
diff --git a/docs/img/hep_all_comparisons.svg b/docs/img/hep_all_comparisons.svg
new file mode 100644
index 00000000..c406a407
--- /dev/null
+++ b/docs/img/hep_all_comparisons.svg
@@ -0,0 +1,5823 @@
+
+
+
diff --git a/docs/img/hep_all_comparisons_no_stat_MC_unc.svg b/docs/img/hep_all_comparisons_no_stat_MC_unc.svg
new file mode 100644
index 00000000..d5e24ad1
--- /dev/null
+++ b/docs/img/hep_all_comparisons_no_stat_MC_unc.svg
@@ -0,0 +1,5284 @@
+
+
+
diff --git a/docs/img/hep_comparisons_ratio_options.svg b/docs/img/hep_comparisons_ratio_options.svg
new file mode 100644
index 00000000..7ed5c5ba
--- /dev/null
+++ b/docs/img/hep_comparisons_ratio_options.svg
@@ -0,0 +1,6003 @@
+
+
+
diff --git a/docs/img/hep_examples_dataMC_pull_no_MC_stat_unc.svg b/docs/img/hep_examples_dataMC_pull_no_MC_stat_unc.svg
index e830703c..f7656e3f 100644
--- a/docs/img/hep_examples_dataMC_pull_no_MC_stat_unc.svg
+++ b/docs/img/hep_examples_dataMC_pull_no_MC_stat_unc.svg
@@ -35,760 +35,759 @@ z
" style="fill: #ffffff"/>
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -805,56 +804,56 @@ z
" style="stroke: #000000"/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1045,12 +1044,12 @@ L 6 0
" style="stroke: #1a1a1a; stroke-width: 0.8"/>
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/plothist/__init__.py b/plothist/__init__.py
index cf1ef564..8415cdf9 100644
--- a/plothist/__init__.py
+++ b/plothist/__init__.py
@@ -26,7 +26,7 @@
set_style,
cubehelix_palette,
get_color_palette,
- get_fitting_ylabel_fontsize,
+ set_fitting_ylabel_fontsize,
add_text,
)
@@ -51,7 +51,7 @@
"set_style",
"cubehelix_palette",
"get_color_palette",
- "get_fitting_ylabel_fontsize",
+ "set_fitting_ylabel_fontsize",
"add_text",
]
diff --git a/plothist/hep_plotters.py b/plothist/hep_plotters.py
index a7ba5a1c..d2b0d5d0 100644
--- a/plothist/hep_plotters.py
+++ b/plothist/hep_plotters.py
@@ -13,7 +13,7 @@
create_comparison_figure,
_hist_ratio_variances,
)
-from plothist.plothist_style import get_fitting_ylabel_fontsize, add_text
+from plothist.plothist_style import set_fitting_ylabel_fontsize, add_text
def compare_data_mc(
@@ -129,6 +129,11 @@ def compare_data_mc(
flatten_2d_hist=False, # Already done
)
+ if not mc_uncertainty:
+ mc_hist_total[:] = np.stack(
+ [mc_hist_total.values(), np.zeros_like(mc_hist_total.values())], axis=-1
+ )
+
# Compute data uncertainties
if np.allclose(data_hist.variances(), data_hist.values()):
# If the variances are equal to the bin contents (i.e. un-weighted data), use the Poisson confidence intervals as uncertainties
@@ -144,8 +149,9 @@ def compare_data_mc(
uncertainties_low**2,
uncertainties_high**2,
)
+ data_hist = data_hist.copy()
data_hist[:] = np.stack([data_hist.values(), data_variances], axis=-1)
- elif comparison_kwargs["comparison"] == "ratio":
+ elif comparison_kwargs["comparison"] in ["ratio", "relative_difference"]:
if comparison_kwargs["ratio_uncertainty"] == "split":
np.seterr(divide="ignore", invalid="ignore")
# Compute asymmetrical uncertainties to plot_comparison()
@@ -190,6 +196,10 @@ def compare_data_mc(
np.sqrt(data_hist_high.variances() + mc_hist_total.variances()),
],
)
+ else:
+ raise ValueError(
+ f"Unknown comparison {comparison_kwargs['comparison']}. Please choose from 'pull', 'ratio', 'relative_difference', or 'difference'."
+ )
plot_error_hist(
data_hist,
@@ -216,9 +226,6 @@ def compare_data_mc(
label=mc_uncertainty_label,
)
else:
- mc_hist_total[:] = np.stack(
- [mc_hist_total.values(), np.zeros_like(mc_hist_total.values())], axis=-1
- )
if comparison_kwargs["comparison"] == "pull":
comparison_kwargs.setdefault(
"comparison_ylabel",
@@ -235,7 +242,7 @@ def compare_data_mc(
**comparison_kwargs,
)
- ylabel_fontsize = get_fitting_ylabel_fontsize(ax_main)
+ ylabel_fontsize = set_fitting_ylabel_fontsize(ax_main)
ax_main.get_yaxis().get_label().set_size(ylabel_fontsize)
ax_comparison.get_yaxis().get_label().set_size(ylabel_fontsize)
@@ -395,7 +402,7 @@ def plot_mc(
xlim = (mc_hist_list[0].axes[0].edges[0], mc_hist_list[0].axes[0].edges[-1])
ax.set_xlim(xlim)
ax.set_xlabel(xlabel)
- ax.set_ylabel(ylabel, fontsize=get_fitting_ylabel_fontsize(ax))
+ ax.set_ylabel(ylabel, fontsize=set_fitting_ylabel_fontsize(ax))
ax.tick_params(axis="x", labelbottom="off")
ax.legend(ncol=leg_ncol)
diff --git a/plothist/plothist_style.py b/plothist/plothist_style.py
index 51684616..f0ea3fe1 100644
--- a/plothist/plothist_style.py
+++ b/plothist/plothist_style.py
@@ -167,7 +167,7 @@ def get_color_palette(cmap, N):
return colors
-def get_fitting_ylabel_fontsize(ax):
+def set_fitting_ylabel_fontsize(ax):
"""
Get the suitable font size for a ylabel text that fits within the plot's y-axis limits.
@@ -248,14 +248,14 @@ def add_text(
x = 0.0
elif x=="right":
x = 1.0
- elif type(x)!=float and type(x)!=int:
+ elif type(x) not in [float, int]:
raise ValueError(f"x should be a float or 'left'/'right' ({x} given))")
if y=="top":
y = 1.01
elif y=="bottom":
y = 0.0
- elif type(y)!=float and type(y)!=int:
+ elif type(y) not in [float, int]:
raise ValueError(f"y should be a float or 'top'/'bottom' ({y} given)")
t = ax.text(