Skip to content

Add polar-aware rlabel and thetalabel support#714

Open
kinyatoride wants to merge 2 commits intoUltraplot:mainfrom
kinyatoride:feat-polar-thetalabel-rlabel
Open

Add polar-aware rlabel and thetalabel support#714
kinyatoride wants to merge 2 commits intoUltraplot:mainfrom
kinyatoride:feat-polar-thetalabel-rlabel

Conversation

@kinyatoride
Copy link
Copy Markdown
Contributor

Add polar-aware rlabel and thetalabel support

Hi! I think having rlabel and thetalabel for polar plots is useful for many
cases — Taylor diagrams being one example. I've added this support along with
tests. Let me know what you think!

Summary

This PR adds polar-aware axis label support to PolarAxes.format() with new
thetalabel and rlabel arguments rendered via CurvedText.

Key Features

  • Add thetalabel for labels that follow the outer polar arc.
  • Add rlabel for labels that follow a radial spoke.
  • Add thetalabelloc to control the center angle of the theta label.
  • Add rlabelloc to control which side or spoke the radial label uses.
  • Support explicit rlabelpos placement for radial labels.
  • Support styling through thetalabel_kw and rlabel_kw.
  • Keep label placement correct for:
    • full-circle plots
    • sector plots
    • wrapped theta intervals
    • transformed theta orientation (theta0, thetadir)
    • annular polar axes
  • Refresh label geometry during draw and tight-bbox updates.

Implementation

  • Add polar-label geometry and state handling in ultraplot/axes/polar.py
  • Update CurvedText in ultraplot/text.py so transformed and styled curved labels
    behave correctly on polar axes
  • Split pseudo label props in ultraplot/internals/labels.py so border and bbox
    styling can be applied safely to curved labels

Validation

Focused polar regression tests pass:

python -m pytest ultraplot/tests/test_projections.py -k "polar and not mpl_image_compare"

This also adds regression coverage for:

  • transformed thetalabel outward placement
  • annular polar label positioning with finite glyph positions

Examples

Examples of full-circle, sector, annular, and rotated-axis polar labels:

import ultraplot as uplt

fig, axs = uplt.subplots(
    proj='polar', ncols=2, nrows=3, share=0,
)

axs[0, 0].format(
    thetalabel='Full circle',
    rlabel='Radius',
    title='Full circle, default locs',
    labelsize=10,
)

axs[0, 1].format(
    thetalim=(0, 360),
    rlim=(5, 10),
    thetalabel='Label at 250°',
    thetalabelloc=250,
    rlabel='left label',
    rlabelloc='left',
    title='Full circle, custom locs',
    labelsize=10,
)

axs[1, 0].format(
    thetalim=(0, 90),
    rlim=(0, 1),
    thetalabel='Quarter arc',
    rlabel='r [0-1]',
    title='Section, default locs',
    labelsize=10,
)

axs[1, 1].format(
    thetalim=(0, 180),
    rlim=(0, 10),
    thetalabel='Label at 135°',
    thetalabelloc=135,
    rlabel='Left spoke',
    rlabelloc='left',
    title='Section, custom locs',
    labelsize=10,
)

axs[2, 0].format(
    thetalim=(50, 70),
    r0=0, rlim=(1, 5),
    thetalabel='Narrow section',
    thetalabel_kw={'color': 'steelblue', 'style': 'italic'},
    rlabel='labelpad=50',
    rlabel_kw={'labelpad': 50, 'weight': 'bold', 'size': 13},
    title='Section, labelpad',
    labelsize=10,
)

axs[2, 1].format(
    thetalim=(0, 180),
    rlim=(2, 10),
    theta0='N',
    thetadir=-1,
    thetalabel='Reversed theta direction',
    rlabel='Radius',
    rlabelloc='right',
    title="theta0='N', thetadir=-1",
)
axs.format(
    suptitle='Polar labels demo',
    titlepad=30,
)
polar_labels_demo

@codecov
Copy link
Copy Markdown

codecov Bot commented May 6, 2026

Codecov Report

❌ Patch coverage is 95.74468% with 18 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
ultraplot/axes/polar.py 93.33% 5 Missing and 7 partials ⚠️
ultraplot/text.py 80.00% 4 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

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.

1 participant