Utile lorsque les signaux sont complémentaires
Avant-propos
Expand
, collapse
: pour avoir les mêmes raccourcis clavier sur Pycharm
comme sur SublimeText
, éditer le fichier KeyBindings
.
Menu de SublimeText / Preferences / Key Bindings
(Volet de droite) :
[
{ "keys": ["ctrl+s"], "command": "save_all" },
{ "keys": ["ctrl+q"], "command": "save" },
{ "keys": ["ctrl+keypad_divide"], "command": "toggle_comment", "args": { "block": false } },
{ "keys": ["ctrl+keypad_plus"], "command": "unfold" },
{ "keys": ["ctrl+keypad_minus"], "command": "fold" },
{ "keys": ["ctrl+shift+keypad_plus"], "command": "unfold_all" },
{ "keys": ["ctrl+shift+keypad_minus"], "command": "fold_all" },
]
Après avoir copié ce code, enregistrer (Ctrl + s
).
fold
et unfold
permettent de faire collapse
et expand
sur des parties de code (ou tout si _all
).Description
Exemple de 2 subplots : [5, 2, 3, 4] et [1, 7, 8, 4]
ShowMatPlotLib.gridspec
.ShowMatPlotLib.get_default_grid()
:
self.ax[0]
.ShowMatPlotLib
en implémentant des boucles de parcours sur les entrées actives.update_figure()
, appelée lors des modifications de paramètres (dockable et yaml),show_anim()
, lancée de façon récurrente par QTimer.get_défault_grid()
.show_matplotlib.py
:
from PyQt5.QtCore import QTimer
from show.show_base import ShowBase
from functions.utils import Utils, Dictionary
from nodes.afficheurs.plots.matplotlib_yaml import YamlParams
from matplotlib import pyplot as plt, rcParams
import psutil
import pickle
import numpy as np
import sys
import os
# noinspection PyUnresolvedReferences
class ShowMatPlotLib(ShowBase):
def __init__(self):
super().__init__()
self.graph_name = sys.argv[1]
self.node_id = int(sys.argv[2])
self.parent_pid = int(sys.argv[3])
self.final_path = ''
self.od_calc = Dictionary() # super-dic des modèles de calcul (un par entrée) affectés à ce node (des pkl)
self.o_yaml = None # Instance de la classe Yaml de matplotlib
self.l_files_ante = list()
self.lo_calc = [None for _ in range(8)] # Liste d'objets 'Calcul' des nodes directement connectés (8 entrées)
self.ut = None
self.fig = None
self.ax = [None for _ in range(8)] # Liste de 8 valeurs (les axes, ou graphiques : 1 par entrée)
self.gridspec = None
self.geometry = None
self.b_paused = False
self.b_busy = False
self.nb_points = 350
self.delay = 50
self.listen = QTimer()
self.anim = QTimer()
self.setup()
def setup(self):
""" Chemin complet du node final 'Plots' contenant les modèles de calculs. """
bk_path = os.path.dirname(__file__).replace('show', 'backups') # Dossier de backup.
self.final_path = os.path.normpath(os.path.join(bk_path, self.graph_name, f'node{self.node_id}')) # 'Plots'
self.ut = Utils(self.final_path, 'matplotlib')
""" Fichier de configuration, éditable manuellement en yaml. """
# [print(style) for style in plt.style.available] # Décommenter pour voir la liste des styles disponibles.
# Dictionary(rcParams).print() # Décommenter pour voir la liste des paramètres disponibles.
yaml_file = os.path.normpath(f'{self.final_path}/{self.node_id}-matplotlib.yaml')
self.o_yaml = YamlParams(yaml_file)
rc_params = self.o_yaml.get_rcparams()
for key, val in rc_params.items():
rcParams[key] = val
plt.style.use(self.o_yaml.get_style())
""" Initialisation de matplotlib.pyplot. """
self.fig = plt.figure()
plt.subplots_adjust(top=.93, bottom=.07, left=.07, right=.98, wspace=2., hspace=10.) # à ajuster.
self.gridspec = [12, 12] # Découpe de la figure : Nb lignes, nb colonnes.
""" Restauration de l'état de la fenêtre. """
self.ut.restore_state(self.mgr.window)
""" Surveillance des fichiers '.pkl'. """
self.ini_watch()
""" É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)
""" Boucles. """
self.listen.start(1000)
self.anim.start(self.delay)
plt.show()
def show_anim(self):
""" Une entrée (num_input = 0) donc un seul graphique occupant tout l'espace de self.fig (de la fenêtre). """
""" Ini. """
if self.b_busy:
return
self.b_busy = True # Occupé. Évite une réentrance.
for num_input in range(8):
ax = self.ax[num_input]
if not ax:
continue
""" Lecture des données à afficher : entre {pointer} et {pointer+nb_points}. """
x = np.arange(ax.pointer, ax.pointer + self.nb_points)
y = ax.o_calc.np_array[ax.pointer: ax.pointer + self.nb_points]
if y.shape[1] == 0: # Nombre de courbes.
continue
""" Limites x et y (abscisses et ordonnées). """
ax.set_xlim(ax.pointer, ax.pointer + self.nb_points) # Abscisses.
y_min, y_max = np.min(y), np.max(y)
y_padding = (y_max - y_min) * 0.05 # Marges top et bottom du graphique.
y_min, y_max = y_min - y_padding, y_max + y_padding
ax.set_ylim(y_min, y_max) # Ordonnées.
""" Attribution des valeurs. """
for o_line in ax.lines:
if hasattr(o_line, 'attr'):
num_col = int(o_line.attr['num_col'])
o_line.set_xdata(x)
o_line.set_ydata(y[:, num_col])
""" Avancement du pointeur. """
if len(ax.lines) > 0: # Immobile si aucune courbe n'est affichée.
ax.pointer += 1
if ax.pointer > 90_000: # Bouclage provisoire.
ax.pointer = 0
""" Affichage. """
plt.draw()
self.b_busy = False # Libre.
def ini_watch(self):
""" Liste des éléments à surveiller : dossier {graphe} + dossiers {nodes} + fichiers .pkl + fichiers .yaml
- Le dossier est self.final_path, dans les backups.
- Les fichiers calc_*.pkl : un par entrée active de ce node d'affichage.
- Les fichiers .yaml : valeurs des clés 'Yaml file' dans les .pkl """
""" 1) - Dossier du graphe dans les backups :dossier-parent de tous les nodes du graphe. """
graph_path = os.path.normpath(f"{os.path.dirname(__file__).replace('show', 'backups')}/{self.graph_name}")
""" 2) - Liste des dossiers des nodes du graphe (qui contiennent des fichiers nécessaires aux calculs) """
l_folders = [graph_path] + [f'{graph_path}{os.sep}{node}' for node in os.listdir(graph_path) if
str(node).startswith('node')]
""" 3) - Liste des fichiers calc_*.pkl physiquement présents dans le dossier self.final_path """
l_watched_files = [os.path.normpath(f'{self.final_path}/{calc}') for calc in
os.listdir(self.final_path) if calc.startswith('calc_')]
""" 4) - Liste des fichiers .yaml : chaque od_calc (extrait du pkl) contient plusieurs clés 'Yaml file'.
On en fait une liste sans doublons. """
s_yaml = set() # set() au lieu de list() pour s'affranchir des doublons.
for path, folder, l_files in os.walk(graph_path):
[s_yaml.add(os.path.normpath(f'{path}/{file}')) for file in l_files if os.path.splitext(file)[1] == '.yaml']
""" 5) - Concaténation des listes précédentes. """
l_watched_files += list(s_yaml) # Concaténation de 2 listes de fichiers.
l_files = l_folders + l_watched_files # Concaténation de la liste des dossiers et de celle des fichiers.
""" 6) - Vérification des changements dans cette liste, mais non dans le contenu des fichiers. """
if self.l_files_ante != l_files:
self.l_files_ante = self.ut.deepcopy(l_files) # Mémorisation (copie profonde).
self.ut.watch_file(l_files, self.watch) # (Re)lancement de la surveillance.
self.watch(l_watched_files)
def watch(self, l_files):
files_only = [file for file in l_files if os.path.isfile(file)]
if len(files_only) == 0:
""" l_files ne contient que des dossiers : cela signifie que des fichiers ont été ajoutés ou supprimés. """
self.ini_watch()
return
""" Lecture de tous les calc_*.pkl (un par entrée) et écriture de leur contenu dans une liste. """
self.od_calc = Dictionary()
l_pkl = [(f'calc_{i}', os.path.normpath(f'{self.final_path}/calc_{i}.pkl')) for i in range(8)]
for name_input, pkl_file in l_pkl:
try:
with open(pkl_file, 'rb') as pk:
d_calc = pickle.load(pk)
self.od_calc.write(name_input, d_calc)
except (Exception,):
pass
""" Création ou update du super-dictionnaire self.od_yaml de matplotlib. """
self.o_yaml.set_yaml(self.od_calc)
""" La méthode self.update_figure() est chargée des mises à jour des calculs et des affichages. """
self.update_figure()
def update_figure(self):
""" Update suite aux modifications .pkl et .yaml """
l_inputs = [key for (key, val) in self.od_calc.items() if val['edges']] # Entrées actives seulement.
d_default_grid = self.get_default_grid(l_inputs) # Dictionnaire. Les clés sont 'calc_0', 'calc_1', etc.
""" 1 - Titre de la fenêtre. """
figure_title = self.od_calc.read(['calc_0', f'Node{self.node_id}', 'Fenêtre', 'Titre'], 'Graphiques')
local = ' - Mode local' if len(sys.argv) < 6 else ''
self.mgr.set_window_title(figure_title + local)
""" Exemple de compilation dynamique au niveau de la figure. """
# d_context = {'msg': 'Bonjour les codeurs !'}
# self.o_yaml.compile(['Figure', 'Code'], d_context)
# print(d_context['return_value'])
# print(d_context['error'])
""" Boucle sur les entrées du node afficheur. """
for name_input in l_inputs:
""" 2 - Serveur de signaux : Il s'agit du node connecté à cette entrée.
Création si inexistant de l'objet Calcul par compilation dynamique. """
od_calc = Dictionary(self.od_calc[name_input])
node_sid, num_input = self.get_server_node(od_calc)
""" 3 - Subplots : création, update, géométrie. """
pointer = self.ax[num_input].pointer if self.ax[num_input].__class__.__name__ == 'AxesSubplot' else 0
default_grid = [self.gridspec] + d_default_grid[name_input]
self.o_yaml.subplot2grid(plt, self.ax, num_input, default_grid) # Création ou update de self.ax[num_input]
ax = self.ax[num_input] # Copie par référence.
ax.pointer = pointer
""" 4 - Actualisation de la liste des courbes ax.lines. """
l_keys, l_keys_default = [f'Node{self.node_id}', f'Entrée {num_input}'], [f'Node{self.node_id}']
od_lines = Dictionary(od_calc.read(l_keys, od_calc.read(l_keys_default)))
self.update_lines(num_input, od_lines) # Suppressions et ajouts de courbes.
if node_sid is None:
continue
""" 5 - Délégation des calculs à l'objet o_calc. """
o_calc = self.lo_calc[num_input]
od_calc.write([node_sid, 'Taille buffer'], 100_000)
o_calc.create_values(node_sid, od_calc) # od_calc = dico entrée 0.
""" 6 - show_anim() a besoin de connaître les colonnes du tableau numpy qui contiennent les valeurs. """
indx = 0
l_key_lines = [key for (key, val) in od_lines.items() if isinstance(val, dict) and 'Signal actif' in val]
for key, val in o_calc.od_config.items():
if isinstance(val, dict) and val['actif'] and 'num_col' in val:
od_lines.write([l_key_lines[indx], 'num_col'], val['num_col'])
o_line = self.get_line(num_input, l_key_lines[indx])
if o_line is not None:
o_line.attr = od_lines.read(l_key_lines[indx])
indx += 1
""" 7 - Ajout d'attributs (o_calc et d_columns) à l'objet self.ax """
ax.o_calc = o_calc
ax.d_columns = {'Entrée': num_input}
""" 8 - Affichage - Pour chaque subplot : update des courbes avant leur traitement. """
for o_line in ax.lines: # Parcours des courbes de cette entrée de node.
""" Affectation des attributs aux courbes : couleur, épaisseur, style, légende. """
od_line = Dictionary(od_lines.read(o_line.name))
if not od_line:
continue
od_line.write('Entrée', f'Entrée {num_input}')
ax.d_columns[o_line.name] = od_line.read('num_col')
# https://matplotlib.org/stable/api/_as_gen/matplotlib.lines.Line2D.html
o_line.od = od_line # Création de l'attribut .od : Ajout du dictionnaire à l'objet o_line.
o_line.set_color(od_line.read('Couleur'))
o_line.set_linewidth(od_line.read('Épaisseur'))
o_line.set_linestyle(self.get_linestyle(od_line.read('Style')))
o_line.set_label(od_line.read('Légende'))
self.o_yaml.line_params(o_line) # Paramètres étendus pour cette courbe.
""" Exemple de compilation dynamique au niveau de la courbe 'o_line'. Décommenter si nécessaire. """
# d_context = {'line': o_line}
# self.o_yaml.compile([f'Entrée {num_input}', o_line.name, 'Code'], d_context)
""" 9 - Subplot : titre et légendes et autres attributs ... """
self.o_yaml.subplot_params(ax) # Paramètres étendus pour le subplot.
""" Exemple de compilation dynamique au niveau du subplot 'num_input'. Décommenter si nécessaire. """
# d_context = {'subplot': ax}
# self.o_yaml.compile([f'Entrée {num_input}', 'Code'], d_context)
title = f"gr {num_input} - {od_lines.read('Titre')}"
ax.title.set_text(title)
self.o_yaml.legend(self.ax, num_input)
self.o_yaml.labels(self.ax, num_input)
plt.draw() # Nécessaire lorsque l'affichage est en pause.
@staticmethod
def get_default_grid(l_inputs):
""" Le gridspec est de 12 x 12 cellules.
https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplot2grid.html#matplotlib.pyplot.subplot2grid
https://www.youtube.com/watch?v=OebyvmZo3w0 <- Sentdex
https://www.youtube.com/playlist?list=PLQVvvaa0QuDfefDfXb9Yf0la1fPDKluPF
"""
nb_inputs = len(l_inputs)
d_gs = dict()
if nb_inputs == 1: # Un seul subplot de 12 x 12.
d_gs[l_inputs[0]] = [(0, 0), 12, 12]
elif nb_inputs == 2: # 2 subplots empilés de 6 x 12 (6 lignes, 12 colonnes)
for i in range(nb_inputs):
d_gs[l_inputs[i]] = [(i * 6, 0), 6, 12]
elif nb_inputs == 3: # 3 subplots empilés de 4 x 12
for i in range(nb_inputs):
d_gs[l_inputs[i]] = [(i * 4, 0), 4, 12]
elif nb_inputs == 4: # 4 subplots de 6 x 6
for i in range(nb_inputs):
row = 6 * (i // 2) # 0, 0, 6, 6
col = 6 * (i % 2) # 0, 6, 0, 6
d_gs[l_inputs[i]] = [(row, col), 6, 6]
elif nb_inputs == 5: # 1 subplot de 4 x 12 au dessus de 4 subplots de 4 x 6
d_gs[l_inputs[0]] = [(0, 0), 4, 12]
for i in range(4):
row = 4 + 4 * (i // 2) # 4, 4, 8, 8
col = 6 * (i % 2) # 0, 6, 0, 6
d_gs[l_inputs[i+1]] = [(row, col), 4, 6]
elif nb_inputs == 6: # 6 subplots de 4 x 6
for i in range(nb_inputs):
row = 4 * (i // 2) # 0, 0, 4, 4, 8, 8
col = 6 * (i % 2) # 0, 6, 0, 6, 0, 6
d_gs[l_inputs[i]] = [(row, col), 4, 6]
elif nb_inputs == 7: # 1 subplot de 3 x 12 au dessus de 6 subplots de 3 x 6
d_gs[l_inputs[0]] = [(0, 0), 3, 12]
for i in range(6):
row = 3 + 3 * (i // 2) # 3, 3, 6, 6, 9, 9
col = 6 * (i % 2) # 0, 6, 0, 6, 0, 6
d_gs[l_inputs[i+1]] = [(row, col), 3, 6]
elif nb_inputs == 8: # 8 subplots de 3 x 6
for i in range(nb_inputs):
row = 3 * (i // 2) # 0, 0, 3, 3, 6, 6, 9, 9
col = 6 * (i % 2) # 0, 6, 0, 6, 0, 6, 0, 6
d_gs[l_inputs[i]] = [(row, col), 3, 6]
return d_gs
def remove_lines(self):
""" En cas d'absence de dictionnaire de calcul, on efface les courbes affichées. """
for num_input in range(8):
try:
l_lines = self.ax[num_input].lines[:]
for o_line in l_lines:
self.ax[num_input].lines.remove(o_line)
except AttributeError:
pass
plt.draw()
@staticmethod
def get_linestyle(param_style):
if param_style.startswith('___'):
return '-'
elif param_style.startswith('- -'):
return '--'
elif param_style.startswith('. .'):
return ':'
return '-.'
def update_lines(self, num_input, d_plots):
""" Actualisation de la liste de courbes self.ax[num_input].lines[].
On compare les listes de coubes nécessaires et de courbes existantes.
On en déduit celles qu'il faut ajouter, celles qu'il faut supprimer. """
""" 1) Courbes nécessaires : l_needed. """
l_needed = list()
for key, val in d_plots.items():
if isinstance(val, dict) and 'Signal actif' in val and val['Signal actif']:
l_needed.append(key)
""" 2) Courbes existantes : l_exist. """
l_exist = self.line_exist(num_input)
""" 3) Ajout (création) de courbes. """
for needed in l_needed:
if needed not in l_exist:
o_line, = self.ax[num_input].plot(np.empty(0)) # [num_input] = Élément 0 de la liste.
o_line.name = needed
""" 4) Suppression de courbes. """
for exist in l_exist:
if exist not in l_needed:
o_line = self.get_line(num_input, exist)
if o_line is not None:
self.ax[num_input].lines.remove(o_line)
def line_exist(self, num_input):
l_lines = list()
for line in self.ax[num_input].lines:
l_lines.append(line.name)
return l_lines
def get_line(self, num_input, line_name):
for o_line in self.ax[num_input].lines:
if o_line.name == line_name:
return o_line
return None
def get_server_node(self, od_calc):
"""
:param od_calc: Dictionnaire de l'entrée appelante.
:return: Tuple (Nom du node-serveur, Num entrée de moi-même (Node 'Plots')).
"""
s_edges = od_calc.read('edges', None) # Préfixe 's_' car les edges sont groupés dans un set().
""" Recherche du socket_out emetteur (directement connecté au socket_in de ce node 'Plots'). """
socket_from, socket_to = None, None
for edge in s_edges:
socket_to = edge[1]
if socket_to[0] == self.node_id:
socket_from = edge[0]
break
if socket_from is None or socket_to is None:
return None, None
node_sid = f'Node{socket_from[0]}'
num_input = socket_to[1]
if node_sid not in od_calc:
return None, None
if self.lo_calc[num_input] is not None:
""" Retour si l'objet o_calc existe déjà. """
return node_sid, num_input
""" Création de l'objet o_calc par compilation dynamique."""
compile_from = od_calc.read([node_sid, 'Compile from'], None)
d_context = {'yaml_file': od_calc.read([node_sid, 'Yaml file'])}
code = f'from {compile_from} import Calcul; o_calcul = Calcul(yaml_file)'
try:
code = compile(code, '<string>', 'exec')
eval(code, d_context)
o_calcul = d_context['o_calcul']
self.lo_calc[num_input] = o_calcul
return node_sid, num_input
except (Exception,):
print(f'Erreur de compilation dans {compile_from}')
return None, num_input
@property
def mgr(self):
return plt.get_current_fig_manager()
def listener(self):
""" 1 - Si le poste de contrôle est fermé => fin programme, sauf en mode autonome. """
if self.parent_pid > 0 and not psutil.pid_exists(self.parent_pid):
exit()
""" 2 - Persistance géométrie. """
geometry = self.get_real_geometry()
if self.geometry != geometry:
self.ut.save_state(self.mgr.window)
self.geometry = geometry
def get_real_geometry(self):
geom = self.mgr.window.geometry()
return geom.x(), geom.y(), geom.width(), geom.height()
def key_event(self, ev):
""" Appui sur une touche du clavier. """
keycode = ev.key
if keycode == ' ':
""" Pause on/off. """
self.b_paused = not self.b_paused
self.anim.stop() if self.b_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(3000, self.delay)
self.anim.start(int(self.delay))
if __name__ == '__main__':
sys.argv.append('Signaux') # Nom du graphe.
sys.argv.append('0') # 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()
file
au constructeur de Utils
.Utils.__init__()
:
def __init__(self, path='', file='params'):
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}{file}.conf", QSettings.IniFormat)
self.watcher = None
matplotlib_yaml.py > YamlParams
.YamlParams.subplot2grid(), YamlParams.legend(), YamlParams.labels()
:
def subplot2grid(self, plt, ax, num_input, default_grid):
grid = self.od_yaml.read(['Figure', 'Grille'], default_grid[0])
geometry = self.od_yaml.read([f'Entrée {num_input}', 'Géométrie'])
try:
grid = [grid] + [geometry[:2]] + geometry[2:]
ax[num_input] = plt.subplot2grid(*grid)
except (Exception,):
ax[num_input] = plt.subplot2grid(*default_grid)
def legend(self, ax, num_input):
""" https://matplotlib.org/stable/api/legend_api.html """
default = dict(loc='upper left', ncol=2, framealpha=.3, facecolor='#ffe')
d_legend = self.od_yaml.read([f'Entrée {num_input}', 'Légende'], default)
b_show = True
if 'show' in d_legend:
b_show = d_legend['show']
del d_legend['show']
if b_show:
try:
ax[num_input].legend(**d_legend).set_frame_on(True)
except (Exception,):
ax[num_input].legend(**default).set_frame_on(True)
def labels(self, ax, num_input):
try:
ax[num_input].set_xlabel(xlabel=self.od_yaml.read([f'Entrée {num_input}', 'xlabel']), loc='left')
ax[num_input].set_ylabel(self.od_yaml.read([f'Entrée {num_input}', 'ylabel']))
except (Exception,):
pass
yaml_parent.py > Yaml
: Une méthode modifiée, une méthode ajoutée.yaml_parent.py
:
from functions.utils import Dictionary
import yaml
import os
class YamlParent:
def __init__(self, yaml_file):
self.yaml_file = yaml_file
self.od_params = Dictionary()
self.od_yaml = Dictionary()
self.set_yaml()
def set_yaml(self, od_params=None):
""" Affectation de 2 membres : od_params et od_yaml. """
self.od_params = Dictionary() if od_params is None else od_params
try:
with open(self.yaml_file, 'r', encoding='utf-8') as yml:
self.od_yaml = Dictionary(yaml.safe_load(yml))
except (Exception,) as err:
if os.path.isfile(self.yaml_file):
print(f'Erreur dans le fichier {self.yaml_file}.\n{err}')
def compile(self, l_keys, d_context):
"""
Exemple de code appelant :
d_context = {'msg': 'Bonjour les codeurs !'}
self.o_yaml.compile(d_context)
print(d_context['return_value'])
Exemple de code dans le fichier Yaml :
Figure:
Code: |
print(f'Je suis dans le code compilé.\n{msg}')
return_value = 'Terminé.'
En cas d'erreur de compilation, celle-ci peut être lue dans d_context['error'].
"""
yaml_code = self.od_yaml.read(l_keys)
try:
code = compile(yaml_code, '<string>', 'exec')
eval(code, d_context)
d_context['error'] = "Pas d'erreur."
except (Exception,) as err:
d_context['error'] = f'Erreur :\n{err}'
Plots-0
, forcer la géométrie de l'entrée 0 seulement : [0, 1, 3, 4]Plots-0
, s'il y a des références à des signaux, par exemple dans fill between
, vérifier qu'elles soient en accord avec le graphe ci-dessus.
---
Fenêtre:
# Redémarrer pour la prise en compte des paramètres de la fenêtre.
# Styles disponibles, faire : [print(style) for style in plt.style.available]
# ['seaborn', 'Solarize_Light2', '_classic_test_patch', 'bmh', 'classic', 'dark_background', 'fast', ...]
style: dark_background
# Pour voir tous les paramètres disponibles, faire: Dictionary(rcParams).print()
# (Vérifier l'import : from matplotlib import rcParams)
rcParams:
toolbar: 'None' # 'None', 'toolbar2', 'toolmanager'
Figure:
Grille: [12, 12]
Code: |
# code python ici sur plusieurs lignes
# Exemple de code appelant :
# d_context = {'msg': 'Bonjour les codeurs !'}
# self.o_yaml.compile(d_context)
# valeur_de_retour = d_context['retour']
print(f'Je suis dans le code compilé.\n{msg}')
return_value = 'Terminé.' # Variable de retour.
Entrée 0:
Géométrie: [0, 1, 3, 4] # [N° ligne, N° col., Nb lignes, Nb cols.]
# |_ Grille de 12 x 12
Légende:
show: False
fill between: # 'x' au début : En changeant l'orthographe, la clé devient inactive.
lines:
- Signaux1-Sinus
# - 10
# - Signaux1-Triangle
- Signaux1-Cosinus
color: C0 # C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 - https://matplotlib.org/2.0.2/users/colors.html
Signaux1-Cosinus: # Lines2D : https://matplotlib.org/stable/api/_as_gen/matplotlib.lines.Line2D.html
alpha: .7
Entrée 1:
xlabel: 'Abscisse de gr1'
ylabel: 'Ordonnée de gr1'
Entrée 2:
# géométrie : [6, 12, 4, 8]
fill between:
lines:
- Signaux3-Triangle
- Signaux3-Cosinus
color: C7
Entrée 3:
# géométrie : [7, 7, 4, 5]
Légende:
show: False
Entrée 4:
xfill between:
lines:
- Signaux2-Triangle
- Signaux2-Cosinus
color: '#ff0' # C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 - https://matplotlib.org/2.0.2/users/colors.html
Entrée 5:
Légende:
show: False
ncol: 2
loc: 'upper left'
framealpha: 0
facecolor: '#ffe'
Entrée 6:
Entrée 7:
Légende:
show: False
Signaux
et de leur yaml
n'a pas d'importance.Voir
:
Nous voyons 7 graphiques car 7 entrées sont connectées.
7 entrées actives, 7 graphiques affichés : normal !
Signaux-3
:
4 entrées actives : 5 graphiques affichés : anormal !
Vérification
matplotlib_yaml.py
contient des méthodes telles que legend()
ou labels()
:
yaml
.YamlParent.compile()
Snippets
Bonjour les codeurs !