Salome HOME
Code improvements, review and simplifications (2)
[modules/adao.git] / src / daComposant / daCore / Interfaces.py
index 969686ae5fdf69d2482afba6bc620288bff08390..34508cb233aeb851fdde8bf1b0f0558c4689b4ea 100644 (file)
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2008-2018 EDF R&D
+# Copyright (C) 2008-2022 EDF R&D
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -28,17 +28,19 @@ __all__ = []
 
 import os
 import sys
+import numpy
+import mimetypes
 import logging
 import copy
-import numpy
 from daCore import Persistence
 from daCore import PlatformInfo
 from daCore import Templates
+from daCore import Reporting
 
 # ==============================================================================
 class GenericCaseViewer(object):
     """
-    Gestion des commandes de creation d'une vue de cas
+    Gestion des commandes de création d'une vue de cas
     """
     def __init__(self, __name="", __objname="case", __content=None, __object=None):
         "Initialisation et enregistrement de l'entete"
@@ -51,15 +53,20 @@ class GenericCaseViewer(object):
         self._object       = __object
         self._missing = """raise ValueError("This case requires beforehand to import or define the variable named <%s>. When corrected, remove this command, correct and uncomment the following one.")\n# """
     def _append(self, *args):
-        "Transformation de commande individuelle en enregistrement"
+        "Transformation d'une commande individuelle en un enregistrement"
         raise NotImplementedError()
     def _extract(self, *args):
-        "Transformation d'enregistrement en commande individuelle"
+        "Transformation d'enregistrement(s) en commande(s) individuelle(s)"
         raise NotImplementedError()
     def _finalize(self, __upa=None):
         "Enregistrement du final"
-        if __upa is not None and len(__upa)>0:
+        __hasNotExecute = True
+        for l in self._lineSerie:
+            if "%s.execute"%(self._objname,) in l: __hasNotExecute = False
+        if __hasNotExecute:
             self._lineSerie.append("%s.execute()"%(self._objname,))
+        if __upa is not None and len(__upa)>0:
+            __upa = __upa.replace("ADD",str(self._objname))
             self._lineSerie.append(__upa)
     def _addLine(self, line=""):
         "Ajoute un enregistrement individuel"
@@ -92,7 +99,7 @@ class GenericCaseViewer(object):
 
 class _TUIViewer(GenericCaseViewer):
     """
-    Etablissement des commandes d'un cas ADAO TUI (Cas<->TUI)
+    Établissement des commandes d'un cas ADAO TUI (Cas<->TUI)
     """
     def __init__(self, __name="", __objname="case", __content=None, __object=None):
         "Initialisation et enregistrement de l'entete"
@@ -100,7 +107,7 @@ class _TUIViewer(GenericCaseViewer):
         self._addLine("# -*- coding: utf-8 -*-")
         self._addLine("#\n# Python script using ADAO TUI\n#")
         self._addLine("from numpy import array, matrix")
-        self._addLine("import adaoBuilder")
+        self._addLine("from adao import adaoBuilder")
         self._addLine("%s = adaoBuilder.New('%s')"%(self._objname, self._name))
         if self._content is not None:
             for command in self._content:
@@ -108,6 +115,8 @@ class _TUIViewer(GenericCaseViewer):
     def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
         "Transformation d'une commande individuelle en un enregistrement"
         if __command is not None and __keys is not None and __local is not None:
+            if "Concept" in __keys:
+                logging.debug("TUI Order processed: %s"%(__local["Concept"],))
             __text  = ""
             if __pre is not None:
                 __text += "%s = "%__pre
@@ -115,12 +124,16 @@ class _TUIViewer(GenericCaseViewer):
             if "self" in __keys: __keys.remove("self")
             if __command not in ("set","get") and "Concept" in __keys: __keys.remove("Concept")
             for k in __keys:
+                if k not in __local: continue
                 __v = __local[k]
                 if __v is None: continue
-                if   k == "Checked" and not __v: continue
-                if   k == "Stored"  and not __v: continue
-                if   k == "AvoidRC" and __v: continue
-                if   k == "noDetails": continue
+                if   k == "Checked"              and not __v: continue
+                if   k == "Stored"               and not __v: continue
+                if   k == "ColMajor"             and not __v: continue
+                if   k == "InputFunctionAsMulti" and not __v: continue
+                if   k == "nextStep"             and not __v: continue
+                if   k == "PerformanceProfile"   and     __v: continue
+                if   k == "noDetails":                        continue
                 if isinstance(__v,Persistence.Persistence): __v = __v.values()
                 if callable(__v): __text = self._missing%__v.__name__+__text
                 if isinstance(__v,dict):
@@ -129,11 +142,11 @@ class _TUIViewer(GenericCaseViewer):
                 numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
                 __text += "%s=%s, "%(k,repr(__v))
                 numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
-            __text.rstrip(", ")
-            __text += ")"
+            __text = __text.rstrip(", ")
+            __text += " )"
             self._addLine(__text)
     def _extract(self, __multilines="", __object=None):
-        "Transformation un enregistrement en une commande individuelle"
+        "Transformation d'enregistrement(s) en commande(s) individuelle(s)"
         __is_case = False
         __commands = []
         __multilines = __multilines.replace("\r\n","\n")
@@ -152,7 +165,7 @@ class _TUIViewer(GenericCaseViewer):
 
 class _COMViewer(GenericCaseViewer):
     """
-    Etablissement des commandes d'un cas COMM (Eficas Native Format/Cas<-COM)
+    Établissement des commandes d'un cas COMM (Eficas Native Format/Cas<-COM)
     """
     def __init__(self, __name="", __objname="case", __content=None, __object=None):
         "Initialisation et enregistrement de l'entete"
@@ -167,10 +180,26 @@ class _COMViewer(GenericCaseViewer):
             for command in self._content:
                 self._append(*command)
     def _extract(self, __multilines=None, __object=None):
-        "Transformation un enregistrement en une commande individuelle"
+        "Transformation d'enregistrement(s) en commande(s) individuelle(s)"
+        __suppparameters = {}
         if __multilines is not None:
