Skip to content

Improve plotter labels and automatic axis limits - #110

Open
jniedzie wants to merge 8 commits into
mainfrom
agent/issue-106-plotter-improvements
Open

Improve plotter labels and automatic axis limits#110
jniedzie wants to merge 8 commits into
mainfrom
agent/issue-106-plotter-improvements

Conversation

@jniedzie

@jniedzie jniedzie commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • add label_outside_axes for CMS and extra text placement in the top margin
  • use None as the default for unspecified 1D and 2D axis limits
  • derive missing bounds from the drawn stack after it is populated
  • add margins around automatic bounds (including positive-only handling for log axes)
  • keep explicit finite limits and partial histogram cropping supported

Issue

Closes #106.

Validation

  • python3 -m py_compile pylibs/plotting/Histogram.py pylibs/plotting/Styler.py pylibs/plotting/CmsLabelsManager.py pylibs/plotting/HistogramPlotter.py
  • git diff --check
  • A rendered ROOT plot test remains to be run in a ROOT-enabled environment; local instructions are included below.

Local testing

  1. Build/install tea and activate the environment that provides PyROOT.
  2. From tea/, set PYTHONPATH as required by setup.sh.
  3. Omit histogram x_min, x_max, y_min, and y_max (they default to None). Generate a plot and verify the limits are derived from the populated stack with visible padding.
  4. Repeat with a log-y histogram and verify the lower bound is positive and based on the smallest positive stack bin.
  5. Add label_outside_axes = True and show_cms_labels = True; confirm CMS/extra text is in the top margin rather than inside the axes frame.
  6. Set explicit finite limits on another histogram and confirm those limits still apply.
  7. Run the repository smoke test if the normal build has been performed: cmake --build build --target tea_smoke_examples.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_axes support 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.

Comment thread pylibs/plotting/Styler.py
Comment thread pylibs/plotting/Styler.py Outdated
Comment thread pylibs/plotting/Histogram.py Outdated
@jniedzie
jniedzie marked this pull request as ready for review July 28, 2026 07:59
@jniedzie
jniedzie requested a review from twybo July 28, 2026 07:59
@twybo

twybo commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

re plotting label, please follow the instructions at https://cms-analysis.docs.cern.ch/guidelines/plotting/general/
specifically missing:

  • removing the bold CMS label_text for Private work extraText without linebreaks
  • padding of labels is incorrect (including lumi/energy)
  • xticks and yticks also at top and right respectively

@jniedzie

Copy link
Copy Markdown
Owner Author

@twybo, ready for you to test and review again. Thanks :)

@twybo

twybo commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Here are some further comments:

  • when bold CMS is not written (e.g. private work) there should not be the reserved space for CMS above (i.e. Private work should move up a line)
  • scientific notation exponent moved left when choosing the CMS label to be outside
  • capture ROOT warnings for:
    • empty histograms: TH1::TH1:0: RuntimeWarning: nbins is <=0 - set to nbins = 1
    • rebinning non-exact divider: TH1F::Rebin:0: RuntimeWarning: ngroup=2 is not an exact divider of nbins=299.
  • print output directory instead of ROOT's info: Saving file: for each plot
  • update plotter_config.py example
  • optional: configurable padding for all figures with one variable (separately for left, right, top)
  • ratio plot range should be picked automatically by default

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Suggested plotter improvements

3 participants