Équation du temps en 2023 – Python

Un script Python – pandas – matplotlib qui compose un calendrier de l’équation du temps, d’après les éphémérides de l’IMCCE

Dans le même ordre idée qu’un article précédent concernant la déclinaison du Soleil, voici comment obtenir les valeurs de l’équation du temps pour chaque jour, sous forme de calendrier.

L’équation du temps est plus difficile à modéliser que la déclinaison du Soleil (voir cette source, pour la déclinaison).

Les éphémérides de l’IMCCE permettent indirectement d’obtenir les valeurs de l’équation du temps avec la procédure suivante :

se rendre sur le portail des éphémérides de l’IMCCE :

Parmi les services proposés, choisir ‘Visibilité des astres”, qui donne pour le Soleil les heures de lever et coucher, les azimuts aux lever et coucher, ainsi que l’heure de passage au méridien, qui nous intéresse.

Dans le champ des coordonnées, entrez votre latitude préférée, ainsi qu’une longitude nulle. C’est important pour s’affranchir de la correction des heures selon la longitude.

On peut télécharger les données calculées sous forme de fichier .csv. Pour le format de dates, on peut choisir le format sexagésimal (base 60) ou le format décimal. Le script ci-dessous nécessite le format décimal.

Le tracé de l’heure de passage au méridien au fil des jours donne le résultat suivant :

Le Soleil ne culmine pas au méridien à midi pile ( ce serait le cas si les heures étaient les heures solaires). Puisqu’on a choisi une longitude nulle, le décalage entre les heures de culmination et midi pile est uniquement dû à l’équation du temps.

Si l’on soustrait 12 heures à ces valeurs, on obtient la liste des valeurs de l’équation du temps pour chaque jour :

Le code Python qui trace ces deux graphes lit les valeurs présentes dans le fichier .csv téléchargé sur le portail IMCCE, et trace les graphiques. Le code Python :

import matplotlib.pyplot as plt#graphique
import pandas as pd#lecture du fichier csv
import matplotlib.dates as mdates
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
import matplotlib.ticker as tick#mise en forme des étiquettes de graduations

#Extraction des données depuis le fichier .csv :
soleil=pd.read_csv('EdTimcce2023.csv',
sep=';', #séparateur des colonnes
usecols=[1, 4], #seules colonnes utiles,  ici
names=['date', 'midi'], #renomme les deux colonnes
parse_dates=['date'], #reconnaît les données de cette colonne comme des dates
skiprows=1, #supprime la ligne 1 (noms de colonnes d'origine)
)
#Extraction des listes de données pour les graphes :
soleil=soleil.set_index('date')#indexation du tableau de valeurs sur les dates
dates=soleil.index

midi=soleil['midi']

EDT=(midi-12)*60#calcul de l'équation du temps

plt.rcParams["font.family"] = "Ubuntu"#ou autre police installée
plt.rcParams["font.size"] = 9

def HHmm(heure, lever):#écrit en base 60
    H=int(heure)
    min=round((heure-H)*60)
    if min<10:
        min="0"+str(min)
    return str(H)+'h'+str(min)[:]

def mmss(min, EDT):#écrit en base 60    
#    sec=round((M-int(M))*60, 2)
    min=round(min)
    return str(min)+' min'#+str(sec)

#Paramètres du graphique :
fig=plt.figure(figsize=(7, 8), tight_layout=True)

locator1 = mdates.AutoDateLocator(minticks=11, maxticks=12, interval_multiples=True)
formatter = mdates.ConciseDateFormatter(locator1)

#Graphe 1---------------------------------------------------
ax1=plt.subplot(211)
ax1.set_title("Heure de passage du Soleil au méridien (midi moyen)")
ax1.grid()

ax1.plot(dates, midi, c='slateblue')
ax1.xaxis.set_major_locator(locator1)
ax1.xaxis.set_major_formatter(formatter)
ax1.set_xlim('2022-01-01', '2022-12-31')
ax1.yaxis.set_major_formatter(tick.FuncFormatter(HHmm))

#Graphe 2---------------------------------------------------
ax2=plt.subplot(212)
ax2.set_title("Équation du temps")
ax2.grid()

ax2.plot(dates, EDT, c='firebrick')
ax2.xaxis.set_major_locator(locator1)
ax2.xaxis.set_major_formatter(formatter)
ax2.set_xlim('2022-01-01', '2022-12-31')
ax2.yaxis.set_major_formatter(tick.FuncFormatter(mmss))

#fig.savefig("EquationDuTemps.png", dpi=200)
#fig.savefig("EquationDuTemps.pdf")
plt.show()

Pour placer les valeurs de l’équation du temps dans un calendrier :

J’utilise le module datetime pour gérer les dates et leur affichage personnalisé.

J’importe les données du fichier .csv comme indiqué précédemment.

Je définis une fonction minsecondes qui transforme des minutes décimales en format sexagésimal (“xx min yy s”). Ainsi qu’une fonction minutes qui arrondit ce temps à la minute.

import pandas as pd#lecture du fichier csv
import matplotlib.pyplot as plt
import datetime#Gestion des dates
from datetime import timedelta

