Positions héliocentriques des planètes (Python)

Ce script Python calcule les coordonnées héliocentriques des planètes, et les trace dans un diagramme polaire.

Dans un précédent article, je proposais un code Python destiné à placer sur un diagramme polaire les positions héliocentriques des planètes, les données étant stockées dans un fichier d’éphémérides distinct.

Pour éviter d’avoir à télécharger au préalable les données calculées par des éphémérides, une solution est d’utiliser un module pour Python qui calcule lui-même ces données.

Le module PyEphem : dédié aux calculs d’éphémérides, que j’ai déjà utilisé pour construire un calendrier lunaire.

Le module Astropy : il semble extrêmement complet, et utilisé par des astronomes professionnels. Le pendant de cette polyvalence est une prise en main assez exigeante. Je ne m’y suis pas encore penché.

Le module PyEphem fera l’affaire, ici. Voici ce qu’on obtient :

L’idée est de choisir facilement un intervalle de temps délimité par deux dates (époque), ainsi qu’un pas de calcul en nombre de jours.

Il vous faudra pour cela installer le module PyEphem.

Voici les modules à appeler en début de script :

import ephem
from ephem import * #pour les coordonnées du Soleil
import matplotlib.pyplot as plt
import datetime as dt
import numpy as np
from statistics import mean#calcul de la moyenne des longitudes (planètes gazeuses)

Définition des dates avec le module datetime, suivie de la création d’une liste de dates avec une boucle while :

#Dates limitant la période souhaitée :---------------------------------------------------------
date_debut=dt.datetime(2022, 10, 1)
date_fin=dt.datetime(2023, 2, 1)
pasJours=3#intervalle entre deux dates
pas=dt.timedelta(days=pasJours)
#-------------------------------------------------------------------
#Création d'une liste de dates :
epoque=[]
date=date_debut
while date<date_fin:
    epoque.append(date)
    date=date+pas

Avec le module datetime, pour afficher les noms des jours et des mois en français, il faut ajouter en début de code les deux lignes suivantes :

import locale
locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8')#dates en français

Je définis ensuite un dict, qui associe un nom de planète à une couleur. Je me suis basé sur les couleurs approximatives des planètes.

#Liste des couleurs par planète :
couleurs={
'Mercure':'gray',
'Vénus':'tan',
'Terre':'royalblue', 
'Mars':'orangered',
'Jupiter':'orange',
'Saturne':'goldenrod', 
'Uranus' : 'skyblue', 
'Neptune' : 'mediumblue'
}

Je définis deux fonctions :

  • la première calcule les coordonnées héliocentriques d’une planète (longitude et distance au Soleil) et renvoie ces coordonnées comme deux listes de valeurs.
  • la seconde fonction calcule le complémentaire d’un angle (pour une série de valeurs). J’y reviendrai.
def coordonneesplanete(planete, periode):#calcule et renvoie listes de longitude et latitude
    longitude, distance=[], []
    for jour in periode:
        planete.compute(str(jour))
        longitude.append(float(planete.hlong))
        distance.append(planete.sun_distance)
    return longitude, distance

def angleComplem(serie):
    for n,  angle in enumerate(serie):
        if angle >np.pi:
            angle=angle-2*np.pi
        serie[n]=angle
    return serie

Viennent ensuite les paramètres du graphique créé avec le module Matplotlib :

#Paramètres du graphique :
#fig=plt.figure(figsize=(21/2.54, 29.7/2.54 ), tight_layout=True)#dimensions A4
fig=plt.figure(figsize=(10, 10), tight_layout=True)
ax=plt.subplot(projection='polar')
plt.title("Position héliocentrique des planètes", pad=20, fontsize=16)
plt.scatter(0, 0, s=200, c='orange', zorder=2)    #Soleil
taillePoint=40#taille du point des planètes sur le tracé

#plt.yticks([], [])#suppression des cercles et graduations en rayon.
plt.yticks([1], [])#conserver un cercle de rayon 1 UA.
#plt.yticks(np.arange(0, 2, 0.5), [])#graduer tous les 0.5 UA,sans chiffraison
plt.xticks(np.radians(np.arange(0, 360, 15)))#lignes d'angles, tous les 15°

Les graduations en cercle peuvent être utilisées pour faire ressortir la forme non circulaire des planètes.