-            __multilines = __multilines.replace("ASSIMILATION_STUDY","dict")
-            __multilines = __multilines.replace("CHECKING_STUDY",    "dict")
+            if 'adaoBuilder' in __multilines:
+                raise ValueError("Impossible to load given content as an ADAO COMM one (Hint: it's perhaps not a COMM input, but a TUI one).")
+            if "ASSIMILATION_STUDY" in __multilines:
+                __suppparameters.update({'StudyType':"ASSIMILATION_STUDY"})
+                __multilines = __multilines.replace("ASSIMILATION_STUDY","dict")
+            elif "OPTIMIZATION_STUDY" in __multilines:
+                __suppparameters.update({'StudyType':"ASSIMILATION_STUDY"})
+                __multilines = __multilines.replace("OPTIMIZATION_STUDY",    "dict")
+            elif "REDUCTION_STUDY" in __multilines:
+                __suppparameters.update({'StudyType':"ASSIMILATION_STUDY"})
+                __multilines = __multilines.replace("REDUCTION_STUDY",    "dict")
+            elif "CHECKING_STUDY" in __multilines:
+                __suppparameters.update({'StudyType':"CHECKING_STUDY"})
+                __multilines = __multilines.replace("CHECKING_STUDY",    "dict")
+            else:
+                __multilines = __multilines.replace("ASSIMILATION_STUDY","dict")
+            #
             __multilines = __multilines.replace("_F(",               "dict(")
             __multilines = __multilines.replace(",),);",             ",),)")
         __fulllines = ""
@@ -195,18 +224,33 @@ class _COMViewer(GenericCaseViewer):
                 __commands.append( "set( Concept='Name', String='%s')"%(str(r),) )
             elif   __command == "StudyRepertory":
                 __commands.append( "set( Concept='Directory', String='%s')"%(str(r),) )
+            elif   __command == "Debug" and str(r) == "0":
+                __commands.append( "set( Concept='NoDebug' )" )
+            elif   __command == "Debug" and str(r) == "1":
+                __commands.append( "set( Concept='Debug' )" )
+            elif   __command == "ExecuteInContainer":
+                __suppparameters.update({'ExecuteInContainer':r})
             #
             elif __command == "UserPostAnalysis" and type(r) is dict:
                 if 'STRING' in r:
-                    __UserPostAnalysis = r['STRING']
+                    __UserPostAnalysis = r['STRING'].replace("ADD",str(self._objname))
+                    __commands.append( "set( Concept='UserPostAnalysis', String=\"\"\"%s\"\"\" )"%(__UserPostAnalysis,) )
                 elif 'SCRIPT_FILE' in r and os.path.exists(r['SCRIPT_FILE']):
                     __UserPostAnalysis = open(r['SCRIPT_FILE'],'r').read()
-                elif 'Template' in r and 'ValueTemplate' in r:
+                    __commands.append( "set( Concept='UserPostAnalysis', Script='%s' )"%(r['SCRIPT_FILE'],) )
+                elif 'Template' in r and not 'ValueTemplate' in r:
                     # AnalysisPrinter...
+                    if r['Template'] not in Templates.UserPostAnalysisTemplates:
+                        raise ValueError("User post-analysis template \"%s\" does not exist."%(r['Template'],))
+                    else:
+                        __UserPostAnalysis = Templates.UserPostAnalysisTemplates[r['Template']]
+                    __commands.append( "set( Concept='UserPostAnalysis', Template='%s' )"%(r['Template'],) )
+                elif 'Template' in r and 'ValueTemplate' in r:
+                    # Le template ayant pu être modifié, donc on ne prend que le ValueTemplate...
                     __UserPostAnalysis = r['ValueTemplate']
+                    __commands.append( "set( Concept='UserPostAnalysis', String=\"\"\"%s\"\"\" )"%(__UserPostAnalysis,) )
                 else:
                     __UserPostAnalysis = ""
-                __UserPostAnalysis = __UserPostAnalysis.replace("ADD",self._objname)
             #
             elif __command == "AlgorithmParameters" and type(r) is dict and 'Algorithm' in r:
                 if 'data' in r and r['Parameters'] == 'Dict':
@@ -238,13 +282,13 @@ class _COMViewer(GenericCaseViewer):
                     if __idata['NodeType'] == 'Template' and 'Template' in __idata:
                         __template = __idata['Template']
                         if 'Info' in __idata:
-                            __info = ", Info='%s'"%(__idata['Info'],)
+                            __info = ", Info=\"\"\"%s\"\"\""%(__idata['Info'],)
                         else:
                             __info = ""
-                        __commands.append( "set( Concept='Observer', Variable='%s', Template='%s'%s )"%(sk,__template,__info) )
+                        __commands.append( "set( Concept='Observer', Variable='%s', Template=\"\"\"%s\"\"\"%s )"%(sk,__template,__info) )
                     if __idata['NodeType'] == 'String' and 'Value' in __idata:
                         __value =__idata['Value']
-                        __commands.append( "set( Concept='Observer', Variable='%s', String='%s' )"%(sk,__value) )
+                        __commands.append( "set( Concept='Observer', Variable='%s', String=\"\"\"%s\"\"\" )"%(sk,__value) )
             #
             # Background, ObservationError, ObservationOperator...
             elif type(r) is dict:
@@ -256,7 +300,7 @@ class _COMViewer(GenericCaseViewer):
                     __itype = r['INPUT_TYPE']
                     __idata = r['data']
                     if 'FROM' in __idata:
-                        # String, Script, Template, ScriptWithOneFunction, ScriptWithFunctions
+                        # String, Script, DataFile, Template, ScriptWithOneFunction, ScriptWithFunctions
                         __ifrom = __idata['FROM']
                         __idata.pop('FROM','')
                         if __ifrom == 'String' or __ifrom == 'Template':
@@ -264,6 +308,9 @@ class _COMViewer(GenericCaseViewer):
                         if __ifrom == 'Script':
                             __argumentsList.append([__itype,True])
                             __argumentsList.append(['Script',__idata['SCRIPT_FILE']])
