-
Notifications
You must be signed in to change notification settings - Fork 28
feat: Add ratio plot support through .plot_ratio API #161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Minimal toy working example before beginning revision work: # example.py
import matplotlib.pyplot as plt
import numpy as np
import hist
if __name__ == "__main__":
np.random.seed(0)
n_fill_1 = 5000
n_fill_2 = n_fill_1 * 1.7
hist_1 = hist.Hist(
hist.axis.Regular(
50, -5, 5, name="X", label="x [units]", underflow=False, overflow=False
)
).fill(np.random.normal(size=int(n_fill_1)))
hist_2 = hist.Hist(
hist.axis.Regular(
50, -5, 5, name="X", label="x [units]", underflow=False, overflow=False
)
).fill(np.random.normal(size=int(n_fill_2)))
fig = plt.figure(figsize=(10, 8))
artists = hist_1.plot_ratio(hist_2)
fig.savefig("hist_ratio_plot.png") Support for both callables and hists exists. |
1d9ab39
to
05071ba
Compare
1190f81
to
2286550
Compare
3539424
to
897a582
Compare
c13bf5d
to
e70bce0
Compare
@henryiii This PR still isn't done, as I still have plenty to do on the checklist I added in the PR body, but after I rebase this off PR #168 if you have time to give general thoughts and feedback on better design of the refactor and clarity of control flow I would be very happy to make any and all suggested revisions while adding tests and docs. |
e70bce0
to
73ec024
Compare
(Copying from #161 (comment) to make it easier for me to find later)
Oh, I see the CI is failing as As for having |
After doing some more refactoring (perhaps too much?), this PR is getting pretty ugly looking in the review panels. If this is too much (this is definitely no longer atomic) I could make another PR that would do the refactoring of things first and then fix this PR to just do the ratio plot and pull plot work.
As the pulls and the ratios have little overlap in what is actually being plotted (beyond that they are both in a subplot) the current setup has the Thoughts? Am I missing something about the logic/design here? |
The GitHub rich diff tools for images are quite nice, hadn't played with them before (there are three modes, for example). The image changes do not look very good; the band is darker, hiding the function plot, and the data points now plot over the legend. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, I had a few very minor comments. After this goes in, I might try to do a tiny bit of cleanup. (typing.py, fix an Any or two)
FYI, this is the changes I tried; no fixes but added strings / callables and removed quotes in plot.py (since matplotlib is available there) (in .patch form if you want to apply them): diff --git a/src/hist/basehist.py b/src/hist/basehist.py
index 45c1665..cf281a6 100644
--- a/src/hist/basehist.py
+++ b/src/hist/basehist.py
@@ -405,7 +405,7 @@ class BaseHist(bh.Histogram, metaclass=MetaConstructor, family=hist):
def plot_ratio(
self,
- other: Callable[[np.ndarray], np.ndarray],
+ other: Union[np.ndarray, str, Callable[[np.ndarray], np.ndarray]],
*,
ax_dict: "Optional[Dict[str, matplotlib.axes.Axes]]" = None,
**kwargs: Any,
@@ -425,7 +425,7 @@ class BaseHist(bh.Histogram, metaclass=MetaConstructor, family=hist):
def plot_pull(
self,
- func: Callable[[np.ndarray], np.ndarray],
+ func: Union[str, Callable[[np.ndarray], np.ndarray]],
*,
ax_dict: "Optional[Dict[str, matplotlib.axes.Axes]]" = None,
**kwargs: Any,
diff --git a/src/hist/plot.py b/src/hist/plot.py
index ed3d7b1..c861f37 100644
--- a/src/hist/plot.py
+++ b/src/hist/plot.py
@@ -182,9 +182,9 @@ def _curve_fit_wrapper(
def plot2d_full(
self: hist.BaseHist,
*,
- ax_dict: "Optional[Dict[str, matplotlib.axes.Axes]]" = None,
+ ax_dict: Optional[Dict[str, matplotlib.axes.Axes]] = None,
**kwargs: Any,
-) -> "Tuple[Hist2DArtists, Hist1DArtists, Hist1DArtists]":
+) -> Tuple[Hist2DArtists, Hist1DArtists, Hist1DArtists]:
"""
Plot2d_full method for BaseHist object.
@@ -364,7 +364,7 @@ def _plot_fit_result(
def plot_ratio(
_hist: hist.BaseHist,
- ratio: np.ndarray,
+ ratio: Union[str, Callable[[np.ndarray], np.ndarray], np.ndarray],
ratio_uncert: np.ndarray,
ax: matplotlib.axes.Axes,
**kwargs: Any,
@@ -456,7 +456,7 @@ def plot_ratio(
def plot_pull(
_hist: hist.BaseHist,
- pulls: np.ndarray,
+ pulls: Union[str, Callable[[np.ndarray], np.ndarray], np.ndarray],
ax: matplotlib.axes.Axes,
bar_kwargs: Dict[str, Any],
pp_kwargs: Dict[str, Any],
@@ -505,10 +505,10 @@ def plot_pull(
def _plot_ratiolike(
self: hist.BaseHist,
- other: Union[hist.BaseHist, Callable[[np.ndarray], np.ndarray]],
+ other: Union[hist.BaseHist, Callable[[np.ndarray], np.ndarray], np.ndarray, str],
likelihood: bool = False,
*,
- ax_dict: "Optional[Dict[str, matplotlib.axes.Axes]]" = None,
+ ax_dict: Optional[Dict[str, matplotlib.axes.Axes]] = None,
view: Literal["ratio", "pull"],
fit_fmt: Optional[str] = None,
**kwargs: Any,
@@ -676,7 +676,7 @@ def get_center(x: Union[str, int, Tuple[float, float]]) -> Union[str, float]:
def plot_pie(
self: hist.BaseHist,
*,
- ax: "Optional[matplotlib.axes.Axes]" = None,
+ ax: Optional[matplotlib.axes.Axes] = None,
**kwargs: Any,
) -> Any: |
9cd3967
to
89c4172
Compare
* Ensure default uncertainty band color visible * bump location of __all__ to just below imports * Remove quotes * Rename _hist vars to either __hist or histogram * Add test for str alias for plot_ratio and plot_pull * Add str to types for plot_ratiolike * use TypeVar to type hist.BaseHist
89c4172
to
b9d0942
Compare
Co-authored-by: Henry Schreiner <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks! I'll likely add your example into the docs.
Awesome! Thanks for being so helpful and patient on this PR @henryiii — truly appreciate all of your help and guidance here as it ended up being highly educational for me. |
Thanks @matthewfeickert. I had not appreciated that. I will comment further on the related thoughts from Henry ... |
And I tend to agree with you that something more pythonic is preferable, like a callable and a Gaussian function provided by default, for example. Here I'm simply thinking about the user since 99.99% of the time one calls a pull, that's for a Gaussian check (bias and correctness of the error estimation). In that sense, and given that the package is still rather young, I would see no issue in your removing the strings option eventually, TBH. At this point in time, while we don't get there, some consistency is good, as you also say. Happy to continue the discussion in a ... Discussion :-). |
* Update minimum required version of hist to v2.3.0 - c.f. scikit-hep/hist#161 * Add stack_ratio_plot to heputils.plot API - Will be revised in future release for better API * Update dev-example notebook with examples of ratio plots
Resolves #148
This PR adds support for ratio plots to the
.plot...
API by adding.plot_ratio
and refactoring.plot_pull
to use.plot_ratio
.This PR is still very rough, but I thought I'd open it up as there is a minimal working example now and then revise it heavily from there.
As the commit log is huge and messy I'll rebase and squash things into more reasonable commit sections to make review more digestible.
Questions to come to consensus on
(Discussion can happen on Issue #148)
stat_interval
module?Answer: Yes, this is PR #176.
TODO before requesting review
.plot_pull
Suggested squash and merge message