jumeaux-numeriques/twin_plot_wx.py

187 lines
7.4 KiB
Python

import sys
import csv # Creating/parsing CSV file
import xml.etree.ElementTree as ET # Creating/parsing XML file
from twin_plot import plot_config_get_dict, plot_config_get, plot_config_get_enable, plot_nb, csv_read, plots_static # Gestion communes des graphiques (Qt, wx)
import wx # GUI wxPython
import matplotlib # Grapheur Matplotlib
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import (FigureCanvasWxAgg as FigureCanvas, NavigationToolbar2WxAgg as NavigationToolbar)
###############################################################################
# twin_plot_wx.py
# @title: Visualisation des données (wxPython + Matplotlib)
# @project: Blender-EduTech
# @lang: fr
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
# @copyright: Copyright (C) 2023 Philippe Roy
# @license: GNU GPL
###############################################################################
plot_config={}
###############################################################################
# Création des graphiques
###############################################################################
def plot_draw(plt):
twin_config = ET.parse('twin_config.xml').getroot()
# Lecture fichier CSV
fields = []
rows = []
with open(sys.argv[1], 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
# 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 twin_config[1][0].text == "True": # Configuration des plots activée
plt.plot(xdata[i], ydata[i], 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'))
else:
plt.plot(xdata[i], ydata[i], '.-', label=var) # Configuration matplotlib par défaut
# Légende ou titre d'axe y
if plt_grp[plt_current][1]==0:
plt.set_ylabel(var)
else:
plt.legend()
# Création des subplots
if plot_nb(plot_config) >1:
if twin_config[1][0].text == "True": # Configuration des plots activée
plt[plt_current].plot(xdata[i], ydata[i], 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'))
else:
plt[plt_current].plot(xdata[i], ydata[i], '.-', label=var) # Configuration matplotlib par défaut
# Légende ou titre d'axe y
if plt_grp[plt_current][1]==0:
plt[plt_current].set_ylabel(var)
else:
plt[plt_current].legend()
# Décoration
if plot_nb(plot_config) ==1: # 1 plot
plt.set_xlabel("Temps (s)")
# self.canvas.plt[0].set_ylabel("Valeurs")
plt.set_title(sys.argv[1])
plt.axhline(linewidth=1, color='k')
plt.grid(True, linestyle='--')
# self.canvas.plt.legend()
else: # Plusieurs plots
plt[plt_i-1].set_xlabel("Temps (s)")
# self.canvas.plt[0].set_ylabel("Valeurs")
plt[0].set_title(sys.argv[1])
for i in range (plt_i):
plt[i].axhline(linewidth=1, color='k')
plt[i].grid(True, linestyle='--')
# self.canvas.plt[i].legend()
###############################################################################
# Zone de dessin
###############################################################################
class CanvasFrame(wx.Frame):
def __init__(self):
super().__init__(None, -1, 'Visualisation des données')
# Création des zones graphique (Plots)
self.figure = Figure()
if plot_nb(plot_config) ==1: # plot_nb() : nombre de graphiques
plt = self.figure.subplots() # plot_nb() : nombre de graphiques
else:
plt = self.figure.subplots(plot_nb(plot_config), 1, sharex=True) # plot_nb() : nombre de graphiques
self.canvas = FigureCanvas(self, -1, self.figure)
# Création des graphive à partir du fichier CSV
fields, xdata, ydata = csv_read(sys.argv[1])
plots_static(plt, fields, xdata, ydata, plot_config, sys.argv[1])
self.canvas.draw()
# Implantation de la fenêtre (canvas)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND)
self.add_toolbar()
self.SetSizer(self.sizer)
self.Fit()
def add_toolbar(self):
self.toolbar = NavigationToolbar(self.canvas)
self.toolbar.Realize()
self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
self.toolbar.update()
###############################################################################
# Application
###############################################################################
class App(wx.App):
def OnInit(self):
frame = CanvasFrame()
frame.Show(True)
return True
if __name__ == "__main__":
# Configuration des plots
plot_config=plot_config_get_dict()
# Fenêtre
app = App()
app.MainLoop() # StaticPlot()