2 Copyright (C) 2008-2023 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]_, qui est une interface de
143 contrôle et transmission d'arguments à l'utilitaire classique de tracé
144 graphique Gnuplot [Gnuplot]_. Disponible sous la grande majorité des
145 environnements, ce dernier est indépendant et doit être correctement
146 préinstallé. Gnuplot.py est ici mis à jour pour supporter Python 3
148 On donne ci-après l'identifiant et le contenu de tous les modèles "*observer*"
151 .. _section_ref_observers_templates:
153 Inventaire des modèles de fonctions "*observer*" disponibles ("*Template*")
154 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
156 .. index:: single: ValuePrinter (Observer)
158 Modèle **ValuePrinter**
159 .......................
161 Imprime sur la sortie standard la valeur courante de la variable.
165 print(str(info)+" "+str(var[-1]))
167 .. index:: single: ValueAndIndexPrinter (Observer)
169 Modèle **ValueAndIndexPrinter**
170 ...............................
172 Imprime sur la sortie standard la valeur courante de la variable, en ajoutant son index.
176 print(str(info)+(" index %i:"%(len(var)-1))+" "+str(var[-1]))
178 .. index:: single: ValueSeriePrinter (Observer)
180 Modèle **ValueSeriePrinter**
181 ............................
183 Imprime sur la sortie standard la série des valeurs de la variable.
187 print(str(info)+" "+str(var[:]))
189 .. index:: single: ValueSaver (Observer)
191 Modèle **ValueSaver**
192 .....................
194 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.
199 v=numpy.array(var[-1], ndmin=1)
205 f='/tmp/value_%s_%05i.txt'%(info,istep)
207 print('Value saved in "%s"'%f)
210 .. index:: single: ValueSerieSaver (Observer)
212 Modèle **ValueSerieSaver**
213 ..........................
215 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.
220 v=numpy.array(var[:], ndmin=1)
226 f='/tmp/value_%s_%05i.txt'%(info,istep)
228 print('Value saved in "%s"'%f)
231 .. index:: single: ValuePrinterAndSaver (Observer)
233 Modèle **ValuePrinterAndSaver**
234 ...............................
236 Imprime sur la sortie standard et, en même temps enregistre dans un fichier du répertoire '/tmp', la valeur courante de la variable.
241 v=numpy.array(var[-1], ndmin=1)
242 print(str(info)+" "+str(v))
248 f='/tmp/value_%s_%05i.txt'%(info,istep)
250 print('Value saved in "%s"'%f)
253 .. index:: single: ValueIndexPrinterAndSaver (Observer)
255 Modèle **ValueIndexPrinterAndSaver**
256 ....................................
258 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.
263 v=numpy.array(var[-1], ndmin=1)
264 print(str(info)+(" index %i:"%(len(var)-1))+" "+str(v))
270 f='/tmp/value_%s_%05i.txt'%(info,istep)
272 print('Value saved in "%s"'%f)
275 .. index:: single: ValueSeriePrinterAndSaver (Observer)
277 Modèle **ValueSeriePrinterAndSaver**
278 ....................................
280 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.
285 v=numpy.array(var[:], ndmin=1)
286 print(str(info)+" "+str(v))
292 f='/tmp/value_%s_%05i.txt'%(info,istep)
294 print('Value saved in "%s"'%f)
297 .. index:: single: ValueGnuPlotter (Observer)
299 Modèle **ValueGnuPlotter**
300 ..........................
302 Affiche graphiquement avec Gnuplot la valeur courante de la variable.
306 import numpy, Gnuplot
307 v=numpy.array(var[-1], ndmin=1)
311 gp('set style data lines')
314 gp=Gnuplot.Gnuplot(persist=1)
315 gp('set style data lines')
316 gp('set title "%s (Figure %i)"'%(info,ifig))
317 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
319 .. index:: single: ValueSerieGnuPlotter (Observer)
321 Modèle **ValueSerieGnuPlotter**
322 ...............................
324 Affiche graphiquement avec Gnuplot la série des valeurs de la variable.
328 import numpy, Gnuplot
329 v=numpy.array(var[:], ndmin=1)
333 gp('set style data lines')
336 gp=Gnuplot.Gnuplot(persist=1)
337 gp('set style data lines')
338 gp('set title "%s (Figure %i)"'%(info,ifig))
339 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
341 .. index:: single: ValuePrinterAndGnuPlotter (Observer)
343 Modèle **ValuePrinterAndGnuPlotter**
344 ....................................
346 Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la valeur courante de la variable.
350 print(str(info)+' '+str(var[-1]))
351 import numpy, Gnuplot
352 v=numpy.array(var[-1], ndmin=1)
356 gp('set style data lines')
359 gp=Gnuplot.Gnuplot(persist=1)
360 gp('set style data lines')
361 gp('set title "%s (Figure %i)"'%(info,ifig))
362 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
364 .. index:: single: ValueSeriePrinterAndGnuPlotter (Observer)
366 Modèle **ValueSeriePrinterAndGnuPlotter**
367 .........................................
369 Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la série des valeurs de la variable.
373 print(str(info)+' '+str(var[:]))
374 import numpy, Gnuplot
375 v=numpy.array(var[:], ndmin=1)
379 gp('set style data lines')
382 gp=Gnuplot.Gnuplot(persist=1)
383 gp('set style data lines')
384 gp('set title "%s (Figure %i)"'%(info,ifig))
385 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
387 .. index:: single: ValuePrinterSaverAndGnuPlotter (Observer)
389 Modèle **ValuePrinterSaverAndGnuPlotter**
390 .........................................
392 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.
396 print(str(info)+' '+str(var[-1]))
398 v=numpy.array(var[-1], ndmin=1)
404 f='/tmp/value_%s_%05i.txt'%(info,istep)
406 print('Value saved in "%s"'%f)
412 gp('set style data lines')
415 gp=Gnuplot.Gnuplot(persist=1)
416 gp('set style data lines')
417 gp('set title "%s (Figure %i)"'%(info,ifig))
418 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
420 .. index:: single: ValueSeriePrinterSaverAndGnuPlotter (Observer)
422 Modèle **ValueSeriePrinterSaverAndGnuPlotter**
423 ..............................................
425 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.
429 print(str(info)+' '+str(var[:]))
431 v=numpy.array(var[:], ndmin=1)
437 f='/tmp/value_%s_%05i.txt'%(info,istep)
439 print('Value saved in "%s"'%f)
445 gp('set style data lines')
448 gp=Gnuplot.Gnuplot(persist=1)
449 gp('set style data lines')
450 gp('set title "%s (Figure %i)"'%(info,ifig))
451 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
453 .. index:: single: ValueMean (Observer)
458 Imprime sur la sortie standard la moyenne de la valeur courante de la variable.
463 print(str(info)+' '+str(numpy.nanmean(var[-1])))
465 .. index:: single: ValueStandardError (Observer)
467 Modèle **ValueStandardError**
468 .............................
470 Imprime sur la sortie standard l'écart-type de la valeur courante de la variable.
475 print(str(info)+' '+str(numpy.nanstd(var[-1])))
477 .. index:: single: ValueVariance (Observer)
479 Modèle **ValueVariance**
480 ........................
482 Imprime sur la sortie standard la variance de la valeur courante de la variable.
487 print(str(info)+' '+str(numpy.nanvar(var[-1])))
489 .. index:: single: ValueL2Norm (Observer)
491 Modèle **ValueL2Norm**
492 ......................
494 Imprime sur la sortie standard la norme L2 de la valeur courante de la variable.
499 v = numpy.ravel( var[-1] )
500 print(str(info)+' '+str(float( numpy.linalg.norm(v) )))
502 .. index:: single: ValueRMS (Observer)
507 Imprime sur la sortie standard la racine de la moyenne des carrés (RMS), ou moyenne quadratique, de la valeur courante de la variable.
512 v = numpy.ravel( var[-1] )
513 print(str(info)+' '+str(float( numpy.sqrt((1./v.size)*numpy.dot(v,v)) )))