Salome HOME
Minor internal clarification and performance improvements
[modules/adao.git] / src / daComposant / daCore / Aidsm.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2008-2021 EDF R&D
4 #
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License.
9 #
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 #
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #
21 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
22
23 """
24     Normalized interface for ADAO scripting (generic API).
25 """
26 __author__ = "Jean-Philippe ARGAUD"
27 __all__ = ["Aidsm"]
28
29 import os
30 import sys
31 import inspect
32 #
33 from daCore.BasicObjects import State, Covariance, FullOperator, Operator
34 from daCore.BasicObjects import AlgorithmAndParameters, DataObserver
35 from daCore.BasicObjects import RegulationAndParameters, CaseLogger
36 from daCore.BasicObjects import UserScript, ExternalParameters
37 from daCore import PlatformInfo
38 #
39 from daCore import ExtendedLogging ; ExtendedLogging.ExtendedLogging() # A importer en premier
40 import logging
41
42 # ==============================================================================
43 class Aidsm(object):
44     """ ADAO Internal Data Structure Model """
45     def __init__(self, name = "", addViewers=None):
46         self.__name         = str(name)
47         self.__objname      = None
48         self.__directory    = None
49         self.__case = CaseLogger(self.__name, "case", addViewers)
50         #
51         self.__adaoObject   = {}
52         self.__StoredInputs = {}
53         self.__PostAnalysis = []
54         #
55         self.__Concepts = [ # Liste exhaustive
56             "AlgorithmParameters",
57             "Background",
58             "BackgroundError",
59             "CheckingPoint",
60             "ControlInput",
61             "ControlModel",
62             "Debug",
63             "Directory",
64             "EvolutionError",
65             "EvolutionModel",
66             "Name",
67             "NoDebug",
68             "Observation",
69             "ObservationError",
70             "ObservationOperator",
71             "Observer",
72             "RegulationParameters",
73             "SupplementaryParameters",
74             "UserPostAnalysis",
75             ]
76         #
77         for ename in self.__Concepts:
78             self.__adaoObject[ename] = None
79         for ename in ("ObservationOperator", "EvolutionModel", "ControlModel"):
80             self.__adaoObject[ename] = {}
81         for ename in ("Observer", "UserPostAnalysis"):
82             self.__adaoObject[ename]   = []
83             self.__StoredInputs[ename] = [] # Vide par defaut
84         self.__StoredInputs["Name"] = self.__name
85         self.__StoredInputs["Directory"] = self.__directory
86         #
87         # Récupère le chemin du répertoire parent et l'ajoute au path
88         # (Cela complète l'action de la classe PathManagement dans PlatformInfo,
89         # qui est activée dans Persistence)
90         self.__parent = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
91         sys.path.insert(0, self.__parent)
92         sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
93
94     def set(self,
95             Concept              = None, # Premier argument
96             Algorithm            = None,
97             AppliedInXb          = None,
98             AvoidRC              = True,
99             Checked              = False,
100             ColMajor             = False,
101             ColNames             = None,
102             DataFile             = None,
103             DiagonalSparseMatrix = None,
104             ExtraArguments       = None,
105             Info                 = None,
106             InputFunctionAsMulti = False,
107             Matrix               = None,
108             ObjectFunction       = None,
109             ObjectMatrix         = None,
110             OneFunction          = None,
111             Parameters           = None,
112             ScalarSparseMatrix   = None,
113             Scheduler            = None,
114             Script               = None,
115             Stored               = False,
116             String               = None,
117             Template             = None,
118             ThreeFunctions       = None,
119             Variable             = None,
120             Vector               = None,
121             VectorSerie          = None,
122             ):
123         "Interface unique de definition de variables d'entrees par argument"
124         self.__case.register("set",dir(),locals(),None,True)
125         try:
126             if   Concept in ("Background", "CheckingPoint", "ControlInput", "Observation"):
127                 commande = getattr(self,"set"+Concept)
128                 commande(Vector, VectorSerie, Script, DataFile, ColNames, ColMajor, Stored, Scheduler, Checked )
129             elif Concept in ("BackgroundError", "ObservationError", "EvolutionError"):
130                 commande = getattr(self,"set"+Concept)
131                 commande(Matrix, ScalarSparseMatrix, DiagonalSparseMatrix,
132                          Script, Stored, ObjectMatrix, Checked )
133             elif Concept == "AlgorithmParameters":
134                 self.setAlgorithmParameters( Algorithm, Parameters, Script )
135             elif Concept == "RegulationParameters":
136                 self.setRegulationParameters( Algorithm, Parameters, Script )
137             elif Concept == "Name":
138                 self.setName(String)
139             elif Concept == "Directory":
140                 self.setDirectory(String)
141             elif Concept == "Debug":
142                 self.setDebug()
143             elif Concept == "NoDebug":
144                 self.setNoDebug()
145             elif Concept == "Observer":
146                 self.setObserver( Variable, Template, String, Script, Info, ObjectFunction, Scheduler )
147             elif Concept == "UserPostAnalysis":
148                 self.setUserPostAnalysis( Template, String, Script )
149             elif Concept == "SupplementaryParameters":
150                 self.setSupplementaryParameters( Parameters, Script )
151             elif Concept == "ObservationOperator":
152                 self.setObservationOperator(
153                     Matrix, OneFunction, ThreeFunctions, AppliedInXb,
154                     Parameters, Script, ExtraArguments,
155                     Stored, AvoidRC, InputFunctionAsMulti, Checked )
156             elif Concept in ("EvolutionModel", "ControlModel"):
157                 commande = getattr(self,"set"+Concept)
158                 commande(
159                     Matrix, OneFunction, ThreeFunctions,
160                     Parameters, Script, Scheduler, ExtraArguments,
161                     Stored, AvoidRC, InputFunctionAsMulti, Checked )
162             else:
163                 raise ValueError("the variable named '%s' is not allowed."%str(Concept))
164         except Exception as e:
165             if isinstance(e, SyntaxError): msg = "at %s: %s"%(e.offset, e.text)
166             else: msg = ""
167             raise ValueError(("during settings, the following error occurs:\n"+\
168                               "\n%s %s\n\nSee also the potential messages, "+\
169                               "which can show the origin of the above error, "+\
170                               "in the launching terminal.")%(str(e),msg))
171
172     # -----------------------------------------------------------
173
174     def setBackground(self,
175             Vector         = None,
176             VectorSerie    = None,
177             Script         = None,
178             DataFile       = None,
179             ColNames       = None,
180             ColMajor       = False,
181             Stored         = False,
182             Scheduler      = None,
183             Checked        = False):
184         "Definition d'un concept de calcul"
185         Concept = "Background"
186         self.__case.register("set"+Concept, dir(), locals())
187         self.__adaoObject[Concept] = State(
188             name               = Concept,
189             asVector           = Vector,
190             asPersistentVector = VectorSerie,
191             asScript           = self.__with_directory(Script),
192             asDataFile         = DataFile,
193             colNames           = ColNames,
194             colMajor           = ColMajor,
195             scheduledBy        = Scheduler,
196             toBeChecked        = Checked,
197             )
198         if Stored:
199             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
200         return 0
201
202     def setCheckingPoint(self,
203             Vector         = None,
204             VectorSerie    = None,
205             Script         = None,
206             DataFile       = None,
207             ColNames       = None,
208             ColMajor       = False,
209             Stored         = False,
210             Scheduler      = None,
211             Checked        = False):
212         "Definition d'un concept de calcul"
213         Concept = "CheckingPoint"
214         self.__case.register("set"+Concept, dir(), locals())
215         self.__adaoObject[Concept] = State(
216             name               = Concept,
217             asVector           = Vector,
218             asPersistentVector = VectorSerie,
219             asScript           = self.__with_directory(Script),
220             asDataFile         = DataFile,
221             colNames           = ColNames,
222             colMajor           = ColMajor,
223             scheduledBy        = Scheduler,
224             toBeChecked        = Checked,
225             )
226         if Stored:
227             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
228         return 0
229
230     def setControlInput(self,
231             Vector         = None,
232             VectorSerie    = None,
233             Script         = None,
234             DataFile       = None,
235             ColNames       = None,
236             ColMajor       = False,
237             Stored         = False,
238             Scheduler      = None,
239             Checked        = False):
240         "Definition d'un concept de calcul"
241         Concept = "ControlInput"
242         self.__case.register("set"+Concept, dir(), locals())
243         self.__adaoObject[Concept] = State(
244             name               = Concept,
245             asVector           = Vector,
246             asPersistentVector = VectorSerie,
247             asScript           = self.__with_directory(Script),
248             asDataFile         = DataFile,
249             colNames           = ColNames,
250             colMajor           = ColMajor,
251             scheduledBy        = Scheduler,
252             toBeChecked        = Checked,
253             )
254         if Stored:
255             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
256         return 0
257
258     def setObservation(self,
259             Vector         = None,
260             VectorSerie    = None,
261             Script         = None,
262             DataFile       = None,
263             ColNames       = None,
264             ColMajor       = False,
265             Stored         = False,
266             Scheduler      = None,
267             Checked        = False):
268         "Definition d'un concept de calcul"
269         Concept = "Observation"
270         self.__case.register("set"+Concept, dir(), locals())
271         self.__adaoObject[Concept] = State(
272             name               = Concept,
273             asVector           = Vector,
274             asPersistentVector = VectorSerie,
275             asScript           = self.__with_directory(Script),
276             asDataFile         = DataFile,
277             colNames           = ColNames,
278             colMajor           = ColMajor,
279             scheduledBy        = Scheduler,
280             toBeChecked        = Checked,
281             )
282         if Stored:
283             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
284         return 0
285
286     def setBackgroundError(self,
287             Matrix               = None,
288             ScalarSparseMatrix   = None,
289             DiagonalSparseMatrix = None,
290             Script               = None,
291             Stored               = False,
292             ObjectMatrix         = None,
293             Checked              = False):
294         "Definition d'un concept de calcul"
295         Concept = "BackgroundError"
296         self.__case.register("set"+Concept, dir(), locals())
297         self.__adaoObject[Concept] = Covariance(
298             name          = Concept,
299             asCovariance  = Matrix,
300             asEyeByScalar = ScalarSparseMatrix,
301             asEyeByVector = DiagonalSparseMatrix,
302             asCovObject   = ObjectMatrix,
303             asScript      = self.__with_directory(Script),
304             toBeChecked   = Checked,
305             )
306         if Stored:
307             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
308         return 0
309
310     def setObservationError(self,
311             Matrix               = None,
312             ScalarSparseMatrix   = None,
313             DiagonalSparseMatrix = None,
314             Script               = None,
315             Stored               = False,
316             ObjectMatrix         = None,
317             Checked              = False):
318         "Definition d'un concept de calcul"
319         Concept = "ObservationError"
320         self.__case.register("set"+Concept, dir(), locals())
321         self.__adaoObject[Concept] = Covariance(
322             name          = Concept,
323             asCovariance  = Matrix,
324             asEyeByScalar = ScalarSparseMatrix,
325             asEyeByVector = DiagonalSparseMatrix,
326             asCovObject   = ObjectMatrix,
327             asScript      = self.__with_directory(Script),
328             toBeChecked   = Checked,
329             )
330         if Stored:
331             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
332         return 0
333
334     def setEvolutionError(self,
335             Matrix               = None,
336             ScalarSparseMatrix   = None,
337             DiagonalSparseMatrix = None,
338             Script               = None,
339             Stored               = False,
340             ObjectMatrix         = None,
341             Checked              = False):
342         "Definition d'un concept de calcul"
343         Concept = "EvolutionError"
344         self.__case.register("set"+Concept, dir(), locals())
345         self.__adaoObject[Concept] = Covariance(
346             name          = Concept,
347             asCovariance  = Matrix,
348             asEyeByScalar = ScalarSparseMatrix,
349             asEyeByVector = DiagonalSparseMatrix,
350             asCovObject   = ObjectMatrix,
351             asScript      = self.__with_directory(Script),
352             toBeChecked   = Checked,
353             )
354         if Stored:
355             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
356         return 0
357
358     def setObservationOperator(self,
359             Matrix               = None,
360             OneFunction          = None,
361             ThreeFunctions       = None,
362             AppliedInXb          = None,
363             Parameters           = None,
364             Script               = None,
365             ExtraArguments       = None,
366             Stored               = False,
367             AvoidRC              = True,
368             InputFunctionAsMulti = False,
369             Checked              = False):
370         "Definition d'un concept de calcul"
371         Concept = "ObservationOperator"
372         self.__case.register("set"+Concept, dir(), locals())
373         self.__adaoObject[Concept] = FullOperator(
374             name             = Concept,
375             asMatrix         = Matrix,
376             asOneFunction    = OneFunction,
377             asThreeFunctions = ThreeFunctions,
378             asScript         = self.__with_directory(Script),
379             asDict           = Parameters,
380             appliedInX       = AppliedInXb,
381             extraArguments   = ExtraArguments,
382             avoidRC          = AvoidRC,
383             inputAsMF        = InputFunctionAsMulti,
384             scheduledBy      = None,
385             toBeChecked      = Checked,
386             )
387         if Stored:
388             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
389         return 0
390
391     def setEvolutionModel(self,
392             Matrix               = None,
393             OneFunction          = None,
394             ThreeFunctions       = None,
395             Parameters           = None,
396             Script               = None,
397             Scheduler            = None,
398             ExtraArguments       = None,
399             Stored               = False,
400             AvoidRC              = True,
401             InputFunctionAsMulti = False,
402             Checked              = False):
403         "Definition d'un concept de calcul"
404         Concept = "EvolutionModel"
405         self.__case.register("set"+Concept, dir(), locals())
406         self.__adaoObject[Concept] = FullOperator(
407             name             = Concept,
408             asMatrix         = Matrix,
409             asOneFunction    = OneFunction,
410             asThreeFunctions = ThreeFunctions,
411             asScript         = self.__with_directory(Script),
412             asDict           = Parameters,
413             appliedInX       = None,
414             extraArguments   = ExtraArguments,
415             avoidRC          = AvoidRC,
416             inputAsMF        = InputFunctionAsMulti,
417             scheduledBy      = Scheduler,
418             toBeChecked      = Checked,
419             )
420         if Stored:
421             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
422         return 0
423
424     def setControlModel(self,
425             Matrix               = None,
426             OneFunction          = None,
427             ThreeFunctions       = None,
428             Parameters           = None,
429             Script               = None,
430             Scheduler            = None,
431             ExtraArguments       = None,
432             Stored               = False,
433             AvoidRC              = True,
434             InputFunctionAsMulti = False,
435             Checked              = False):
436         "Definition d'un concept de calcul"
437         Concept = "ControlModel"
438         self.__case.register("set"+Concept, dir(), locals())
439         self.__adaoObject[Concept] = FullOperator(
440             name             = Concept,
441             asMatrix         = Matrix,
442             asOneFunction    = OneFunction,
443             asThreeFunctions = ThreeFunctions,
444             asScript         = self.__with_directory(Script),
445             asDict           = Parameters,
446             appliedInX       = None,
447             extraArguments   = ExtraArguments,
448             avoidRC          = AvoidRC,
449             inputAsMF        = InputFunctionAsMulti,
450             scheduledBy      = Scheduler,
451             toBeChecked      = Checked,
452             )
453         if Stored:
454             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
455         return 0
456
457     def setName(self, String=None):
458         "Definition d'un concept de calcul"
459         self.__case.register("setName",dir(),locals())
460         if String is not None:
461             self.__name = str(String)
462         else:
463             self.__name = None
464         self.__StoredInputs["Name"] = self.__name
465
466     def setDirectory(self, String=None):
467         "Definition d'un concept de calcul"
468         self.__case.register("setDirectory",dir(),locals())
469         if os.path.isdir(os.path.abspath(str(String))):
470             self.__directory = os.path.abspath(str(String))
471         else:
472             self.__directory = None
473         self.__StoredInputs["Directory"] = self.__directory
474
475     def setDebug(self, __level = 10):
476         "NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50"
477         self.__case.register("setDebug",dir(),locals())
478         log = logging.getLogger()
479         log.setLevel( __level )
480         self.__StoredInputs["Debug"]   = __level
481         self.__StoredInputs["NoDebug"] = False
482         return 0
483
484     def setNoDebug(self):
485         "NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50"
486         self.__case.register("setNoDebug",dir(),locals())
487         log = logging.getLogger()
488         log.setLevel( logging.WARNING )
489         self.__StoredInputs["Debug"]   = logging.WARNING
490         self.__StoredInputs["NoDebug"] = True
491         return 0
492
493     def setAlgorithmParameters(self,
494             Algorithm  = None,
495             Parameters = None,
496             Script     = None):
497         "Definition d'un concept de calcul"
498         Concept = "AlgorithmParameters"
499         self.__case.register("set"+Concept, dir(), locals())
500         self.__adaoObject[Concept] = AlgorithmAndParameters(
501             name          = Concept,
502             asAlgorithm   = Algorithm,
503             asDict        = Parameters,
504             asScript      = self.__with_directory(Script),
505             )
506         return 0
507
508     def updateAlgorithmParameters(self,
509             Parameters = None,
510             Script     = None):
511         "Mise a jour d'un concept de calcul"
512         Concept = "AlgorithmParameters"
513         if Concept not in self.__adaoObject or self.__adaoObject[Concept] is None:
514             raise ValueError("\n\nNo algorithm registred, set one before updating parameters or executing\n")
515         self.__adaoObject[Concept].updateParameters(
516             asDict        = Parameters,
517             asScript      = self.__with_directory(Script),
518             )
519         # RaJ du register
520         return 0
521
522     def setRegulationParameters(self,
523             Algorithm  = None,
524             Parameters = None,
525             Script     = None):
526         "Definition d'un concept de calcul"
527         Concept = "RegulationParameters"
528         self.__case.register("set"+Concept, dir(), locals())
529         self.__adaoObject[Concept] = RegulationAndParameters(
530             name        = Concept,
531             asAlgorithm = Algorithm,
532             asDict      = Parameters,
533             asScript    = self.__with_directory(Script),
534             )
535         return 0
536
537     def setSupplementaryParameters(self,
538             Parameters = None,
539             Script     = None):
540         "Definition d'un concept de calcul"
541         Concept = "SupplementaryParameters"
542         self.__case.register("set"+Concept, dir(), locals())
543         self.__adaoObject[Concept] = ExternalParameters(
544             name     = Concept,
545             asDict   = Parameters,
546             asScript = self.__with_directory(Script),
547             )
548         return 0
549
550     def updateSupplementaryParameters(self,
551             Parameters = None,
552             Script     = None):
553         "Mise a jour d'un concept de calcul"
554         Concept = "SupplementaryParameters"
555         if Concept not in self.__adaoObject or self.__adaoObject[Concept] is None:
556             self.__adaoObject[Concept] = ExternalParameters(name = Concept)
557         self.__adaoObject[Concept].updateParameters(
558             asDict   = Parameters,
559             asScript = self.__with_directory(Script),
560             )
561         return 0
562
563     def setObserver(self,
564             Variable       = None,
565             Template       = None,
566             String         = None,
567             Script         = None,
568             Info           = None,
569             ObjectFunction = None,
570             Scheduler      = None):
571         "Definition d'un concept de calcul"
572         Concept = "Observer"
573         self.__case.register("set"+Concept, dir(), locals())
574         self.__adaoObject[Concept].append( DataObserver(
575             name        = Concept,
576             onVariable  = Variable,
577             asTemplate  = Template,
578             asString    = String,
579             asScript    = self.__with_directory(Script),
580             asObsObject = ObjectFunction,
581             withInfo    = Info,
582             scheduledBy = Scheduler,
583             withAlgo    = self.__adaoObject["AlgorithmParameters"]
584             ))
585         return 0
586
587     def removeObserver(self,
588             Variable       = None,
589             ObjectFunction = None,
590             ):
591         "Permet de retirer un observer à une ou des variable nommée"
592         if "AlgorithmParameters" not in self.__adaoObject:
593             raise ValueError("No algorithm registred, ask for one before removing observers")
594         #
595         # Vérification du nom de variable et typage
596         # -----------------------------------------
597         if isinstance(Variable, str):
598             VariableNames = (Variable,)
599         elif isinstance(Variable, list):
600             VariableNames = tuple(map( str, Variable ))
601         else:
602             raise ValueError("The observer requires a name or a list of names of variables.")
603         #
604         # Association interne de l'observer à la variable
605         # -----------------------------------------------
606         for ename in VariableNames:
607             if ename not in self.__adaoObject["AlgorithmParameters"]:
608                 raise ValueError("An observer requires to be removed on a variable named %s which does not exist."%ename)
609             else:
610                 return self.__adaoObject["AlgorithmParameters"].removeObserver( ename, ObjectFunction )
611
612     def setUserPostAnalysis(self,
613             Template       = None,
614             String         = None,
615             Script         = None):
616         "Definition d'un concept de calcul"
617         Concept = "UserPostAnalysis"
618         self.__case.register("set"+Concept, dir(), locals())
619         self.__adaoObject[Concept].append( repr(UserScript(
620             name        = Concept,
621             asTemplate  = Template,
622             asString    = String,
623             asScript    = self.__with_directory(Script),
624             )))
625
626     # -----------------------------------------------------------
627
628     def get(self, Concept=None, noDetails=True ):
629         "Recuperation d'une sortie du calcul"
630         if Concept is not None:
631             try:
632                 self.__case.register("get", dir(), locals(), Concept) # Break pickle in Python 2
633             except Exception:
634                 pass
635             if Concept in self.__StoredInputs:
636                 return self.__StoredInputs[Concept]
637                 #
638             elif self.__adaoObject["AlgorithmParameters"] is not None and Concept == "AlgorithmParameters":
639                 return self.__adaoObject["AlgorithmParameters"].get()
640                 #
641             elif self.__adaoObject["AlgorithmParameters"] is not None and Concept in self.__adaoObject["AlgorithmParameters"]:
642                 return self.__adaoObject["AlgorithmParameters"].get( Concept )
643                 #
644             elif Concept == "AlgorithmRequiredParameters" and self.__adaoObject["AlgorithmParameters"] is not None:
645                 return self.__adaoObject["AlgorithmParameters"].getAlgorithmRequiredParameters(noDetails)
646                 #
647             elif Concept == "AlgorithmRequiredInputs" and self.__adaoObject["AlgorithmParameters"] is not None:
648                 return self.__adaoObject["AlgorithmParameters"].getAlgorithmInputArguments()
649                 #
650             elif Concept == "AlgorithmAttributes" and self.__adaoObject["AlgorithmParameters"] is not None:
651                 return self.__adaoObject["AlgorithmParameters"].getAlgorithmAttributes()
652                 #
653             elif self.__adaoObject["SupplementaryParameters"] is not None and Concept == "SupplementaryParameters":
654                 return self.__adaoObject["SupplementaryParameters"].get()
655                 #
656             elif self.__adaoObject["SupplementaryParameters"] is not None and Concept in self.__adaoObject["SupplementaryParameters"]:
657                 return self.__adaoObject["SupplementaryParameters"].get( Concept )
658                 #
659             else:
660                 raise ValueError("The requested key \"%s\" does not exists as an input or a stored variable."%Concept)
661         else:
662             allvariables = {}
663             allvariables.update( {"AlgorithmParameters":self.__adaoObject["AlgorithmParameters"].get()} )
664             if self.__adaoObject["SupplementaryParameters"] is not None:
665                 allvariables.update( {"SupplementaryParameters":self.__adaoObject["SupplementaryParameters"].get()} )
666             # allvariables.update( self.__adaoObject["AlgorithmParameters"].get() )
667             allvariables.update( self.__StoredInputs )
668             allvariables.pop('Observer', None)
669             allvariables.pop('UserPostAnalysis', None)
670             return allvariables
671
672     # -----------------------------------------------------------
673
674     def get_available_variables(self):
675         """
676         Renvoie les variables potentiellement utilisables pour l'étude,
677         initialement stockées comme données d'entrées ou dans les algorithmes,
678         identifiés par les chaînes de caractères. L'algorithme doit avoir été
679         préalablement choisi sinon la méthode renvoie "None".
680         """
681         if len(list(self.__adaoObject["AlgorithmParameters"].keys())) == 0 and \
682             len(list(self.__StoredInputs.keys())) == 0:
683             return None
684         else:
685             variables = []
686             if len(list(self.__adaoObject["AlgorithmParameters"].keys())) > 0:
687                 variables.extend(list(self.__adaoObject["AlgorithmParameters"].keys()))
688             if self.__adaoObject["SupplementaryParameters"] is not None and \
689                 len(list(self.__adaoObject["SupplementaryParameters"].keys())) > 0:
690                 variables.extend(list(self.__adaoObject["SupplementaryParameters"].keys()))
691             if len(list(self.__StoredInputs.keys())) > 0:
692                 variables.extend( list(self.__StoredInputs.keys()) )
693             variables.remove('Observer')
694             variables.remove('UserPostAnalysis')
695             variables.sort()
696             return variables
697
698     def get_available_algorithms(self):
699         """
700         Renvoie la liste des algorithmes potentiellement utilisables, identifiés
701         par les chaînes de caractères.
702         """
703         files = []
704         for directory in sys.path:
705             trypath = os.path.join(directory,"daAlgorithms")
706             if os.path.isdir(trypath):
707                 for fname in os.listdir(trypath):
708                     if os.path.isfile(os.path.join(trypath,fname)):
709                         root, ext = os.path.splitext(fname)
710                         if ext != ".py": continue
711                         with open(os.path.join(trypath,fname)) as fc:
712                             iselal = bool("class ElementaryAlgorithm" in fc.read())
713                             if iselal and ext == '.py' and root != '__init__':
714                                 files.append(root)
715         files.sort()
716         return files
717
718     def get_algorithms_main_path(self):
719         """
720         Renvoie le chemin pour le répertoire principal contenant les algorithmes
721         """
722         return self.__parent
723
724     def add_algorithms_path(self, Path=None):
725         """
726         Ajoute au chemin de recherche des algorithmes un répertoire dans lequel
727         se trouve un sous-répertoire "daAlgorithms"
728         """
729         if not os.path.isdir(Path):
730             raise ValueError("The given "+Path+" argument must exist as a directory")
731         if not os.path.isdir(os.path.join(Path,"daAlgorithms")):
732             raise ValueError("The given \""+Path+"\" argument must contain a subdirectory named \"daAlgorithms\"")
733         if not os.path.isfile(os.path.join(Path,"daAlgorithms","__init__.py")):
734             raise ValueError("The given \""+Path+"/daAlgorithms\" path must contain a file named \"__init__.py\"")
735         sys.path.insert(0, os.path.abspath(Path))
736         sys.path = PlatformInfo.uniq( sys.path ) # Conserve en unique exemplaire chaque chemin
737         return 0
738
739     # -----------------------------------------------------------
740
741     def execute(self, Executor=None, SaveCaseInFile=None, nextStep=False):
742         "Lancement du calcul"
743         self.__case.register("execute",dir(),locals(),None,True)
744         self.updateAlgorithmParameters(Parameters={"nextStep":bool(nextStep)})
745         if not nextStep: Operator.CM.clearCache()
746         try:
747             if   Executor == "YACS": self.__executeYACSScheme( SaveCaseInFile )
748             else:                    self.__executePythonScheme( SaveCaseInFile )
749         except Exception as e:
750             if isinstance(e, SyntaxError): msg = "at %s: %s"%(e.offset, e.text)
751             else: msg = ""
752             raise ValueError(("during execution, the following error occurs:\n"+\
753                              "\n%s %s\n\nSee also the potential messages, "+\
754                              "which can show the origin of the above error, "+\
755                              "in the launching terminal.\n")%(str(e),msg))
756         return 0
757
758     def __executePythonScheme(self, FileName=None):
759         "Lancement du calcul"
760         self.__case.register("executePythonScheme", dir(), locals())
761         if FileName is not None:
762             self.dump( FileName, "TUI")
763         self.__adaoObject["AlgorithmParameters"].executePythonScheme( self.__adaoObject )
764         if "UserPostAnalysis" in self.__adaoObject and len(self.__adaoObject["UserPostAnalysis"])>0:
765             self.__objname = self.__retrieve_objname()
766             __Upa = map(str, self.__adaoObject["UserPostAnalysis"])
767             __Upa = eval("\n".join(__Upa))
768             exec(__Upa, {}, {'self':self, 'ADD':self, 'case':self, 'adaopy':self, self.__objname:self})
769         return 0
770
771     def __executeYACSScheme(self, FileName=None):
772         "Lancement du calcul"
773         self.__case.register("executeYACSScheme", dir(), locals())
774         self.dump( FileName, "YACS")
775         self.__adaoObject["AlgorithmParameters"].executeYACSScheme( FileName )
776         return 0
777
778     # -----------------------------------------------------------
779
780     def dump(self, FileName=None, Formater="TUI"):
781         "Restitution normalisée des commandes"
782         __Upa = "\n".join(self.__PostAnalysis)
783         return self.__case.dump(FileName, Formater, __Upa)
784
785     def load(self, FileName=None, Content=None, Object=None, Formater="TUI"):
786         "Chargement normalisé des commandes"
787         __commands = self.__case.load(FileName, Content, Object, Formater)
788         from numpy import array, matrix
789         for __command in __commands:
790             if (__command.find("set")>-1 and __command.find("set_")<0) or 'UserPostAnalysis' in __command:
791                 exec("self."+__command, {}, locals())
792             else:
793                 self.__PostAnalysis.append(__command)
794         return self
795
796     def convert(self,
797         FileNameFrom=None, ContentFrom=None, ObjectFrom=None, FormaterFrom="TUI",
798         FileNameTo=None, FormaterTo="TUI",
799         ):
800         "Conversion normalisée des commandes"
801         return self.load(
802             FileName=FileNameFrom, Content=ContentFrom, Object=ObjectFrom, Formater=FormaterFrom
803             ).dump(
804             FileName=FileNameTo, Formater=FormaterTo
805             )
806
807     def clear(self):
808         "Effacement du contenu du cas en cours"
809         self.__init__(self.__name)
810
811     # -----------------------------------------------------------
812
813     def __with_directory(self, __filename=None):
814         if os.path.exists(str(__filename)):
815             __fullpath = __filename
816         elif os.path.exists(os.path.join(str(self.__directory), str(__filename))):
817             __fullpath = os.path.join(self.__directory, str(__filename))
818         else:
819             __fullpath = __filename
820         return __fullpath
821
822     def __retrieve_objname(self):
823         "Ne pas utiliser dans le __init__, la variable appelante n'existe pas encore"
824         __names  = []
825         for level in reversed(inspect.stack()):
826             __names += [name for name, value in level.frame.f_locals.items() if value is self]
827         __names += [name for name, value in globals().items() if value is self]
828         __names.remove('self') # Devrait toujours être trouvé, donc pas d'erreur
829         if len(__names) > 0:
830             logging.debug("Cet objet est appelé par au moins une variable :",__names)
831             self.__objname = __names[0]
832         else:
833             self.__objname = "ADD"
834         return self.__objname
835
836     def __dir__(self):
837         "Clarifie la visibilité des méthodes"
838         return ['set', 'get', 'execute', 'dump', 'load', '__doc__', '__init__', '__module__']
839
840     def __str__(self):
841         "Représentation pour impression (mais pas repr)"
842         msg  = self.dump(None, "SimpleReportInPlainTxt")
843         return msg
844
845     def prepare_to_pickle(self):
846         "Retire les variables non pickelisables, avec recopie efficace"
847         if self.__adaoObject['AlgorithmParameters'] is not None:
848             for k in self.__adaoObject['AlgorithmParameters'].keys():
849                 if k == "Algorithm": continue
850                 if k in self.__StoredInputs:
851                     raise ValueError("The key \"%s\" to be transfered for pickling will overwrite an existing one."%(k,))
852                 if self.__adaoObject['AlgorithmParameters'].hasObserver( k ):
853                     self.__adaoObject['AlgorithmParameters'].removeObserver( k, "", True )
854                 self.__StoredInputs[k] = self.__adaoObject['AlgorithmParameters'].pop(k, None)
855         if sys.version_info[0] == 2:
856             del self.__adaoObject # Because it breaks pickle in Python 2. Not required for Python 3
857             del self.__case       # Because it breaks pickle in Python 2. Not required for Python 3
858         if sys.version_info.major < 3:
859             return 0
860         else:
861             return self.__StoredInputs
862
863 # ==============================================================================
864 if __name__ == "__main__":
865     print('\n AUTODIAGNOSTIC\n')