Neue Seite fuer Mond-Planeten-Bedeckungen mit Jahresberechnung hinzufuegen
Berechnet Bedeckungen der Planeten Merkur bis Neptun durch den Mond fuer ein ganzes Jahr am Standardstandort, inklusive Detailkarte. Ereignisse unter dem Horizont werden weiterhin angezeigt statt gefiltert, dafuer mit eigenem Sichtbarkeits-Hinweis. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+155
-2
@@ -5844,6 +5844,154 @@ def action_moon_star_occultations(args: list[str]) -> dict:
|
||||
}
|
||||
|
||||
|
||||
PLANET_OCCULTATION_DEFS = [
|
||||
("Merkur", astronomy.Body.Mercury, "mercury"),
|
||||
("Venus", astronomy.Body.Venus, "venus"),
|
||||
("Mars", astronomy.Body.Mars, "mars"),
|
||||
("Jupiter", astronomy.Body.Jupiter, "jupiter"),
|
||||
("Saturn", astronomy.Body.Saturn, "saturn"),
|
||||
("Uranus", astronomy.Body.Uranus, "uranus"),
|
||||
("Neptun", astronomy.Body.Neptune, "neptune"),
|
||||
]
|
||||
|
||||
|
||||
def compute_moon_planet_occultations_for_range(
|
||||
observer: astronomy.Observer,
|
||||
utc_start: datetime,
|
||||
utc_end: datetime,
|
||||
tz: ZoneInfo,
|
||||
) -> list[dict]:
|
||||
scan_step = timedelta(hours=1)
|
||||
coarse_threshold_deg = 3.0
|
||||
results: list[dict] = []
|
||||
|
||||
for label, body, key in PLANET_OCCULTATION_DEFS:
|
||||
samples: list[tuple[datetime, float]] = []
|
||||
current = utc_start
|
||||
while current <= utc_end:
|
||||
samples.append((current, moon_planet_separation_deg(body, observer, current)))
|
||||
current += scan_step
|
||||
if samples[-1][0] < utc_end:
|
||||
samples.append((utc_end, moon_planet_separation_deg(body, observer, utc_end)))
|
||||
|
||||
seen_ranges: list[tuple[datetime, datetime]] = []
|
||||
for index in range(1, len(samples) - 1):
|
||||
prev_t, prev_sep = samples[index - 1]
|
||||
curr_t, curr_sep = samples[index]
|
||||
next_t, next_sep = samples[index + 1]
|
||||
|
||||
if curr_sep > coarse_threshold_deg:
|
||||
continue
|
||||
if curr_sep > prev_sep or curr_sep > next_sep:
|
||||
continue
|
||||
|
||||
left = max(utc_start, curr_t - scan_step)
|
||||
right = min(utc_end, curr_t + scan_step)
|
||||
|
||||
if any(not (right <= seen_left or left >= seen_right) for seen_left, seen_right in seen_ranges):
|
||||
continue
|
||||
|
||||
min_time_utc, min_sep = refine_minimum_separation(body, observer, left, right)
|
||||
seen_ranges.append((left, right))
|
||||
|
||||
overlap_fraction = moon_planet_overlap_fraction(body, observer, min_time_utc)
|
||||
if overlap_fraction <= 0.0:
|
||||
continue
|
||||
|
||||
time_value = dt_to_time(min_time_utc)
|
||||
moon_eq = astronomy.Equator(astronomy.Body.Moon, time_value, observer, True, True)
|
||||
planet_eq = astronomy.Equator(body, time_value, observer, True, True)
|
||||
sun_eq = astronomy.Equator(astronomy.Body.Sun, time_value, observer, True, True)
|
||||
moon_hor = astronomy.Horizon(time_value, observer, moon_eq.ra, moon_eq.dec, astronomy.Refraction.Normal)
|
||||
planet_hor = astronomy.Horizon(time_value, observer, planet_eq.ra, planet_eq.dec, astronomy.Refraction.Normal)
|
||||
sun_hor = astronomy.Horizon(time_value, observer, sun_eq.ra, sun_eq.dec, astronomy.Refraction.Normal)
|
||||
|
||||
below_horizon = float(moon_hor.altitude) <= 0.0 or float(planet_hor.altitude) <= 0.0
|
||||
|
||||
ingress_time = refine_occultation_contact(body, observer, min_time_utc, -1)
|
||||
egress_time = refine_occultation_contact(body, observer, min_time_utc, 1)
|
||||
|
||||
duration_seconds = None
|
||||
if ingress_time is not None and egress_time is not None:
|
||||
duration_seconds = int(round((egress_time - ingress_time).total_seconds()))
|
||||
|
||||
moon_radius_deg = moon_angular_radius_deg(float(moon_eq.dist))
|
||||
planet_radius_deg = planet_angular_radius_deg(body, float(planet_eq.dist))
|
||||
|
||||
results.append({
|
||||
"planet_key": key,
|
||||
"planet_label": label,
|
||||
"ingress": serialize_occultation_time(ingress_time, tz),
|
||||
"maximum": serialize_occultation_time(min_time_utc, tz),
|
||||
"egress": serialize_occultation_time(egress_time, tz),
|
||||
"partial_start": ingress_time is None,
|
||||
"partial_end": egress_time is None,
|
||||
"duration_seconds": duration_seconds,
|
||||
"separation_arcmin": float(min_sep) * 60.0,
|
||||
"moon_radius_arcmin": moon_radius_deg * 60.0,
|
||||
"planet_radius_arcsec": planet_radius_deg * 3600.0,
|
||||
"overlap_fraction": float(overlap_fraction),
|
||||
"is_total": overlap_fraction >= 0.999,
|
||||
"moon_alt_deg": float(moon_hor.altitude),
|
||||
"planet_alt_deg": float(planet_hor.altitude),
|
||||
"sun_alt_deg": float(sun_hor.altitude),
|
||||
"below_horizon": below_horizon,
|
||||
"visibility": {"key": "below_horizon", "label": "Unter Horizont"} if below_horizon
|
||||
else classify_visibility(float(sun_hor.altitude)),
|
||||
})
|
||||
|
||||
results.sort(
|
||||
key=lambda item: item["maximum"]["utc_iso"] if item["maximum"] else "9999-99-99T99:99:99Z"
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def action_moon_planet_occultations_for_year(args: list[str]) -> dict:
|
||||
if len(args) != 5:
|
||||
fail(
|
||||
"Aktion moon_planet_occultations_for_year erwartet 5 Argumente: latitude longitude elevation year timezone",
|
||||
extra={"argv": args},
|
||||
)
|
||||
|
||||
latitude = parse_float(args[0], "Latitude")
|
||||
longitude = parse_float(args[1], "Longitude")
|
||||
elevation = parse_float(args[2], "Elevation")
|
||||
|
||||
try:
|
||||
year = int(args[3])
|
||||
except ValueError as exc:
|
||||
fail("Jahr ist ungueltig.", extra={"details": str(exc), "argv": args})
|
||||
|
||||
timezone_name = args[4]
|
||||
try:
|
||||
tz = ZoneInfo(timezone_name)
|
||||
except Exception as exc:
|
||||
fail("Zeitzone ist ungueltig oder auf dem Server nicht verfuegbar.", extra={"details": str(exc)})
|
||||
|
||||
observer = astronomy.Observer(latitude, longitude, elevation)
|
||||
local_start = datetime(year, 1, 1, 0, 0, 0, tzinfo=tz)
|
||||
local_end = datetime(year + 1, 1, 1, 0, 0, 0, tzinfo=tz)
|
||||
utc_start = local_start.astimezone(timezone.utc)
|
||||
utc_end = local_end.astimezone(timezone.utc)
|
||||
|
||||
results = compute_moon_planet_occultations_for_range(observer, utc_start, utc_end, tz)
|
||||
|
||||
return {
|
||||
"ok": True,
|
||||
"action": "moon_planet_occultations_for_year",
|
||||
"selected": {
|
||||
"year": year,
|
||||
"timezone": timezone_name,
|
||||
},
|
||||
"observer": {
|
||||
"latitude": latitude,
|
||||
"longitude": longitude,
|
||||
"elevation": elevation,
|
||||
},
|
||||
"results": results,
|
||||
}
|
||||
|
||||
|
||||
# ── satellite_passes ──────────────────────────────────────────────────────────
|
||||
|
||||
import math as _math
|
||||
@@ -6415,7 +6563,7 @@ def action_barycenter(args: list[str]) -> dict:
|
||||
|
||||
def main() -> None:
|
||||
if len(sys.argv) < 2:
|
||||
fail("Es wurde keine Aktion uebergeben.", extra={"available_actions": ["sun_moon_rise_set", "solar_longitude_to_datetime", "current_solar_longitude", "astronomical_conversions", "comet_brightnesses", "favorite_comet_events_for_month", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "planet_ephemeris", "month_sky_context", "moon_phases_for_month", "golden_handle_for_month", "season_changes_for_month", "time_changes_for_month", "moon_planet_approaches", "moon_deep_sky_approaches_for_month", "planet_bright_star_approaches_for_month", "golden_gate_of_ecliptic_for_month", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "jupiter_moons_one_side_for_month", "mercury_good_visibility_for_month", "planet_parades_for_month", "planet_constellation_changes_for_month", "sun_constellation_changes_for_year", "sun_constellation_offset_statistics", "moon_star_occultations_for_month"]})
|
||||
fail("Es wurde keine Aktion uebergeben.", extra={"available_actions": ["sun_moon_rise_set", "solar_longitude_to_datetime", "current_solar_longitude", "astronomical_conversions", "comet_brightnesses", "favorite_comet_events_for_month", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "planet_ephemeris", "month_sky_context", "moon_phases_for_month", "golden_handle_for_month", "season_changes_for_month", "time_changes_for_month", "moon_planet_approaches", "moon_deep_sky_approaches_for_month", "planet_bright_star_approaches_for_month", "golden_gate_of_ecliptic_for_month", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "jupiter_moons_one_side_for_month", "mercury_good_visibility_for_month", "planet_parades_for_month", "planet_constellation_changes_for_month", "sun_constellation_changes_for_year", "sun_constellation_offset_statistics", "moon_star_occultations_for_month", "moon_planet_occultations_for_year"]})
|
||||
|
||||
action = sys.argv[1]
|
||||
args = sys.argv[2:]
|
||||
@@ -6605,6 +6753,11 @@ def main() -> None:
|
||||
print(json.dumps(result, ensure_ascii=True))
|
||||
return
|
||||
|
||||
if action == "moon_planet_occultations_for_year":
|
||||
result = action_moon_planet_occultations_for_year(args)
|
||||
print(json.dumps(result, ensure_ascii=True))
|
||||
return
|
||||
|
||||
if action == "lunar_eclipses_for_year":
|
||||
result = action_lunar_eclipses_for_year(args)
|
||||
print(json.dumps(result, ensure_ascii=True))
|
||||
@@ -6615,7 +6768,7 @@ def main() -> None:
|
||||
print(json.dumps(result, ensure_ascii=True))
|
||||
return
|
||||
|
||||
fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "solar_longitude_to_datetime", "current_solar_longitude", "astronomical_conversions", "twilight_chart", "comet_brightnesses", "favorite_comet_events_for_month", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "planet_ephemeris", "planet_visibility_chart", "month_sky_context", "moon_phases_for_month", "golden_handle_for_month", "season_changes_for_month", "time_changes_for_month", "moon_planet_approaches", "moon_deep_sky_approaches_for_month", "planet_bright_star_approaches_for_month", "golden_gate_of_ecliptic_for_month", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "jupiter_moons_one_side_for_month", "mercury_good_visibility_for_month", "planet_parades_for_month", "planet_constellation_changes_for_month", "sun_constellation_changes_for_year", "sun_constellation_offset_statistics", "moon_star_occultations_for_month"]})
|
||||
fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "solar_longitude_to_datetime", "current_solar_longitude", "astronomical_conversions", "twilight_chart", "comet_brightnesses", "favorite_comet_events_for_month", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "planet_ephemeris", "planet_visibility_chart", "month_sky_context", "moon_phases_for_month", "golden_handle_for_month", "season_changes_for_month", "time_changes_for_month", "moon_planet_approaches", "moon_deep_sky_approaches_for_month", "planet_bright_star_approaches_for_month", "golden_gate_of_ecliptic_for_month", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "jupiter_moons_one_side_for_month", "mercury_good_visibility_for_month", "planet_parades_for_month", "planet_constellation_changes_for_month", "sun_constellation_changes_for_year", "sun_constellation_offset_statistics", "moon_star_occultations_for_month", "moon_planet_occultations_for_year"]})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user