+                        if __ifrom == 'DataFile':
+                            __argumentsList.append([__itype,True])
+                            __argumentsList.append(['DataFile',__idata['DATA_FILE']])
                         if __ifrom == 'ScriptWithOneFunction':
                             __argumentsList.append(['OneFunction',True])
                             __argumentsList.append(['Script',__idata.pop('SCRIPTWITHONEFUNCTION_FILE')])
@@ -277,6 +324,8 @@ class _COMViewer(GenericCaseViewer):
                 __arguments = ["%s = %s"%(k,repr(v)) for k,v in __argumentsList]
                 __commands.append( "set( Concept='%s', %s )"%(__command, ", ".join(__arguments)))
         #
+        __commands.append( "set( Concept='%s', Parameters=%s )"%('SupplementaryParameters', repr(__suppparameters)))
+        #
         # ----------------------------------------------------------------------
         __commands.sort() # Pour commencer par 'AlgorithmParameters'
         __commands.append(__UserPostAnalysis)
@@ -284,20 +333,30 @@ class _COMViewer(GenericCaseViewer):
 
 class _SCDViewer(GenericCaseViewer):
     """
-    Etablissement des commandes d'un cas SCD (Study Config Dictionary/Cas->SCD)
+    Établissement des commandes d'un cas SCD (Study Config Dictionary/Cas->SCD)
+
+    Remarque : le fichier généré est différent de celui obtenu par EFICAS
     """
     def __init__(self, __name="", __objname="case", __content=None, __object=None):
-        "Initialisation et enregistrement de l'entete"
+        "Initialisation et enregistrement de l'entête"
         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
+        #
+        if __content is not None:
+            for command in __content:
+                if command[0] == "set": __command = command[2]["Concept"]
+                else:                   __command = command[0].replace("set", "", 1)
+                if __command == 'Name':
+                    self._name = command[2]["String"]
+        #
+        self.__DebugCommandNotSet = True
+        self.__ObserverCommandNotSet = True
+        self.__UserPostAnalysisNotSet = True
+        #
         self._addLine("# -*- coding: utf-8 -*-")
-        self._addLine("#\n# Input for ADAO converter to YACS\n#")
-        self._addLine("from numpy import array, matrix")
+        self._addLine("#\n# Input for ADAO converter to SCD\n#")
         self._addLine("#")
         self._addLine("study_config = {}")
-        self._addLine("study_config['StudyType'] = 'ASSIMILATION_STUDY'")
         self._addLine("study_config['Name'] = '%s'"%self._name)
-        self._addLine("observers = {}")
-        self._addLine("study_config['Observers'] = observers")
         self._addLine("#")
         self._addLine("inputvariables_config = {}")
         self._addLine("inputvariables_config['Order'] =['adao_default']")
@@ -315,15 +374,24 @@ class _SCDViewer(GenericCaseViewer):
         "Transformation d'une commande individuelle en un enregistrement"
         if __command == "set": __command = __local["Concept"]
         else:                  __command = __command.replace("set", "", 1)
+        logging.debug("SCD Order processed: %s"%(__command))
         #
         __text  = None
         if __command in (None, 'execute', 'executePythonScheme', 'executeYACSScheme', 'get', 'Name'):
             return
+        elif __command in ['Directory',]:
+            __text  = "#\nstudy_config['Repertory'] = %s"%(repr(__local['String']))
         elif __command in ['Debug', 'setDebug']:
             __text  = "#\nstudy_config['Debug'] = '1'"
+            self.__DebugCommandNotSet = False
         elif __command in ['NoDebug', 'setNoDebug']:
             __text  = "#\nstudy_config['Debug'] = '0'"
+            self.__DebugCommandNotSet = False
         elif __command in ['Observer', 'setObserver']:
+            if self.__ObserverCommandNotSet:
+                self._addLine("observers = {}")
+                self._addLine("study_config['Observers'] = observers")
+                self.__ObserverCommandNotSet = False
             __obs   = __local['Variable']
             self._numobservers += 1
             __text  = "#\n"
@@ -342,21 +410,50 @@ class _SCDViewer(GenericCaseViewer):
             else:
                 __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __obs)
             __text += "observers['%s']['number'] = %s"%(__obs, self._numobservers)
+        elif __command in ['UserPostAnalysis', 'setUserPostAnalysis']:
+            __text  = "#\n"
+            __text += "Analysis_config = {}\n"
+            if __local['String'] is not None:
+                __text += "Analysis_config['From'] = 'String'\n"
+                __text += "Analysis_config['Data'] = \"\"\"%s\"\"\"\n"%(__local['String'],)
+            if __local['Script'] is not None:
+                __text += "Analysis_config['From'] = 'Script'\n"
+                __text += "Analysis_config['Data'] = \"\"\"%s\"\"\"\n"%(__local['Script'],)
+            if __local['Template'] is not None and __local['Template'] in Templates.UserPostAnalysisTemplates:
+                __text += "Analysis_config['From'] = 'String'\n"
+                __text += "Analysis_config['Data'] = \"\"\"%s\"\"\"\n"%(Templates.UserPostAnalysisTemplates[__local['Template']],)
+            __text += "study_config['UserPostAnalysis'] = Analysis_config"
+            self.__UserPostAnalysisNotSet = False
         elif __local is not None: # __keys is not None and
             numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
             __text  = "#\n"
             __text += "%s_config = {}\n"%__command
             __local.pop('self','')
             __to_be_removed = []
+            __vectorIsDataFile = False
+            __vectorIsScript = False
             for __k,__v in __local.items():
                 if __v is None: __to_be_removed.append(__k)
             for __k in __to_be_removed:
                 __local.pop(__k)
             for __k,__v in __local.items():
                 if __k == "Concept": continue
