Skip to content

Callables

Many functions in Starplot allow you to pass a callable for creating dynamic styles and labels for objects. For example, when you plot stars you can optionally specify a callable for determining the size of each star. Starplot has a few basic callables built-in, but you can also create your own.

What's a Callable?

In Python, a "callable" is anything that can be "called" (e.g. a function or a class with __call__ implemented).

As a simple example, here's how you can pass a callable to Python's sorted function to sort a list of strings by their length:

>>> animals = ["elephant","cat", "dog", "tiger"]

>>> sorted(animals, key=lambda a: len(a))

['cat', 'dog', 'tiger', 'elephant']

In the example above, the value of key is the callable — in this case, a lambda function.

Here's another way to write the code above:

>>> animals = ["elephant","cat", "dog", "tiger"]

>>> def length(a):
...   return len(a)
...
>>> sorted(animals, key=length)

['cat', 'dog', 'tiger', 'elephant']

Size

starplot.callables.size_by_magnitude

size_by_magnitude(star: Star) -> float

Simple sizing by magnitude, using a step size of 1.

Parameters:

Name Type Description Default
star Star

The Star instance to size

required
Source code in src/starplot/callables.py
def size_by_magnitude(star: Star) -> float:
    """
    Simple sizing by magnitude, using a step size of 1.

    Args:
        star: The Star instance to size
    """
    mag = star.magnitude
    size = 0
    if mag <= 0:
        size = 50
    elif mag <= 1:  # <= 1
        size = 42
    elif mag <= 2:  # 1..2
        size = 32
    elif mag <= 3:  # 2..3
        size = 25
    elif mag <= 4:  # 3..4
        size = 18
    elif mag <= 5:  # 4..5
        size = 10
    elif mag <= 6:  # 5..6
        size = 8
    elif mag <= 7:  # 6..7
        size = 6
    elif mag <= 8:  # 7..8
        size = 3
    elif mag <= 9:
        size = 2
    else:
        size = 1.25

    return size

starplot.callables.size_by_magnitude_galaxy

size_by_magnitude_galaxy(star: Star) -> float

Star sizer for galaxy plots that assumes only brighter stars will be plotted, so it uses smaller sizes overall.

This is the default star sizing function for GalaxyPlot.

Parameters:

Name Type Description Default
star Star

The Star instance to size

required
Source code in src/starplot/callables.py
def size_by_magnitude_galaxy(star: Star) -> float:
    """
    Star sizer for galaxy plots that assumes only brighter stars will be plotted, so it uses smaller sizes overall.

    _This is the default star sizing function for GalaxyPlot._

    Args:
        star: The Star instance to size
    """
    sizes = [
        15,
        15,
        10,
        8,
        5,
        3,
        2,
        1,
    ]
    mag = max(0, star.magnitude)
    mag_index = min(int(mag), len(sizes) - 1)
    return sizes[mag_index]

starplot.callables.size_by_fov_factory

size_by_fov_factory(fov: float) -> Callable[[Star], float]

Returns a callable for sizing stars based on the field of view of an optic.

This is the default star sizing function for OpticPlot.

Parameters:

Name Type Description Default
fov float

Field of view (in degrees)

required
Source code in src/starplot/callables.py
def size_by_fov_factory(fov: float) -> Callable[[Star], float]:
    """
    Returns a callable for sizing stars based on the field of view of an optic.

    _This is the default star sizing function for OpticPlot._

    Args:
        fov: Field of view (in degrees)
    """
    fov_multiplier = 20 / fov

    return lambda s: size_by_magnitude(s) * fov_multiplier * 0.64

Color

starplot.callables.color_by_bv

color_by_bv(star: Star) -> str

Calculates color by the object's B-V index

Color hex values from: Mitchell Charity

Source code in src/starplot/callables.py
def color_by_bv(star: Star) -> str:
    """
    Calculates color by the object's [B-V index](https://en.wikipedia.org/wiki/Color_index)

    Color hex values from: [Mitchell Charity](http://www.vendian.org/mncharity/dir3/starcolor/details.html)
    """
    if math.isnan(star.bv):
        bv = 0
    else:
        bv = star.bv
    return bv_to_hex_color(bv)

