..
- Copyright (C) 2008-2015 EDF R&D
+ Copyright (C) 2008-2021 EDF R&D
This file is part of SALOME ADAO module.
Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
-.. _ref_observers_requirements:
+.. _section_ref_observers_requirements:
-Exigences pour les fonctions décrivant un "*observer*"
+Exigences pour les fonctions décrivant un "*observer*"
------------------------------------------------------
+.. index:: single: Observer
+.. index:: single: setObserver
+.. index:: single: Observer Template
+
+Certaines variables spéciales, internes à l'optimisation et utilisées au cours
+des calculs, peuvent être surveillées durant un calcul ADAO. Ces variables
+peuvent être affichées, tracées, enregistrées, etc. par l'utilisateur. C'est
+réalisable en utilisant des "*observer*", parfois aussi appelés des "callback"
+sur une variable. Ce sont des fonctions Python spéciales, qui sont chacune
+associées à une variable donnée, comme décrit conceptuellement dans la figure
+suivante :
+
+ .. ref_observer_simple:
+ .. image:: images/ref_observer_simple.png
+ :align: center
+ :width: 75%
+ .. centered::
+ **Définition conceptuelle d'une fonction "observer"**
+
+Ces fonctions "*observer*" sont décrites dans les sous-sections suivantes.
+
+Enregistrer et activer une fonction "*observer*"
+++++++++++++++++++++++++++++++++++++++++++++++++
+
+Dans l'interface graphique EFICAS d'ADAO, il y a 3 méthodes pratiques pour
+intégrer une fonction "*observer*" dans un cas ADAO. La méthode est choisie à
+l'aide du mot-clé "*NodeType*" de chaque entrée de type "*observer*", comme
+montré dans la figure qui suit :
+
+ .. eficas_observer_nodetype:
+ .. image:: images/eficas_observer_nodetype.png
+ :align: center
+ :width: 100%
+ .. centered::
+ **Choisir son type d'entrée pour une fonction "observer"**
+
+Une fonction "*observer*" peut être fourni sous la forme d'un script explicite
+(entrée de type "*String*"), d'un script contenu dans un fichier externe
+(entrée de type "*Script*"), ou en utilisant un modèle (entrée de type
+"*Template*") fourni par défaut dans ADAO lors de l'usage de l'éditeur
+graphique EFICAS d'ADAO et détaillé dans la partie
+:ref:`section_ref_observers_templates` qui suit. Ces derniers sont des scripts
+simples qui peuvent être adaptés par l'utilisateur, soit dans l'étape d'édition
+intégrée du cas avec EFICAS d'ADAO, soit dans l'étape d'édition du schéma avant
+l'exécution, pour améliorer la performance du calcul ADAO dans le superviseur
+d'exécution de SALOME.
+
+Dans l'interface textuelle (TUI) d'ADAO (voir la partie :ref:`section_tui`),
+les mêmes informations peuvent être données à l'aide de la commande
+"*setObserver*" appliquée pour une variable donnée indiquée en utilisant
+l'argument "*Variable*". Les autres arguments de cette commande permettent de
+définir un "*observer*" soit comme un template (argument "*Template*")
+désignant l'un des scripts détaillés dans la partie
+:ref:`section_ref_observers_templates`, soit comme un script explicite
+(argument "*String*"), soit comme un script contenu dans un fichier externe
+(argument "*Script*").
+
+Forme générale d'un script permettant de définir une fonction "*observer*"
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Une fonction "*observer*" est un script Python spécial, associé à une variable
+donnée, et qui est automatiquement activée à chaque modification de la variable
+lors du calcul. Chaque fonction (soigneusement établie) qui s'applique à la
+variable sélectionnée peut être utilisée. De nombreuses fonctions "*observer*"
+sont disponibles par défaut.
+
+Pour pouvoir utiliser directement cette capacité "*observer*", l'utilisateur
+doit utiliser ou construire un script utilisant en entrée standard (i.e.
+disponible dans l'espace de nommage) les variables ``var`` et ``info``. La
+variable ``var`` est à utiliser comme un objet de type liste/tuple, contenant
+l'historique de la variable d'intérêt, indicé par les pas d'itérations. Seul le
+corps de la fonction "*observer*" doit être spécifié par l'utilisateur, pas
+l'appel de fonction lui-même.
+
+A titre d'exemple, voici un script très simple (similaire au modèle
+"*ValuePrinter*"), utilisable pour afficher la valeur d'une variable
+surveillée::
+
+ print(" --->",info," Value =",var[-1])
+
+Stockées comme un fichier Python ou une chaîne de caractères explicite, ces
+lignes de script peuvent être associées à chaque variable présente dans le
+mot-clé "*SELECTION*" de la commande "*Observers*" du cas ADAO : "*Analysis*",
+"*CurrentState*", "*CostFunction*"... La valeur courante de la variable sera
+par exemple affichée à chaque étape de l'algorithme d'optimisation ou
+d'assimilation. Les "*observer*" peuvent inclure des capacités d'affichage
+graphique, de stockage, de traitement complexe, d'analyse statistique, etc. Si
+une variable, à laquelle est lié un "*observer*", n'est pas requise dans le
+calcul et par l'utilisateur, l'exécution de cet "*observer*" n'est tout
+simplement jamais activée.
+
+.. warning::
+ Si les modèles disponibles par défaut ne sont pas utilisés, il revient à
+ l'utilisateur de faire des scripts de fonctions soigneusement établis ou
+ des programmes externes qui ne se plantent pas avant d'être enregistrés
+ comme une fonction "*observer*". Le débogage peut sinon être vraiment
+ difficile !
+
+On donne ci-après l'identifiant et le contenu de tous les modèles "*observer*"
+disponibles.
+
+.. _section_ref_observers_templates:
+
+Inventaire des modèles de fonctions "*observer*" disponibles ("*Template*")
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+.. index:: single: ValuePrinter (Observer)
+
+Modèle **ValuePrinter** :
+.........................
+
+Imprime sur la sortie standard la valeur courante de la variable.
+
+::
+
+ print(str(info)+" "+str(var[-1]))
+
+.. index:: single: ValueAndIndexPrinter (Observer)
+
+Modèle **ValueAndIndexPrinter** :
+.................................
+
+Imprime sur la sortie standard la valeur courante de la variable, en ajoutant son index.
+
+::
+
+ print(str(info)+(" index %i:"%(len(var)-1))+" "+str(var[-1]))
+
+.. index:: single: ValueSeriePrinter (Observer)
+
+Modèle **ValueSeriePrinter** :
+..............................
+
+Imprime sur la sortie standard la série des valeurs de la variable.
+
+::
+
+ print(str(info)+" "+str(var[:]))
+
+.. index:: single: ValueSaver (Observer)
+
+Modèle **ValueSaver** :
+.......................
+
+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.
+
+::
+
+ import numpy, re
+ v=numpy.array(var[-1], ndmin=1)
+ global istep
+ try:
+ istep += 1
+ except:
+ istep = 0
+ f='/tmp/value_%s_%05i.txt'%(info,istep)
+ f=re.sub('\s','_',f)
+ print('Value saved in "%s"'%f)
+ numpy.savetxt(f,v)
+
+.. index:: single: ValueSerieSaver (Observer)
+
+Modèle **ValueSerieSaver** :
+............................
+
+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.
+
+::
+
+ import numpy, re
+ v=numpy.array(var[:], ndmin=1)
+ global istep
+ try:
+ istep += 1
+ except:
+ istep = 0
+ f='/tmp/value_%s_%05i.txt'%(info,istep)
+ f=re.sub('\s','_',f)
+ print('Value saved in "%s"'%f)
+ numpy.savetxt(f,v)
+
+.. index:: single: ValuePrinterAndSaver (Observer)
+
+Modèle **ValuePrinterAndSaver** :
+.................................
+
+Imprime sur la sortie standard et, en même temps enregistre dans un fichier du répertoire '/tmp', la valeur courante de la variable.
+
+::
+
+ import numpy, re
+ v=numpy.array(var[-1], ndmin=1)
+ print(str(info)+" "+str(v))
+ global istep
+ try:
+ istep += 1
+ except:
+ istep = 0
+ f='/tmp/value_%s_%05i.txt'%(info,istep)
+ f=re.sub('\s','_',f)
+ print('Value saved in "%s"'%f)
+ numpy.savetxt(f,v)
+
+.. index:: single: ValueIndexPrinterAndSaver (Observer)
+
+Modèle **ValueIndexPrinterAndSaver** :
+......................................
+
+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.
+
+::
+
+ import numpy, re
+ v=numpy.array(var[-1], ndmin=1)
+ print(str(info)+(" index %i:"%(len(var)-1))+" "+str(v))
+ global istep
+ try:
+ istep += 1
+ except:
+ istep = 0
+ f='/tmp/value_%s_%05i.txt'%(info,istep)
+ f=re.sub('\s','_',f)
+ print('Value saved in "%s"'%f)
+ numpy.savetxt(f,v)
+
+.. index:: single: ValueSeriePrinterAndSaver (Observer)
+
+Modèle **ValueSeriePrinterAndSaver** :
+......................................
+
+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.
+
+::
+
+ import numpy, re
+ v=numpy.array(var[:], ndmin=1)
+ print(str(info)+" "+str(v))
+ global istep
+ try:
+ istep += 1
+ except:
+ istep = 0
+ f='/tmp/value_%s_%05i.txt'%(info,istep)
+ f=re.sub('\s','_',f)
+ print('Value saved in "%s"'%f)
+ numpy.savetxt(f,v)
+
+.. index:: single: ValueGnuPlotter (Observer)
+
+Modèle **ValueGnuPlotter** :
+............................
+
+Affiche graphiquement avec Gnuplot la valeur courante de la variable.
+
+::
+
+ import numpy, Gnuplot
+ v=numpy.array(var[-1], ndmin=1)
+ global ifig, gp
+ try:
+ ifig += 1
+ gp(' set style data lines')
+ except:
+ ifig = 0
+ gp = Gnuplot.Gnuplot(persist=1)
+ gp(' set style data lines')
+ gp('set title "%s (Figure %i)"'%(info,ifig))
+ gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
+
+.. index:: single: ValueSerieGnuPlotter (Observer)
+
+Modèle **ValueSerieGnuPlotter** :
+.................................
+
+Affiche graphiquement avec Gnuplot la série des valeurs de la variable.
+
+::
+
+ import numpy, Gnuplot
+ v=numpy.array(var[:], ndmin=1)
+ global ifig, gp
+ try:
+ ifig += 1
+ gp(' set style data lines')
+ except:
+ ifig = 0
+ gp = Gnuplot.Gnuplot(persist=1)
+ gp(' set style data lines')
+ gp('set title "%s (Figure %i)"'%(info,ifig))
+ gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
+
+.. index:: single: ValuePrinterAndGnuPlotter (Observer)
+
+Modèle **ValuePrinterAndGnuPlotter** :
+......................................
+
+Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la valeur courante de la variable.
+
+::
+
+ print(str(info)+" "+str(var[-1]))
+ import numpy, Gnuplot
+ v=numpy.array(var[-1], ndmin=1)
+ global ifig,gp
+ try:
+ ifig += 1
+ gp(' set style data lines')
+ except:
+ ifig = 0
+ gp = Gnuplot.Gnuplot(persist=1)
+ gp(' set style data lines')
+ gp('set title "%s (Figure %i)"'%(info,ifig))
+ gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
+
+.. index:: single: ValueSeriePrinterAndGnuPlotter (Observer)
+
+Modèle **ValueSeriePrinterAndGnuPlotter** :
+...........................................
+
+Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la série des valeurs de la variable.
+
+::
+
+ print(str(info)+" "+str(var[:]))
+ import numpy, Gnuplot
+ v=numpy.array(var[:], ndmin=1)
+ global ifig,gp
+ try:
+ ifig += 1
+ gp(' set style data lines')
+ except:
+ ifig = 0
+ gp = Gnuplot.Gnuplot(persist=1)
+ gp(' set style data lines')
+ gp('set title "%s (Figure %i)"'%(info,ifig))
+ gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
+
+.. index:: single: ValuePrinterSaverAndGnuPlotter (Observer)
+
+Modèle **ValuePrinterSaverAndGnuPlotter** :
+...........................................
+
+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.
+
+::
+
+ print(str(info)+" "+str(var[-1]))
+ import numpy, re
+ v=numpy.array(var[-1], ndmin=1)
+ global istep
+ try:
+ istep += 1
+ except:
+ istep = 0
+ f='/tmp/value_%s_%05i.txt'%(info,istep)
+ f=re.sub('\s','_',f)
+ print('Value saved in "%s"'%f)
+ numpy.savetxt(f,v)
+ import Gnuplot
+ global ifig,gp
+ try:
+ ifig += 1
+ gp(' set style data lines')
+ except:
+ ifig = 0
+ gp = Gnuplot.Gnuplot(persist=1)
+ gp(' set style data lines')
+ gp('set title "%s (Figure %i)"'%(info,ifig))
+ gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
+
+.. index:: single: ValueSeriePrinterSaverAndGnuPlotter (Observer)
+
+Modèle **ValueSeriePrinterSaverAndGnuPlotter** :
+................................................
+
+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.
+
+::
+
+ print(str(info)+" "+str(var[:]))
+ import numpy, re
+ v=numpy.array(var[:], ndmin=1)
+ global istep
+ try:
+ istep += 1
+ except:
+ istep = 0
+ f='/tmp/value_%s_%05i.txt'%(info,istep)
+ f=re.sub('\s','_',f)
+ print('Value saved in "%s"'%f)
+ numpy.savetxt(f,v)
+ import Gnuplot
+ global ifig,gp
+ try:
+ ifig += 1
+ gp(' set style data lines')
+ except:
+ ifig = 0
+ gp = Gnuplot.Gnuplot(persist=1)
+ gp(' set style data lines')
+ gp('set title "%s (Figure %i)"'%(info,ifig))
+ gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
+
+.. index:: single: ValueMean (Observer)
+
+Modèle **ValueMean** :
+......................
+
+Imprime sur la sortie standard la moyenne de la valeur courante de la variable.
+
+::
+
+ import numpy
+ print(str(info)+" "+str(numpy.nanmean(var[-1])))
+
+.. index:: single: ValueStandardError (Observer)
+
+Modèle **ValueStandardError** :
+...............................
+
+Imprime sur la sortie standard l'écart-type de la valeur courante de la variable.
+
+::
+
+ import numpy
+ print(str(info)+" "+str(numpy.nanstd(var[-1])))
+
+.. index:: single: ValueVariance (Observer)
+
+Modèle **ValueVariance** :
+..........................
+
+Imprime sur la sortie standard la variance de la valeur courante de la variable.
+
+::
+
+ import numpy
+ print(str(info)+" "+str(numpy.nanvar(var[-1])))
+
+.. index:: single: ValueL2Norm (Observer)
+
+Modèle **ValueL2Norm** :
+........................
+
+Imprime sur la sortie standard la norme L2 de la valeur courante de la variable.
+
+::
+
+ import numpy
+ v = numpy.ravel( var[-1] )
+ print(str(info)+" "+str(float( numpy.linalg.norm(v) )))
+
+.. index:: single: ValueRMS (Observer)
+
+Modèle **ValueRMS** :
+.....................
+
+Imprime sur la sortie standard la racine de la moyenne des carrés (RMS), ou moyenne quadratique, de la valeur courante de la variable.
+
+::
+
+ import numpy
+ v = numpy.ravel( var[-1] )
+ print(str(info)+" "+str(float( numpy.sqrt((1./v.size)*numpy.dot(v,v)) )))