Sonnenstandsdiagramm mit skyfield in Python berechnen & plotten

English Deutsch

In diesem Beispiel zeigen wir, wie man ein Sonnenstandsdiagramm für einen beliebigen Tag für einen vorgewählten Standort generiert. Durch die Verwendung der skyfield-Bibliothek können wir extrem genaue Vorhersagen der Sonnenposition am Himmel erhalten, und im Gegensatz zu vielen anderen Bibliotheken können wir dieselbe Methode verwenden, um die Position anderer Himmelskörper vorherzusagen.

Sonnenstandsdiagramm

sun_path_plot.py
#!/usr/bin/env python3
from skyfield import api
from skyfield import almanac
from datetime import datetime
from datetime import timedelta
from matplotlib import pyplot as plt
import pytz
import dateutil.parser
from collections import namedtuple
from UliEngineering.Utils.Date import *
import matplotlib.ticker as mtick

# Matplotlib-Formatter
def format_degrees(value, pos=None):
    return f'{value:.0f} °'

ts = api.load.timescale()
ephem = api.load_file('de421.bsp')

sun = ephem["Sun"]
earth = ephem["Earth"]

# Datentypen
AltAz = namedtuple("AltAz", ["altitude", "azimuth", "distance"])
TimeAltAz = namedtuple("TimeAltAz", ["time", "altitude", "azimuth", "distance"])

def sun_altaz(planet_at_location, ts):
    # Sonnenposition vom Beobachter an <location> berechnen
    sun_pos = planet_at_location.at(ts).observe(sun).apparent()
    # Scheinbare Höhe & Azimut für die Sonnenposition berechnen
    altitude, azimuth, distance = sun_pos.altaz()
    return AltAz(altitude, azimuth, distance)

def sun_altaz_for_day(location, year, month, day, tz):
    earth_at_location = (earth + location)

    minutes = list(yield_minutes_on_day(year=year, month=month, day=day, tz=tz))
    skyfield_minutes = ts.from_datetimes(minutes)

    minutely_altaz = [sun_altaz(earth_at_location, ts) for ts in skyfield_minutes]
    # Komponenten zum Plotten extrahieren
    minutely_alt = [altaz.altitude.degrees for altaz in minutely_altaz]
    minutely_az = [altaz.azimuth.degrees for altaz in minutely_altaz]
    minutely_distance = [altaz.distance for altaz in minutely_altaz]

    return TimeAltAz(minutes, minutely_alt, minutely_az, minutely_distance)

# Zufälliger Standort in der Nähe von München
location = api.Topos('48.324777 N', '11.405610 E', elevation_m=519)
# Alt/Az für zwei verschiedene Tage berechnen
jun = sun_altaz_for_day(location, 2022, 6, 15, pytz.timezone("Europe/Berlin"))
dec = sun_altaz_for_day(location, 2022, 12, 15, pytz.timezone("Europe/Berlin"))

# Plotten!
plt.gca().yaxis.set_major_formatter(mtick.FuncFormatter(format_degrees))
plt.gca().xaxis.set_major_formatter(mtick.FuncFormatter(format_degrees))

plt.plot(jun.azimuth, jun.altitude, label="15. Juni")
plt.plot(dec.azimuth, dec.altitude, label="15. Dezember")
plt.ylim([0, None]) # Sonnenwinkel unter dem Horizont nicht anzeigen
plt.ylabel("Sonnenhöhe")
plt.xlabel("Sonnenazimut")
plt.title("Scheinbare Sonnenposition an unserem Büro")
plt.grid()
plt.gca().legend()
plt.gcf().set_size_inches(10,5)

plt.savefig("Sun path.svg")

Check out similar posts by category: Physics, Python, Skyfield