Planeten helle Sterne begegnung rein
This commit is contained in:
@@ -18,6 +18,9 @@ $messierDatabaseMagnitudeLimit = 4.0;
|
|||||||
$messierDisplayMagnitudeLimit = 1.0;
|
$messierDisplayMagnitudeLimit = 1.0;
|
||||||
$moonPlanetMaxSeparationDeg = 1.5;
|
$moonPlanetMaxSeparationDeg = 1.5;
|
||||||
$moonDeepSkyMaxSeparationDeg = 1.0;
|
$moonDeepSkyMaxSeparationDeg = 1.0;
|
||||||
|
$planetBrightStarMaxSeparationDeg = 1.0;
|
||||||
|
// Maximaler Winkelabstand fuer Begegnungen zwischen hellen Planeten und
|
||||||
|
// ausgewaehlten hellen Sternen wie Regulus oder Spica.
|
||||||
$planetConjunctionMaxSeparationDeg = 1.0;
|
$planetConjunctionMaxSeparationDeg = 1.0;
|
||||||
$moonOccultationMaxMag = 2.0;
|
$moonOccultationMaxMag = 2.0;
|
||||||
// Gute Merkur-Sichtbarkeit wird nicht nur über Elongation, sondern über echte
|
// Gute Merkur-Sichtbarkeit wird nicht nur über Elongation, sondern über echte
|
||||||
@@ -78,6 +81,7 @@ $moonPhaseEvents = [];
|
|||||||
$goldenHandleEvents = [];
|
$goldenHandleEvents = [];
|
||||||
$moonPlanetApproaches = [];
|
$moonPlanetApproaches = [];
|
||||||
$moonDeepSkyApproaches = [];
|
$moonDeepSkyApproaches = [];
|
||||||
|
$planetBrightStarApproaches = [];
|
||||||
$mercuryGoodVisibilityEvents = [];
|
$mercuryGoodVisibilityEvents = [];
|
||||||
$planetConjunctions = [];
|
$planetConjunctions = [];
|
||||||
$eclipseEvents = [];
|
$eclipseEvents = [];
|
||||||
@@ -696,6 +700,27 @@ if (is_array($moonDeepSkyDecoded) && ($moonDeepSkyDecoded['ok'] ?? false)) {
|
|||||||
$moonDeepSkyApproaches = is_array($moonDeepSkyDecoded['approaches'] ?? null) ? $moonDeepSkyDecoded['approaches'] : [];
|
$moonDeepSkyApproaches = is_array($moonDeepSkyDecoded['approaches'] ?? null) ? $moonDeepSkyDecoded['approaches'] : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$planetBrightStarOutput = [];
|
||||||
|
$planetBrightStarExitCode = 0;
|
||||||
|
$planetBrightStarArgs = [
|
||||||
|
$pythonScriptPath,
|
||||||
|
'planet_bright_star_approaches_for_month',
|
||||||
|
(string) $chartLatitude,
|
||||||
|
(string) $chartLongitude,
|
||||||
|
(string) $chartElevation,
|
||||||
|
(string) $selectedYear,
|
||||||
|
(string) $selectedMonth,
|
||||||
|
$chartTimezone,
|
||||||
|
(string) $planetBrightStarMaxSeparationDeg,
|
||||||
|
];
|
||||||
|
$planetBrightStarCommand = $pythonExecutable . ' ' . implode(' ', array_map('escapeshellarg', $planetBrightStarArgs)) . ' 2>&1';
|
||||||
|
exec($planetBrightStarCommand, $planetBrightStarOutput, $planetBrightStarExitCode);
|
||||||
|
$planetBrightStarRaw = trim(implode("\n", $planetBrightStarOutput));
|
||||||
|
$planetBrightStarDecoded = json_decode($planetBrightStarRaw, true);
|
||||||
|
if (is_array($planetBrightStarDecoded) && ($planetBrightStarDecoded['ok'] ?? false)) {
|
||||||
|
$planetBrightStarApproaches = is_array($planetBrightStarDecoded['approaches'] ?? null) ? $planetBrightStarDecoded['approaches'] : [];
|
||||||
|
}
|
||||||
|
|
||||||
$planetConjunctionOutput = [];
|
$planetConjunctionOutput = [];
|
||||||
$planetConjunctionExitCode = 0;
|
$planetConjunctionExitCode = 0;
|
||||||
$planetConjunctionArgs = [
|
$planetConjunctionArgs = [
|
||||||
@@ -1069,6 +1094,24 @@ foreach ($moonDeepSkyApproaches as $approachEvent) {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($planetBrightStarApproaches as $approachEvent) {
|
||||||
|
if (!is_array($approachEvent)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$distanceText = isset($approachEvent['separation_deg'])
|
||||||
|
? number_format((float) ($approachEvent['separation_deg']), 2, ',', '') . ' Grad'
|
||||||
|
: '';
|
||||||
|
|
||||||
|
$monthEventList[] = [
|
||||||
|
'event' => trim((string) ($approachEvent['label'] ?? 'Planet nahe hellem Stern') . ($distanceText !== '' ? ' (' . $distanceText . ')' : '')),
|
||||||
|
'date' => (string) ($approachEvent['local_date'] ?? ''),
|
||||||
|
'time' => (string) ($approachEvent['local_time'] ?? ''),
|
||||||
|
'local_iso' => (string) ($approachEvent['local_iso'] ?? ''),
|
||||||
|
'type' => 'planet_bright_star',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($planetConjunctions as $conjunctionEvent) {
|
foreach ($planetConjunctions as $conjunctionEvent) {
|
||||||
if (!is_array($conjunctionEvent)) {
|
if (!is_array($conjunctionEvent)) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Binary file not shown.
+196
-2
@@ -950,6 +950,18 @@ def planet_pair_separation_deg(
|
|||||||
return spherical_separation_deg(float(eq_a.ra), float(eq_a.dec), float(eq_b.ra), float(eq_b.dec))
|
return spherical_separation_deg(float(eq_a.ra), float(eq_a.dec), float(eq_b.ra), float(eq_b.dec))
|
||||||
|
|
||||||
|
|
||||||
|
def planet_fixed_equatorial_separation_deg(
|
||||||
|
body: astronomy.Body,
|
||||||
|
ra_hours: float,
|
||||||
|
dec_deg: float,
|
||||||
|
observer: astronomy.Observer,
|
||||||
|
dt_utc: datetime,
|
||||||
|
) -> float:
|
||||||
|
time_value = dt_to_time(dt_utc)
|
||||||
|
body_eq = astronomy.Equator(body, time_value, observer, True, True)
|
||||||
|
return spherical_separation_deg(float(body_eq.ra), float(body_eq.dec), float(ra_hours), float(dec_deg))
|
||||||
|
|
||||||
|
|
||||||
def refine_minimum_separation(
|
def refine_minimum_separation(
|
||||||
body: astronomy.Body,
|
body: astronomy.Body,
|
||||||
observer: astronomy.Observer,
|
observer: astronomy.Observer,
|
||||||
@@ -1024,6 +1036,32 @@ def refine_fixed_target_minimum_separation(
|
|||||||
return best, moon_fixed_equatorial_separation_deg(ra_hours, dec_deg, observer, best)
|
return best, moon_fixed_equatorial_separation_deg(ra_hours, dec_deg, observer, best)
|
||||||
|
|
||||||
|
|
||||||
|
def refine_planet_fixed_target_minimum_separation(
|
||||||
|
body: astronomy.Body,
|
||||||
|
ra_hours: float,
|
||||||
|
dec_deg: float,
|
||||||
|
observer: astronomy.Observer,
|
||||||
|
left_utc: datetime,
|
||||||
|
right_utc: datetime,
|
||||||
|
) -> tuple[datetime, float]:
|
||||||
|
left = left_utc
|
||||||
|
right = right_utc
|
||||||
|
|
||||||
|
for _ in range(32):
|
||||||
|
span = (right - left) / 3
|
||||||
|
m1 = left + span
|
||||||
|
m2 = right - span
|
||||||
|
f1 = planet_fixed_equatorial_separation_deg(body, ra_hours, dec_deg, observer, m1)
|
||||||
|
f2 = planet_fixed_equatorial_separation_deg(body, ra_hours, dec_deg, observer, m2)
|
||||||
|
if f1 <= f2:
|
||||||
|
right = m2
|
||||||
|
else:
|
||||||
|
left = m1
|
||||||
|
|
||||||
|
best = left + (right - left) / 2
|
||||||
|
return best, planet_fixed_equatorial_separation_deg(body, ra_hours, dec_deg, observer, best)
|
||||||
|
|
||||||
|
|
||||||
def action_moon_planet_approaches(args: list[str]) -> dict:
|
def action_moon_planet_approaches(args: list[str]) -> dict:
|
||||||
if len(args) != 7:
|
if len(args) != 7:
|
||||||
fail(
|
fail(
|
||||||
@@ -1135,6 +1173,157 @@ def action_moon_planet_approaches(args: list[str]) -> dict:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def action_planet_bright_star_approaches_for_month(args: list[str]) -> dict:
|
||||||
|
if len(args) != 7:
|
||||||
|
fail(
|
||||||
|
"Aktion planet_bright_star_approaches_for_month erwartet 7 Argumente: latitude longitude elevation year month timezone max_sep_deg",
|
||||||
|
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])
|
||||||
|
month = int(args[4])
|
||||||
|
except ValueError as exc:
|
||||||
|
fail("Jahr oder Monat sind ungueltig.", extra={"details": str(exc), "argv": args})
|
||||||
|
|
||||||
|
if month < 1 or month > 12:
|
||||||
|
fail("Monat muss zwischen 1 und 12 liegen.", extra={"month": month})
|
||||||
|
|
||||||
|
timezone_name = args[5]
|
||||||
|
max_sep_deg = parse_float(args[6], "Maximalabstand")
|
||||||
|
|
||||||
|
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, month, 1, 0, 0, 0, tzinfo=tz)
|
||||||
|
if month == 12:
|
||||||
|
local_end = datetime(year + 1, 1, 1, 0, 0, 0, tzinfo=tz)
|
||||||
|
else:
|
||||||
|
local_end = datetime(year, month + 1, 1, 0, 0, 0, tzinfo=tz)
|
||||||
|
|
||||||
|
utc_start = local_start.astimezone(timezone.utc)
|
||||||
|
utc_end = local_end.astimezone(timezone.utc)
|
||||||
|
scan_step = timedelta(hours=1)
|
||||||
|
coarse_threshold = max_sep_deg + 1.0
|
||||||
|
|
||||||
|
planet_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"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Helle, auffaellige Sterne nahe der Ekliptik, die regelmaessig
|
||||||
|
# attraktive Begegnungen mit den hellen Planeten liefern.
|
||||||
|
star_defs = [
|
||||||
|
("Alrescha", 2.0341, 2.7638),
|
||||||
|
("Hamal", 2.1196, 23.4624),
|
||||||
|
("Menkar", 3.0380, 4.0897),
|
||||||
|
("Aldebaran", 4.5987, 16.5093),
|
||||||
|
("Elnath", 5.4382, 28.6075),
|
||||||
|
("Pollux", 7.7553, 28.0262),
|
||||||
|
("Alphard", 9.4598, -8.6586),
|
||||||
|
("Regulus", 10.1395, 11.9672),
|
||||||
|
("Denebola", 11.8177, 14.5721),
|
||||||
|
("Spica", 13.4199, -11.1613),
|
||||||
|
("Zubenelgenubi", 14.8479, -16.0418),
|
||||||
|
("Antares", 16.4901, -26.4319),
|
||||||
|
]
|
||||||
|
|
||||||
|
approaches = []
|
||||||
|
for planet_label, planet_body, planet_key in planet_defs:
|
||||||
|
for star_label, ra_hours, dec_deg in star_defs:
|
||||||
|
samples: list[tuple[datetime, float]] = []
|
||||||
|
current = utc_start
|
||||||
|
while current <= utc_end:
|
||||||
|
samples.append((current, planet_fixed_equatorial_separation_deg(planet_body, ra_hours, dec_deg, observer, current)))
|
||||||
|
current += scan_step
|
||||||
|
if samples[-1][0] < utc_end:
|
||||||
|
samples.append((utc_end, planet_fixed_equatorial_separation_deg(planet_body, ra_hours, dec_deg, observer, utc_end)))
|
||||||
|
|
||||||
|
seen_ranges: list[tuple[datetime, datetime]] = []
|
||||||
|
for index in range(1, len(samples) - 1):
|
||||||
|
curr_t, curr_sep = samples[index]
|
||||||
|
prev_sep = samples[index - 1][1]
|
||||||
|
next_sep = samples[index + 1][1]
|
||||||
|
|
||||||
|
if curr_sep > coarse_threshold:
|
||||||
|
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_planet_fixed_target_minimum_separation(
|
||||||
|
planet_body,
|
||||||
|
ra_hours,
|
||||||
|
dec_deg,
|
||||||
|
observer,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
)
|
||||||
|
local_dt = min_time_utc.astimezone(tz)
|
||||||
|
if local_dt.year != year or local_dt.month != month:
|
||||||
|
continue
|
||||||
|
if min_sep > max_sep_deg:
|
||||||
|
continue
|
||||||
|
|
||||||
|
seen_ranges.append((left, right))
|
||||||
|
approaches.append({
|
||||||
|
"planet_key": planet_key,
|
||||||
|
"planet_label": planet_label,
|
||||||
|
"star_label": star_label,
|
||||||
|
"label": f"{planet_label} nahe {star_label}",
|
||||||
|
"separation_deg": float(min_sep),
|
||||||
|
"utc_iso": min_time_utc.isoformat().replace("+00:00", "Z"),
|
||||||
|
"local_iso": local_dt.isoformat(),
|
||||||
|
"local_date": local_dt.strftime("%d.%m.%Y"),
|
||||||
|
"local_time": local_dt.strftime("%H:%M"),
|
||||||
|
})
|
||||||
|
|
||||||
|
approaches.sort(key=lambda item: item["local_iso"])
|
||||||
|
|
||||||
|
deduplicated_approaches: list[dict] = []
|
||||||
|
for approach in approaches:
|
||||||
|
if deduplicated_approaches:
|
||||||
|
previous = deduplicated_approaches[-1]
|
||||||
|
same_pair = (
|
||||||
|
previous["planet_key"] == approach["planet_key"]
|
||||||
|
and previous["star_label"] == approach["star_label"]
|
||||||
|
)
|
||||||
|
previous_local = datetime.fromisoformat(previous["local_iso"])
|
||||||
|
current_local = datetime.fromisoformat(approach["local_iso"])
|
||||||
|
if same_pair and abs((current_local - previous_local).total_seconds()) <= 36 * 3600:
|
||||||
|
if float(approach["separation_deg"]) < float(previous["separation_deg"]):
|
||||||
|
deduplicated_approaches[-1] = approach
|
||||||
|
continue
|
||||||
|
deduplicated_approaches.append(approach)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"ok": True,
|
||||||
|
"action": "planet_bright_star_approaches_for_month",
|
||||||
|
"selected": {
|
||||||
|
"year": year,
|
||||||
|
"month": month,
|
||||||
|
"timezone": timezone_name,
|
||||||
|
"max_separation_deg": max_sep_deg,
|
||||||
|
},
|
||||||
|
"approaches": deduplicated_approaches,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def action_moon_deep_sky_approaches_for_month(args: list[str]) -> dict:
|
def action_moon_deep_sky_approaches_for_month(args: list[str]) -> dict:
|
||||||
if len(args) != 7:
|
if len(args) != 7:
|
||||||
fail(
|
fail(
|
||||||
@@ -3430,7 +3619,7 @@ def action_satellite_passes(args: list[str]) -> dict:
|
|||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
fail("Es wurde keine Aktion uebergeben.", extra={"available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "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_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", "moon_star_occultations_for_month"]})
|
fail("Es wurde keine Aktion uebergeben.", extra={"available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "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", "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", "moon_star_occultations_for_month"]})
|
||||||
|
|
||||||
action = sys.argv[1]
|
action = sys.argv[1]
|
||||||
args = sys.argv[2:]
|
args = sys.argv[2:]
|
||||||
@@ -3495,6 +3684,11 @@ def main() -> None:
|
|||||||
print(json.dumps(result, ensure_ascii=False))
|
print(json.dumps(result, ensure_ascii=False))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if action == "planet_bright_star_approaches_for_month":
|
||||||
|
result = action_planet_bright_star_approaches_for_month(args)
|
||||||
|
print(json.dumps(result, ensure_ascii=False))
|
||||||
|
return
|
||||||
|
|
||||||
if action == "planet_conjunctions_for_month":
|
if action == "planet_conjunctions_for_month":
|
||||||
result = action_planet_conjunctions_for_month(args)
|
result = action_planet_conjunctions_for_month(args)
|
||||||
print(json.dumps(result, ensure_ascii=False))
|
print(json.dumps(result, ensure_ascii=False))
|
||||||
@@ -3550,7 +3744,7 @@ def main() -> None:
|
|||||||
print(json.dumps(result, ensure_ascii=False))
|
print(json.dumps(result, ensure_ascii=False))
|
||||||
return
|
return
|
||||||
|
|
||||||
fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "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_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", "moon_star_occultations_for_month"]})
|
fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "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", "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", "moon_star_occultations_for_month"]})
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user