#Données csv issues de du portail IMCCE : https://ssp.imcce.fr/forms/ephemeris

annee=2023

tableau=pd.read_csv("EphemSoleil"+str(annee)+".csv", 
sep=';', #caractère de séparation des colonnes
skiprows=1, #ne pas lire la première ligne, car les noms des colonnes sont renommés 
usecols=[1, 4], 
names=['date', 'midi'], 
parse_dates=['date'], #reconnaître la colonne date comme des dates formatées
)

tableau=tableau.set_index('date')#réindexer le tableau avec les dates

midi=tableau['midi']
EDT=midi-12

plt.rcParams["font.family"] = "Ubuntu"#ou autre police installée
plt.rcParams["font.size"] = 10#à adapter aux dimensions des axes

def minsecondes(temps):#cette fonction transforme un temps décimal en écriture sexagésimale
    if temps<0:
        signe='-'
    else: signe='+'
    min=int(temps)
    secondes=abs(temps-min)*60
    return signe + str(abs(min)) +" min " + str(round(secondes))+" s"#renvoie une chaîne de caractères


def minutes(temps):#arrondit à la minute
    return str(round(temps)) + " min."

Ensuite, je crée une figure avec 12 axes en grille (2 lignes x 6 colonnes) qui seront autant de mois de l’année.

Ces axes sont rendus itérables par la commande axs.flatten().

Je crée une boucle for qui parcourt les 12 mois. Au début de chaque itération, je définis les dates de début de mois et de fin du mois. Pour chaque mois, une nouvelle boucle imbriquée dans la précédente affiche la date de chaque jour et la valeur de l’équation du temps de ce jour (formatée par la fonction minsecondes.


fig, axs=plt.subplots(nrows=2, ncols=6, tight_layout=True)#création d'une figure et de 12 axes (1 par mois)
#Les graphes forment une grille de 2 lignes et 6 colonnes
#on peut modifier le nombre de grilles et colonnes, pourvu que le produit fasse 12.
axs=axs.flatten()#pour accéder à chaque graphe par axs[N]
fig.set_size_inches(21/2.54, 29.7/2.54)#dimensions de la figure, en pouces
#"""
#En modifiant les dimensions de la figure, il faudra peut-être ajuster :
#- la taille de la police
#- les limites des axes en x et en y
#Et réciproquement.

plt.suptitle("Équation du temps en %s"%(annee), fontsize=17, color='royalblue')

for N in range(1, 12+1):#N : numéro du mois courant, de 1 à 12
    ax=axs[N-1]
    date_debut=datetime.datetime(annee, N, 1)
    ax.set_title(date_debut.strftime("%B"), fontsize=13, c='blueviolet')#nom complet du mois
    ax.set_xticks([])#suppression des graduations
    ax.set_yticks([])#suppression des graduations
#    ax.axis('tight')
#    ax.axis('off')#efface les cadres des axes
    ax.set_ylim(-32, 0.5)#hauteur suffisante pour les listes de dates
    ax.set_xlim(-1.20, 50)#largeur suffisante pour le texte
    if N==12:
        date_fin=datetime.datetime(annee+1, 1, 1) - timedelta(days=1)#mois suivant moins 1 jour 
    else:
        date_fin=datetime.datetime(annee, N+1, 1) - timedelta(days=1)#mois suivant moins 1 jour 
    mois=tableau.loc[date_debut:date_fin]#filtrer le mois courant
    for jour in mois.index:
        Y=-float(jour.strftime('%d'))#numéro du jour, pris comme coordonnée verticale
        texte1=jour.strftime("%d %b")#N° du jours et nom abrégé du mois (nom complet : %B)
        EDT=float(mois.loc[jour, ['midi']]-12)*60#calcule le nombre de minutes décimales de l'équation du temps
        #pour la précision du résultat, choisir l'une des deux lignes suivantes :
        texte2=minsecondes(EDT)
#        texte2=minutes(EDT)
        ax.text(0, Y, texte1 +"    " +texte2, fontsize=8)#écriture des données

texte="Les calculs d’éphémérides de position des corps du Système solaire ont été réalisés par le service de calcul des éphémérides de l’IMCCE à travers son portail Système solaire (https://ssp.imcce.fr)"
fig.text(0.01, 0.005, texte, fontsize=6, ha='left', va='bottom')

NomFichier="EquationDuTemps_"+str(annee)
fig.savefig(NomFichier+".png", dpi=200)#création d'un fichier image PNG
fig.savefig(NomFichier+".pdf")#création d'un fichier PDF
plt.show()

Pour trouver la date de fin du mois courant, alors que la durée des mois varie, je prends le 1er jour du mois suivant, auquel je retire un jour (timedelta).

Résultat avec l’arrondi à la minute (suffisant pour l’utilisation d’un cadran solaire) :

Ce code ne modifie pas le contenu du fichier .csv obtenu via l’IMCCE. La valeur de l’année est définie comme paramètre au début, ce qui signifie qu’il suffit de changer l’année pour exécuter ce code avec les données d’une autre année. Le nom des fichiers (image ou pdf) se terminent pas l’année choisie.

Soyez le premier à commenter

Laisser un commentaire