Skip to content

capturegraph.data.load.types.solar #

Solar Position - Calculate sun altitude and azimuth from datetime and location.#

Vectorized functions for calculating solar position (altitude and azimuth) based on date/time and geographic coordinates.

Example
import capturegraph.data as cg
import capturegraph.scheduling.forecast as cgsh
from datetime import datetime

# Create a location
loc = cg.Location(latitude=42.445, longitude=-76.480, altitude=0)

# Single calculation
pos = cgsh.forecast.solar_position(loc, datetime(2026, 1, 9, 12, 0))
print(pos.altitude)  # Sun elevation in degrees
print(pos.azimuth)   # Sun azimuth in degrees (0=N, 90=E)

# Vectorized with Lists
dates = sessions.date
locs = sessions.location
positions = cgsh.forecast.solar_position(locs, dates)
altitudes = positions.altitude  # → List of altitudes
Notes
  • Uses the astral library for accurate solar position calculations
  • Altitude: degrees above horizon (-90 to 90), negative = below horizon
  • Azimuth: degrees clockwise from North (0-360)
  • Works with naive datetime (assumes UTC) or timezone-aware datetime
  • Install the optional dependency with: pip install astral

SolarPosition dataclass #

Solar position with altitude (elevation) and azimuth.

Attributes:

Name Type Description
altitude float

Sun elevation angle in degrees above the horizon. Positive = above horizon, negative = below horizon. Range: -90° to 90°.

azimuth float

Sun azimuth angle in degrees clockwise from North. 0° = North, 90° = East, 180° = South, 270° = West. Range: 0° to 360°.

Source code in capturegraph-lib/capturegraph/data/load/types/solar.py
@dataclass
class SolarPosition:
    """Solar position with altitude (elevation) and azimuth.

    Attributes:
        altitude: Sun elevation angle in degrees above the horizon.
            Positive = above horizon, negative = below horizon.
            Range: -90° to 90°.
        azimuth: Sun azimuth angle in degrees clockwise from North.
            0° = North, 90° = East, 180° = South, 270° = West.
            Range: 0° to 360°.
    """

    altitude: float
    azimuth: float

    def __repr__(self) -> str:
        return f"SolarPosition(alt={self.altitude:.1f}°, az={self.azimuth:.1f}°)"

    def to_json(self) -> dict:
        return {
            "altitude": self.altitude,
            "azimuth": self.azimuth,
        }

    @classmethod
    def from_json(cls, obj: dict) -> "SolarPosition":
        return cls(
            altitude=obj["altitude"],
            azimuth=obj["azimuth"],
        )