12.4. Conditions requises pour les fonctions décrivant un « observer »¶
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 :
Ces fonctions « observer » sont décrites dans les sous-sections suivantes.
12.4.1. 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 :
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 »). Les modèles sont fournis par défaut dans ADAO, lors de l’usage de l’éditeur graphique EFICAS d’ADAO ou de l’interface TUI, et sont détaillés dans la partie Inventaire des modèles de fonctions « observer » disponibles (« Template ») 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 [DocR] Interface textuelle pour l’utilisateur (TUI/API)), 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 modèle (argument « Template ») désignant l’un des scripts détaillés dans la partie Inventaire des modèles de fonctions « observer » disponibles (« Template »), soit comme un script explicite (argument « String »), soit comme un script contenu dans un fichier externe (argument « Script »).
12.4.2. 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 et/ou de
temps. Seul le corps de la fonction « observer » doit être spécifié par
l’utilisateur, pas l’appel Python def
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, cette ou 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.
Avertissement
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 !
Certains « observer » permettent de créer des fichiers ou des figures
successives, qui sont numérotées de manière unique et, le cas échéant,
enregistrées par défaut dans le répertoire standard /tmp
. Dans le cas où
ces informations sont à modifier (comme par exemple lorsque le répertoire
/tmp
est un dossier virtuel ou local non pérenne, ou lorsque l’on désire
une numérotation en fonction de l’itération), l’utilisateur est invité à
s’inspirer d’un modèle lui convenant pour le modifier en spécifiant
différemment ces informations communes. Ensuite, la fonction modifiée peut être
utilisée dans une entrée de type « String » ou de type « Script ».
Note
Une partie des « observer » permet de créer des figures en utilisant le module Python intégré Gnuplot.py [Gnuplot.py], ici mis à jour pour supporter Python 3. Ce module est une interface de contrôle et de transmission d’arguments au remarquable utilitaire classique de tracé graphique Gnuplot [Gnuplot]. Disponible pour la grande majorité des environnements, ce dernier est indépendant et doit être correctement préinstallé.
On donne ci-après l’identifiant et le contenu de tous les modèles « observer » disponibles.
12.4.3. Inventaire des modèles de fonctions « observer » disponibles (« Template »)¶
12.4.3.1. Modèle ValuePrinter¶
Imprime sur la sortie standard la valeur courante de la variable.
print(str(info)+" "+str(var[-1]))
12.4.3.2. 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]))
12.4.3.3. Modèle ValueSeriePrinter¶
Imprime sur la sortie standard la série des valeurs de la variable.
print(str(info)+" "+str(var[:]))
12.4.3.4. 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(r'\s','_',f)
print('Value saved in "%s"'%f)
numpy.savetxt(f,v)
12.4.3.5. 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(r'\s','_',f)
print('Value saved in "%s"'%f)
numpy.savetxt(f,v)
12.4.3.6. 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(r'\s','_',f)
print('Value saved in "%s"'%f)
numpy.savetxt(f,v)
12.4.3.7. 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(r'\s','_',f)
print('Value saved in "%s"'%f)
numpy.savetxt(f,v)
12.4.3.8. 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(r'\s','_',f)
print('Value saved in "%s"'%f)
numpy.savetxt(f,v)
12.4.3.9. 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' ) )
12.4.3.10. 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' ) )
12.4.3.11. 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' ) )
12.4.3.12. 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' ) )
12.4.3.13. 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(r'\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' ) )
12.4.3.14. 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(r'\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' ) )
12.4.3.15. 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])))
12.4.3.16. 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])))
12.4.3.17. 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])))
12.4.3.18. 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) )))
12.4.3.19. 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)) )))