2 Copyright (C) 2008-2024 EDF R&D
4 This file is part of SALOME ADAO module.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
24 .. _section_ref_observers_requirements:
26 Conditions requises pour les fonctions décrivant un "*observer*"
27 ----------------------------------------------------------------
29 .. index:: single: Observer
30 .. index:: single: setObserver
31 .. index:: single: Observer Template
33 Certaines variables spéciales, internes à l'optimisation et utilisées au cours
34 des calculs, peuvent être surveillées durant un calcul ADAO. Ces variables
35 peuvent être affichées, tracées, enregistrées, etc. par l'utilisateur. C'est
36 réalisable en utilisant des "*observer*", parfois aussi appelés des "callback",
37 sur une variable. Ce sont des fonctions Python spéciales, qui sont chacune
38 associées à une variable donnée, comme décrit conceptuellement dans la figure
41 .. ref_observer_simple:
42 .. image:: images/ref_observer_simple.png
46 **Définition conceptuelle d'une fonction "observer"**
48 Ces fonctions "*observer*" sont décrites dans les sous-sections suivantes.
50 Enregistrer et activer une fonction "*observer*"
51 ++++++++++++++++++++++++++++++++++++++++++++++++
53 Dans l'interface graphique EFICAS d'ADAO, il y a 3 méthodes pratiques pour
54 intégrer une fonction "*observer*" dans un cas ADAO. La méthode est choisie à
55 l'aide du mot-clé "*NodeType*" de chaque entrée de type "*observer*", comme
56 montré dans la figure qui suit :
58 .. eficas_observer_nodetype:
59 .. image:: images/eficas_observer_nodetype.png
63 **Choisir son type d'entrée pour une fonction "observer"**
65 Une fonction "*observer*" peut être fourni sous la forme d'un script explicite
66 (entrée de type "*String*"), d'un script contenu dans un fichier externe
67 (entrée de type "*Script*"), ou en utilisant un modèle (entrée de type
68 "*Template*"). Les modèles sont fournis par défaut dans ADAO, lors de l'usage
69 de l'éditeur graphique EFICAS d'ADAO ou de l'interface TUI, et sont détaillés
70 dans la partie :ref:`section_ref_observers_templates` qui suit. Ces derniers
71 sont des scripts simples qui peuvent être adaptés par l'utilisateur, soit dans
72 l'étape d'édition intégrée du cas avec EFICAS d'ADAO, soit dans l'étape
73 d'édition du schéma avant l'exécution, pour améliorer la performance du calcul
74 ADAO dans le superviseur d'exécution de SALOME.
76 Dans l'interface textuelle (TUI) d'ADAO (voir la partie :ref:`section_tui`),
77 les mêmes informations peuvent être données à l'aide de la commande
78 "*setObserver*" appliquée pour une variable donnée indiquée en utilisant
79 l'argument "*Variable*". Les autres arguments de cette commande permettent de
80 définir un "*observer*" soit comme un modèle (argument "*Template*") désignant
81 l'un des scripts détaillés dans la partie
82 :ref:`section_ref_observers_templates`, soit comme un script explicite
83 (argument "*String*"), soit comme un script contenu dans un fichier externe
84 (argument "*Script*").
86 Forme générale d'un script permettant de définir une fonction "*observer*"
87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
89 Une fonction "*observer*" est un script Python spécial, associé à une variable
90 donnée, et qui est automatiquement activée à chaque modification de la variable
91 lors du calcul. Chaque fonction (soigneusement établie) qui s'applique à la
92 variable sélectionnée peut être utilisée. De nombreuses fonctions "*observer*"
93 sont disponibles par défaut.
95 Pour pouvoir utiliser directement cette capacité "*observer*", l'utilisateur
96 doit utiliser ou construire un script utilisant en entrée standard (i.e.
97 disponible dans l'espace de nommage) les variables ``var`` et ``info``. La
98 variable ``var`` est à utiliser comme un objet de type liste/tuple, contenant
99 l'historique de la variable d'intérêt, indicé par les pas d'itérations et/ou de
100 temps. Seul le corps de la fonction "*observer*" doit être spécifié par
101 l'utilisateur, pas l'appel Python ``def`` de fonction lui-même.
103 A titre d'exemple, voici un script très simple (similaire au modèle
104 "*ValuePrinter*"), utilisable pour afficher la valeur d'une variable
108 print(" --->",info," Value =",var[-1])
110 Stockées comme un fichier Python ou une chaîne de caractères explicite, cette
111 ou ces lignes de script peuvent être associées à chaque variable présente dans
112 le mot-clé "*SELECTION*" de la commande "*Observers*" du cas ADAO :
113 "*Analysis*", "*CurrentState*", "*CostFunction*"... La valeur courante de la
114 variable sera par exemple affichée à chaque étape de l'algorithme
115 d'optimisation ou d'assimilation. Les "*observer*" peuvent inclure des
116 capacités d'affichage graphique, de stockage, de traitement complexe, d'analyse
117 statistique, etc. Si une variable, à laquelle est lié un "*observer*", n'est
118 pas requise dans le calcul et par l'utilisateur, l'exécution de cet
119 "*observer*" n'est tout simplement jamais activée.
123 Si les modèles disponibles par défaut ne sont pas utilisés, il revient à
124 l'utilisateur de faire des scripts de fonctions soigneusement établis ou
125 des programmes externes qui ne se plantent pas avant d'être enregistrés
126 comme une fonction "*observer*". Le débogage peut sinon être vraiment
129 Certains "*observer*" permettent de créer des fichiers ou des figures
130 successives, qui sont numérotées de manière unique et, le cas échéant,
131 enregistrées par défaut dans le répertoire standard ``/tmp``. Dans le cas où
132 ces informations sont à modifier (comme par exemple lorsque le répertoire
133 ``/tmp`` est un dossier virtuel ou local non pérenne, ou lorsque l'on désire
134 une numérotation en fonction de l'itération), l'utilisateur est invité à
135 s'inspirer d'un modèle lui convenant pour le modifier en spécifiant
136 différemment ces informations communes. Ensuite, la fonction modifiée peut être
137 utilisée dans une entrée de type "*String*" ou de type "*Script*".
141 Une partie des "*observer*" permet de créer des figures en utilisant le
142 module Python intégré Gnuplot.py [Gnuplot.py]_, ici mis à jour pour
143 supporter Python 3. Ce module est une interface de contrôle et de
144 transmission d'arguments au remarquable utilitaire classique de tracé
145 graphique Gnuplot [Gnuplot]_. Disponible pour la grande majorité des
146 environnements, ce dernier est indépendant et doit être correctement
149 On donne ci-après l'identifiant et le contenu de tous les modèles "*observer*"
152 .. _section_ref_observers_templates:
154 Inventaire des modèles de fonctions "*observer*" disponibles ("*Template*")
155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
157 .. index:: single: ValuePrinter (Observer)
159 Modèle **ValuePrinter**
160 .......................
162 Imprime sur la sortie standard la valeur courante de la variable.
166 print(str(info)+" "+str(var[-1]))
168 .. index:: single: ValueAndIndexPrinter (Observer)
170 Modèle **ValueAndIndexPrinter**
171 ...............................
173 Imprime sur la sortie standard la valeur courante de la variable, en ajoutant son index.
177 print(str(info)+(" index %i:"%(len(var)-1))+" "+str(var[-1]))
179 .. index:: single: ValueSeriePrinter (Observer)
181 Modèle **ValueSeriePrinter**
182 ............................
184 Imprime sur la sortie standard la série des valeurs de la variable.
188 print(str(info)+" "+str(var[:]))
190 .. index:: single: ValueSaver (Observer)
192 Modèle **ValueSaver**
193 .....................
195 Enregistre la valeur courante de la variable dans un fichier du répertoire '/tmp' nommé 'value...txt' selon le nom de la variable et l'étape d'enregistrement.
200 v=numpy.array(var[-1], ndmin=1)
206 f='/tmp/value_%s_%05i.txt'%(info,istep)
207 f=re.sub(r'\s','_',f)
208 print('Value saved in "%s"'%f)
211 .. index:: single: ValueSerieSaver (Observer)
213 Modèle **ValueSerieSaver**
214 ..........................
216 Enregistre la série des valeurs de la variable dans un fichier du répertoire '/tmp' nommé 'value...txt' selon le nom de la variable et l'étape.
221 v=numpy.array(var[:], ndmin=1)
227 f='/tmp/value_%s_%05i.txt'%(info,istep)
228 f=re.sub(r'\s','_',f)
229 print('Value saved in "%s"'%f)
232 .. index:: single: ValuePrinterAndSaver (Observer)
234 Modèle **ValuePrinterAndSaver**
235 ...............................
237 Imprime sur la sortie standard et, en même temps enregistre dans un fichier du répertoire '/tmp', la valeur courante de la variable.
242 v=numpy.array(var[-1], ndmin=1)
243 print(str(info)+" "+str(v))
249 f='/tmp/value_%s_%05i.txt'%(info,istep)
250 f=re.sub(r'\s','_',f)
251 print('Value saved in "%s"'%f)
254 .. index:: single: ValueIndexPrinterAndSaver (Observer)
256 Modèle **ValueIndexPrinterAndSaver**
257 ....................................
259 Imprime sur la sortie standard et, en même temps enregistre dans un fichier du répertoire '/tmp', la valeur courante de la variable, en ajoutant son index.
264 v=numpy.array(var[-1], ndmin=1)
265 print(str(info)+(" index %i:"%(len(var)-1))+" "+str(v))
271 f='/tmp/value_%s_%05i.txt'%(info,istep)
272 f=re.sub(r'\s','_',f)
273 print('Value saved in "%s"'%f)
276 .. index:: single: ValueSeriePrinterAndSaver (Observer)
278 Modèle **ValueSeriePrinterAndSaver**
279 ....................................
281 Imprime sur la sortie standard et, en même temps, enregistre dans un fichier du répertoire '/tmp', la série des valeurs de la variable.
286 v=numpy.array(var[:], ndmin=1)
287 print(str(info)+" "+str(v))
293 f='/tmp/value_%s_%05i.txt'%(info,istep)
294 f=re.sub(r'\s','_',f)
295 print('Value saved in "%s"'%f)
298 .. index:: single: ValueGnuPlotter (Observer)
300 Modèle **ValueGnuPlotter**
301 ..........................
303 Affiche graphiquement avec Gnuplot la valeur courante de la variable (affichage persistant).
307 import numpy, Gnuplot
308 v=numpy.array(var[-1], ndmin=1)
312 gp('set title "%s (Figure %i)"'%(info,igfig))
315 gp=Gnuplot.Gnuplot(persist=1)
316 gp('set title "%s (Figure %i)"'%(info,igfig))
317 gp('set style data lines')
318 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
320 .. index:: single: ValueSerieGnuPlotter (Observer)
322 Modèle **ValueSerieGnuPlotter**
323 ...............................
325 Affiche graphiquement avec Gnuplot la série des valeurs de la variable (affichage persistant).
329 import numpy, Gnuplot
330 v=numpy.array(var[:], ndmin=1)
334 gp('set title "%s (Figure %i)"'%(info,igfig))
337 gp=Gnuplot.Gnuplot(persist=1)
338 gp('set title "%s (Figure %i)"'%(info,igfig))
339 gp('set style data lines')
340 gp('set xlabel "Step"')
341 gp('set ylabel "Variable"')
342 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
344 .. index:: single: ValuePrinterAndGnuPlotter (Observer)
346 Modèle **ValuePrinterAndGnuPlotter**
347 ....................................
349 Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la valeur courante de la variable (affichage persistant).
353 print(str(info)+' '+str(var[-1]))
354 import numpy, Gnuplot
355 v=numpy.array(var[-1], ndmin=1)
359 gp('set title "%s (Figure %i)"'%(info,igfig))
362 gp=Gnuplot.Gnuplot(persist=1)
363 gp('set title "%s (Figure %i)"'%(info,igfig))
364 gp('set style data lines')
365 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
367 .. index:: single: ValueSeriePrinterAndGnuPlotter (Observer)
369 Modèle **ValueSeriePrinterAndGnuPlotter**
370 .........................................
372 Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la série des valeurs de la variable (affichage persistant).
376 print(str(info)+' '+str(var[:]))
377 import numpy, Gnuplot
378 v=numpy.array(var[:], ndmin=1)
382 gp('set title "%s (Figure %i)"'%(info,igfig))
385 gp=Gnuplot.Gnuplot(persist=1)
386 gp('set title "%s (Figure %i)"'%(info,igfig))
387 gp('set style data lines')
388 gp('set xlabel "Step"')
389 gp('set ylabel "Variable"')
390 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
392 .. index:: single: ValuePrinterSaverAndGnuPlotter (Observer)
394 Modèle **ValuePrinterSaverAndGnuPlotter**
395 .........................................
397 Imprime sur la sortie standard et, en même temps, enregistre dans un fichier du répertoire '/tmp' et affiche graphiquement la valeur courante de la variable (affichage persistant).
401 print(str(info)+' '+str(var[-1]))
403 v=numpy.array(var[-1], ndmin=1)
409 f='/tmp/value_%s_%05i.txt'%(info,istep)
410 f=re.sub(r'\s','_',f)
411 print('Value saved in "%s"'%f)
417 gp('set title "%s (Figure %i)"'%(info,igfig))
420 gp=Gnuplot.Gnuplot(persist=1)
421 gp('set title "%s (Figure %i)"'%(info,igfig))
422 gp('set style data lines')
423 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
425 .. index:: single: ValueSeriePrinterSaverAndGnuPlotter (Observer)
427 Modèle **ValueSeriePrinterSaverAndGnuPlotter**
428 ..............................................
430 Imprime sur la sortie standard et, en même temps, enregistre dans un fichier du répertoire '/tmp' et affiche graphiquement la série des valeurs de la variable (affichage persistant).
434 print(str(info)+' '+str(var[:]))
436 v=numpy.array(var[:], ndmin=1)
442 f='/tmp/value_%s_%05i.txt'%(info,istep)
443 f=re.sub(r'\s','_',f)
444 print('Value saved in "%s"'%f)
450 gp('set title "%s (Figure %i)"'%(info,igfig))
453 gp=Gnuplot.Gnuplot(persist=1)
454 gp('set title "%s (Figure %i)"'%(info,igfig))
455 gp('set style data lines')
456 gp('set xlabel "Step"')
457 gp('set ylabel "Variable"')
458 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
460 .. index:: single: ValueMatPlotter (Observer)
462 Modèle **ValueMatPlotter**
463 ..........................
465 Affiche graphiquement avec Matplolib la valeur courante de la variable (affichage non persistant).
470 import matplotlib.pyplot as plt
471 v=numpy.array(var[-1], ndmin=1)
476 mp.suptitle('%s (Figure %i)'%(info,imfig))
480 ax = mp.add_subplot(1, 1, 1)
481 mp.suptitle('%s (Figure %i)'%(info,imfig))
485 .. index:: single: ValueMatPlotterSaver (Observer)
487 Modèle **ValueMatPlotterSaver**
488 ...............................
490 Affiche graphiquement avec Matplolib la valeur courante de la variable, et enregistre la figure dans un fichier du répertoire '/tmp' (figure persistante).
495 import matplotlib.pyplot as plt
496 v=numpy.array(var[-1], ndmin=1)
501 mp.suptitle('%s (Figure %i)'%(info,imfig))
505 ax = mp.add_subplot(1, 1, 1)
506 mp.suptitle('%s (Figure %i)'%(info,imfig))
508 f='/tmp/figure_%s_%05i.pdf'%(info,imfig)
509 f=re.sub(r'\s','_',f)
513 .. index:: single: ValueSerieMatPlotter (Observer)
515 Modèle **ValueSerieMatPlotter**
516 ...............................
518 Affiche graphiquement avec Matplolib la série des valeurs de la variable (affichage non persistant).
523 import matplotlib.pyplot as plt
524 v=numpy.array(var[:], ndmin=1)
529 mp.suptitle('%s (Figure %i)'%(info,imfig))
533 ax = mp.add_subplot(1, 1, 1)
534 mp.suptitle('%s (Figure %i)'%(info,imfig))
535 ax.set_xlabel('Step')
536 ax.set_ylabel('Variable')
540 .. index:: single: ValueSerieMatPlotterSaver (Observer)
542 Modèle **ValueSerieMatPlotterSaver**
543 ....................................
545 Affiche graphiquement avec Matplolib la série des valeurs de la variable, et enregistre la figure dans un fichier du répertoire '/tmp' (figure persistante).
550 import matplotlib.pyplot as plt
551 v=numpy.array(var[:], ndmin=1)
556 mp.suptitle('%s (Figure %i)'%(info,imfig))
560 ax = mp.add_subplot(1, 1, 1)
561 mp.suptitle('%s (Figure %i)'%(info,imfig))
562 ax.set_xlabel('Step')
563 ax.set_ylabel('Variable')
565 f='/tmp/figure_%s_%05i.pdf'%(info,imfig)
566 f=re.sub(r'\s','_',f)
570 .. index:: single: ValuePrinterAndMatPlotter (Observer)
572 Modèle **ValuePrinterAndMatPlotter**
573 ....................................
575 Affiche graphiquement avec Matplolib la valeur courante de la variable (affichage non persistant).
579 print(str(info)+' '+str(var[-1]))
581 import matplotlib.pyplot as plt
582 v=numpy.array(var[-1], ndmin=1)
587 mp.suptitle('%s (Figure %i)'%(info,imfig))
591 ax = mp.add_subplot(1, 1, 1)
592 mp.suptitle('%s (Figure %i)'%(info,imfig))
596 .. index:: single: ValuePrinterAndMatPlotterSaver (Observer)
598 Modèle **ValuePrinterAndMatPlotterSaver**
599 .........................................
601 Affiche graphiquement avec Matplolib la valeur courante de la variable, et enregistre la figure dans un fichier du répertoire '/tmp' (figure persistante).
605 print(str(info)+' '+str(var[-1]))
607 import matplotlib.pyplot as plt
608 v=numpy.array(var[-1], ndmin=1)
613 mp.suptitle('%s (Figure %i)'%(info,imfig))
617 ax = mp.add_subplot(1, 1, 1)
618 mp.suptitle('%s (Figure %i)'%(info,imfig))
620 f='/tmp/figure_%s_%05i.pdf'%(info,imfig)
621 f=re.sub(r'\s','_',f)
625 .. index:: single: ValueSeriePrinterAndMatPlotter (Observer)
627 Modèle **ValueSeriePrinterAndMatPlotter**
628 .........................................
630 Affiche graphiquement avec Matplolib la série des valeurs de la variable (affichage non persistant).
634 print(str(info)+' '+str(var[:]))
636 import matplotlib.pyplot as plt
637 v=numpy.array(var[:], ndmin=1)
642 mp.suptitle('%s (Figure %i)'%(info,imfig))
646 ax = mp.add_subplot(1, 1, 1)
647 mp.suptitle('%s (Figure %i)'%(info,imfig))
648 ax.set_xlabel('Step')
649 ax.set_ylabel('Variable')
653 .. index:: single: ValueSeriePrinterAndMatPlotterSaver (Observer)
655 Modèle **ValueSeriePrinterAndMatPlotterSaver**
656 ..............................................
658 Affiche graphiquement avec Matplolib la série des valeurs de la variable, et enregistre la figure dans un fichier du répertoire '/tmp' (figure persistante).
662 print(str(info)+' '+str(var[:]))
664 import matplotlib.pyplot as plt
665 v=numpy.array(var[:], ndmin=1)
670 mp.suptitle('%s (Figure %i)'%(info,imfig))
674 ax = mp.add_subplot(1, 1, 1)
675 mp.suptitle('%s (Figure %i)'%(info,imfig))
676 ax.set_xlabel('Step')
677 ax.set_ylabel('Variable')
679 f='/tmp/figure_%s_%05i.pdf'%(info,imfig)
680 f=re.sub(r'\s','_',f)
684 .. index:: single: ValueMean (Observer)
689 Imprime sur la sortie standard la moyenne de la valeur courante de la variable.
694 print(str(info)+' '+str(numpy.nanmean(var[-1])))
696 .. index:: single: ValueStandardError (Observer)
698 Modèle **ValueStandardError**
699 .............................
701 Imprime sur la sortie standard l'écart-type de la valeur courante de la variable.
706 print(str(info)+' '+str(numpy.nanstd(var[-1])))
708 .. index:: single: ValueVariance (Observer)
710 Modèle **ValueVariance**
711 ........................
713 Imprime sur la sortie standard la variance de la valeur courante de la variable.
718 print(str(info)+' '+str(numpy.nanvar(var[-1])))
720 .. index:: single: ValueL2Norm (Observer)
722 Modèle **ValueL2Norm**
723 ......................
725 Imprime sur la sortie standard la norme L2 de la valeur courante de la variable.
730 v = numpy.ravel( var[-1] )
731 print(str(info)+' '+str(float( numpy.linalg.norm(v) )))
733 .. index:: single: ValueRMS (Observer)
738 Imprime sur la sortie standard la racine de la moyenne des carrés (RMS), ou moyenne quadratique, de la valeur courante de la variable.
743 v = numpy.ravel( var[-1] )
744 print(str(info)+' '+str(float( numpy.sqrt((1./v.size)*numpy.dot(v,v)) )))