Salome HOME
Adding data file input capacity for vectors
[modules/adao.git] / bin / AdaoCatalogGenerator.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2008-2019 EDF R&D
4 #
5 # This file is part of SALOME ADAO module
6 #
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License.
11 #
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 # Lesser General Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
20 #
21 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #
23 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
24
25 import logging
26 import traceback
27 import sys
28 import io
29 import os
30
31 import module_version
32
33 logging.basicConfig(level=logging.WARNING)
34
35 if sys.version_info.major > 2:
36     def unicode(text, encoding='utf-8'): return text
37
38 print("-- Starting AdaoCalatogGenerator.py --")
39
40 try:
41   import adao
42   import daEficas
43   import daYacsSchemaCreator
44   import daCore.AssimilationStudy
45   import daYacsSchemaCreator.infos_daComposant as infos
46 except:
47   logging.fatal("Import of ADAO python modules failed !" +
48                 "\n add ADAO python installation directory in your PYTHONPATH")
49   traceback.print_exc()
50   sys.exit(1)
51
52 #----------- Templates Part ---------------#
53 begin_catalog_file = """# -*- coding: utf-8 -*-
54 #
55 # Copyright (C) 2008-2019 EDF R&D
56 #
57 # This file is part of SALOME ADAO module
58 #
59 # This library is free software; you can redistribute it and/or
60 # modify it under the terms of the GNU Lesser General Public
61 # License as published by the Free Software Foundation; either
62 # version 2.1 of the License.
63 #
64 # This library is distributed in the hope that it will be useful,
65 # but WITHOUT ANY WARRANTY; without even the implied warranty of
66 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
67 # Lesser General Public License for more details.
68 #
69 # You should have received a copy of the GNU Lesser General Public
70 # License along with this library; if not, write to the Free Software
71 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
72 #
73 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
74 #
75 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
76
77 # --------------------------------------------------------
78 # Generated by AdaoCatalogGenerator on {date}
79 # --------------------------------------------------------
80
81 import os, re
82 import Accas
83 from Accas import *
84
85 JdC = JDC_CATA (
86     code = '%s',
87     execmodul = None,
88     regles = ( AU_MOINS_UN ('ASSIMILATION_STUDY','CHECKING_STUDY'), AU_PLUS_UN ('ASSIMILATION_STUDY','CHECKING_STUDY')),
89     )
90 VERSION_CATALOGUE='%s'
91
92 def NoCheckInNS(filename):
93     return 1
94 NoCheckInNS.info = u""
95 def DirectOperatorInNS(filename):
96     if os.path.exists(filename):
97         fc = open(filename, 'r').readlines()
98         cr = re.compile("^def[\s]*DirectOperator[\s]*\(")
99         for ln in fc:
100             if cr.match(ln): return 1
101         cr = re.compile("^DirectOperator[\s]*=")
102         for ln in fc:
103             if cr.match(ln): return 1
104     return 0
105 DirectOperatorInNS.info = u"The Python file has to contain explicitly a \\"DirectOperator\\" function definition with only one vector as argument."
106 def TangentOperatorInNS(filename):
107     if os.path.exists(filename):
108         fc = open(filename, 'r').readlines()
109         cr = re.compile("^def[\s]*TangentOperator[\s]*\(")
110         for ln in fc:
111             if cr.match(ln): return 1
112         cr = re.compile("^TangentOperator[\s]*=")
113         for ln in fc:
114             if cr.match(ln): return 1
115     return 0
116 TangentOperatorInNS.info = u"The Python file has to contain explicitly a \\"TangentOperator\\" function definition with only one pair of vectors as argument."
117 def AdjointOperatorInNS(filename):
118     if os.path.exists(filename):
119         fc = open(filename, 'r').readlines()
120         cr = re.compile("^def[\s]*AdjointOperator[\s]*\(")
121         for ln in fc:
122             if cr.match(ln): return 1
123         cr = re.compile("^AdjointOperator[\s]*=")
124         for ln in fc:
125             if cr.match(ln): return 1
126     return 0
127 AdjointOperatorInNS.info = u"The Python file has to contain explicitly an \\"AdjointOperator\\" function definition with only one pair of vectors as argument."
128 def ColDataFileExtVal(filename):
129     __readable = (".csv", ".tsv", ".txt", ".npy", ".npz")
130     if os.path.exists(filename) and os.path.splitext(filename)[1] in __readable:
131         return 1
132     return 0
133 ColDataFileExtVal.info = u"The data file has to contain explicitly one or more number columns with separator, or one variable, that can fit in a unique continuous vector."
134 """%(module_version.name,module_version.cata)
135
136 # Important : validators=[...] pour que les conditions soient traitees simultanement, en "ET", et pas en "OU" (choisi dans le cas du tuple a la place de la liste)
137 # validators=[OnlyStr(), FileExtVal('py'), FunctionVal(fv)]
138 data_method = """
139 def F_{data_name}(statut, fv=NoCheckInNS) : return FACT(
140     statut = statut,
141     FROM = SIMP(statut = "o", typ = "TXM", into=({data_into}), defaut={data_default}),
142     SCRIPT_DATA = BLOC ( condition = " FROM in ( 'Script', ) ",
143         SCRIPT_FILE = SIMP(statut = "o", typ = ("FichierNoAbs",'Python Files (*.py)',), validators=[OnlyStr(), FileExtVal('py'), FunctionVal(fv)], fr="En attente d'un nom de fichier script, avec ou sans le chemin complet pour le trouver, contenant si nécessaire la définition d'une variable interne de même nom que le concept parent", ang="Waiting for a script file name, with or without the full path to find it, containing if necessary the definition of an internal variable of the same name as the parent concept"),
144         ),
145     DATA_DATA = BLOC ( condition = " FROM in ( 'DataFile', ) ",
146         DATA_FILE = SIMP(statut = "o", typ = ("FichierNoAbs",'CSV Text Files (*.csv);;TSV Text Files (*.tsv);;TXT Text Files (*.txt);;NPY Binary Numpy Files (*.npy);;NPZ Binary Numpy Files (*.npz);;All Files (*)", ',), validators=[OnlyStr(), FunctionVal(ColDataFileExtVal)], fr="En attente d'un nom de fichier de données, avec ou sans le chemin complet pour le trouver, contenant ou plusieurs colonnes pour définir un unique vecteur continu", ang="Waiting for a data file name, with or without the full path to find it, containing one or more columns to define a unique continuous vector"),
147         ),
148     STRING_DATA = BLOC ( condition = " FROM in ( 'String', ) ",
149         STRING = SIMP(statut = "o", typ = "TXM",{ms_default} fr="En attente d'une chaine de caractères entre guillements. Pour construire un vecteur ou une matrice, ce doit être une suite de nombres, utilisant un espace ou une virgule pour séparer deux éléments et un point-virgule pour séparer deux lignes", ang="Waiting for a string in quotes. To build a vector or a matrix, it has to be a float serie, using a space or comma to separate two elements in a line, a semi-colon to separate rows"),
150         ),
151     SCRIPTWITHFUNCTIONS_DATA = BLOC ( condition = " FROM in ( 'ScriptWithFunctions', ) ",
152         SCRIPTWITHFUNCTIONS_FILE = SIMP(statut = "o", typ = "FichierNoAbs", validators=[OnlyStr(), FileExtVal('py'), FunctionVal(DirectOperatorInNS), FunctionVal(TangentOperatorInNS), FunctionVal(AdjointOperatorInNS)], fr="En attente d'un nom de fichier script, avec ou sans le chemin complet pour le trouver, contenant en variables internes trois fonctions de calcul nommées DirectOperator, TangentOperator et AdjointOperator", ang="Waiting for a script file name, with or without the full path to find it, containing as internal variables three computation functions named DirectOperator, TangentOperator and AdjointOperator"),
153         ),
154     SCRIPTWITHONEFUNCTION_DATA = BLOC ( condition = " FROM in ( 'ScriptWithOneFunction', ) ",
155         SCRIPTWITHONEFUNCTION_FILE = SIMP(statut = "o", typ = "FichierNoAbs", validators=[OnlyStr(), FileExtVal('py'), FunctionVal(DirectOperatorInNS)], fr="En attente d'un nom de fichier script, avec ou sans le chemin complet pour le trouver, contenant en variable interne une seule fonction de calcul nommée DirectOperator", ang="Waiting for a script file name, with or without the full path to find it, containing as internal variable only one function named DirectOperator"),
156         DifferentialIncrement = SIMP(statut="o", typ = "R", val_min=0, val_max=1, defaut=0.01, fr="Incrément de la perturbation dX pour calculer la dérivée, construite en multipliant X par l'incrément en évitant les valeurs nulles", ang="Increment of dX perturbation to calculate the derivative, build multiplying X by the increment avoiding null values"),
157         CenteredFiniteDifference = SIMP(statut="o", typ = "I", into=(0, 1), defaut=0, fr="Formulation centrée (1) ou décentrée (0) pour la méthode des différences finies", ang="Centered (1) or uncentered (0) formulation for the finite differences method"),
158         EnableMultiProcessing = SIMP(statut="f", typ = "I", into=(0, 1), defaut=0, fr="Calculs élémentaires effectués en séquentiel (0) ou en parallèle (1) dans la méthode des différences finies", ang="Elementary calculations done sequentially (0) or in parallel (1) in the finite differences method"),
159         NumberOfProcesses = SIMP(statut="f", typ = "I", val_min=0, defaut=0, fr="Nombre de processus parallèles, 0 pour un contrôle automatique", ang="Number of parallel processes, 0 for automatic control"),
160         ),
161     SCRIPTWITHSWITCH_DATA = BLOC ( condition = " FROM in ( 'ScriptWithSwitch', ) ",
162         SCRIPTWITHSWITCH_FILE = SIMP(statut = "o", typ = "FichierNoAbs", validators=[OnlyStr(), FileExtVal('py')], fr="En attente d'un nom de fichier script, avec ou sans le chemin complet pour le trouver, contenant un switch pour les calculs direct, tangent et adjoint", ang="Waiting for a script file name, with or without the full path to find it, containing a switch for direct, tangent and adjoint computations"),
163         ),
164     TEMPLATE_DATA =  BLOC (condition = " FROM in ( 'Template', ) ",
165         Template = SIMP(statut = "o", typ = "TXM", min=1, max=1, defaut = "AnalysisPrinter", into=("AnalysisPrinter", "AnalysisSaver", "AnalysisPrinterAndSaver")),
166         AnalysisPrinter = BLOC (condition = " Template == 'AnalysisPrinter' ",
167             ValueTemplate = SIMP(statut = "o", typ = "TXM", min=1, max=1, defaut = "import numpy\\nxa=numpy.ravel(ADD.get('Analysis')[-1])\\nprint('Analysis:',xa)" ),
168             ),
169         AnalysisSaver = BLOC (condition = " Template == 'AnalysisSaver' ",
170             ValueTemplate = SIMP(statut = "o", typ = "TXM", min=1, max=1, defaut = "import numpy\\nxa=numpy.ravel(ADD.get('Analysis')[-1])\\nf='/tmp/analysis.txt'\\nprint('Analysis saved in \\"%s\\"'%f)\\nnumpy.savetxt(f,xa)" ),
171             ),
172         AnalysisPrinterAndSaver = BLOC (condition = " Template == 'AnalysisPrinterAndSaver' ",
173             ValueTemplate = SIMP(statut = "o", typ = "TXM", min=1, max=1, defaut = "import numpy\\nxa=numpy.ravel(ADD.get('Analysis')[-1])\\nprint 'Analysis:',xa\\nf='/tmp/analysis.txt'\\nprint('Analysis saved in \\"%s\\"'%f)\\nnumpy.savetxt(f,xa)" ),
174             ),
175         ),
176     )
177 """
178
179 init_method = """
180 def F_InitChoice() : return  ("Background",
181                               "BackgroundError",
182                               "Observation",
183                               "ObservationError",
184                               "ObservationOperator",
185                               "EvolutionModel",
186                               "EvolutionError",
187                               "AlgorithmParameters",
188                               "UserPostAnalysis",
189                              )
190
191 def F_Init(statut) : return FACT(statut = statut,
192     INIT_FILE = SIMP(statut = "o", typ = "FichierNoAbs", validators=[OnlyStr(), FileExtVal('py')]),
193     TARGET_LIST = SIMP(statut = "o", typ = "TXM", min=1, max="**", into=F_InitChoice(),  validators=(VerifExiste(2))),
194     )
195 """
196
197 assim_data_method = """
198 def {assim_name}InNS(filename):
199     if os.path.exists(filename):
200         fc = open(filename, 'r').readlines()
201         cr = re.compile("^{assim_name}[\s]*=")
202         for ln in fc:
203             if cr.match(ln): return 1
204     return 0
205 {assim_name}InNS.info = u"The Python file has to contain explicitly a \\"{assim_name}\\" variable."
206 def F_{assim_name}(statut, fv=NoCheckInNS) : return FACT(
207     statut=statut,
208 {storage}
209     INPUT_TYPE = SIMP(statut="o", typ = "TXM", into=({choices}), defaut={default_choice}),{decl_choices}
210     )
211 """
212
213 assim_data_choice = """
214     {choice_name} = BLOC ( condition = " INPUT_TYPE in ( '{choice_name}', ) ",
215         data = F_{choice_name}("o", fv),
216         ),"""
217
218 observers_choice = """
219     {var_name} = BLOC (condition=" '{var_name}' in set(SELECTION) ",
220         {var_name}_data = FACT(statut = "o",
221             Scheduler    = SIMP(statut = "f", typ = "TXM"),
222             Info         = SIMP(statut = "o", typ = "TXM", defaut = "{var_name}"),
223             NodeType     = SIMP(statut = "o", typ = "TXM", min=1, max=1, defaut = "Template", into=("String", "Script", "Template")),
224             PythonScript = BLOC (condition = " NodeType == 'String' ",
225                 Value = SIMP(statut = "o", typ = "TXM")
226                 ),
227             UserFile = BLOC (condition = " NodeType == 'Script' ",
228                 Value = SIMP(statut = "o", typ = "FichierNoAbs", validators=[OnlyStr(), FileExtVal('py')])
229                 ),
230             ObserverTemplate = F_ObserverTemplate(),
231             ),
232         ),"""
233
234 from daCore.Templates import ObserverTemplates
235 observers_list = ObserverTemplates.keys_in_presentation_order()
236 observers_list = '"%s"'%str('", "'.join(observers_list))
237 observers_cont = ""
238 for k in ObserverTemplates.keys_in_presentation_order():
239     observers_cont += """                %s = BLOC (condition = " Template == '%s' ",\n"""%(k,k)
240     observers_cont += """                    ValueTemplate = SIMP(statut = "o", typ = "TXM", min=1, max=1, defaut = "%s", fr="%s", ang="%s" ),\n"""%(
241         ObserverTemplates[k].replace("\n","\\n").replace('"','\\"'),
242         ObserverTemplates.getdoc(k, "fr_FR"),
243         ObserverTemplates.getdoc(k, "en_EN"),
244         )
245     observers_cont += """                    ),\n"""
246 observers_method = """
247 def F_ObserverTemplate() : return BLOC(condition = " NodeType == 'Template' ",
248                 Template = SIMP(statut = "o", typ = "TXM", min=1, max=1, defaut = "ValuePrinter", into=(%s)),
249 %s                )
250
251 def F_Observers(statut) : return FACT(
252     statut=statut,
253     SELECTION = SIMP(statut="o", defaut=[], typ="TXM", min=0, max="**", homo="SansOrdreNiDoublon", validators=NoRepeat(), into=({choices})),{decl_choices}
254     )
255 """%(observers_list,observers_cont)
256
257 algo_choices = """
258 def AlgorithmParametersInNS(filename):
259     if os.path.exists(filename):
260         fc = open(filename, 'r').readlines()
261         cr = re.compile("^AlgorithmParameters[\s]*=")
262         for ln in fc:
263             if cr.match(ln): return 1
264     return 0
265 AlgorithmParametersInNS.info = u"The Python file has to contain explicitly an \\"AlgorithmParameters\\" variable."
266 def F_AlgorithmParameters(statut, algos_names, fv=NoCheckInNS) : return FACT(
267     statut = statut,
268     Algorithm = SIMP(statut="o", typ = "TXM", into = algos_names ),
269     Parameters = SIMP(statut="f", typ = "TXM", into=("Defaults", "Dict"), defaut="Defaults"),
270     Dict = BLOC ( condition = " Parameters == 'Dict' ",
271         statut="f",
272         data = F_Dict("o", fv),
273         ),{all_algo_defaults}
274     )
275 """
276 one_algo_choices = """
277     Parameters{algo_name} = BLOC (condition = " (Parameters == 'Defaults') and (Algorithm == '{algo_name}') ",
278         statut="f",
279 {algo_parameters}        ),"""
280
281 assim_study = """
282 def F_variables(statut) : return FACT(
283     statut=statut,
284     regles = ( MEME_NOMBRE ('NAMES', 'SIZES')),
285     NAMES = SIMP(statut="o", typ="TXM", max="**", validators=NoRepeat()),
286     SIZES = SIMP(statut="o", typ="I", val_min=1, max="**")
287     )
288 def ChDir(dirname):
289     os.chdir(os.path.abspath(dirname))
290     return 1
291 ChDir.info = u"This has to be a regular directory path."
292
293 ASSIMILATION_STUDY = PROC(nom="ASSIMILATION_STUDY",
294     op=None,
295     repetable           = "n",
296     StudyName           = SIMP(statut="o", typ = "TXM", defaut="ADAO Calculation Case"),
297     StudyRepertory      = SIMP(statut="f", typ = "Repertoire", validators=FunctionVal(ChDir), min=1, max=1),
298     Debug               = SIMP(statut="f", typ = "I", into=(0, 1), defaut=0),
299     AlgorithmParameters = F_AlgorithmParameters("o",({algos_names}), AlgorithmParametersInNS),
300     Background          = F_Background("o", BackgroundInNS),
301     BackgroundError     = F_BackgroundError("o", BackgroundErrorInNS),
302     Observation         = F_Observation("o", ObservationInNS),
303     ObservationError    = F_ObservationError("o", ObservationErrorInNS),
304     ObservationOperator = F_ObservationOperator("o"),
305     EvolutionModel      = F_EvolutionModel("f"),
306     EvolutionError      = F_EvolutionError("f", EvolutionErrorInNS),
307     ControlInput        = F_ControlInput("f"),
308     UserDataInit        = F_Init("f"),
309     UserPostAnalysis    = F_UserPostAnalysis("o"),
310     InputVariables      = F_variables("f"),
311     OutputVariables     = F_variables("f"),
312     Observers           = F_Observers("f")
313     )
314
315 CHECKING_STUDY = PROC(nom="CHECKING_STUDY",
316     op=None,
317     repetable           = "n",
318     StudyName           = SIMP(statut="o", typ = "TXM", defaut="ADAO Checking Case"),
319     StudyRepertory      = SIMP(statut="f", typ = "Repertoire", validators=FunctionVal(ChDir), min=1, max=1),
320     Debug               = SIMP(statut="f", typ = "I", into=(0, 1), defaut=0),
321     AlgorithmParameters = F_AlgorithmParameters("o", ({check_names}), AlgorithmParametersInNS),
322     CheckingPoint       = F_CheckingPoint("o", CheckingPointInNS),
323     BackgroundError     = F_BackgroundError("f", BackgroundErrorInNS),
324     Observation         = F_Observation("f", ObservationInNS),
325     ObservationError    = F_ObservationError("f", ObservationErrorInNS),
326     ObservationOperator = F_ObservationOperator("o"),
327     UserDataInit        = F_Init("f"),
328     Observers           = F_Observers("f")
329     )
330 """
331
332 #----------- End of Templates Part ---------------#
333
334
335
336 #----------- Begin generation script -----------#
337
338 # Parse arguments
339 from argparse import ArgumentParser
340 usage = "usage: %(prog)s [options] catalog_path catalog_name"
341 version="%(prog)s 0.1"
342 my_parser = ArgumentParser(usage=usage)
343 my_parser.add_argument('-v', '--version', action='version', version=version)
344 my_parser.add_argument('catalog_path')
345 my_parser.add_argument('catalog_name')
346 args = my_parser.parse_args()
347
348 # Generates into a string
349 mem_file = io.StringIO()
350
351 # Start file
352 from time import strftime
353 mem_file.write(unicode(begin_catalog_file, 'utf-8').format(**{'date':strftime("%Y-%m-%d %H:%M:%S")}))
354
355 # Step initial: on obtient la liste des algos
356 algos_names = ""
357 check_names = ""
358 decl_algos  = ""
359 assim_study_object = daCore.AssimilationStudy.AssimilationStudy()
360 algos_list = assim_study_object.get_available_algorithms()
361 del assim_study_object
362 for algo_name in algos_list:
363   if algo_name in infos.AssimAlgos:
364     logging.debug("An assimilation algorithm is found: " + algo_name)
365     algos_names += "\"" + algo_name + "\", "
366   elif algo_name in infos.CheckAlgos:
367     logging.debug("A checking algorithm is found: " + algo_name)
368     check_names += "\"" + algo_name + "\", "
369   else:
370     logging.debug("This algorithm is not considered: " + algo_name)
371
372 # Step 1: A partir des infos, on cree les fonctions qui vont permettre
373 # d'entrer les donnees utilisateur
374 for data_input_name in infos.DataTypeDict:
375   logging.debug('A data input Type is found: ' + data_input_name)
376   data_name = data_input_name
377   data_into = ""
378   data_default = ""
379   ms_default = ""
380
381   # On recupere les differentes facon d'entrer les donnees
382   for basic_type in infos.DataTypeDict[data_input_name]:
383     data_into += "\"" + basic_type + "\", "
384
385   # On choisit le default
386   data_default = "\"" + infos.DataTypeDefaultDict[data_input_name] + "\""
387   if data_input_name in infos.DataSValueDefaultDict:
388     ms_default = " defaut=\"" + infos.DataSValueDefaultDict[data_input_name] + "\","
389
390   mem_file.write(unicode(data_method, 'utf-8').format(**{
391     'data_name'    : data_name,
392     'data_into'    : data_into,
393     'data_default' : data_default,
394     'ms_default'   : ms_default,
395     'algos_names'  : algos_names+check_names,
396     }))
397
398 # Step 2: On cree les fonctions qui permettent de rentrer les donnees des algorithmes
399 for assim_data_input_name in infos.AssimDataDict:
400   logging.debug("An input function data input is found: " + assim_data_input_name)
401   # assim_name = assim_data_input_name
402   storage = ""
403   choices = ""
404   default_choice = ""
405   decl_choices = ""
406   decl_opts = ""
407   if infos.AssimDataDefaultDict[assim_data_input_name] in infos.StoredAssimData:
408     storage = "    Stored = SIMP(statut=\"f\", typ = \"I\", into=(0, 1), defaut=0, fr=\"Choix de stockage interne ou non du concept parent\", ang=\"Choice of the storage or not of the parent concept\"),"
409   for choice in infos.AssimDataDict[assim_data_input_name]:
410     choices += "\"" + choice + "\", "
411     decl_choices += assim_data_choice.format(**{'choice_name' : choice})
412     if choice in infos.StoredAssimData:
413       storage = "    Stored = SIMP(statut=\"f\", typ = \"I\", into=(0, 1), defaut=0, fr=\"Choix de stockage interne ou non du concept parent\", ang=\"Choice of the storage or not of the parent concept\"),"
414   default_choice = "\"" + infos.AssimDataDefaultDict[assim_data_input_name] + "\""
415
416   mem_file.write(unicode(assim_data_method, 'utf-8').format(**{
417     'assim_name'     : assim_data_input_name,
418     'storage'        : storage,
419     'choices'        : choices,
420     'decl_choices'   : decl_choices,
421     'default_choice' : default_choice,
422     }))
423
424 # Step 3: On ajoute les fonctions representant les options possibles
425 for opt_name in infos.OptDict:
426   logging.debug("An optional node is found: " + opt_name)
427   data_name = opt_name
428   data_into = ""
429   data_default = ""
430   ms_default = ""
431
432   for choice in infos.OptDict[opt_name]:
433     data_into += "\"" + choice + "\", "
434
435   # On choisit le default
436   data_default = "\"" + infos.OptDefaultDict[opt_name] + "\""
437   if opt_name in infos.DataSValueDefaultDict:
438     ms_default = " defaut=\"" + infos.DataSValueDefaultDict[opt_name] + "\","
439
440   mem_file.write(unicode(data_method, 'utf-8').format(**{
441     'data_name'    : data_name,
442     'data_into'    : data_into,
443     'data_default' : data_default,
444     'ms_default'   : ms_default,
445     'algos_names'  : algos_names+check_names,
446     }))
447
448 # Step 4: On ajoute la methode optionnelle init
449 # TODO uniformiser avec le step 3
450 mem_file.write(unicode(init_method, 'utf-8'))
451
452 # Step 5: Add observers
453 decl_choices = ""
454 for obs_var in infos.ObserversList:
455   decl_choices += observers_choice.format(**{'var_name':obs_var})
456 mem_file.write(unicode(observers_method, 'utf-8').format(**{
457   'choices' : infos.ObserversList,
458   'decl_choices' : decl_choices,
459   }))
460
461 # Step 5: Add algorithmic choices
462
463 all_names = eval((algos_names+check_names))
464 all_algo_defaults = ""
465 for algo in all_names:
466     assim_study_object = daCore.AssimilationStudy.AssimilationStudy()
467     assim_study_object.setAlgorithmParameters(Algorithm=algo)
468     par_dict = assim_study_object.get("AlgorithmRequiredParameters",False)
469     par_keys = sorted(par_dict.keys())
470     algo_parameters = ""
471     for pn in par_keys:
472         if pn in ("StoreInternalVariables", "PlotAndSave", "ResultFile", "ResultTitle", "ResultLabel"): continue # Cles a supprimer
473         pt = par_dict[pn]["typecast"] # Pointeur de type
474         pd = par_dict[pn]["default"]
475         pm = par_dict[pn]["message"]
476         if "minval" in par_dict[pn] and par_dict[pn]["minval"] is not None:
477             vi = ", val_min=%s"%par_dict[pn]["minval"]
478         else:
479             vi = ""
480         if "minval" in par_dict[pn] and par_dict[pn]["maxval"] is not None:
481             vs = ", val_max=%s"%par_dict[pn]["maxval"]
482         else:
483             vs = ""
484         if   pt is int:
485             algo_parameters += """        %s = SIMP(statut="f", typ="I"%s%s, min=1, max=1, defaut=%s, fr="%s"),\n"""%(pn,vi,vs,int(pd),pm)
486         elif pt is float:
487             algo_parameters += """        %s = SIMP(statut="f", typ="R"%s%s, min=1, max=1, defaut=%s, fr="%s"),\n"""%(pn,vi,vs,float(pd),pm)
488         elif pt is bool:
489             algo_parameters += """        %s = SIMP(statut="f", typ="I", min=1, max=1, defaut=%s, fr="%s"),\n"""%(pn,int(pd),pm)
490         elif pt is str and "listval" in par_dict[pn]:
491             algo_parameters += """        %s = SIMP(statut="f", typ="TXM", min=1, max=1, defaut="%s", into=%s, fr="%s"),\n"""%(pn,pd,par_dict[pn]["listval"],pm)
492         elif pt is tuple and "listval" in par_dict[pn]:
493             algo_parameters += """        %s = SIMP(statut="f", typ="TXM", max="**", into=%s, fr="%s"),\n"""%(pn,par_dict[pn]["listval"],pm)
494         else:
495             algo_parameters += """        %s = SIMP(statut="f", typ="TXM", fr="%s"),\n"""%(pn,pm)
496     del assim_study_object
497     if algo_parameters != "":
498         all_algo_defaults += one_algo_choices.format(**{
499             'algo_name':algo,
500             'algo_parameters':algo_parameters,
501             })
502 mem_file.write(unicode(algo_choices, 'utf-8').format(**{'all_algo_defaults':unicode(all_algo_defaults, 'utf-8')}))
503
504 # Final step: Add algorithm and assim_study
505 mem_file.write(unicode(assim_study, 'utf-8').format(**{
506   'algos_names':algos_names,
507   'check_names':check_names,
508   'decl_algos':decl_algos,
509   }))
510
511 # Write file
512 if sys.version_info.major > 2:
513     with open(os.path.join(args.catalog_path, args.catalog_name), "w", encoding='utf8') as final_file:
514         final_file.write(mem_file.getvalue())
515 else:
516     with open(os.path.join(args.catalog_path, args.catalog_name), "wr") as final_file:
517         final_file.write(mem_file.getvalue().encode('utf-8'))
518 mem_file.close()