12.5. 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 :

_images/ref_observer_simple.png

Définition conceptuelle d’une fonction « observer »

Ces fonctions « observer » sont décrites dans les sous-sections suivantes.

12.5.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 :

_images/eficas_observer_nodetype.png

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 »). 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.5.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.5.3. Inventaire des modèles de fonctions « observer » disponibles (« Template »)

12.5.3.1. Modèle ValuePrinter

Imprime sur la sortie standard la valeur courante de la variable.

print(str(info)+" "+str(var[-1]))

12.5.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.5.3.3. Modèle ValueSeriePrinter

Imprime sur la sortie standard la série des valeurs de la variable.

print(str(info)+" "+str(var[:]))

12.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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)) )))