starplot.callables.color_by_bv_gradient

color_by_bv_gradient(star: Star) -> GradientStyle

Calculates a radial gradient by the object's B-V index, meant to resemble how a star looks through binoculars or a telescope: a bright core that gradually fades to fully transparent at the edge.

Uses the same base color as color_by_bv, lightened at the center of the gradient and faded to transparent at the outer edge.

Source code in src/starplot/callables.py
def color_by_bv_gradient(star: Star) -> GradientStyle:
    """
    Calculates a radial gradient by the object's [B-V index](https://en.wikipedia.org/wiki/Color_index),
    meant to resemble how a star looks through binoculars or a telescope: a bright core that gradually fades to fully transparent at the edge.

    Uses the same base color as `color_by_bv`, lightened at the center of the gradient and faded to transparent at the outer edge.
    """
    color = color_by_bv(star) or "#ffffff"
    r, g, b = hex_to_rgb(color)

    return GradientStyle(
        stops=(
            (0.0, f"rgba({r}, {g}, {b}, 0)"),
            (0.6, color),
            (1.0, lighten_hex_color(color, 0.2)),
        ),
        type="radial",
    )

Labels

starplot.callables.floor_hours_label

floor_hours_label(value: float) -> str

Returns the floor of the value, with an 'h' appended to it.

Example: floor_hours_label(50) = '3h'

Parameters:

Name Type Description Default
value float

The value to label

required
Source code in src/starplot/callables.py
def floor_hours_label(value: float) -> str:
    """
    Returns the floor of the value, with an 'h' appended to it.

    Example: `floor_hours_label(50) = '3h'`

    Args:
        value: The value to label

    """
    return f"{math.floor(value / 15)}h"

starplot.callables.rounded_degrees_label

rounded_degrees_label(value: float) -> str

Returns the rounded value with a degree symbol appended to it.

Example: rounded_degrees_label(50.45) = '50°'

Parameters:

Name Type Description Default
value float

The value to label

required
Source code in src/starplot/callables.py
def rounded_degrees_label(value: float) -> str:
    """
    Returns the rounded value with a degree symbol appended to it.

    Example: `rounded_degrees_label(50.45) = '50°'`

    Args:
        value: The value to label

    """
    return f"{round(value)}° "

starplot.callables.azimuth_with_cardinal_direction_label_factory

azimuth_with_cardinal_direction_label_factory(
    language: str,
) -> Callable[[float], str]

Returns a callable for labeling azimuth values. The callable returns the cardinal directions (e.g. North, South, etc) where applicable, and returns the rounded azimuth value with a degree symbol appended for other azimuths (e.g. '120°').

This is the default label function for azimuths on HorizonPlot.

Parameters:

Name Type Description Default
language str

Language for the cardinal directions

required
Source code in src/starplot/callables.py
def azimuth_with_cardinal_direction_label_factory(
    language: str,
) -> Callable[[float], str]:
    """
    Returns a callable for labeling azimuth values. The callable returns the cardinal directions
    (e.g. North, South, etc) where applicable, and returns the rounded azimuth value with a degree
    symbol appended for other azimuths (e.g. `'120°'`).

    _This is the default label function for azimuths on HorizonPlot._

    Args:
        language: Language for the cardinal directions
    """

    def az_label_fn(az):
        cardinal_directions = {
            0: "NORTH",
            90: "EAST",
            180: "SOUTH",
            270: "WEST",
        }
        label = translate(cardinal_directions.get(az), language)
        return label.upper() if label else f"{round(az)}\u00b0"

    return az_label_fn

Creating Your Own Callable

Let's say you wanted to create a plot where the stars brighter than magnitude 4 should be colored blue and stars dimmer than that should be colored red. Here's a way to do that with a custom callable:

# first we define the callable:
def color_by_mag(star: Star) -> str:
    if star.magnitude <= 4:
        return "#218fef"
    else:
        return "#d52727"

# then to use your callable:
p = MapPlot(...)
p.stars(
    where=[_.magnitude < 12],
    color_fn=color_by_mag,
)
Every callable for stars is passed an instance of Star, so you can reference various properties of stars in your callables. Similarly, every callable for a DSO is passed an instance of DSO.