Intégration Python
Cette page fournit des exemples Python pratiques pour travailler avec le FGA Logger — lire des données série en direct, enregistrer en CSV et charger des données pour analyse.
Dépendances :
pyserial— communication port sériepandas— analyse de données (optionnel, pour les exemples d'analyse)
Installer avec :
pip install pyserial pandas
Lire des données série en direct
Cet exemple se connecte au FGA Logger via USB et affiche chaque ligne CSV entrante :
import serial
# Changer pour votre port :
# Windows : 'COM3', 'COM4', etc.
# Linux : '/dev/ttyUSB0'
# macOS : '/dev/tty.usbserial-XXXX'
PORT = 'COM3'
BAUD = 115200 # Ajuster selon vos paramètres série du FGA Logger
def read_logger(port, baud):
with serial.Serial(port, baud, timeout=2) as ser:
print(f"Connecté à {port} à {baud} bauds")
print("En attente de données...\n")
while True:
line = ser.readline().decode('utf-8', errors='replace').strip()
if line:
print(line)
if __name__ == '__main__':
read_logger(PORT, BAUD)
Enregistrer les données série en CSV
Cet exemple lit depuis le FGA Logger et enregistre toutes les lignes entrantes dans un fichier CSV local. La première ligne d'en-tête reçue est écrite une seule fois ; toutes les lignes de données suivantes sont ensuite ajoutées.
import serial
import csv
from datetime import datetime
PORT = 'COM3'
BAUD = 115200
OUTFILE = f"fga_log_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
# En-tête CSV attendu du FGA Logger
EXPECTED_HEADER = [
'Timestamp_ms', 'B1x_nT', 'B1y_nT', 'B1z_nT', 'B1v_nT',
'B2x_nT', 'B2y_nT', 'B2z_nT', 'B2v_nT',
'Lat_deg', 'Lon_deg', 'Alt_m', 'SIV', 'Fix', 'HDOP_m'
]
def save_to_csv(port, baud, outfile):
header_written = False
with serial.Serial(port, baud, timeout=5) as ser, \
open(outfile, 'w', newline='') as f:
writer = csv.writer(f)
print(f"Journalisation dans {outfile}")
try:
while True:
line = ser.readline().decode('utf-8', errors='replace').strip()
if not line:
continue
fields = line.split(',')
# Écrire l'en-tête une fois (depuis le dispositif ou notre en-tête attendu)
if not header_written:
if fields[0] == 'Timestamp_ms':
writer.writerow(fields) # Utiliser l'en-tête du dispositif
else:
writer.writerow(EXPECTED_HEADER) # Utiliser l'en-tête attendu
writer.writerow(fields) # Écrire cette ligne comme données
header_written = True
f.flush()
continue
# Écrire les lignes de données
writer.writerow(fields)
f.flush()
print(f" {line[:80]}") # Afficher les 80 premiers caractères
except KeyboardInterrupt:
print(f"\nJournalisation arrêtée. Fichier sauvegardé : {outfile}")
if __name__ == '__main__':
save_to_csv(PORT, BAUD, OUTFILE)
Charger un fichier CSV avec pandas
Une fois que vous avez un fichier CSV — soit depuis la carte SD, soit sauvegardé via série — chargez-le avec pandas pour analyse :
import pandas as pd
CSV_FILE = 'fga_log_20240315_143022.csv'
# Charger le CSV
df = pd.read_csv(CSV_FILE)
print("Forme :", df.shape)
print("\nPremières lignes :")
print(df.head())
print("\nTypes de colonnes :")
print(df.dtypes)
print("\nStatistiques de base :")
print(df[['B1x_nT', 'B1y_nT', 'B1z_nT', 'B1v_nT']].describe())
Calculer le gradient (mode gradiomètre)
Dans les configurations gradiomètre avec deux assemblages de capteurs, calculer le gradient par axe :
import pandas as pd
df = pd.read_csv('fga_log.csv')
# Calculer le gradient (capteur 1 moins capteur 2) par axe
df['Grad_x_nT'] = df['B1x_nT'] - df['B2x_nT']
df['Grad_y_nT'] = df['B1y_nT'] - df['B2y_nT']
df['Grad_z_nT'] = df['B1z_nT'] - df['B2z_nT']
# Magnitude totale du gradient
df['Grad_v_nT'] = (
df['Grad_x_nT']**2 +
df['Grad_y_nT']**2 +
df['Grad_z_nT']**2
) ** 0.5
print(df[['Timestamp_ms', 'Grad_x_nT', 'Grad_y_nT', 'Grad_z_nT', 'Grad_v_nT']].head(10))
Filtrer par qualité GPS
Filtrer les lignes sans fix GPS ou de faible précision avant l'analyse :
import pandas as pd
df = pd.read_csv('fga_log.csv')
# Garder uniquement les lignes avec fix GPS 3D et HDOP inférieur à 2.0
df_clean = df[
(df['Fix'] == 3) &
(df['HDOP_m'] < 2.0) &
(df['SIV'] >= 4)
].copy()
print(f"Total lignes : {len(df)}")
print(f"Lignes propres : {len(df_clean)}")
print(f"Supprimées : {len(df) - len(df_clean)}")
Tracer le champ total
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('fga_log.csv')
plt.figure(figsize=(12, 4))
plt.plot(df['Timestamp_ms'] / 1000, df['B1v_nT'], linewidth=0.8)
plt.xlabel('Temps (s)')
plt.ylabel('Champ total B1 (nT)')
plt.title('FGA Logger — Champ magnétique total')
plt.tight_layout()
plt.savefig('field_plot.png', dpi=150)
plt.show()
Exporter la trace GPS en GeoJSON
Exporter la trace GPS pour utilisation dans QGIS ou autres outils SIG :
import pandas as pd
import json
df = pd.read_csv('fga_log.csv')
# Garder uniquement les lignes avec fix GPS valide
df_gps = df[df['Fix'] >= 2].dropna(subset=['Lat_deg', 'Lon_deg'])
# Construire une FeatureCollection GeoJSON
features = []
for _, row in df_gps.iterrows():
feature = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [row['Lon_deg'], row['Lat_deg'], row['Alt_m']]
},
"properties": {
"timestamp_ms": row['Timestamp_ms'],
"B1v_nT": row['B1v_nT'],
"B2v_nT": row['B2v_nT'],
}
}
features.append(feature)
geojson = {"type": "FeatureCollection", "features": features}
with open('track.geojson', 'w') as f:
json.dump(geojson, f, indent=2)
print(f"{len(features)} points exportés dans track.geojson")