Skip to content

fix: Correct label positioning across figure sizes and DPIs#711

Merged
andrzejnovak merged 2 commits into
mainfrom
fix-label-scaling-dpi-14182033389645325178
May 13, 2026
Merged

fix: Correct label positioning across figure sizes and DPIs#711
andrzejnovak merged 2 commits into
mainfrom
fix-label-scaling-dpi-14182033389645325178

Conversation

@andrzejnovak
Copy link
Copy Markdown
Member

This PR addresses issue #709 where the positioning of mh.<exp>.label (such as the gap between "CMS" and "Preliminary") was inconsistent across different figure sizes and aspect ratios.

The root cause was traced to how font sizes (which are provided in typography points, 1 point = 1/72 inch) were being converted into axis fraction units. The code was incorrectly dividing the point size by ax.figure.dpi (effectively treating points as pixels) instead of by 72.

This has been fixed in _fontsize_axis and append_text within src/mplhep/label.py by properly converting points to inches via fontsize / 72. Test baselines generated via pytest-mpl have been updated to reflect this corrected spacing.


PR created automatically by Jules for task 14182033389645325178 started by @andrzejnovak

@google-labs-jules
Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Copilot AI review requested due to automatic review settings March 11, 2026 14:03
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 fixes inconsistent mh.<exp>.label positioning across figure sizes/DPIs by correcting point-to-axis-fraction conversions in mplhep.label. The update ensures font sizes (points) are converted via points→inches (/ 72) rather than incorrectly treating points as pixels (/ dpi), and refreshes pytest-mpl baselines accordingly.

Changes:

  • Correct point→axis-fraction conversion in _fontsize_axis by converting points to inches (fontsize_points / 72) instead of dividing by DPI.
  • Fix append_text auto-spacing correction terms to use points→inches (fontsize / 72) rather than points→pixels (/ dpi).
  • Update pytest-mpl baseline images to reflect the corrected spacing/placement.

Reviewed changes

Copilot reviewed 1 out of 19 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/mplhep/label.py Fixes unit conversion for font-size-derived spacing so label/append offsets scale consistently across DPI and figure sizes.
tests/baseline/test_style_dune.png Updated visual baseline for DUNE style after spacing correction.
tests/baseline/test_style_atlas.png Updated visual baseline for ATLAS style after spacing correction.
tests/baseline/test_labeltext_loc.png Updated visual baseline for label text placement tests.
tests/baseline/test_label_loc.png Updated visual baseline for label location tests.
tests/baseline/test_dune_label_loc.png Updated visual baseline for DUNE label location tests.
tests/baseline/test_append_text_multiline.png Updated visual baseline for multiline append_text placement after spacing correction.

Rescues #711 / refs #709.

The dimensional bug Jules's PR identified is real: `fontsize` is in
points (1pt = 1/72 in) and `ax_height * dpi = ax_height_px`, so
`fontsize / ax_height / dpi` is points-per-pixel, not an axis-fraction.

But applying the points->inches conversion naively (PR #711 as opened)
inflates every label gap by 100/72 ~= 1.39x at the default DPI, which
would silently shift every existing CMS/ATLAS/etc. label slightly to the
right and require regenerating 18 baselines.

This version applies the dimensional fix AND retunes the calibration
constants so that, at the legacy default DPI of 100, the rendered pixel
gap is bit-for-bit identical to the current behaviour:

  FONT_WIDTH_CORRECTION_FACTOR : 3  -> 3 * 100/72
  FONT_HEIGHT_CORRECTION_FACTOR: 10 -> 10 * 100/72
  _inside_pad multiplier       : 100 -> 72 (since _fontsize_axis is
                                 now a true axis-fraction, not the
                                 pt/(ax_height_in*dpi) hybrid)

Verified:
- pixel gap is constant across figsize (10x10, 12x5, 16x4, 20x3,
  6x6, 5x12, 8x6) at every DPI tested
- pixel gap scales linearly with DPI (constant 0.087" everywhere)
  i.e. constant physical inches across dpi=50/100/200/300
- at dpi=100 the rendered pixel gap (8.67px) matches main exactly
- full suite (323 tests) passes with the original baselines, no
  regeneration needed
@andrzejnovak andrzejnovak force-pushed the fix-label-scaling-dpi-14182033389645325178 branch from 5e95a00 to 6411c7d Compare May 13, 2026 12:03
@andrzejnovak
Copy link
Copy Markdown
Member Author

Force-pushed a revised version of the fix. Same correct math (points→inches, no /dpi), but the calibration constants are retuned so the rendered output at the default DPI of 100 is byte-identical to current main — no baseline regeneration needed.

What changed vs the original commit

Original commit This commit
_fontsize_axis math (fontsize/72) / ax_height same
text_width_corr / text_height_corr math (fontsize/72) / FACTOR / ax_width same
FONT_WIDTH_CORRECTION_FACTOR 3 3 × 100/72
FONT_HEIGHT_CORRECTION_FACTOR 10 10 × 100/72
_inside_pad multiplier _fontsize_axis × 100 _fontsize_axis × 72
Baseline images regenerated 18 0

Why retune

Without the calibration constants, the dimensionally-correct formula makes every label gap ~38% wider at default DPI (factor 100/72 ≈ 1.388). That would silently shift CMS/ATLAS/etc. labels everywhere and was the reason 18 baselines moved in the original PR. Pre-tuning the correction factors by 100/72 cancels that exactly at the calibration DPI.

Verification

  • At dpi=100 (legacy default), pixel gap matches main exactly: 8.67 px on every figsize tested (10×10, 12×5, 16×4, 20×3, 5×12, 6×6).
  • Pixel gap scales linearly with DPI now — constant 0.087 inches across dpi=50/100/200/300 (vs current main which keeps a fixed 8.67px regardless of DPI, so the inch-gap shrinks at print resolution).
  • Full test suite: 323 passed, 0 failed against the existing baselines.

So the fix is now strictly a DPI-correctness improvement that's invisible at the default DPI and only kicks in when users render at non-100 DPI (e.g. savefig(..., dpi=300) for publication).

🤖 Generated with Claude Code

Two regression guards for the dpi-vs-points fix:

- test_cms_label_dpi_invariance: pytest-mpl visual at figsize=(12, 5),
  dpi=200 covering both loc=0 (label outside axes) and loc=2 (stacked
  inside). Catches reintroduction of the pixel-pinned gap, which at
  dpi=200 would shrink the gap to a sliver next to the DPI-scaled text.

- test_cms_label_gap_is_dpi_invariant: assertion test that renders the
  label at dpi=50/100/200/300 and asserts the CMS<->Preliminary gap is
  constant in inches across all DPIs. Math-only, font-rendering
  independent.
@andrzejnovak andrzejnovak changed the title Fix: Correct label positioning across figure sizes and DPIs fix: Correct label positioning across figure sizes and DPIs May 13, 2026
@andrzejnovak andrzejnovak merged commit cf267e4 into main May 13, 2026
12 checks passed
@andrzejnovak andrzejnovak deleted the fix-label-scaling-dpi-14182033389645325178 branch May 13, 2026 12:30
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.

2 participants