Pour le calcul des coordonnées de la Terre, la méthode doit être différente de celle des autres planètes, malheureusement, et c’est un défaut du module PyEphem : la commande qui calcule les coordonnées de la Terre n’existe pas dans ce module (!) Cependant, j’ai trouvé au détour d’un forum que, avec ce module, si l’on calcule la longitude héliocentrique du Soleil (absurde, car elle est nulle !), on obtient en réalité celle de la Terre… En espérant que cette bizarrerie soit rectifiée un jour (mais je ne suis pas certain que le développement de ce module soit très actif…)

# Calcul des coordonnées de la Terre, et tracé de trajectoire :
soleil=Sun()
longitudeTerre, distanceTerre=[], []
for jour in epoque:
    soleil.compute(str(jour))
    longitudeTerre.append(float(soleil.hlong))#en calculant la longitude héliocentrique du Soleil, on a en fait celle de la Terre...
    distanceTerre.append(soleil.earth_distance)
ax.scatter(longitudeTerre, distanceTerre, s=taillePoint, ec='k', fc=couleurs['Terre'], label='Terre', zorder=3)
ax.scatter(longitudeTerre[0], distanceTerre[0], s=taillePoint, c='k')#1e position en noir

#----------------------------------------------------------------------------
#Autres planètes :
#mercure=ephem.Mercury()
#longitude, distance=coordonneesplanete(mercure, epoque)
#ax.scatter(longitude, distance, s=taillePoint,  ec='k', fc=couleurs['Mercure'], label='Mercure', zorder=3)
#ax.scatter(longitude[0], distance[0], s=taillePoint, c='k')#1e position en noir
#
#venus=ephem.Venus()
#longitude, distance=coordonneesplanete(venus, epoque)
#ax.scatter(longitude, distance, s=taillePoint,  ec='k', fc=couleurs['Vénus'], label='Vénus', zorder=3)
#ax.scatter(longitude[0], distance[0], s=taillePoint, c='k')#1e position en noir

mars=ephem.Mars()
longitude, distance=coordonneesplanete(mars, epoque)
ax.scatter(longitude, distance, s=taillePoint, ec='k', fc=couleurs['Mars'], label='Mars', zorder=3)
ax.scatter(longitude[0], distance[0], s=taillePoint, c='k')#1e position en noir

Les paramètres “zorder=3” servent à éviter que les points des planètes soient recouverts par les lignes grises de la grille.

En fonction de la planète choisie, de sa période orbitale et de la durée de l’époque choisie, on peut avoir une trajectoire complète avec des positions qui se superposent. En plaçant le premier point en noir, on repère plus facilement la position de la première date.

Pour les planètes gazeuses, la méthode précédente fonctionne, mais l’échelle des distances est comprimée. J’ai fait le choix de tracer une flèche pointant vers la planète. La méthode consiste à calculer la longitude moyenne de la planète gazeuse sur l’époque considérée, et de supposer que la longitude varie assez peu si l’époque inférieure à quelques mois.

Attention cependant : si la longitude de la planète passe d’une valeur inférieure à 360 à une valeur supérieure à 0, la discontinuité des angles va renvoyer une valeur fantaisiste pour la moyenne de l’angle. Pour éviter cela, j’ai défini une fonction calculant l’angle complémentaire, ce qui a pour effet de reporter la position de la discontinuité. Cette méthode est un pis-aller car elle est à ajuster au cas par cas. La fonction n’est pas appelée dans l’exemple qui suit.

saturne=ephem.Saturn()
longitude, distance=coordonneesplanete(saturne, epoque)
#ax.scatter(longitude, distance, s=taillePoint, ec='k', fc=couleurs['Saturne'], label='Saturne')
#ax.scatter(longitude[0], distance[0], s=taillePoint, c='k')#1e position en noir
#Tracé d'une flèche indiquant la longitude moyenne de Saturne sur la période considérée :
ax.annotate("", xy=(mean(longitude), 0.1*mean(distance)), xytext=(0, 0),arrowprops=dict(arrowstyle="->", color=couleurs['Saturne']), zorder=3)
plt.text(mean(longitude), 0.1*mean(distance), 'Saturne', ha='left',va='center', rotation=np.degrees(mean(longitude)))

L’image suivante montre que l’on peut exploiter ce graphique pour visualiser les périodes d’opposition des planètes et expliquer le mouvement de rétrogradation de Mars :

J’ai ajouté dans le code quelques lignes qui tracent des lignes joignant la Terre et Mars pour expliquer la rétrogradation :

#longitudeMars, distanceMars=coordonneesplanete(mars, epoque)
#for N in range(len(longitudeTerre)):
#    plt.plot((longitudeTerre[N], longitudeMars[N]), (distanceTerre[N], distanceMars[N]), 'k')

Le code complet (compressé) :

Soyez le premier à commenter

Laisser un commentaire