-                if __k in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix','OneFunction','ThreeFunctions'] and 'Script' in __local: continue
+                if __k in ['ScalarSparseMatrix','DiagonalSparseMatrix','Matrix','OneFunction','ThreeFunctions'] and 'Script' in __local and __local['Script'] is not None: continue
+                if __k in ['Vector','VectorSerie'] and 'DataFile' in __local and __local['DataFile'] is not None: continue
+                if __k == 'Parameters' and not (__command in ['AlgorithmParameters','SupplementaryParameters']): continue
                 if __k == 'Algorithm':
                     __text += "study_config['Algorithm'] = %s\n"%(repr(__v))
+                elif __k == 'DataFile':
+                    __k = 'Vector'
+                    __f = 'DataFile'
+                    __v = "'"+repr(__v)+"'"
+                    for __lk in ['Vector','VectorSerie']:
+                        if __lk in __local and __local[__lk]: __k = __lk
+                    __text += "%s_config['Type'] = '%s'\n"%(__command,__k)
+                    __text += "%s_config['From'] = '%s'\n"%(__command,__f)
+                    __text += "%s_config['Data'] = %s\n"%(__command,__v)
+                    __text = __text.replace("''","'")
+                    __vectorIsDataFile = True
                 elif __k == 'Script':
                     __k = 'Vector'
                     __f = 'Script'
@@ -390,13 +487,16 @@ class _SCDViewer(GenericCaseViewer):
                     __text += "%s_config['From'] = '%s'\n"%(__command,__f)
                     __text += "%s_config['Data'] = %s\n"%(__command,__v)
                     __text = __text.replace("''","'")
-                elif __k in ('Stored', 'Checked'):
+                    __vectorIsScript = True
+                elif __k in ('Stored', 'Checked', 'ColMajor', 'InputFunctionAsMulti', 'nextStep'):
                     if bool(__v):
                         __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
-                elif __k in ('AvoidRC', 'noDetails'):
+                elif __k in ('PerformanceProfile', 'noDetails'):
                     if not bool(__v):
                         __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v)))
                 else:
+                    if __k == 'Vector' and __vectorIsScript: continue
+                    if __k == 'Vector' and __vectorIsDataFile: continue
                     if __k == 'Parameters': __k = "Dict"
                     if isinstance(__v,Persistence.Persistence): __v = __v.values()
                     if callable(__v): __text = self._missing%__v.__name__+__text
@@ -415,13 +515,16 @@ class _SCDViewer(GenericCaseViewer):
             self._switchoff = False
     def _finalize(self, *__args):
         self.__loadVariablesByScript()
-        self._addLine("#")
-        self._addLine("Analysis_config = {}")
-        self._addLine("Analysis_config['From'] = 'String'")
-        self._addLine("Analysis_config['Data'] = \"\"\"import numpy")
-        self._addLine("xa=numpy.ravel(ADD.get('Analysis')[-1])")
-        self._addLine("print 'Analysis:',xa\"\"\"")
-        self._addLine("study_config['UserPostAnalysis'] = Analysis_config")
+        if self.__DebugCommandNotSet:
+            self._addLine("#\nstudy_config['Debug'] = '0'")
+        if self.__UserPostAnalysisNotSet:
+            self._addLine("#")
+            self._addLine("Analysis_config = {}")
+            self._addLine("Analysis_config['From'] = 'String'")
+            self._addLine("Analysis_config['Data'] = \"\"\"import numpy")
+            self._addLine("xa=ADD.get('Analysis')[-1]")
+            self._addLine("print('Analysis:',xa)\"\"\"")
+            self._addLine("study_config['UserPostAnalysis'] = Analysis_config")
     def __loadVariablesByScript(self):
         __ExecVariables = {} # Necessaire pour recuperer la variable
         exec("\n".join(self._lineSerie), __ExecVariables)
@@ -451,6 +554,20 @@ class _SCDViewer(GenericCaseViewer):
             __text += "AlgorithmParameters_config['From'] = 'String'\n"
             __text += "AlgorithmParameters_config['Data'] = '{}'\n"
             self._addLine(__text)
+        if 'SupplementaryParameters' in study_config and \
+                isinstance(study_config['SupplementaryParameters'], dict) and \
+                "From" in study_config['SupplementaryParameters'] and \
+                study_config['SupplementaryParameters']["From"] == 'String' and \
+                "Data" in study_config['SupplementaryParameters']:
+            __dict = eval(study_config['SupplementaryParameters']["Data"])
+            if 'ExecuteInContainer' in __dict:
+                self._addLine("#\nstudy_config['ExecuteInContainer'] = '%s'"%__dict['ExecuteInContainer'])
+            else:
+                self._addLine("#\nstudy_config['ExecuteInContainer'] = 'No'")
+            if 'StudyType' in __dict:
+                self._addLine("#\nstudy_config['StudyType'] = '%s'"%__dict['StudyType'])
+            if 'StudyType' in __dict and __dict['StudyType'] != "ASSIMILATION_STUDY":
+                self.__UserPostAnalysisNotSet = False
         del study_config
 
 class _YACSViewer(GenericCaseViewer):
@@ -475,8 +592,8 @@ class _YACSViewer(GenericCaseViewer):
         if not PlatformInfo.has_salome or \
             not PlatformInfo.has_adao:
             raise ImportError(
-                "Unable to get SALOME or ADAO environnement variables for YACS conversion.\n"+\
-                "Please load the right environnement before trying to use it.")
+                "Unable to get SALOME or ADAO environnement for YACS conversion.\n"+\
+                "Please load the right SALOME environnement before trying to use it.")
         else:
             from daYacsSchemaCreator.run import create_schema_from_content
         # -----
@@ -496,6 +613,76 @@ class _YACSViewer(GenericCaseViewer):
         __fid.close()
         return __text
 
