Plotly — Ingenuity
Mis à jour le 14/11/2024
ATTENTION (mise à jour du 14/11/2024) : L’hélicoptère Ingenuity a cessé de fonctionner après son 72e vol le 18 janvier 2024. Le journal de vol final se trouve dans le fichier PDF https://science.nasa.gov/wp-content/uploads/2024/06/ingenuity-helicopter-flight-log.pdf. Mais le tableau des vols n'est plus disponible sur le lien http:https://mars.nasa.gov/technology/helicopter/#Flight-Log, le script Python qui suit ne fonctionne donc plus.
Ingenuity est le petit hélicoptère qui accompagne le robot Perseverance sur Mars. La NASA propose une page dédiée aux exploits d'Ingenuity, avec en particulier son journal de vol :
On se propose ici de récupérer le tableau du journal de vol avec
la fonction read_html
de Pandas.
Puis d'afficher pour chaque vol, sur un même graphique, à la fois la distance horizontale parcourue et l'altitude maximale atteinte. Pour cela on utilisera les fonctionnalités d'affichage d'axes multiples de Plotly.
Code source
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import locale
# récupération de la table HTML
url = "https://mars.nasa.gov/technology/helicopter/#Flight-Log"
df_list = pd.read_html(
url,
attrs={"id": "flight-log-table"},
header=1,
)
# dataframe
df = df_list[0]
# noms des colonnes
df.columns = [
"Flight",
"Sol",
"Date",
"Horizontal Distance m",
"Horizontal Distance ft",
"Max. Altitude m",
"Max. Altitude ft",
"Max. Groundspeed m/s",
"Max. Groundspeed mph",
"Duration seconds",
"Route of Flight From",
"Route of Flight To",
]
# traitement des dates
df.replace("Jan.", "January", regex=True, inplace=True)
df.replace("Feb.", "February", regex=True, inplace=True)
df.replace("Aug.", "August", regex=True, inplace=True)
df.replace("Sept.", "September", regex=True, inplace=True)
df.replace("Oct.", "October", regex=True, inplace=True)
df.replace("Nov.", "November", regex=True, inplace=True)
df.replace("Dec.", "December", regex=True, inplace=True)
locale.setlocale(locale.LC_TIME, "en_US.utf8")
df["Date"] = pd.to_datetime(df["Date"], format="%B %d, %Y")
# création du diagramme
fig = make_subplots(specs=[[{"secondary_y": True}]])
# axe y primaire : distance horizontale parcourue
fig.add_trace(
go.Scatter(
mode="lines+markers",
x=df["Date"],
y=df["Horizontal Distance m"],
name="Horiz. dist. in m",
),
secondary_y=False,
)
# axe y secondaire : altitude maximale atteinte
fig.add_trace(
go.Scatter(
mode="lines+markers",
x=df["Date"],
y=df["Max. Altitude m"],
name="Max. alt. in m",
),
secondary_y=True,
)
# centrage du titre, arrière plan, style du hover label, position de la légende
fig.update_layout(
title_text="<b>Ingenuity - "
+ str(df.shape[0])
+ " flights</b><br>"
+ 'Data from <a href="https://mars.nasa.gov/technology/helicopter#Flight-Log">'
+ "https://mars.nasa.gov/technology/helicopter/</a><br>",
title_x=0.5,
hovermode="x unified",
hoverlabel=dict(
bgcolor="white",
bordercolor="red",
namelength=500,
),
showlegend=True,
legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
)
# modebar toujours visible
config = {"displayModeBar": True}
# légende axe x
fig.update_xaxes(
title_text="<b>Date</b>",
showgrid=False,
linecolor="black",
)
# légende axe y primaire
fig.update_yaxes(
title_text="<b>Horizontal distance in meters</b>",
secondary_y=False,
showgrid=False,
rangemode="tozero",
color="blue",
linecolor="blue",
)
# légende axe y secondaire
fig.update_yaxes(
title_text="<b>Maximum altitude in meters</b>",
secondary_y=True,
showgrid=False,
rangemode="tozero",
color="red",
linecolor="red",
)
# affichage et sauvegarde
fig.show(config=config)
fig.write_html("plotly-ingenuity.html")