mirror of
https://forge.apps.education.fr/blender-edutech/jumeaux-numeriques.git
synced 2024-01-27 06:56:18 +01:00
Factorisation de la création des plots
This commit is contained in:
parent
b1be7d960d
commit
4d809d45da
@ -18,7 +18,7 @@ scene = bge.logic.getCurrentScene()
|
||||
|
||||
# Configuration des variables publiques
|
||||
# 'nom_variable' :
|
||||
# - Objet 3D : [nom de l'objet 3D, propriété du stockage de la valeur (activate ou activated_real), échelle (1 si ommis)]
|
||||
# - Objet 3D : [nom de l'objet 3D, propriété associée à la valeur (activate ou activated_real), type de la valeur ('d' (digital, binary), 'a', (analog) ou 'n' (numeric)), échelle (1 si ommis)]
|
||||
# - Configuration de la broche : [nom de la propriété stockant l'object broche (pyfirmata), type de broche par défaut('d','a' ou 'p'), 'mode de la broche par défaut ('i' ou 'o')]
|
||||
# - Configuration du graphique : ['marque', 'type de ligne', 'couleur', linewidth]] (matplotlib)
|
||||
#
|
||||
|
1
monte_charge/twin_file_wx.py
Symbolic link
1
monte_charge/twin_file_wx.py
Symbolic link
@ -0,0 +1 @@
|
||||
/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_file_wx.py
|
1
monte_charge/twin_plot.py
Symbolic link
1
monte_charge/twin_plot.py
Symbolic link
@ -0,0 +1 @@
|
||||
/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot.py
|
1
monte_charge/twin_plot_wx.py
Symbolic link
1
monte_charge/twin_plot_wx.py
Symbolic link
@ -0,0 +1 @@
|
||||
/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot_wx.py
|
1
poppy_ergo_jr/twin_file_wx.py
Symbolic link
1
poppy_ergo_jr/twin_file_wx.py
Symbolic link
@ -0,0 +1 @@
|
||||
/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_file_wx.py
|
1
poppy_ergo_jr/twin_plot.py
Symbolic link
1
poppy_ergo_jr/twin_plot.py
Symbolic link
@ -0,0 +1 @@
|
||||
/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot.py
|
1
poppy_ergo_jr/twin_plot_wx.py
Symbolic link
1
poppy_ergo_jr/twin_plot_wx.py
Symbolic link
@ -0,0 +1 @@
|
||||
/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot_wx.py
|
@ -18,8 +18,8 @@ scene = bge.logic.getCurrentScene()
|
||||
|
||||
# Configuration des variables publiques
|
||||
# 'nom_variable' :
|
||||
# - Objet 3D : [nom de l'objet 3D, propriété du stockage de la valeur (activate ou activated_real)]
|
||||
# - Configuration de la broche : [nom de la propriété stockant l'object broche (pyfirmata), type de broche par défaut('d','a' ou 'p'), 'mode de la broche par défaut ('i' ou 'o')]
|
||||
# - Objet 3D : [nom de l'objet 3D, propriété associée à la valeur (activate ou activated_real), type de la valeur ('d' (digital, binary), 'a', (analog) ou 'n' (numeric)), échelle (1 si ommis)]
|
||||
# - Configuration de la broche : [nom de la propriété stockant l'object broche (pyfirmata), type de broche par défaut ('d','a' ou 'p'), 'mode de la broche par défaut ('i' ou 'o')]
|
||||
# - Configuration du graphique : ['marque', 'type de ligne', 'couleur', linewidth]] (Codification de Matplotlib)
|
||||
#
|
||||
# 'nom_variable_r' est la valeur réelle de la variable (valeur numérique) 'nom_variable' issue du jumelage numérique.
|
||||
@ -27,27 +27,27 @@ scene = bge.logic.getCurrentScene()
|
||||
# Ce distinguo ne concerne que les entrées, les sorties réelles sont forcées par les sorties numériques et vice-versa.
|
||||
|
||||
public_vars = {
|
||||
't' : [['System','time'], [], []],
|
||||
'bp_ext' : [['Bp cote rue','activated'], ['pin', 'd','i'], ['.','-', 'green', 1]],
|
||||
'bp_ext_r' : [['Bp cote rue','activated_real'], [], ['.','--', 'green', 1]],
|
||||
'bp_int' : [['Bp cote cour','activated'], ['pin', 'd','i'], ['.','-', 'darkgreen', 1]],
|
||||
'bp_int_r' : [['Bp cote cour','activated_real'], [], ['.','--', 'darkgreen', 1]],
|
||||
'fdc_o' : [['Microrupteur fdc ouvert','activated'], ['pin', 'd','i'], ['.','-', 'orange', 1]],
|
||||
'fdc_o_r' : [['Microrupteur fdc ouvert','activated_real'], [], ['.','--', 'orange', 1]],
|
||||
'fdc_f' : [['Microrupteur fdc ferme','activated'], ['pin', 'd','i'], ['.','-', 'darkorange', 1]],
|
||||
'fdc_f_r' : [['Microrupteur fdc ferme','activated_real'], [], ['.','--', 'darkorange', 1]],
|
||||
'mot_o' : [['Moteur','open'], ['pin_open', 'd','o'], ['.','-', 'violet', 1]],
|
||||
'mot_f' : [['Moteur','close'], ['pin_close', 'd','o'], ['.','-', 'darkviolet', 1]],
|
||||
'mot_angle' : [['Moteur','alpha'], [], ['.','-', 'blue', 1]],
|
||||
'mot_vitesse' : [['Moteur','speed'], [], ['.','-', 'darkblue', 1]],
|
||||
'mot_pas' : [['Moteur','step'], [], []],
|
||||
'portail_x' : [['Portail','x'], [], ['.','-', 'turquoise', 1]],
|
||||
'portail_vitesse' : [['Portail','speed'], [], ['.','-', 'darkturquoise', 1]],
|
||||
'portail_pas' : [['Portail','step'], [], []],
|
||||
'gyr' : [['Led','activated'], ['pin', 'd','.'], ['.','-', 'gold', 1]],
|
||||
'ir_emet' : [['Emetteur IR', 'activated'], ['pin', 'd','o'],['.','-', 'red', 1]],
|
||||
'ir_recep' : [['Recepteur IR','activated'], ['pin', 'd','i'],['.','-', 'darkred', 1]],
|
||||
'ir_recep_r' : [['Recepteur IR','activated_real'], [],['.','--', 'darkred', 1]]}
|
||||
't' : [['System','time','a'],[],[]],
|
||||
'bp_ext' : [['Bp cote rue','activated','d'],['pin','d','i'],['.','-','green',1]],
|
||||
'bp_ext_r' : [['Bp cote rue','activated_real','d'],[],['.','--','green',1]],
|
||||
'bp_int' : [['Bp cote cour','activated','d'],['pin','d','i'],['.','-','darkgreen',1]],
|
||||
'bp_int_r' : [['Bp cote cour','activated_real','d'],[],['.','--','darkgreen',1]],
|
||||
'fdc_o' : [['Microrupteur fdc ouvert','activated','d'],['pin','d','i'],['.','-','orange',1]],
|
||||
'fdc_o_r' : [['Microrupteur fdc ouvert','activated_real','d'],[],['.','--','orange',1]],
|
||||
'fdc_f' : [['Microrupteur fdc ferme','activated','d'],['pin','d','i'],['.','-','darkorange',1]],
|
||||
'fdc_f_r' : [['Microrupteur fdc ferme','activated_real','d'],[],['.','--','darkorange',1]],
|
||||
'mot_o' : [['Moteur','open','d'],['pin_open','d','o'],['.','-','violet',1]],
|
||||
'mot_f' : [['Moteur','close','d'],['pin_close','d','o'],['.','-','darkviolet',1]],
|
||||
'mot_angle' : [['Moteur','alpha','a'],[],['.','-','blue',1]],
|
||||
'mot_vitesse' : [['Moteur','speed','a'],[],['.','-','darkblue',1]],
|
||||
'mot_pas' : [['Moteur','step','a'],[],[]],
|
||||
'portail_x' : [['Portail','x','a'],[],['.','-','turquoise',1]],
|
||||
'portail_vitesse' : [['Portail','speed','a'],[],['.','-','darkturquoise',1]],
|
||||
'portail_pas' : [['Portail','step','a'],[],[]],
|
||||
'gyr' : [['Led','activated','d'],['pin','d','.'],['.','-','gold',1]],
|
||||
'ir_emet' : [['Emetteur IR','activated','d'],['pin','d','o'],['.','-','red',1]],
|
||||
'ir_recep' : [['Recepteur IR','activated','d'],['pin','d','i'],['.','-','darkred',1]],
|
||||
'ir_recep_r' : [['Recepteur IR','activated_real','d'],[],['.','--','darkred',1]]}
|
||||
|
||||
# Couleurs
|
||||
color_passive = (0.800, 0.005, 0.315,1) # bouton non activable : magenta
|
||||
|
Binary file not shown.
1
portail_coulissant/twin_file_wx.py
Symbolic link
1
portail_coulissant/twin_file_wx.py
Symbolic link
@ -0,0 +1 @@
|
||||
/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_file_wx.py
|
1
portail_coulissant/twin_plot.py
Symbolic link
1
portail_coulissant/twin_plot.py
Symbolic link
@ -0,0 +1 @@
|
||||
/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot.py
|
1
portail_coulissant/twin_plot_wx.py
Symbolic link
1
portail_coulissant/twin_plot_wx.py
Symbolic link
@ -0,0 +1 @@
|
||||
/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot_wx.py
|
10
twin_daq.py
10
twin_daq.py
@ -34,8 +34,8 @@ daq_data=[]
|
||||
|
||||
def get(data):
|
||||
if data in daq_config:
|
||||
if len (daq_config[data][0])>2: # Echelle à prendre en compte
|
||||
return(scene.objects[daq_config[data][0][0]][daq_config[data][0][1]]*daq_config[data][0][2])
|
||||
if len (daq_config[data][0])>3: # Echelle à prendre en compte
|
||||
return(scene.objects[daq_config[data][0][0]][daq_config[data][0][1]]*daq_config[data][0][3])
|
||||
else:
|
||||
return(scene.objects[daq_config[data][0][0]][daq_config[data][0][1]])
|
||||
else:
|
||||
@ -126,6 +126,8 @@ def plot_config_generate(data_groups):
|
||||
xml_color.text=daq_config[var][2][2]
|
||||
xml_size = ET.SubElement(xml_var, 'linewidth')
|
||||
xml_size.text=str(daq_config[var][2][3])
|
||||
xml_type = ET.SubElement(xml_var, 'type')
|
||||
xml_type.text=str(daq_config[var][0][2])
|
||||
|
||||
# Détection de groupe de graphique
|
||||
data_group_i=0
|
||||
@ -160,9 +162,9 @@ def plot(data_groups):
|
||||
##
|
||||
|
||||
def plot_generate_thread(csv_file):
|
||||
if sys.platform=="linux": # wxPython ne s'installe pas bien sur GNU/linux -> Qt6
|
||||
if sys.platform=="linux": # wxPython ne s'installe pas bien sur GNU/linux -> Qt5
|
||||
command = sys.executable + " " + os.path.join(sys.executable, os.getcwd(), "twin_plot_qt.py") + " "+ csv_file
|
||||
else: # Qt6 ne s'installe pas bien sur Windows -> wxPython
|
||||
else: # Qt5 ne s'installe pas bien sur Windows -> wxPython
|
||||
command = sys.executable + " " + os.path.join(sys.executable, os.getcwd(), "twin_plot_wx.py") + " "+ csv_file
|
||||
os.system(command)
|
||||
|
||||
|
198
twin_plot.py
Normal file
198
twin_plot.py
Normal file
@ -0,0 +1,198 @@
|
||||
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
|
||||
##
|
||||
|
||||
def plot_config_get_dict():
|
||||
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)
|
||||
##
|
||||
|
||||
def plot_nb(plot_config):
|
||||
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
|
||||
##
|
||||
|
||||
def csv_read(file):
|
||||
|
||||
# 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
|
||||
###############################################################################
|
||||
|
||||
def plot_static(canvas, fields, xdata, ydata, plot_config, title):
|
||||
|
||||
# Configuration des plots activée
|
||||
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
|
||||
canvas.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:
|
||||
canvas.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:
|
||||
canvas.plt.set_ylabel(var)
|
||||
else:
|
||||
canvas.plt.legend()
|
||||
|
||||
# Création des subplots
|
||||
if plot_nb(plot_config) >1:
|
||||
if plot_config_enable: # Configuration des plots activée
|
||||
canvas.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:
|
||||
canvas.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:
|
||||
canvas.plt[plt_current].set_ylabel(var)
|
||||
else:
|
||||
canvas.plt[plt_current].legend()
|
||||
|
||||
# Décoration
|
||||
if plot_nb(plot_config) ==1: # 1 plot
|
||||
canvas.plt.set_xlabel("Temps (s)")
|
||||
canvas.plt.set_title(title)
|
||||
canvas.plt.axhline(linewidth=1, color='k')
|
||||
canvas.plt.grid(True, linestyle='--')
|
||||
# canvas.plt.legend()
|
||||
else: # Plusieurs plots
|
||||
canvas.plt[plt_i-1].set_xlabel("Temps (s)")
|
||||
canvas.plt[0].set_title(title)
|
||||
for i in range (plt_i):
|
||||
canvas.plt[i].axhline(linewidth=1, color='k')
|
||||
canvas.plt[i].grid(True, linestyle='--')
|
||||
# canvas.plt[i].legend()
|
||||
|
||||
# Redraw
|
||||
canvas.draw()
|
||||
|
||||
|
187
twin_plot_qt.py
187
twin_plot_qt.py
@ -1,15 +1,11 @@
|
||||
import sys
|
||||
import random
|
||||
import importlib
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plts
|
||||
import csv
|
||||
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, plot_static # Gestion communes des graphiques (Qt, wx)
|
||||
|
||||
matplotlib.use('Qt5Agg')
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT as NavigationToolbar
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets # GUI Qt5
|
||||
import matplotlib # Grapheur Matplotlib
|
||||
import matplotlib.pyplot as plts
|
||||
matplotlib.use('Qt5Agg')
|
||||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT as NavigationToolbar
|
||||
|
||||
###############################################################################
|
||||
# twin_plot_qt.py
|
||||
@ -21,70 +17,18 @@ import matplotlib.pyplot as plts
|
||||
# @license: GNU GPL
|
||||
###############################################################################
|
||||
|
||||
# Lecture des configurations
|
||||
twin_config = ET.parse('twin_config.xml').getroot()
|
||||
plot_config_tree = ET.parse('plot_config.xml').getroot()
|
||||
plot_config={}
|
||||
|
||||
###############################################################################
|
||||
# Configuration des plots
|
||||
###############################################################################
|
||||
|
||||
##
|
||||
# Génère le dictionnaire plot_config à partir du fichier XML plot_config.xml
|
||||
##
|
||||
|
||||
def plot_config_dict():
|
||||
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.update({var.text: var_dict})
|
||||
|
||||
##
|
||||
# Returne une valeur du dictionnaire plot_config
|
||||
##
|
||||
|
||||
def plot_config_get(var, key):
|
||||
if key in plot_config[var]:
|
||||
return plot_config[var][key]
|
||||
else:
|
||||
return None
|
||||
|
||||
##
|
||||
# Nombre de groupe de courbe(s)
|
||||
##
|
||||
|
||||
def plot_nb():
|
||||
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
|
||||
|
||||
###############################################################################
|
||||
# Zone de dessin
|
||||
###############################################################################
|
||||
|
||||
class MplCanvas(FigureCanvasQTAgg):
|
||||
def __init__(self, parent=None, width=5, height=4, dpi=100):
|
||||
if plot_nb() ==1: # plot_nb() : nombre de graphiques
|
||||
fig, self.plt = plts.subplots() # plot_nb() : nombre de graphiques
|
||||
if plot_nb(plot_config) ==1: # plot_nb() : nombre de graphiques
|
||||
fig, self.plt = plts.subplots()
|
||||
else:
|
||||
fig, self.plt = plts.subplots(plot_nb(), 1, sharex=True) # plot_nb() : nombre de graphiques
|
||||
fig, self.plt = plts.subplots(plot_nb(plot_config), 1, sharex=True) # plot_nb() : nombre de graphiques
|
||||
super(MplCanvas, self).__init__(fig)
|
||||
|
||||
###############################################################################
|
||||
@ -212,9 +156,6 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
# Création du graphique
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
# Configuration des plots
|
||||
plot_config_dict()
|
||||
|
||||
# Zone graphique (barre d'outil et graphique)
|
||||
# FIXME : perd de la place quand on agrandi
|
||||
super(MainWindow, self).__init__(*args, **kwargs)
|
||||
@ -235,110 +176,9 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.setCentralWidget(widget)
|
||||
# print (self.getContentsMargins())
|
||||
|
||||
# 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() ==1:
|
||||
if twin_config[1][0].text == "True": # Configuration des plots activée
|
||||
self.canvas.plt.plot(xdata[i], ydata[i], label=var, color=plot_config_get(var, 'color'), linewidth=plot_config_get(var, 'linewidth'),
|
||||
linestyle=plot_config_get(var, 'linestyle'), marker=plot_config_get(var, 'marker'))
|
||||
else:
|
||||
self.canvas.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:
|
||||
self.canvas.plt.set_ylabel(var)
|
||||
else:
|
||||
self.canvas.plt.legend()
|
||||
|
||||
# Création des subplots
|
||||
if plot_nb() >1:
|
||||
if twin_config[1][0].text == "True": # Configuration des plots activée
|
||||
self.canvas.plt[plt_current].plot(xdata[i], ydata[i], label=var, color=plot_config_get(var, 'color'), linewidth=plot_config_get(var, 'linewidth'),
|
||||
linestyle=plot_config_get(var, 'linestyle'), marker=plot_config_get(var, 'marker'))
|
||||
else:
|
||||
self.canvas.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:
|
||||
self.canvas.plt[plt_current].set_ylabel(var)
|
||||
else:
|
||||
self.canvas.plt[plt_current].legend()
|
||||
|
||||
# Décoration
|
||||
if plot_nb() ==1: # 1 plot
|
||||
self.canvas.plt.set_xlabel("Temps (s)")
|
||||
# self.canvas.plt[0].set_ylabel("Valeurs")
|
||||
self.canvas.plt.set_title(sys.argv[1])
|
||||
self.canvas.plt.axhline(linewidth=1, color='k')
|
||||
self.canvas.plt.grid(True, linestyle='--')
|
||||
# self.canvas.plt.legend()
|
||||
else: # Plusieurs plots
|
||||
self.canvas.plt[plt_i-1].set_xlabel("Temps (s)")
|
||||
# self.canvas.plt[0].set_ylabel("Valeurs")
|
||||
self.canvas.plt[0].set_title(sys.argv[1])
|
||||
for i in range (plt_i):
|
||||
self.canvas.plt[i].axhline(linewidth=1, color='k')
|
||||
self.canvas.plt[i].grid(True, linestyle='--')
|
||||
# self.canvas.plt[i].legend()
|
||||
|
||||
# Redraw
|
||||
self.canvas.draw()
|
||||
# Création des graphive à partir du fichier CSV
|
||||
fields, xdata, ydata = csv_read(sys.argv[1])
|
||||
plot_static(self.canvas, fields, xdata, ydata, plot_config, sys.argv[1])
|
||||
self.show()
|
||||
|
||||
###############################################################################
|
||||
@ -346,6 +186,11 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
###############################################################################
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# Configuration des plots
|
||||
plot_config=plot_config_get_dict()
|
||||
|
||||
# Fenêtre
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
# w = DynamicPlot()
|
||||
w = MainWindow() # StaticPlot()
|
||||
|
@ -1,10 +1,8 @@
|
||||
import sys
|
||||
import importlib
|
||||
import csv
|
||||
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, plot_static # Gestion communes des graphiques (Qt, wx)
|
||||
|
||||
import wx
|
||||
import matplotlib
|
||||
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)
|
||||
|
||||
@ -18,61 +16,8 @@ from matplotlib.backends.backend_wxagg import (FigureCanvasWxAgg as FigureCanvas
|
||||
# @license: GNU GPL
|
||||
###############################################################################
|
||||
|
||||
# Lecture des configurations
|
||||
twin_config = ET.parse('twin_config.xml').getroot()
|
||||
plot_config_tree = ET.parse('plot_config.xml').getroot()
|
||||
plot_config={}
|
||||
|
||||
###############################################################################
|
||||
# Configuration des graphiques
|
||||
###############################################################################
|
||||
|
||||
##
|
||||
# Génère le dictionnaire plot_config à partir du fichier XML plot_config.xml
|
||||
##
|
||||
|
||||
def plot_config_dict():
|
||||
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.update({var.text: var_dict})
|
||||
|
||||
##
|
||||
# Returne une valeur du dictionnaire plot_config
|
||||
##
|
||||
|
||||
def plot_config_get(var, key):
|
||||
if key in plot_config[var]:
|
||||
return plot_config[var][key]
|
||||
else:
|
||||
return None
|
||||
|
||||
##
|
||||
# Nombre de groupe de courbe(s)
|
||||
##
|
||||
|
||||
def plot_nb():
|
||||
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
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Création des graphiques
|
||||
###############################################################################
|
||||
@ -181,32 +126,32 @@ def plot_draw(plt):
|
||||
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')
|
||||
|
||||
# Configuration des graphiques
|
||||
plot_config_dict()
|
||||
|
||||
# Création des zones graphique (Plots)
|
||||
self.figure = Figure()
|
||||
if plot_nb() ==1: # plot_nb() : nombre de graphiques
|
||||
plt = self.figure.subplots() # plot_nb() : nombre de graphiques
|
||||
else:
|
||||
plt = self.figure.subplots(plot_nb(), 1, sharex=True) # plot_nb() : nombre de graphiques
|
||||
|
||||
# Dessin
|
||||
plot_draw(plt)
|
||||
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])
|
||||
plot_static(self.canvas, fields, xdata, ydata, plot_config, sys.argv[1])
|
||||
self.show()
|
||||
|
||||
# # Dessin
|
||||
# plot_draw(plt)
|
||||
|
||||
# Implantation de la fenêtre (canvas)
|
||||
self.canvas = FigureCanvas(self, -1, self.figure)
|
||||
self.sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND)
|
||||
self.add_toolbar()
|
||||
@ -231,5 +176,10 @@ class App(wx.App):
|
||||
return True
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# Configuration des plots
|
||||
plot_config=plot_config_get_dict()
|
||||
|
||||
# Fenêtre
|
||||
app = App()
|
||||
app.MainLoop()
|
||||
app.MainLoop() # StaticPlot()
|
||||
|
1
volet_roulant/twin_file_wx.py
Symbolic link
1
volet_roulant/twin_file_wx.py
Symbolic link
@ -0,0 +1 @@
|
||||
/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_file_wx.py
|
1
volet_roulant/twin_plot.py
Symbolic link
1
volet_roulant/twin_plot.py
Symbolic link
@ -0,0 +1 @@
|
||||
/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot.py
|
1
volet_roulant/twin_plot_wx.py
Symbolic link
1
volet_roulant/twin_plot_wx.py
Symbolic link
@ -0,0 +1 @@
|
||||
/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot_wx.py
|
@ -18,7 +18,7 @@ scene = bge.logic.getCurrentScene()
|
||||
|
||||
# Configuration des variables publiques
|
||||
# 'nom_variable' :
|
||||
# - Objet 3D : [nom de l'objet 3D, propriété du stockage de la valeur (activate ou activated_real)]
|
||||
# - Objet 3D : [nom de l'objet 3D, propriété associée à la valeur (activate ou activated_real), type de la valeur ('d' (digital, binary), 'a', (analog) ou 'n' (numeric)), échelle (1 si ommis)]
|
||||
# - Configuration de la broche : [nom de la propriété stockant l'object broche (pyfirmata), type de broche par défaut('d','a' ou 'p'), 'mode de la broche par défaut ('i' ou 'o')]
|
||||
# - Configuration du graphique : ['marque', 'type de ligne', 'couleur', linewidth]] (matplotlib)
|
||||
#
|
||||
|
Loading…
Reference in New Issue
Block a user