+# ==============================================================================
+class _ReportViewer(GenericCaseViewer):
+    """
+    Partie commune de restitution simple
+    """
+    def __init__(self, __name="", __objname="case", __content=None, __object=None):
+        "Initialisation et enregistrement de l'entete"
+        GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
+        self._r = Reporting.ReportStorage()
+        self._r.clear()
+        if self._name == "":
+            self._r.append("ADAO Study report", "title")
+        else:
+            self._r.append(str(self._name), "title")
+        if self._content is not None:
+            for command in self._content:
+                self._append(*command)
+    def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
+        "Transformation d'une commande individuelle en un enregistrement"
+        if __command is not None and __keys is not None and __local is not None:
+            if __command in ("set","get") and "Concept" in __keys: __command = __local["Concept"]
+            __text  = ""
+            __text += "<i>%s</i> command has been set"%str(__command.replace("set",""))
+            __ktext = ""
+            for k in __keys:
+                if k not in __local: continue
+                __v = __local[k]
+                if __v is None: continue
+                if   k == "Checked"              and not __v: continue
+                if   k == "Stored"               and not __v: continue
+                if   k == "ColMajor"             and not __v: continue
+                if   k == "InputFunctionAsMulti" and not __v: continue
+                if   k == "nextStep"             and not __v: continue
+                if   k == "PerformanceProfile"   and     __v: continue
+                if   k == "noDetails":                        continue
+                if   k == "Concept":                          continue
+                if   k == "self":                             continue
+                if isinstance(__v,Persistence.Persistence): __v = __v.values()
+                numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15)
+                __ktext += "\n        %s = %s,"%(k,repr(__v))
+                numpy.set_printoptions(precision=8,threshold=1000,linewidth=75)
+            if len(__ktext) > 0:
+                __text += " with values:" + __ktext
+            __text = __text.rstrip(", ")
+            self._r.append(__text, "uli")
+    def _finalize(self, __upa=None):
+        "Enregistrement du final"
+        raise NotImplementedError()
+
+class _SimpleReportInRstViewer(_ReportViewer):
+    """
+    Restitution simple en RST
+    """
+    def _finalize(self, __upa=None):
+        self._lineSerie.append(Reporting.ReportViewInRst(self._r).__str__())
+
+class _SimpleReportInHtmlViewer(_ReportViewer):
+    """
+    Restitution simple en HTML
+    """
+    def _finalize(self, __upa=None):
+        self._lineSerie.append(Reporting.ReportViewInHtml(self._r).__str__())
+
+class _SimpleReportInPlainTxtViewer(_ReportViewer):
+    """
+    Restitution simple en TXT
+    """
+    def _finalize(self, __upa=None):
+        self._lineSerie.append(Reporting.ReportViewInPlainTxt(self._r).__str__())
+
 # ==============================================================================
 class ImportFromScript(object):
     """
@@ -513,9 +700,14 @@ class ImportFromScript(object):
             __basename = os.path.basename(__filename).rstrip(".py")
         else:
             __basename = __filename.rstrip(".py")
+        PlatformInfo.checkFileNameImportability( __basename+".py" )
         self.__basename = __basename
-        self.__filenspace = __import__(__basename, globals(), locals(), [])
-        self.__filestring = open(__filename,'r').read()
+        try:
+            self.__filenspace = __import__(__basename, globals(), locals(), [])
+        except NameError:
+            self.__filenspace = ""
+        with open(__filename,'r') as fid:
+            self.__filestring = fid.read()
     def getvalue(self, __varname=None, __synonym=None ):
         "Renvoie la variable demandee par son nom ou son synonyme"
         if __varname is None:
@@ -534,6 +726,92 @@ class ImportFromScript(object):
         return self.__filestring
 
 # ==============================================================================
+class ImportDetector(object):
+    """
+    Détection des caractéristiques de fichiers ou objets en entrée
+    """
+    __slots__ = (
+        "__url", "__usr", "__root", "__end")
+    def __enter__(self): return self
+    def __exit__(self, exc_type, exc_val, exc_tb): return False
+    #
+    def __init__(self, __url, UserMime=""):
+        if __url is None:
+            raise ValueError("The name or url of the file object has to be specified.")
+        if __url is bytes:
+            self.__url = __url.decode()
+        else:
+            self.__url = str(__url)
+        if UserMime is bytes:
+            self.__usr = UserMime.decode().lower()
+        else:
+            self.__usr = str(UserMime).lower()
+        (self.__root, self.__end) = os.path.splitext(self.__url)
+        #
+        mimetypes.add_type('application/numpy.npy', '.npy')
+        mimetypes.add_type('application/numpy.npz', '.npz')
+        mimetypes.add_type('application/dymola.sdf', '.sdf')
+        if sys.platform.startswith("win"):
+            mimetypes.add_type('text/plain', '.txt')
+            mimetypes.add_type('text/csv', '.csv')
+            mimetypes.add_type('text/tab-separated-values', '.tsv')
+    #
+    # File related tests
+    # ------------------
+    def is_local_file(self):
+        if os.path.isfile(os.path.realpath(self.__url)):
+            return True
+        else:
+            return False
+    def is_not_local_file(self):
+        return not self.is_local_file()
+    def raise_error_if_not_local_file(self):
+        if self.is_not_local_file():
+            raise ValueError("The name or the url of the file object doesn't seem to exist. The given name is:\n  \"%s\""%str(self.__url))
+        else:
+            return False
+    #
+    # Directory related tests
+    # -----------------------
+    def is_local_dir(self):
+        if os.path.isdir(self.__url):
+            return True
+        else:
+            return False
+    def is_not_local_dir(self):
+        return not self.is_local_dir()
+    def raise_error_if_not_local_dir(self):
+        if self.is_not_local_dir():
+            raise ValueError("The name or the url of the directory object doesn't seem to exist. The given name is:\n  \"%s\""%str(self.__url))
+        else:
+            return False
+    #
+    # Mime related functions
+    # ------------------------
+    def get_standard_mime(self):
+        (__mtype, __encoding) = mimetypes.guess_type(self.__url, strict=False)
+        return __mtype
+    def get_user_mime(self):
+        __fake = "fake."+self.__usr.lower()
+        (__mtype, __encoding) = mimetypes.guess_type(__fake, strict=False)
+        return __mtype
+    def get_comprehensive_mime(self):
+        if self.get_standard_mime() is not None:
+            return self.get_standard_mime()
+        elif self.get_user_mime() is not None:
+            return self.get_user_mime()
+        else:
+            return None
+    #
+    # Name related functions
+    # ----------------------
+    def get_user_name(self):
+        return self.__url
+    def get_absolute_name(self):
+        return os.path.abspath(os.path.realpath(self.__url))
+    def get_extension(self):
+        return self.__end
+
 class ImportFromFile(object):
     """
     Obtention de variables disrétisées en 1D, définies par une ou des variables
