Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ keywords:
- graphs
- plotting
license: MIT
version: 0.20.2
date-released: '2026-03-31'
version: 0.20.3
date-released: '2026-04-30'
1 change: 1 addition & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- Optimizes coordinate conversions
- Makes constellation lines straight
- [**v0.20.2**] Restricts Pandas to version `2.2.3` or lower
- [**v0.20.3**] Fixes bugs with styling and class variables

## v0.19.x
[Documentation](https://archives.starplot.dev/0.19.6/)
Expand Down
2 changes: 1 addition & 1 deletion src/starplot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

"""Star charts and maps of the sky"""

__version__ = "0.20.2"
__version__ = "0.20.3"

from .plots import (
MapPlot,
Expand Down
49 changes: 21 additions & 28 deletions src/starplot/plots/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,37 +51,9 @@


class BasePlot(DebugPlotterMixin, TextPlotterMixin, ABC):
_background_clip_path = None
_clip_path_polygon: Polygon = None # clip path in display coordinates
_coordinate_system = CoordinateSystem.RA_DEC
_gradient_direction: GradientDirection = GradientDirection.LINEAR

ax: Axes
"""
The underlying [Matplotlib axes](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html#matplotlib.axes.Axes) that everything is plotted on.

**Important**: Most Starplot plotting functions also specify a transform based on the plot's projection when plotting things on the Matplotlib Axes instance, so use this property at your own risk!
"""

fig: Figure
"""
The underlying [Matplotlib figure](https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.Figure.html#matplotlib.figure.Figure) that the axes is drawn on.
"""

style: PlotStyle
"""
The plot's style.
"""

point_label_handler: CollisionHandler
"""Default [collision handler][starplot.CollisionHandler] for point labels."""

area_label_handler: CollisionHandler
"""Default [collision handler][starplot.CollisionHandler] for area labels."""

path_label_handler: CollisionHandler
"""Default [collision handler][starplot.CollisionHandler] for path labels."""

def __init__(
self,
observer: Observer = None,
Expand All @@ -99,6 +71,20 @@ def __init__(
):
super().__init__(*args, **kwargs)

self._clip_path_polygon: Polygon = None # clip path in display coordinates

self.ax: Axes = None
"""
The underlying [Matplotlib axes](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html#matplotlib.axes.Axes) that everything is plotted on.

**Important**: Most Starplot plotting functions also specify a transform based on the plot's projection when plotting things on the Matplotlib Axes instance, so use this property at your own risk!
"""

self.fig: Figure = None
"""
The underlying [Matplotlib figure](https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.Figure.html#matplotlib.figure.Figure) that the axes is drawn on.
"""

if StarplotSettings.svg_text_type == SvgTextType.PATH:
plt.rcParams["svg.fonttype"] = "path"
else:
Expand All @@ -111,6 +97,8 @@ def __init__(
self.language = StarplotSettings.language

self.style = style or PlotStyle()
"""The plot's style."""

self.figure_size = resolution * px
self.resolution = resolution

Expand All @@ -127,12 +115,17 @@ def __init__(
AnchorPointEnum.LEFT_CENTER,
],
)
"""Default [collision handler][starplot.CollisionHandler] for point labels."""

self.area_label_handler = area_label_handler or CollisionHandler(
allow_constellation_line_collisions=True
)
"""Default [collision handler][starplot.CollisionHandler] for area labels."""

self.path_label_handler = path_label_handler or CollisionHandler(
allow_constellation_line_collisions=True
)
"""Default [collision handler][starplot.CollisionHandler] for path labels."""

self.scale = scale
self.autoscale = autoscale
Expand Down
10 changes: 9 additions & 1 deletion src/starplot/styles/helpers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import inspect
import json

from functools import wraps
Expand All @@ -22,9 +23,13 @@ def merge_dict(dict_1: dict, dict_2: dict) -> None:

def use_style(style_class, style_attr: str = None):
def decorator(func):
params = list(inspect.signature(func).parameters.keys())
style_pos = params.index("style") if "style" in params else -1

@wraps(func)
def wrapper(*args, **kwargs):
style = kwargs.get("style")
style_in_positional = 0 <= style_pos < len(args)
style = args[style_pos] if style_in_positional else kwargs.get("style")
style_kwargs = {
kw: value for kw, value in kwargs.items() if kw.startswith("style__")
}
Expand Down Expand Up @@ -78,6 +83,9 @@ def wrapper(*args, **kwargs):
# if no style overrides and there's a base style, then just pass the base style
kwargs["style"] = getattr(args[0].style, style_attr, None)

elif style is None and not style_in_positional:
kwargs["style"] = style_class()

return func(*args, **kwargs)

return wrapper
Expand Down
5 changes: 5 additions & 0 deletions tests/test_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ def test_marker_no_label():
p.marker(ra=150, dec=0, style__marker__color="blue")


def test_text_no_style_kwarg():
p = MapPlot(projection=Mercator())
p.text(ra=100, dec=0, text="hello")


def test_plots_at_astrometric():
"""Asserts that map plots plot astrometric positions, NOT apparent"""

Expand Down