2023-01-31 11:15:21 +01:00
|
|
|
import csv # Creating/parsing CSV file
|
|
|
|
import xml.etree.ElementTree as ET # Creating/parsing XML file
|
|
|
|
|
|
|
|
###############################################################################
|
|
|
|
# twin_plot.py
|
|
|
|
# @title: Visualisation des données (Matplotlib)
|
|
|
|
# @project: Blender-EduTech
|
|
|
|
# @lang: fr
|
|
|
|
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
|
|
|
|
# @copyright: Copyright (C) 2023 Philippe Roy
|
|
|
|
# @license: GNU GPL
|
|
|
|
###############################################################################
|
|
|
|
|
|
|
|
###############################################################################
|
|
|
|
# Configuration des plots
|
|
|
|
###############################################################################
|
|
|
|
|
|
|
|
def plot_config_get_enable():
|
|
|
|
twin_config = ET.parse('twin_config.xml').getroot()
|
|
|
|
if twin_config[1][0].text == "True":
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
|
|
|
##
|
|
|
|
# Génère le dictionnaire plot_config à partir du fichier XML plot_config.xml
|
|
|
|
##
|
|
|
|
|
2023-02-01 18:18:37 +01:00
|
|
|
def plot_config_get_dict():
|
2023-01-31 11:15:21 +01:00
|
|
|
plot_config_tree = ET.parse('plot_config.xml').getroot()
|
|
|
|
plot_config_tmp={}
|
|
|
|
for var in plot_config_tree[0][0]:
|
|
|
|
var_dict={}
|
|
|
|
for i in range (len(var)):
|
|
|
|
if var[i] is not None:
|
|
|
|
var_dict.update({var[i].tag : var[i].text})
|
|
|
|
plot_config_tmp.update({var.text: var_dict})
|
|
|
|
return plot_config_tmp
|
|
|
|
|
|
|
|
##
|
|
|
|
# Returne une valeur du dictionnaire plot_config
|
|
|
|
##
|
|
|
|
|
|
|
|
def plot_config_get(plot_config, var, key):
|
|
|
|
if key in plot_config[var]:
|
|
|
|
return plot_config[var][key]
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
|
|
|
##
|
|
|
|
# Nombre de groupe de courbe(s)
|
|
|
|
##
|
|
|
|
|
2023-02-01 18:18:37 +01:00
|
|
|
def plot_nb(plot_config):
|
2023-01-31 11:15:21 +01:00
|
|
|
plot_config_list=list(plot_config)
|
|
|
|
nbgroup = 0
|
|
|
|
|
|
|
|
# Regroupement ('group' > 0)
|
|
|
|
for var in plot_config_list:
|
|
|
|
if ('group' in plot_config[var]):
|
|
|
|
if nbgroup < int(plot_config[var]['group']):
|
|
|
|
nbgroup = int(plot_config[var]['group'])
|
|
|
|
|
|
|
|
# Plot solitaire ('group' = 0)
|
|
|
|
# 'group' = -1 -> variable non affichée
|
|
|
|
for var in plot_config_list:
|
|
|
|
if ('group' in plot_config[var]):
|
|
|
|
if int(plot_config[var]['group']) == 0:
|
|
|
|
nbgroup +=1
|
|
|
|
|
|
|
|
return nbgroup
|
|
|
|
|
|
|
|
###############################################################################
|
|
|
|
# Fichier CSV
|
|
|
|
###############################################################################
|
|
|
|
|
|
|
|
##
|
|
|
|
# Fichier CSV -> Tableau X,Y
|
|
|
|
##
|
|
|
|
|
2023-02-01 18:18:37 +01:00
|
|
|
def csv_read(file):
|
2023-01-31 11:15:21 +01:00
|
|
|
|
|
|
|
# Lecture fichier CSV
|
|
|
|
fields = []
|
|
|
|
rows = []
|
|
|
|
with open(file, newline='') as csv_buff:
|
|
|
|
csv_reader = csv.reader(csv_buff, delimiter=';')
|
|
|
|
fields = next(csv_reader)
|
|
|
|
for row in csv_reader:
|
|
|
|
rows.append(row)
|
|
|
|
|
|
|
|
# Mise en tableau à deux colonnes (xdata,ydata)
|
|
|
|
xdata=[]
|
|
|
|
ydata=[]
|
|
|
|
i=0
|
|
|
|
for field in fields:
|
|
|
|
xdata_row=[]
|
|
|
|
ydata_row=[]
|
|
|
|
for row in rows:
|
|
|
|
xdata_row.append(float(row[0].replace(',', '.'))) # Revenir au format US des décimaux
|
|
|
|
ydata_row.append(float(row[i].replace(',', '.'))) # Revenir au format US des décimaux
|
|
|
|
xdata.append(xdata_row)
|
|
|
|
ydata.append(ydata_row)
|
|
|
|
i+=1
|
|
|
|
|
|
|
|
return fields, xdata, ydata
|
|
|
|
|
|
|
|
|
|
|
|
###############################################################################
|
|
|
|
# Création des graphiques
|
|
|
|
###############################################################################
|
|
|
|
|
2023-01-31 13:51:32 +01:00
|
|
|
# Création d'une courbe
|
|
|
|
def plot_draw(plt, var, xdata, ydata, plot_config):
|
|
|
|
|
|
|
|
# Courbe d'une variable analogique (continue)
|
|
|
|
if plot_config_get(plot_config, var, 'type') =='a':
|
|
|
|
plt.plot(xdata, ydata, label=var, color=plot_config_get(plot_config, var, 'color'), linewidth=plot_config_get(plot_config, var, 'linewidth'),
|
|
|
|
linestyle=plot_config_get(plot_config, var, 'linestyle'), marker=plot_config_get(plot_config, var, 'marker'))
|
|
|
|
|
|
|
|
# Courbe d'une variable binaire (discret)
|
|
|
|
if plot_config_get(plot_config, var, 'type') =='d':
|
|
|
|
plt.plot(xdata, ydata, label=var, drawstyle='steps-post', color=plot_config_get(plot_config, var, 'color'), linewidth=plot_config_get(plot_config, var, 'linewidth'),
|
|
|
|
linestyle=plot_config_get(plot_config, var, 'linestyle'), marker=plot_config_get(plot_config, var, 'marker'))
|
|
|
|
plt.set_ylim(0,1) # niveau 0 et niveau 1
|
|
|
|
|
|
|
|
# Courbe d'une variable numérique (discret)
|
|
|
|
if plot_config_get(plot_config, var, 'type') =='n':
|
|
|
|
plt.plot(xdata, ydata, label=var, drawstyle='steps-post', color=plot_config_get(plot_config, var, 'color'), linewidth=plot_config_get(plot_config, var, 'linewidth'),
|
|
|
|
linestyle=plot_config_get(plot_config, var, 'linestyle'), marker=plot_config_get(plot_config, var, 'marker'))
|
|
|
|
|
|
|
|
# Création des graphiques statiques
|
2023-02-01 18:18:37 +01:00
|
|
|
def plots_static(plt, fields, xdata, ydata, plot_config, title):
|
2023-01-31 11:15:21 +01:00
|
|
|
|
2023-02-01 18:18:37 +01:00
|
|
|
# Configuration des plots activée
|
2023-01-31 11:15:21 +01:00
|
|
|
plot_config_enable=plot_config_get_enable()
|
|
|
|
|
|
|
|
# Plots
|
|
|
|
# Groupe de plots : si group = 0 -> nouveau groupe, plot solitaire
|
|
|
|
# si group = -1 -> pas de plot
|
|
|
|
# si group > 0 -> numéro du groupe
|
|
|
|
plt_i=0 # Compteur de plot
|
|
|
|
plt_grp=[] # Groupe de plot [[numéro du plot, groupe du fichier CSV]]
|
|
|
|
for i in range(len(fields)):
|
|
|
|
var = fields[i]
|
|
|
|
plt_current=-1 # Numéro du plot à créer
|
|
|
|
|
|
|
|
if ('group' in plot_config[var]): # Pas de Plot
|
|
|
|
if int(plot_config[var]['group']) !=-1: # Pas de Plot
|
|
|
|
|
|
|
|
# Plot solitaire
|
|
|
|
if int(plot_config[var]['group']) ==0:
|
|
|
|
plt_current = plt_i
|
|
|
|
plt_grp.append([plt_i, 0])
|
|
|
|
plt_i +=1
|
|
|
|
|
|
|
|
# Plot groupé
|
|
|
|
else:
|
|
|
|
plt_new = True # Flag d'un nouveau groupe
|
|
|
|
for j in range(len(plt_grp)):
|
|
|
|
if plt_grp[j][1] == int(plot_config[var]['group']): # Groupe déjà existant
|
|
|
|
plt_current = plt_grp[j][0]
|
|
|
|
plt_new = False
|
|
|
|
break
|
|
|
|
|
|
|
|
# Nouveau groupe
|
|
|
|
if plt_new:
|
|
|
|
plt_current = plt_i
|
|
|
|
plt_grp.append([plt_i, int(plot_config[var]['group'])])
|
|
|
|
plt_i +=1
|
|
|
|
|
|
|
|
# Création du plot unique
|
|
|
|
if plot_nb(plot_config) ==1:
|
|
|
|
if plot_config_enable: # Configuration des plots activée
|
2023-02-01 18:18:37 +01:00
|
|
|
plot_draw(plt, var, xdata[i], ydata[i], plot_config)
|
2023-01-31 11:15:21 +01:00
|
|
|
else:
|
2023-02-01 18:18:37 +01:00
|
|
|
plt.plot(xdata[i], ydata[i], '.-', label=var) # Configuration matplotlib par défaut
|
2023-01-31 11:15:21 +01:00
|
|
|
|
|
|
|
# Légende ou titre d'axe y
|
|
|
|
if plt_grp[plt_current][1]==0:
|
2023-02-01 18:18:37 +01:00
|
|
|
plt.set_ylabel(var)
|
2023-01-31 11:15:21 +01:00
|
|
|
else:
|
2023-02-01 18:18:37 +01:00
|
|
|
plt.legend()
|
2023-01-31 11:15:21 +01:00
|
|
|
|
|
|
|
# Création des subplots
|
|
|
|
if plot_nb(plot_config) >1:
|
|
|
|
if plot_config_enable: # Configuration des plots activée
|
2023-02-01 18:18:37 +01:00
|
|
|
plot_draw(plt[plt_current], var, xdata[i], ydata[i], plot_config)
|
2023-01-31 11:15:21 +01:00
|
|
|
else:
|
2023-02-01 18:18:37 +01:00
|
|
|
plt[plt_current].plot(xdata[i], ydata[i], '.-', label=var) # Configuration matplotlib par défaut
|
2023-01-31 11:15:21 +01:00
|
|
|
|
|
|
|
# Légende ou titre d'axe y
|
|
|
|
if plt_grp[plt_current][1]==0:
|
2023-02-01 18:18:37 +01:00
|
|
|
plt[plt_current].set_ylabel(var)
|
2023-01-31 11:15:21 +01:00
|
|
|
else:
|
2023-02-01 18:18:37 +01:00
|
|
|
plt[plt_current].legend()
|
2023-01-31 11:15:21 +01:00
|
|
|
|
|
|
|
# Décoration
|
|
|
|
if plot_nb(plot_config) ==1: # 1 plot
|
2023-02-01 18:18:37 +01:00
|
|
|
plt.set_xlabel("Temps (s)")
|
|
|
|
plt.set_title(title)
|
|
|
|
plt.axhline(linewidth=1, color='k')
|
|
|
|
plt.grid(True, linestyle='--')
|
2023-01-31 11:15:21 +01:00
|
|
|
# canvas.plt.legend()
|
|
|
|
else: # Plusieurs plots
|
2023-02-01 18:18:37 +01:00
|
|
|
plt[plt_i-1].set_xlabel("Temps (s)")
|
|
|
|
plt[0].set_title(title)
|
2023-01-31 11:15:21 +01:00
|
|
|
for i in range (plt_i):
|
2023-02-01 18:18:37 +01:00
|
|
|
plt[i].axhline(linewidth=1, color='k')
|
|
|
|
plt[i].grid(True, linestyle='--')
|
|
|
|
# plt[i].legend()
|