@@ -541,15 +819,16 @@ class ImportFromFile(object):
     lecture d'un fichier au format spécifié (ou intuité) permet de charger ces
     fonctions depuis :
         - des fichiers textes en colonnes de type TXT, CSV, TSV...
-        - des fichiers de données binaires NPY, NPZ...
+        - des fichiers de données binaires NPY, NPZ, SDF...
     La lecture du fichier complet ne se fait que si nécessaire, pour assurer la
     performance tout en disposant de l'interprétation du contenu. Les fichiers
     textes doivent présenter en première ligne (hors commentaire ou ligne vide)
     les noms des variables de colonnes. Les commentaires commencent par un "#".
     """
     __slots__ = (
-        "_filename", "_varsline", "_format", "_delimiter", "_skiprows",
-        "__colnames", "__colindex", "__filestring", "__header", "__allowvoid")
+        "_filename", "_colnames", "_colindex", "_varsline", "_format",
+        "_delimiter", "_skiprows", "__url", "__filestring", "__header",
+        "__allowvoid", "__binaryformats", "__supportedformats")
     def __enter__(self): return self
     def __exit__(self, exc_type, exc_val, exc_tb): return False
     #
@@ -566,68 +845,58 @@ class ImportFromFile(object):
             - AllowVoidNameList : permet, si la liste de noms est vide, de
               prendre par défaut toutes les colonnes
         """
-        if Filename is None:
-            raise ValueError("The name of the file, containing the variables to be read, has to be specified.")
-        if not os.path.isfile(Filename):
-            raise ValueError("The file, containing the variables to be read, doesn't seem to exist. The given file name is:\n  \"%s\""%str(Filename))
-        self._filename = os.path.abspath(Filename)
+        self.__binaryformats =(
+            "application/numpy.npy",
+            "application/numpy.npz",
+            "application/dymola.sdf",
+            )
+        self.__url = ImportDetector( Filename, Format)
+        self.__url.raise_error_if_not_local_file()
+        self._filename = self.__url.get_absolute_name()
+        PlatformInfo.checkFileNameConformity( self._filename )
+        #
+        self._format = self.__url.get_comprehensive_mime()
         #
-        self.__header, self._varsline, self._skiprows = self.__getentete(self._filename)
+        self.__header, self._varsline, self._skiprows = self.__getentete()
         #
-        self._delimiter = None
-        self.__filestring = "".join(self.__header)
-        if Format.upper() == "GUESS":
-            if self._filename.split(".")[-1].lower() == "npy":
-                self._format = "NPY"
-            elif self._filename.split(".")[-1].lower() == "npz":
-                self._format = "NPZ"
-            elif self.__filestring.count(",") > 1  and self._filename.split(".")[-1].lower() == "csv":
-                self._format = "CSV"
+        if self._format == "text/csv" or Format.upper() == "CSV":
+            self._format = "text/csv"
+            self.__filestring = "".join(self.__header)
+            if self.__filestring.count(",") > 1:
                 self._delimiter = ","
-            elif self.__filestring.count(";") > 1  and self._filename.split(".")[-1].lower() == "csv":
-                self._format = "CSV"
+            elif self.__filestring.count(";") > 1:
                 self._delimiter = ";"
-            elif self.__filestring.count("\t") > 1 and self._filename.split(".")[-1].lower() == "tsv":
-                self._format = "TSV"
-                self._delimiter = "\t"
-            elif self.__filestring.count(" ") > 1  and self._filename.split(".")[-1].lower() == "txt":
-                self._format = "TXT"
             else:
-                raise ValueError("Can not guess the file format, please specify the good one")
-        elif Format.upper() == "CSV" and self._delimiter is None:
-            if self.__filestring.count(",") > 1 and self._filename.split(".")[-1].lower() == "csv":
-                self._format    = "CSV"
-                self._delimiter = ","
-            elif self.__filestring.count(";") > 1 and self._filename.split(".")[-1].lower() == "csv":
-                self._format    = "CSV"
-                self._delimiter = ";"
-        elif Format.upper() == "TSV" and self._delimiter is None:
-            self._format    = "TSV"
+                self._delimiter = None
+        elif self._format == "text/tab-separated-values" or Format.upper() == "TSV":
+            self._format = "text/tab-separated-values"
             self._delimiter = "\t"
         else:
-            self._format     = str(Format).upper()
+            self._delimiter = None
         #
-        if ColNames is not None: self.__colnames = tuple(ColNames)
-        else:                    self.__colnames = None
+        if ColNames is not None: self._colnames = tuple(ColNames)
+        else:                    self._colnames = None
         #
-        if ColIndex is not None: self.__colindex = str(ColIndex)
-        else:                    self.__colindex = None
+        if ColIndex is not None: self._colindex = str(ColIndex)
+        else:                    self._colindex = None
         #
         self.__allowvoid = bool(AllowVoidNameList)
 
-    def __getentete(self, __filename, __nblines = 3):
+    def __getentete(self, __nblines = 3):
         "Lit l'entête du fichier pour trouver la définition des variables"
+        # La première ligne non vide non commentée est toujours considérée
+        # porter les labels de colonne, donc pas des valeurs
         __header, __varsline, __skiprows = [], "", 1
-        if __filename.split(".")[-1].lower() in ("npy", "npz"):
+        if self._format in self.__binaryformats:
             pass
         else:
-            with open(__filename,'r') as fid:
+            with open(self._filename,'r') as fid:
                 __line = fid.readline().strip()
                 while "#" in __line or len(__line) < 1:
                     __header.append(__line)
                     __skiprows += 1
                     __line = fid.readline().strip()
-                __varsline = __line # Première ligne non commentée non vide
+                __varsline = __line # Ligne de labels par convention
                 for i in range(max(0,__nblines)):
                     __header.append(fid.readline())
         return (__header, __varsline, __skiprows)
