Expand obs window to full dark+moon period; label with illumination%

moon_phase.py: add sun_altaz() to compute sun altitude for dark-sky check

moon_phase_monthly.py:
- Replace fixed 22:00-23:00 window with dynamic dark+moon intervals:
  sample every 10 min across ±24h of the phase moment, keep blocks where
  sun < DARK_SKY_SUN_ALT_DEG and moon > MIN_ALTITUDE — covers the full
  night the moon is actually visible in a dark sky regardless of month
- First east frame with quality >= MIN_QUALITY in that window wins
- Illumination% computed at the detection time and shown in the image
  caption and Mattermost message
- Remove OBS_TIME_H/M; add DARK_SKY_SUN_ALT_DEG config var

sky-cam.conf: replace MOON_OBS_TIME_LOCAL with MOON_DARK_SKY_SUN_ALT_DEG=-6
and explain the sun-altitude threshold options

https://claude.ai/code/session_01HkTxpNSTWtViZzxbrbKytR
This commit is contained in:
Claude
2026-05-01 22:32:16 +00:00
parent a6989a9ea8
commit 3fc77ab75e
3 changed files with 109 additions and 82 deletions
+16
View File
@@ -179,6 +179,22 @@ def altaz(when: datetime, lat: float | None = None, lon: float | None = None):
return float(alt.degrees), float(az.degrees)
def sun_altaz(when: datetime, lat: float | None = None, lon: float | None = None):
"""Apparent altitude/azimuth of the sun in degrees as seen from (lat, lon)."""
_lazy()
from skyfield.api import wgs84
if lat is None and lon is None:
obs = _observer
else:
obs = _eph['earth'] + wgs84.latlon(
LATITUDE if lat is None else lat,
LONGITUDE if lon is None else lon,
)
t = _t(when)
alt, az, _ = obs.at(t).observe(_eph['sun']).apparent().altaz()
return float(alt.degrees), float(az.degrees)
def parallactic_angle(when: datetime, lat: float | None = None, lon: float | None = None) -> float:
"""Parallactic angle in degrees — rotates a moon image so celestial north is up.