diff --git a/monte_charge/montchg.py b/monte_charge/montchg.py index e36b3d1..4ee9d6c 100644 --- a/monte_charge/montchg.py +++ b/monte_charge/montchg.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), é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) # diff --git a/monte_charge/twin_file_wx.py b/monte_charge/twin_file_wx.py new file mode 120000 index 0000000..854fa40 --- /dev/null +++ b/monte_charge/twin_file_wx.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_file_wx.py \ No newline at end of file diff --git a/monte_charge/twin_plot.py b/monte_charge/twin_plot.py new file mode 120000 index 0000000..96c905c --- /dev/null +++ b/monte_charge/twin_plot.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot.py \ No newline at end of file diff --git a/monte_charge/twin_plot_wx.py b/monte_charge/twin_plot_wx.py new file mode 120000 index 0000000..eb5501b --- /dev/null +++ b/monte_charge/twin_plot_wx.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot_wx.py \ No newline at end of file diff --git a/poppy_ergo_jr/twin_file_wx.py b/poppy_ergo_jr/twin_file_wx.py new file mode 120000 index 0000000..854fa40 --- /dev/null +++ b/poppy_ergo_jr/twin_file_wx.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_file_wx.py \ No newline at end of file diff --git a/poppy_ergo_jr/twin_plot.py b/poppy_ergo_jr/twin_plot.py new file mode 120000 index 0000000..96c905c --- /dev/null +++ b/poppy_ergo_jr/twin_plot.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot.py \ No newline at end of file diff --git a/poppy_ergo_jr/twin_plot_wx.py b/poppy_ergo_jr/twin_plot_wx.py new file mode 120000 index 0000000..eb5501b --- /dev/null +++ b/poppy_ergo_jr/twin_plot_wx.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot_wx.py \ No newline at end of file diff --git a/portail_coulissant/porcou.py b/portail_coulissant/porcou.py index 9e4c647..8538d3f 100644 --- a/portail_coulissant/porcou.py +++ b/portail_coulissant/porcou.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 diff --git a/portail_coulissant/portail_coulissant-17.blend b/portail_coulissant/portail_coulissant-17.blend index 3818cf1..79179dc 100644 Binary files a/portail_coulissant/portail_coulissant-17.blend and b/portail_coulissant/portail_coulissant-17.blend differ diff --git a/portail_coulissant/twin_file_wx.py b/portail_coulissant/twin_file_wx.py new file mode 120000 index 0000000..854fa40 --- /dev/null +++ b/portail_coulissant/twin_file_wx.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_file_wx.py \ No newline at end of file diff --git a/portail_coulissant/twin_plot.py b/portail_coulissant/twin_plot.py new file mode 120000 index 0000000..96c905c --- /dev/null +++ b/portail_coulissant/twin_plot.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot.py \ No newline at end of file diff --git a/portail_coulissant/twin_plot_wx.py b/portail_coulissant/twin_plot_wx.py new file mode 120000 index 0000000..eb5501b --- /dev/null +++ b/portail_coulissant/twin_plot_wx.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot_wx.py \ No newline at end of file diff --git a/twin_daq.py b/twin_daq.py index 167810c..7d8678e 100644 --- a/twin_daq.py +++ b/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) diff --git a/twin_plot.py b/twin_plot.py new file mode 100644 index 0000000..faae6d6 --- /dev/null +++ b/twin_plot.py @@ -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 +# @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() + + diff --git a/twin_plot_qt.py b/twin_plot_qt.py index b133b7f..587c5b7 100644 --- a/twin_plot_qt.py +++ b/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() diff --git a/twin_plot_wx.py b/twin_plot_wx.py index 4b7454e..832dac9 100644 --- a/twin_plot_wx.py +++ b/twin_plot_wx.py @@ -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() diff --git a/volet_roulant/twin_file_wx.py b/volet_roulant/twin_file_wx.py new file mode 120000 index 0000000..854fa40 --- /dev/null +++ b/volet_roulant/twin_file_wx.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_file_wx.py \ No newline at end of file diff --git a/volet_roulant/twin_plot.py b/volet_roulant/twin_plot.py new file mode 120000 index 0000000..96c905c --- /dev/null +++ b/volet_roulant/twin_plot.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot.py \ No newline at end of file diff --git a/volet_roulant/twin_plot_wx.py b/volet_roulant/twin_plot_wx.py new file mode 120000 index 0000000..eb5501b --- /dev/null +++ b/volet_roulant/twin_plot_wx.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_plot_wx.py \ No newline at end of file diff --git a/volet_roulant/volrou.py b/volet_roulant/volrou.py index c7d700f..68903e5 100644 --- a/volet_roulant/volrou.py +++ b/volet_roulant/volrou.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) #