@@ -664,21 +933,35 @@ class ImportFromFile(object):
         #
         return (__usecols, __useindex)
 
+    def getsupported(self):
+        self.__supportedformats = {}
+        self.__supportedformats["text/plain"]                = True
+        self.__supportedformats["text/csv"]                  = True
+        self.__supportedformats["text/tab-separated-values"] = True
+        self.__supportedformats["application/numpy.npy"]     = True
+        self.__supportedformats["application/numpy.npz"]     = True
+        self.__supportedformats["application/dymola.sdf"]    = PlatformInfo.has_sdf
+        return self.__supportedformats
+
     def getvalue(self, ColNames=None, ColIndex=None ):
-        "Renvoie la ou les variables demandees par la liste de leurs noms"
+        "Renvoie la ou les variables demandées par la liste de leurs noms"
         # Uniquement si mise à jour
-        if ColNames is not None: self.__colnames = tuple(ColNames)
-        if ColIndex is not None: self.__colindex = str(ColIndex)
+        if ColNames is not None: self._colnames = tuple(ColNames)
+        if ColIndex is not None: self._colindex = str(ColIndex)
         #
         __index = None
-        if self._format == "NPY":
+        if self._format == "application/numpy.npy":
             __columns = numpy.load(self._filename)
-        elif self._format == "NPZ":
+        #
+        elif self._format == "application/numpy.npz":
             __columns = None
             with numpy.load(self._filename) as __allcolumns:
-                if self.__colnames is None:
-                    self.__colnames = __allcolumns.files
-                for nom in self.__colnames:
+                if self._colnames is None:
+                    self._colnames = __allcolumns.files
+                for nom in self._colnames: # Si une variable demandée n'existe pas
+                    if nom not in __allcolumns.files:
+                        self._colnames = tuple( __allcolumns.files )
+                for nom in self._colnames:
                     if nom in __allcolumns.files:
                         if __columns is not None:
                             # Attention : toutes les variables doivent avoir la même taille
@@ -686,27 +969,51 @@ class ImportFromFile(object):
                         else:
                             # Première colonne
                             __columns = numpy.reshape(__allcolumns[nom], (1,-1))
-                if self.__colindex is not None and self.__colindex in __allcolumns.files:
-                    __index = numpy.array(numpy.reshape(__allcolumns[self.__colindex], (1,-1)), dtype=bytes)
-        elif self._format == "TXT":
-            __usecols, __useindex = self.__getindices(self.__colnames, self.__colindex)
+                if self._colindex is not None and self._colindex in __allcolumns.files:
+                    __index = numpy.array(numpy.reshape(__allcolumns[self._colindex], (1,-1)), dtype=bytes)
+        elif self._format == "text/plain":
+            __usecols, __useindex = self.__getindices(self._colnames, self._colindex)
             __columns = numpy.loadtxt(self._filename, usecols = __usecols, skiprows=self._skiprows)
             if __useindex is not None:
                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), skiprows=self._skiprows)
+            if __usecols is None: # Si une variable demandée n'existe pas
+                self._colnames = None
+        #
+        elif self._format == "application/dymola.sdf" and PlatformInfo.has_sdf:
+            import sdf
+            __content = sdf.load(self._filename)
+            __columns = None
+            if self._colnames is None:
+                self._colnames = [__content.datasets[i].name for i in range(len(__content.datasets))]
+            for nom in self._colnames:
+                if nom in __content:
+                    if __columns is not None:
+                        # Attention : toutes les variables doivent avoir la même taille
+                        __columns = numpy.vstack((__columns, numpy.reshape(__content[nom].data, (1,-1))))
+                    else:
+                        # Première colonne
+                        __columns = numpy.reshape(__content[nom].data, (1,-1))
+            if self._colindex is not None and self._colindex in __content:
+                __index = __content[self._colindex].data
         #
-        elif self._format == "CSV":
-            __usecols, __useindex = self.__getindices(self.__colnames, self.__colindex, self._delimiter)
+        elif self._format == "text/csv":
+            __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
             if __useindex is not None:
                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
+            if __usecols is None: # Si une variable demandée n'existe pas
+                self._colnames = None
         #
-        elif self._format == "TSV":
-            __usecols, __useindex = self.__getindices(self.__colnames, self.__colindex, self._delimiter)
+        elif self._format == "text/tab-separated-values":
+            __usecols, __useindex = self.__getindices(self._colnames, self._colindex, self._delimiter)
             __columns = numpy.loadtxt(self._filename, usecols = __usecols, delimiter = self._delimiter, skiprows=self._skiprows)
             if __useindex is not None:
                 __index = numpy.loadtxt(self._filename, dtype = bytes, usecols = (__useindex,), delimiter = self._delimiter, skiprows=self._skiprows)
+            if __usecols is None: # Si une variable demandée n'existe pas
+                self._colnames = None
         else:
-            raise ValueError("Unkown file format %s"%self._format)
+            raise ValueError("Unkown file format \"%s\" or no reader available"%self._format)
+        if __columns is None: __columns = ()
         #
         def toString(value):
             try:
@@ -716,14 +1023,19 @@ class ImportFromFile(object):
         if __index is not None:
             __index = tuple([toString(v) for v in __index])
         #
-        return (self.__colnames, __columns, self.__colindex, __index)
+        return (self._colnames, __columns, self._colindex, __index)
 
     def getstring(self):
-        "Renvoie le fichier complet"
-        with open(self._filename,'r') as fid:
-            return fid.read()
+        "Renvoie le fichier texte complet"
+        if self._format in self.__binaryformats:
+            return ""
+        else:
+            with open(self._filename,'r') as fid:
+                return fid.read()
+
+    def getformat(self):
+        return self._format
 
