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 Requirements for functions describing an "*observer*"
27 -----------------------------------------------------
29 .. index:: single: Observer
30 .. index:: single: setObserver
31 .. index:: single: Observer Template
33 Some special variables, internal to the optimization process and used inside
34 calculation, can be monitored during an ADAO calculation. These variables can
35 be printed, plotted, saved, etc. by the user. This can be done using some
36 "*observer*", sometimes also called "callback", on a variable. They are special
37 Python functions, each one associated with a given variable, as conceptually
38 described in the following figure:
40 .. ref_observer_simple:
41 .. image:: images/ref_observer_simple.png
45 **Conceptual definition of an "observer" function**
47 These "*observer*" functions are described in the next subsections.
49 Register and activate of an "*observer*" function
50 +++++++++++++++++++++++++++++++++++++++++++++++++
52 In the graphical interface EFICAS of ADAO, there are 3 practical methods to
53 provide an "*observer*" function in an ADAO case. The method is chosen with the
54 "*NodeType*" keyword of each "*observer*" entry type, as shown in the following
57 .. eficas_observer_nodetype:
58 .. image:: images/eficas_observer_nodetype.png
62 **Choosing its entry type for an "observer" function**
64 An "*observer*" function can be given as an explicit script (entry of type
65 "*String*"), as a script in an external file (entry of type "*Script*"), or by
66 using a template or pattern (entry of type"*Template*"). The templates are
67 available by default in ADAO, using the graphical interface EFICAS or the text
68 interface TUI, and are detailed in the following
69 :ref:`section_ref_observers_templates`. These templates are simple scripts that
70 can be tuned by the user, either in the integrated edition stage of the case
71 with ADAO EFICAS, or in the edition stage of the schema before execution, to
72 improve the ADAO case performance in the SALOME execution supervisor YACS.
74 In the textual interface (TUI) of ADAO (see the part :ref:`section_tui`), the
75 same information can be given with the command "*setObserver*" applied to a
76 specific variable indicated using the "*Variable*" argument. The other
77 arguments of this command allow to define an "*observer*" either as a template
78 ("*Template*" argument) representing one of the scripts detailed in the part
79 :ref:`section_ref_observers_templates`, or as an explicit script ("*String*"
80 argument), or as a script in an external file ("*Script*" argument).
82 General form for a script describing an "*observer*" function
83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
85 An "*observer*" function is a special Python script, associated with a given
86 variable, and that is automatically activated for each variable modification
87 during calculation. Every (carefully established) function that applies to the
88 selected variable can be used. Many "*observer*" functions are available by
91 To use directly this "*observer*" capability, the user must use or build a
92 script that have on standard input (that is, in the naming space) the variables
93 ``var`` and ``info``. The variable ``var`` is to be used as an object of
94 list/tuple type, that contains the history of the variable of interest, indexed
95 by the iterating and/or time steps. Only the body of the "*observer*" function
96 has to be specified by the user, not the Python ``def`` function call itself.
98 As an example, here is a very simple script (similar to the "*ValuePrinter*"
99 template), that can be used to print the value of the monitored variable::
101 print(" --->",info," Value =",var[-1])
103 Stored as a Python file or as an explicit string, this or these script lines
104 can be associated to each variable found in the keyword "*SELECTION*" of the
105 "*Observers*" command of the ADAO case: "*Analysis*", "*CurrentState*",
106 "*CostFunction*"... The current value of the variable will for example be
107 printed at each step of the optimization or data assimilation algorithm. The
108 "*observer*" can include graphical output, storage capacities, complex
109 treatment, statistical analysis, etc. If the variable, to which the
110 "*observer*" is linked, is not required in the calculation and by the user, the
111 execution of this "*observer*" is simply never activated.
115 If not using the default available templates, it is up to the user to make
116 carefully established function scripts or external programs that do not
117 crash before being registered as an "*observer*" function. The debugging
118 can otherwise be really difficult!
120 Some "*observer*" allow the creation of successive files or figures, which are
121 uniquely numbered and, if applicable, stored by default in the standard
122 ``/tmp`` directory. In the case where this information needs to be modified (as
123 for example when the ``/tmp`` directory is a virtual or local non-permanent
124 folder, or when one wishes to have a numbering according to the iteration), the
125 user is encouraged to take inspiration from a model that is suitable for him
126 and to modify it by specifying differently this shared information. Then, the
127 modified function can be used in a "*String*" or "*Script*" input.
131 Some of the "observers" allow to create figures using the built-in Python
132 module Gnuplot.py [Gnuplot.py]_, here updated to support Python 3. This
133 module is an interface to control and to send arguments to the outstanding
134 classic utility for graphic plotting Gnuplot [Gnuplot]_. Available for most
135 environments, Gnuplot is independent and must be correctly preinstalled.
137 Hereinafter we give the identifier and the contents of all the available
140 .. _section_ref_observers_templates:
142 Inventory of available "*observer*" function models ("*Template*")
143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
145 .. index:: single: ValuePrinter (Observer)
147 Template **ValuePrinter**
148 .........................
150 Print on standard output the current value of the variable.
154 print(str(info)+" "+str(var[-1]))
156 .. index:: single: ValueAndIndexPrinter (Observer)
158 Template **ValueAndIndexPrinter**
159 .................................
161 Print on standard output the current value of the variable, adding its index.
165 print(str(info)+(" index %i:"%(len(var)-1))+" "+str(var[-1]))
167 .. index:: single: ValueSeriePrinter (Observer)
169 Template **ValueSeriePrinter**
170 ..............................
172 Print on standard output the value series of the variable.
176 print(str(info)+" "+str(var[:]))
178 .. index:: single: ValueSaver (Observer)
180 Template **ValueSaver**
181 .......................
183 Save the current value of the variable in a file of the '/tmp' directory named 'value...txt' from the variable name and the saving step.
188 v=numpy.array(var[-1], ndmin=1)
194 f='/tmp/value_%s_%05i.txt'%(info,istep)
195 f=re.sub(r'\s','_',f)
196 print('Value saved in "%s"'%f)
199 .. index:: single: ValueSerieSaver (Observer)
201 Template **ValueSerieSaver**
202 ............................
204 Save the value series of the variable in a file of the '/tmp' directory named 'value...txt' from the variable name and the saving step.
209 v=numpy.array(var[:], ndmin=1)
215 f='/tmp/value_%s_%05i.txt'%(info,istep)
216 f=re.sub(r'\s','_',f)
217 print('Value saved in "%s"'%f)
220 .. index:: single: ValuePrinterAndSaver (Observer)
222 Template **ValuePrinterAndSaver**
223 .................................
225 Print on standard output and, in the same time save in a file of the '/tmp' directory, the current value of the variable.
230 v=numpy.array(var[-1], ndmin=1)
231 print(str(info)+" "+str(v))
237 f='/tmp/value_%s_%05i.txt'%(info,istep)
238 f=re.sub(r'\s','_',f)
239 print('Value saved in "%s"'%f)
242 .. index:: single: ValueIndexPrinterAndSaver (Observer)
244 Template **ValueIndexPrinterAndSaver**
245 ......................................
247 Print on standard output and, in the same time save in a file of the '/tmp' directory, the current value of the variable, adding its index.
252 v=numpy.array(var[-1], ndmin=1)
253 print(str(info)+(" index %i:"%(len(var)-1))+" "+str(v))
259 f='/tmp/value_%s_%05i.txt'%(info,istep)
260 f=re.sub(r'\s','_',f)
261 print('Value saved in "%s"'%f)
264 .. index:: single: ValueSeriePrinterAndSaver (Observer)
266 Template **ValueSeriePrinterAndSaver**
267 ......................................
269 Print on standard output and, in the same time, save in a file of the '/tmp' directory, the value series of the variable.
274 v=numpy.array(var[:], ndmin=1)
275 print(str(info)+" "+str(v))
281 f='/tmp/value_%s_%05i.txt'%(info,istep)
282 f=re.sub(r'\s','_',f)
283 print('Value saved in "%s"'%f)
286 .. index:: single: ValueGnuPlotter (Observer)
288 Template **ValueGnuPlotter**
289 ............................
291 Graphically plot with Gnuplot the current value of the variable (persistent plot).
295 import numpy, Gnuplot
296 v=numpy.array(var[-1], ndmin=1)
300 gp('set title "%s (Figure %i)"'%(info,igfig))
303 gp=Gnuplot.Gnuplot(persist=1)
304 gp('set title "%s (Figure %i)"'%(info,igfig))
305 gp('set style data lines')
306 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
308 .. index:: single: ValueSerieGnuPlotter (Observer)
310 Template **ValueSerieGnuPlotter**
311 .................................
313 Graphically plot with Gnuplot the value series of the variable (persistent plot).
317 import numpy, Gnuplot
318 v=numpy.array(var[:], ndmin=1)
322 gp('set title "%s (Figure %i)"'%(info,igfig))
325 gp=Gnuplot.Gnuplot(persist=1)
326 gp('set title "%s (Figure %i)"'%(info,igfig))
327 gp('set style data lines')
328 gp('set xlabel "Step"')
329 gp('set ylabel "Variable"')
330 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
332 .. index:: single: ValuePrinterAndGnuPlotter (Observer)
334 Template **ValuePrinterAndGnuPlotter**
335 ......................................
337 Print on standard output and, in the same time, graphically plot with Gnuplot the current value of the variable (persistent plot).
341 print(str(info)+' '+str(var[-1]))
342 import numpy, Gnuplot
343 v=numpy.array(var[-1], ndmin=1)
347 gp('set title "%s (Figure %i)"'%(info,igfig))
350 gp=Gnuplot.Gnuplot(persist=1)
351 gp('set title "%s (Figure %i)"'%(info,igfig))
352 gp('set style data lines')
353 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
355 .. index:: single: ValueSeriePrinterAndGnuPlotter (Observer)
357 Template **ValueSeriePrinterAndGnuPlotter**
358 ...........................................
360 Print on standard output and, in the same time, graphically plot with Gnuplot the value series of the variable (persistent plot).
364 print(str(info)+' '+str(var[:]))
365 import numpy, Gnuplot
366 v=numpy.array(var[:], ndmin=1)
370 gp('set title "%s (Figure %i)"'%(info,igfig))
373 gp=Gnuplot.Gnuplot(persist=1)
374 gp('set title "%s (Figure %i)"'%(info,igfig))
375 gp('set style data lines')
376 gp('set xlabel "Step"')
377 gp('set ylabel "Variable"')
378 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
380 .. index:: single: ValuePrinterSaverAndGnuPlotter (Observer)
382 Template **ValuePrinterSaverAndGnuPlotter**
383 ...........................................
385 Print on standard output and, in the same, time save in a file of the '/tmp' directory and graphically plot the current value of the variable (persistent plot).
389 print(str(info)+' '+str(var[-1]))
391 v=numpy.array(var[-1], ndmin=1)
397 f='/tmp/value_%s_%05i.txt'%(info,istep)
398 f=re.sub(r'\s','_',f)
399 print('Value saved in "%s"'%f)
405 gp('set title "%s (Figure %i)"'%(info,igfig))
408 gp=Gnuplot.Gnuplot(persist=1)
409 gp('set title "%s (Figure %i)"'%(info,igfig))
410 gp('set style data lines')
411 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
413 .. index:: single: ValueSeriePrinterSaverAndGnuPlotter (Observer)
415 Template **ValueSeriePrinterSaverAndGnuPlotter**
416 ................................................
418 Print on standard output and, in the same, time save in a file of the '/tmp' directory and graphically plot the value series of the variable (persistent plot).
422 print(str(info)+' '+str(var[:]))
424 v=numpy.array(var[:], ndmin=1)
430 f='/tmp/value_%s_%05i.txt'%(info,istep)
431 f=re.sub(r'\s','_',f)
432 print('Value saved in "%s"'%f)
438 gp('set title "%s (Figure %i)"'%(info,igfig))
441 gp=Gnuplot.Gnuplot(persist=1)
442 gp('set title "%s (Figure %i)"'%(info,igfig))
443 gp('set style data lines')
444 gp('set xlabel "Step"')
445 gp('set ylabel "Variable"')
446 gp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )
448 .. index:: single: ValueMatPlotter (Observer)
450 Template **ValueMatPlotter**
451 ............................
453 Graphically plot with Matplolib the current value of the variable (non persistent plot).
458 import matplotlib.pyplot as plt
459 v=numpy.array(var[-1], ndmin=1)
464 mp.suptitle('%s (Figure %i)'%(info,imfig))
468 ax = mp.add_subplot(1, 1, 1)
469 mp.suptitle('%s (Figure %i)'%(info,imfig))
473 .. index:: single: ValueMatPlotterSaver (Observer)
475 Template **ValueMatPlotterSaver**
476 .................................
478 Graphically plot with Matplolib the current value of the variable, and save the figure in a file of the '/tmp' directory (persistant figure).
483 import matplotlib.pyplot as plt
484 v=numpy.array(var[-1], ndmin=1)
489 mp.suptitle('%s (Figure %i)'%(info,imfig))
493 ax = mp.add_subplot(1, 1, 1)
494 mp.suptitle('%s (Figure %i)'%(info,imfig))
496 f='/tmp/figure_%s_%05i.pdf'%(info,imfig)
497 f=re.sub(r'\s','_',f)
501 .. index:: single: ValueSerieMatPlotter (Observer)
503 Template **ValueSerieMatPlotter**
504 .................................
506 Graphically plot with Matplolib the value series of the variable (non persistent plot).
511 import matplotlib.pyplot as plt
512 v=numpy.array(var[:], ndmin=1)
517 mp.suptitle('%s (Figure %i)'%(info,imfig))
521 ax = mp.add_subplot(1, 1, 1)
522 mp.suptitle('%s (Figure %i)'%(info,imfig))
523 ax.set_xlabel('Step')
524 ax.set_ylabel('Variable')
528 .. index:: single: ValueSerieMatPlotterSaver (Observer)
530 Template **ValueSerieMatPlotterSaver**
531 ......................................
533 Graphically plot with Matplolib the value series of the variable, and save the figure in a file of the '/tmp' directory (persistant figure).
538 import matplotlib.pyplot as plt
539 v=numpy.array(var[:], ndmin=1)
544 mp.suptitle('%s (Figure %i)'%(info,imfig))
548 ax = mp.add_subplot(1, 1, 1)
549 mp.suptitle('%s (Figure %i)'%(info,imfig))
550 ax.set_xlabel('Step')
551 ax.set_ylabel('Variable')
553 f='/tmp/figure_%s_%05i.pdf'%(info,imfig)
554 f=re.sub(r'\s','_',f)
558 .. index:: single: ValuePrinterAndMatPlotter (Observer)
560 Template **ValuePrinterAndMatPlotter**
561 ......................................
563 Graphically plot with Matplolib the current value of the variable (non persistent plot).
567 print(str(info)+' '+str(var[-1]))
569 import matplotlib.pyplot as plt
570 v=numpy.array(var[-1], ndmin=1)
575 mp.suptitle('%s (Figure %i)'%(info,imfig))
579 ax = mp.add_subplot(1, 1, 1)
580 mp.suptitle('%s (Figure %i)'%(info,imfig))
584 .. index:: single: ValuePrinterAndMatPlotterSaver (Observer)
586 Template **ValuePrinterAndMatPlotterSaver**
587 ...........................................
589 Graphically plot with Matplolib the current value of the variable, and save the figure in a file of the '/tmp' directory (persistant figure).
593 print(str(info)+' '+str(var[-1]))
595 import matplotlib.pyplot as plt
596 v=numpy.array(var[-1], ndmin=1)
601 mp.suptitle('%s (Figure %i)'%(info,imfig))
605 ax = mp.add_subplot(1, 1, 1)
606 mp.suptitle('%s (Figure %i)'%(info,imfig))
608 f='/tmp/figure_%s_%05i.pdf'%(info,imfig)
609 f=re.sub(r'\s','_',f)
613 .. index:: single: ValueSeriePrinterAndMatPlotter (Observer)
615 Template **ValueSeriePrinterAndMatPlotter**
616 ...........................................
618 Graphically plot with Matplolib the value series of the variable (non persistent plot).
622 print(str(info)+' '+str(var[:]))
624 import matplotlib.pyplot as plt
625 v=numpy.array(var[:], ndmin=1)
630 mp.suptitle('%s (Figure %i)'%(info,imfig))
634 ax = mp.add_subplot(1, 1, 1)
635 mp.suptitle('%s (Figure %i)'%(info,imfig))
636 ax.set_xlabel('Step')
637 ax.set_ylabel('Variable')
641 .. index:: single: ValueSeriePrinterAndMatPlotterSaver (Observer)
643 Template **ValueSeriePrinterAndMatPlotterSaver**
644 ................................................
646 Graphically plot with Matplolib the value series of the variable, and save the figure in a file of the '/tmp' directory (persistant figure).
650 print(str(info)+' '+str(var[:]))
652 import matplotlib.pyplot as plt
653 v=numpy.array(var[:], ndmin=1)
658 mp.suptitle('%s (Figure %i)'%(info,imfig))
662 ax = mp.add_subplot(1, 1, 1)
663 mp.suptitle('%s (Figure %i)'%(info,imfig))
664 ax.set_xlabel('Step')
665 ax.set_ylabel('Variable')
667 f='/tmp/figure_%s_%05i.pdf'%(info,imfig)
668 f=re.sub(r'\s','_',f)
672 .. index:: single: ValueMean (Observer)
674 Template **ValueMean**
675 ......................
677 Print on standard output the mean of the current value of the variable.
682 print(str(info)+' '+str(numpy.nanmean(var[-1])))
684 .. index:: single: ValueStandardError (Observer)
686 Template **ValueStandardError**
687 ...............................
689 Print on standard output the standard error of the current value of the variable.
694 print(str(info)+' '+str(numpy.nanstd(var[-1])))
696 .. index:: single: ValueVariance (Observer)
698 Template **ValueVariance**
699 ..........................
701 Print on standard output the variance of the current value of the variable.
706 print(str(info)+' '+str(numpy.nanvar(var[-1])))
708 .. index:: single: ValueL2Norm (Observer)
710 Template **ValueL2Norm**
711 ........................
713 Print on standard output the L2 norm of the current value of the variable.
718 v = numpy.ravel( var[-1] )
719 print(str(info)+' '+str(float( numpy.linalg.norm(v) )))
721 .. index:: single: ValueRMS (Observer)
723 Template **ValueRMS**
724 .....................
726 Print on standard output the root mean square (RMS), or quadratic mean, of the current value of the variable.
731 v = numpy.ravel( var[-1] )
732 print(str(info)+' '+str(float( numpy.sqrt((1./v.size)*numpy.dot(v,v)) )))