Source code for pygmt.src.solar

"""
solar - Plot day-night terminators and other sunlight parameters.
"""

from collections.abc import Sequence
from typing import Literal

import pandas as pd
from pygmt._typing import DatetimeLike
from pygmt.alias import Alias, AliasSystem
from pygmt.clib import Session
from pygmt.exceptions import GMTValueError
from pygmt.helpers import build_arg_list, fmt_docstring
from pygmt.params import Axis, Frame, Pattern

__doctest_skip__ = ["solar"]


@fmt_docstring
def solar(
    self,
    terminator: Literal["astronomical", "civil", "day_night", "nautical"] = "day_night",
    terminator_datetime: DatetimeLike | None = None,
    fill: str | Pattern | None = None,
    pen: str | None = None,
    projection: str | None = None,
    region: Sequence[float | str] | str | None = None,
    frame: Frame | Axis | Literal["none"] | str | Sequence[str] | bool = False,
    verbose: Literal["quiet", "error", "warning", "timing", "info", "compat", "debug"]
    | bool = False,
    panel: int | Sequence[int] | bool = False,
    perspective: float | Sequence[float] | str | bool = False,
    transparency: float | None = None,
    **kwargs,
):
    """
    Plot day-night terminators and other sunlight parameters.

    This method can plot the day-night terminator, and the civil, nautical, and
    astronomical twilights.

    Full GMT docs at :gmt-docs:`solar.html`.

    **Aliases:**

    .. hlist::
       :columns: 3

       - B = frame
       - G = fill
       - J = projection
       - R = region
       - T = terminator, **+d**/**+z**: terminator_datetime
       - V = verbose
       - W = pen
       - c = panel
       - p = perspective
       - t = transparency

    Parameters
    ----------
    terminator
        Set the type of terminator. Choose one of the following:

        - ``"astronomical"``: Astronomical twilight
        - ``"civil"``: Civil twilight
        - ``"day_night"``: Day-night terminator
        - ``"nautical"``: Nautical twilight

        Refer to https://en.wikipedia.org/wiki/Twilight for the definitions of different
        types of twilight.
    terminator_datetime
        Set the date and time for the terminator calculation. It can be provided as a
        string or any datetime-like object recognized by :func:`pandas.to_datetime`. The
        time can be specified in UTC or with a UTC offset of any precision [Default is
        the current UTC date and time].
    fill
        Set color or pattern for filling terminators [Default is no fill].
    pen
        Set pen attributes for lines [Default is ``"0.25p,black,solid"``].
    $projection
    $region
    $frame
    $verbose
    $panel
    $perspective
    $transparency

    Example
    -------

    Plot the day-night terminator at the current UTC date and time.

    >>> import datetime
    >>> import pygmt

    >>> fig = pygmt.Figure()
    >>> fig.coast(land="darkgreen", water="lightblue", projection="W10c", region="d")
    >>> fig.solar()
    >>> fig.show()

    Plot the astronomical twilight at 8:52:18 on June 24, 1997 (time in UTC), with the
    night-section filled with navyblue at 75% transparency.

    >>> import datetime
    >>> # Create a datetime object at 8:52:18 on June 24, 1997 (time in UTC)
    >>> date = datetime.datetime(
    ...     year=1997, month=6, day=24, hour=8, minute=52, second=18
    ... )
    >>> fig = pygmt.Figure()
    >>> fig.coast(land="darkgreen", water="lightblue", projection="W10c", region="d")
    >>> fig.solar(
    ...     terminator="astronomical",
    ...     terminator_datetime=date,
    ...     # Fill the night-section with navyblue at 75% transparency
    ...     fill="navyblue@75",
    ...     pen="1p,black",  # Draw the terminator with a 1-point black line
    ... )
    >>> fig.show()
    """
    datetime_string = None
    if terminator_datetime:
        try:
            _datetime = pd.to_datetime(terminator_datetime)
        except ValueError as verr:
            raise GMTValueError(terminator_datetime, description="datetime") from verr
        # Convert a timezone-aware datetime to UTC, before passing to GMT.
        if _datetime.tzinfo is not None:
            _datetime = _datetime.tz_convert("UTC")
        datetime_string = _datetime.strftime("%Y-%m-%dT%H:%M:%S.%f")

    aliasdict = AliasSystem(
        G=Alias(fill, name="fill"),
        T=[
            Alias(
                terminator,
                name="terminator",
                mapping={
                    "day_night": "d",
                    "civil": "c",
                    "nautical": "n",
                    "astronomical": "a",
                },
            ),
            Alias(datetime_string, name="terminator_datetime", prefix="+d"),
        ],
        W=Alias(pen, name="pen"),
    ).add_common(
        B=frame,
        J=projection,
        R=region,
        V=verbose,
        c=panel,
        p=perspective,
        t=transparency,
    )
    aliasdict.merge(kwargs)

    self._activate_figure()
    with Session() as lib:
        lib.call_module(module="solar", args=build_arg_list(aliasdict))