Improve plotter labels and automatic axis limits - #110
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves the Python ROOT plotting utilities by (1) adding an option to place CMS/extra labels in the top margin (outside the axes frame) and (2) switching axis-limit handling to treat unspecified bounds as None and derive missing limits automatically from the populated/drawn plot (with padding).
Changes:
- Add
label_outside_axessupport and refactor CMS/extra label placement logic. - Change 1D/2D histogram default axis bounds from numeric sentinels to
None, and update histogram cropping logic accordingly. - Add automatic limit derivation (with margins and log-safe lower bounds) after the stack is drawn; adjust ratio plotting behavior for omitted bounds.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
pylibs/plotting/Styler.py |
Adds automatic axis-limit derivation from the drawn plot and updates limit-setting to respect None defaults. |
pylibs/plotting/HistogramPlotter.py |
Adjusts ratio “line at 1” drawing logic in response to None axis bounds. |
pylibs/plotting/Histogram.py |
Changes default axis-bound fields to None and updates 1D cropping behavior to handle partially specified bounds. |
pylibs/plotting/CmsLabelsManager.py |
Adds label_outside_axes and centralizes label position calculation. |
Comments suppressed due to low confidence (3)
pylibs/plotting/Styler.py:204
- __setAutomaticLimits() applies explicit hist.y_min/hist.y_max even when they would be ignored later (e.g. log_y with y_min=0, or y_max<=0). When only one bound is provided, this can set invalid limits (notably y_min<=0 on a log axis) before the guarded setters run.
automatic_y_min = min(values) if values else 0.0
automatic_y_min = min(0.0, automatic_y_min)
automatic_y_max = 1.3 * maximum
plot.SetMinimum(hist.y_min if hist.y_min is not None else automatic_y_min)
plot.SetMaximum(hist.y_max if hist.y_max is not None else automatic_y_max)
pylibs/plotting/HistogramPlotter.py:325
- __drawLineAtOne() now skips drawing the y=1 reference line whenever x_min/x_max are omitted (now the default). The ratio plot still has a well-defined displayed X range after drawing; the line endpoints should fall back to the pad's user coordinates (or the ratio histogram axis) when explicit bounds are not provided.
if not self.show_ratios or hist.x_min is None or hist.x_max is None:
return
global line
line = ROOT.TLine(hist.x_min, 1, hist.x_max, 1)
pylibs/plotting/Histogram.py:137
- Histogram2D bound fields are annotated as float but default to None. Update these to Optional[float] to match the new "None means unspecified" semantics and keep the dataclass type annotations correct.
x_min: float = None
x_max: float = None
y_min: float = None
y_max: float = None
z_min: float = None
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
re plotting label, please follow the instructions at https://cms-analysis.docs.cern.ch/guidelines/plotting/general/
|
|
@twybo, ready for you to test and review again. Thanks :) |
|
Here are some further comments:
|
Summary
label_outside_axesfor CMS and extra text placement in the top marginNoneas the default for unspecified 1D and 2D axis limitsIssue
Closes #106.
Validation
python3 -m py_compile pylibs/plotting/Histogram.py pylibs/plotting/Styler.py pylibs/plotting/CmsLabelsManager.py pylibs/plotting/HistogramPlotter.pygit diff --checkLocal testing
tea/, setPYTHONPATHas required bysetup.sh.x_min,x_max,y_min, andy_max(they default toNone). Generate a plot and verify the limits are derived from the populated stack with visible padding.label_outside_axes = Trueandshow_cms_labels = True; confirm CMS/extra text is in the top margin rather than inside the axes frame.cmake --build build --target tea_smoke_examples.