-# ==============================================================================
 class ImportScalarLinesFromFile(ImportFromFile):
     """
     Importation de fichier contenant des variables scalaires nommées. Le
@@ -739,11 +1051,11 @@ class ImportScalarLinesFromFile(ImportFromFile):
     #
     def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess"):
         ImportFromFile.__init__(self, Filename, ColNames, ColIndex, Format)
-        if self._format not in ["TXT", "CSV", "TSV"]:
+        if self._format not in ["text/plain", "text/csv", "text/tab-separated-values"]:
             raise ValueError("Unkown file format \"%s\""%self._format)
     #
     def getvalue(self, VarNames = None, HeaderNames=()):
-        "Renvoie la ou les variables demandees par la liste de leurs noms"
+        "Renvoie la ou les variables demandées par la liste de leurs noms"
         if VarNames is not None: __varnames = tuple(VarNames)
         else:                    __varnames = None
         #
@@ -777,16 +1089,16 @@ class ImportScalarLinesFromFile(ImportFromFile):
             for i in range(1,len(HeaderNames)):
                 __converters[i] = __replaceNone
         else:
-            raise ValueError("Can not find names of columns for initial values. Wrong first line is:\n            \"%s\""%__firstline)
+            raise ValueError("Can not find names of columns for initial values. Wrong first line is:\n            \"%s\""%self._varsline)
         #
-        if self._format == "TXT":
+        if self._format == "text/plain":
             __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters)
-        elif self._format in ["CSV", "TSV"]:
+        elif self._format in ["text/csv", "text/tab-separated-values"]:
             __content = numpy.loadtxt(self._filename, dtype = __dtypes, usecols = __usecols, skiprows = self._skiprows, converters = __converters, delimiter = self._delimiter)
         else:
             raise ValueError("Unkown file format \"%s\""%self._format)
         #
-        __names, __background, __bounds = [], [], []
+        __names, __thevalue, __bounds = [], [], []
         for sub in __content:
             if len(__usecols) == 4:
                 na, va, mi, ma = sub
@@ -808,15 +1120,92 @@ class ImportScalarLinesFromFile(ImportFromFile):
             if (__varnames is None or na in __varnames) and (na not in __names):
                 # Ne stocke que la premiere occurence d'une variable
                 __names.append(na)
-                __background.append(va)
+                __thevalue.append(va)
                 __bounds.append((mi,ma))
         #
         __names      = tuple(__names)
-        __background = numpy.array(__background)
+        __thevalue = numpy.array(__thevalue)
         __bounds     = tuple(__bounds)
         #
-        return (__names, __background, __bounds)
+        return (__names, __thevalue, __bounds)
+
+# ==============================================================================
+class EficasGUI(object):
+    """
+    Lancement autonome de l'interface EFICAS/ADAO
+    """
+    def __init__(self, __addpath = None):
+        # Chemin pour l'installation (ordre important)
+        self.__msg = ""
+        self.__path_settings_ok = False
+        #----------------
+        if "EFICAS_ROOT" in os.environ:
+            __EFICAS_ROOT = os.environ["EFICAS_ROOT"]
+            __path_ok = True
+        else:
+            self.__msg += "\nKeyError:\n"+\
+                "  the required environment variable EFICAS_ROOT is unknown.\n"+\
+                "  You have either to be in SALOME environment, or to set\n"+\
+                "  this variable in your environment to the right path \"<...>\"\n"+\
+                "  to find an installed EFICAS application. For example:\n"+\
+                "      EFICAS_ROOT=\"<...>\" command\n"
+            __path_ok = False
+        try:
+            import adao
+            __path_ok = True and __path_ok
+        except ImportError:
+            self.__msg += "\nImportError:\n"+\
+                "  the required ADAO library can not be found to be imported.\n"+\
+                "  You have either to be in ADAO environment, or to be in SALOME\n"+\
+                "  environment, or to set manually in your Python 3 environment the\n"+\
+                "  right path \"<...>\" to find an installed ADAO application. For\n"+\
+                "  example:\n"+\
+                "      PYTHONPATH=\"<...>:${PYTHONPATH}\" command\n"
+            __path_ok = False
+        try:
+            import PyQt5
+            __path_ok = True and __path_ok
+        except ImportError:
+            self.__msg += "\nImportError:\n"+\
+                "  the required PyQt5 library can not be found to be imported.\n"+\
+                "  You have either to have a raisonable up-to-date Python 3\n"+\
+                "  installation (less than 5 years), or to be in SALOME environment.\n"
+            __path_ok = False
+        #----------------
+        if not __path_ok:
+            self.__msg += "\nWarning:\n"+\
+                "  It seems you have some troubles with your installation.\n"+\
+                "  Be aware that some other errors may exist, that are not\n"+\
+                "  explained as above, like some incomplete or obsolete\n"+\
+                "  Python 3, or incomplete module installation.\n"+\
+                "  \n"+\
+                "  Please correct the above error(s) before launching the\n"+\
+                "  standalone EFICAS/ADAO interface.\n"
+            logging.debug("Some of the ADAO/EFICAS/QT5 paths have not been found")
+            self.__path_settings_ok = False
+        else:
+            logging.debug("All the ADAO/EFICAS/QT5 paths have been found")
+            self.__path_settings_ok = True
+        #----------------
+        if self.__path_settings_ok:
+            sys.path.insert(0,__EFICAS_ROOT)
+            sys.path.insert(0,os.path.join(adao.adao_py_dir,"daEficas"))
+            if __addpath is not None and os.path.exists(os.path.abspath(__addpath)):
+                sys.path.insert(0,os.path.abspath(__addpath))
+            logging.debug("All the paths have been correctly set up")
+        else:
+            print(self.__msg)
+            logging.debug("Errors in path settings have been found")
+
+    def gui(self):
+        if self.__path_settings_ok:
+            logging.debug("Launching standalone EFICAS/ADAO interface...")
+            from daEficas import prefs
+            from InterfaceQT4 import eficas_go
+            eficas_go.lanceEficas(code=prefs.code)
+        else:
+            logging.debug("Can not launch standalone EFICAS/ADAO interface for path errors.")
 
 # ==============================================================================
 if __name__ == "__main__":
-    print('\n AUTODIAGNOSTIC \n')
+    print('\n AUTODIAGNOSTIC\n')