Complément basique du poste de contrôle.
Avant-propos
Matplotlib
(Rechercher sur Youtube et Google).
subplots
: je dis bien subplots et non subplot !.Numpy
.psutils.Popen
(Utilisé au point 8 du plan du tuto ci-dessous).Description
poste de contrôle / paramétrage des afficheurs / Fenêtre / Interface
.
Matplotlib
et Pyqtgraph
.
ShowBase
, dans le fichier show_base.py
.show
à l'intérieur duquel vous créerez le fichier show_base.py
./show/show_base.py
:
class ShowBase:
""" Classe de base pour Matplotlib, Pyqtgraph, Bokeh, etc. """
def __init__(self):
pass
Pour l'instant vide, cette classe sera complétée au fur et à mesure.
MAP
), partons de l'exemple du dernier tuto :
MAP
, nous utiliserons le 9)/show/show_matplotlib.py
:
from show.show_base import ShowBase
import sys
from matplotlib import pyplot as plt
class ShowMatPlotLib(ShowBase):
def __init__(self):
super().__init__()
self.fig, self.ax = plt.subplots()
plt.show()
if __name__ == '__main__':
sys.argv.append('Exercices') # Nom du graphe.
sys.argv.append('9') # Plots id. (La ligne de commande ne doit contenir que du str).
sys.argv.append('-1') # Gestion de la fermeture automatique. Poste de contrôle PID : -1 en local.
mpl = ShowMatPlotLib()
matplotlib doit être installé !
Exécutez ce code : Clic droit / Run 'show_matplotlib'
Vérification.
show_anim
qui affichera une courbe aléatoire pour nos tests.ShowMatPlotLib.show_anim
:
def show_anim(self):
y = np.random.randn(100)
self.ax.set_ylim(np.min(y), np.max(y))
self.line.set_ydata(y)
plt.pause(.001)
Numpy
:
import numpy as np
init
pour l'appeler.ShowMatPlotLib.__init__
:
def __init__(self):
super().__init__()
self.fig, self.ax = plt.subplots()
self.line = self.ax.plot(np.zeros((100,)))[0]
self.show_anim()
plt.show()
__init__
déclare les attributs, puis appelle le setup
.
init
.setup
affecte les attributs, et lance les diverses initialisations.__init__
par 2 méthodes.ShowMatPlotLib.__init__
:
def __init__(self):
super().__init__()
self.fig = None
self.ax = None
self.line = None
self.setup() # Placé à la fin.
ShowMatPlotLib.setup
:
def setup(self):
""" Chemin complet du node final 'Plots' contenant les modèles de calculs. """
# à compléter plus tard.
""" Nom complet du fichier de configuration, éditable manuellement en yaml. """
# à compléter plus tard.
""" Liste de tous les fichiers du node final : modèles de calcul (calc_*.pkl), config (*.yaml), ... """
# à compléter plus tard.
""" Initialisations. """
self.fig, self.ax = plt.subplots()
self.line = self.ax.plot(np.zeros((100,)))[0]
self.show_anim()
""" Restauration de l'état de la fenêtre. """
# à compléter plus tard.
""" Surveillance des fichiers yaml et pkl. """
# à compléter plus tard.
""" Événements. """
# à compléter plus tard.
""" Boucles. """
plt.show()
On remarque que le setup
est déjà organisé en groupes (nous allons les compléter pas à pas).
__init__
ajouter un timer et une période à priori de 500 ms.ShowMatPlotLib.__init__
:
self.anim = QTimer()
self.delay = 500
QTimer
depuis PyQt5.QtCore
:
from PyQt5.QtCore import QTimer
setup
.ShowMatPlotLib.setup
:
""" Événements. """
self.anim.timeout.connect(self.show_anim)
ShowMatPlotLib.setup
""" Boucles. """
self.anim.start(self.delay)
plt.show()
Main
du poste de contrôle.
save_state
et restore_state
de la classe Utils
.MAP
, ils sont simulés à la fin du fichier show_matplotlib.py
, dans sys.argv.append(...)
.super().__init__()
) au début de la méthode __init__
:
self.graph_name = sys.argv[1]
self.node_id = int(sys.argv[2])
self.parent_pid = int(sys.argv[3])
sys.argv est une liste qui contient tous les arguments de la ligne de commande.
setup
.ShowMatPlotLib.setup
:
""" Chemin complet du node final 'Plots' contenant les modèles de calculs. """
bk_path = os.path.dirname(__file__).replace('show', 'backups') # Dossier de backup.
final_path = os.path.normpath(os.path.join(bk_path, self.graph_name, f'node{self.node_id}')) # Node 'Plots'
self.ut = Utils(final_path)
Importer os
et Utils
(from functions.utils import Utils
).
os
et Utils
, il faut aussi déclarer self.ut
dans __init__
:ShowMatPlotLib.__init__
:
self.ut = None
Utils
(Cette modification n'a aucune incidence sur le reste du code).utils.py > Utils.__init__
:
def __init__(self, path=''):
self.o_dt = DateTime() # o_dt = 'Object DateTime'
self.caller_dir = os.getcwd() # dossier du code appelant. Ne pas remplacer getcwd()
path_conf = self.caller_dir if path == '' else path
self.settings = QSettings(f"{path_conf}{os.sep}params.conf", QSettings.IniFormat)
self.watcher = None
listener
.ShowMatPlotLib.listener
:
def listener(self):
geometry = self.get_real_geometry()
if self.geometry != geometry:
self.ut.save_state(self.mgr.window)
self.geometry = geometry
get_real_geometry
ainsi que la propriété mgr
n'existent pas. Créons-les.ShowMatPlotLib.get_real_geometry
:
def get_real_geometry(self):
geom = self.mgr.window.geometry()
return geom.x(), geom.y(), geom.width(), geom.height()
@property ShowMatPlotLib.mgr
:
@property
def mgr(self):
return plt.get_current_fig_manager()
self.geometry
doit être déclaré dans __init__
:
self.geometry = None
listen
dans __init__
.ShowMatPlotLib.__init__
:
self.listen = QTimer()
1 Hertz
dans le setup
.ShowMatPlotLib.setup
:
""" Événements. """
self.listen.timeout.connect(self.listener)
self.anim.timeout.connect(self.show_anim)
Section """ Boucles. """ ShowMatPlotLib.setup
:
""" Boucles. """
self.listen.start(1000)
self.anim.start(self.delay)
plt.show()
setup
, lire l'état de la fenêtre au lancement et l'appliquer.ShowMatPlotLib.setup
:
""" Restauration de l'état de la fenêtre. """
self.ut.restore_state(self.mgr.window)
key_event
.ShowMatPlotLib.key_event
:
def key_event(self, ev):
""" Appui sur une touche du clavier. """
keycode = ev.key
if keycode == ' ':
""" Pause on/off. """
self.paused = not self.paused
self.anim.stop() if self.paused else self.anim.start(int(self.delay))
elif keycode == '+':
""" Accélérer. """
self.anim.stop()
self.delay /= 1.5
self.delay = max(5, self.delay)
self.anim.start(int(self.delay))
elif keycode == '-':
""" Ralentir. """
self.anim.stop()
self.delay *= 1.5
self.delay = min(5000, self.delay)
self.anim.start(int(self.delay))
self.paused
est nécessaire, mais il est absent.ShowMatPlotLib.__init__
:
self.paused = False
ShowMatPlotLib.setup
:
""" Événements. """
self.listen.timeout.connect(self.listener)
self.anim.timeout.connect(self.show_anim)
self.fig.canvas.mpl_connect('key_press_event', self.key_event)
show_figure
.Voila ce que nous voulons faire :
Paramètres / Fenêtre / Interface
est sur Matplotlib
.self.scripts
dans __init__
.plots.py > Node.__init__
:
self.scripts = dict()
plots.py > Node.setup
:
def setup(self, child_file=__file__):
self.o_grcontent = UiContentPlots(self)
self.scripts = {
'Matplotlib': 'show_matplotlib.py',
'Pyqtgraph': 'show_pyqtgraph.py',
'Plotly': 'show_plotly.py',
'Bokeh': 'show_bokeh.py',
'Cufflinks': 'show_cufflinks.py',
'Dash': 'show_dash.py',
'Guiqwt': 'show_guiqwt.py',
'OpenCV': 'show_opencv.py',
'Seaborn': 'show_seaborn.py',
}
super().setup(child_file)
self.init_calc()
fixed_params
.plots.py > Node.fixed_params
:
def fixed_params(self):
""" Valeurs par défaut. """
return {
"Nombre d'entrées": [1, {'step': 1, 'limits': (1, 8)}],
'Fenêtre': {
'Titre': 'Titre de la fenêtre',
'Interface': ['Matplotlib', {'values': list(self.scripts.keys())}]
}
}
PID
de l'affichage Matplotlib :
Pyton.exe
qui s'exécutent simultanément.PID
.self.graph_pid
, que l'on doit déclarer dans __init__
, et affecter au moment du lancement du process.plots.py > Node.__init__
:
self.graph_pid = None # PID du process affichant le graphique.
PID
ne répond plus, c'est parce que le process est mort (killed), autrement dit, que la fenêtre d'affichage a été fermée.self.clock
.plots.py > Node.__init__
:
self.clock = QTimer()
La classe QTimer
(de QtCore
) doit être importée.self.script = ...
, dans plots.py > Node.setup
:
self.clock.timeout.connect(self.detect_graph_closed)
self.detect_graph_closed
, elle n'existe pas. Créons-la.plots.py > Node.detect_graph_closed
:
def detect_graph_closed(self):
if self.graph_pid is None or not psutil.pid_exists(self.graph_pid):
self.o_grcontent.button.setText('Voir')
self.clock.stop()
Cette méthode rétablit le libellé du bouton à 'Voir' et arrête la surveillance.
Installer puis importer psutil
.
plots.py > Node.show_figure
devient :
def show_figure(self):
""" Désélection de tous les items de la scène, puis sélection de moi-même. """
for item in self.o_scene.o_grscene.items():
item.setSelected(False)
self.o_grnode.setSelected(True)
ui_fig = self.get_param(['Fenêtre', 'Interface'])
# à coder ...
# à coder ...
Vérification
Plots
.Matplotlib
(Dockable des paramètres).Snippets
Bonjour les codeurs !