Як обчислити та побудувати діаграму шляху сонця за допомогою skyfield у Python

У цьому прикладі ми покажемо, як згенерувати діаграму шляху сонця для будь-якого заданого дня для попередньо обраної локації. Використовуючи бібліотеку skyfield, ми можемо отримати надзвичайно точні прогнози положення сонця в небі, і на відміну від багатьох інших бібліотек, ми можемо використовувати той самий метод для прогнозування положення інших небесних тіл.

Діаграма шляху сонця

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-форматтер
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"]

# Типи даних
AltAz = namedtuple("AltAz", ["altitude", "azimuth", "distance"])
TimeAltAz = namedtuple("TimeAltAz", ["time", "altitude", "azimuth", "distance"])

def sun_altaz(planet_at_location, ts):
    # Обчислити положення сонця, як видно зі спостерігача у <location>
    sun_pos = planet_at_location.at(ts).observe(sun).apparent()
    # Обчислити видиму висоту та азимут для положення сонця
    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]
    # Витягти компоненти для побудови графіка
    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)

# Випадкова локація поблизу Мюнхена
location = api.Topos('48.324777 N', '11.405610 E', elevation_m=519)
# Обчислити Alt/Az для двох різних днів
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"))

# Побудувати графік!
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 червня")
plt.plot(dec.azimuth, dec.altitude, label="15 грудня")
plt.ylim([0, None]) # Не показувати кути сонця нижче горизонту
plt.ylabel("Висота сонця")
plt.xlabel("Азимут сонця")
plt.title("Видиме положення сонця в нашому офісі")
plt.grid()
plt.gca().legend()
plt.gcf().set_size_inches(10,5)

plt.savefig("Sun path.svg")

Дивіться схожі статті за категоріями: Фізика Python Skyfield