]> SALOME platform Git repositories - modules/adao.git/commitdiff
Salome HOME
Documentation and code update and corrections
authorJean-Philippe ARGAUD <jean-philippe.argaud@edf.fr>
Tue, 15 Oct 2024 14:10:18 +0000 (16:10 +0200)
committerJean-Philippe ARGAUD <jean-philippe.argaud@edf.fr>
Tue, 15 Oct 2024 14:10:18 +0000 (16:10 +0200)
107 files changed:
doc/en/examples.rst
doc/en/images/sampling_01_SampleAsnUplet.png
doc/en/images/sampling_02_SampleAsExplicitHyperCube.png
doc/en/images/sampling_03_SampleAsMinMaxStepHyperCube.png
doc/en/images/sampling_04_SampleAsMinMaxLatinHyperCube.png
doc/en/images/sampling_05_SampleAsMinMaxSobolSequence.png
doc/en/images/sampling_06_SampleAsIndependantRandomVariables_normal.png
doc/en/images/sampling_07_SampleAsIndependantRandomVariables_uniform.png
doc/en/images/sampling_08_SampleAsIndependantRandomVariables_weibull.png
doc/en/index.rst
doc/en/ref_algorithm_ParticleSwarmOptimization.rst
doc/en/ref_observations_requirements.rst
doc/en/ref_output_variables.rst
doc/en/scripts/simple_3DVAR1.png
doc/en/scripts/simple_3DVAR1Plus.png
doc/en/scripts/simple_3DVAR2_state.png
doc/en/scripts/simple_3DVAR2_variance.png
doc/en/scripts/simple_3DVAR3_state.png
doc/en/scripts/simple_3DVAR3_variance.png
doc/en/scripts/simple_DerivativeFreeOptimization.png
doc/en/scripts/simple_KalmanFilter1_state.png
doc/en/scripts/simple_KalmanFilter1_variance.png
doc/en/scripts/simple_KalmanFilter2_state.png
doc/en/scripts/simple_KalmanFilter2_variance.png
doc/en/scripts/simple_MeasurementsOptimalPositioningTask3.png
doc/en/scripts/simple_NonLinearLeastSquares.png
doc/en/scripts/simple_ParticleSwarmOptimization1.png
doc/en/scripts/simple_ReducedModelingTest1.png
doc/en/scripts/tui_example_07.res
doc/en/scripts/tui_example_12.png [new file with mode: 0644]
doc/en/scripts/tui_example_12.py [new file with mode: 0644]
doc/en/scripts/tui_example_12.res [new file with mode: 0644]
doc/en/snippets/EntryTypeDataFile.rst
doc/en/snippets/Header2Algo04.rst
doc/en/snippets/ModuleCompatibility.rst
doc/en/snippets/ModuleValidation.rst
doc/en/snippets/NoConditionalOutput.rst
doc/en/snippets/StoreInitialState.rst [new file with mode: 0644]
doc/en/tui.rst
doc/fr/examples.rst
doc/fr/images/sampling_01_SampleAsnUplet.png
doc/fr/images/sampling_02_SampleAsExplicitHyperCube.png
doc/fr/images/sampling_03_SampleAsMinMaxStepHyperCube.png
doc/fr/images/sampling_04_SampleAsMinMaxLatinHyperCube.png
doc/fr/images/sampling_05_SampleAsMinMaxSobolSequence.png
doc/fr/images/sampling_06_SampleAsIndependantRandomVariables_normal.png
doc/fr/images/sampling_07_SampleAsIndependantRandomVariables_uniform.png
doc/fr/images/sampling_08_SampleAsIndependantRandomVariables_weibull.png
doc/fr/index.rst
doc/fr/ref_algorithm_EnsembleOfSimulationGenerationTask.rst
doc/fr/ref_algorithm_ParticleSwarmOptimization.rst
doc/fr/ref_output_variables.rst
doc/fr/ref_sampling_requirements.rst
doc/fr/scripts/simple_3DVAR1.png
doc/fr/scripts/simple_3DVAR1Plus.png
doc/fr/scripts/simple_3DVAR2_state.png
doc/fr/scripts/simple_3DVAR2_variance.png
doc/fr/scripts/simple_3DVAR3_state.png
doc/fr/scripts/simple_3DVAR3_variance.png
doc/fr/scripts/simple_DerivativeFreeOptimization.png
doc/fr/scripts/simple_KalmanFilter1_state.png
doc/fr/scripts/simple_KalmanFilter1_variance.png
doc/fr/scripts/simple_KalmanFilter2_state.png
doc/fr/scripts/simple_KalmanFilter2_variance.png
doc/fr/scripts/simple_MeasurementsOptimalPositioningTask3.png
doc/fr/scripts/simple_NonLinearLeastSquares.png
doc/fr/scripts/simple_ParticleSwarmOptimization1.png
doc/fr/scripts/simple_ReducedModelingTest1.png
doc/fr/scripts/tui_example_07.res
doc/fr/scripts/tui_example_11.py
doc/fr/scripts/tui_example_12.png [new file with mode: 0644]
doc/fr/scripts/tui_example_12.py [new file with mode: 0644]
doc/fr/scripts/tui_example_12.res [new file with mode: 0644]
doc/fr/snippets/Header2Algo04.rst
doc/fr/snippets/MaximumNumberOfLocations.rst
doc/fr/snippets/ModuleCompatibility.rst
doc/fr/snippets/ModuleValidation.rst
doc/fr/snippets/NoUnconditionalOutput.rst
doc/fr/snippets/SampleAsIndependantRandomVariables.rst
doc/fr/snippets/SampleAsMinMaxLatinHyperCube.rst
doc/fr/snippets/SampleAsMinMaxSobolSequence.rst
doc/fr/snippets/StoreInitialState.rst [new file with mode: 0644]
doc/fr/tui.rst
src/daComposant/daAlgorithms/Atoms/ecwapso.py
src/daComposant/daAlgorithms/Atoms/ecwnpso.py
src/daComposant/daAlgorithms/Atoms/ecwopso.py
src/daComposant/daAlgorithms/Atoms/ecwpspso.py
src/daComposant/daAlgorithms/Atoms/ecwspso.py
src/daComposant/daAlgorithms/Atoms/incr3dvar.py
src/daComposant/daAlgorithms/Atoms/std3dvar.py
src/daComposant/daAlgorithms/Atoms/van3dvar.py
src/daComposant/daAlgorithms/InterpolationByReducedModelTask.py
src/daComposant/daAlgorithms/ParticleSwarmOptimization.py
src/daComposant/daCore/Aidsm.py
src/daComposant/daCore/AssimilationStudy.py
src/daComposant/daCore/BasicObjects.py
src/daComposant/daCore/ExtendedLogging.py
src/daComposant/daCore/Interfaces.py
src/daComposant/daCore/NumericObjects.py
src/daComposant/daCore/Persistence.py
src/daComposant/daCore/PlatformInfo.py
src/daComposant/daCore/Reporting.py
src/daComposant/daCore/Templates.py
src/daComposant/daNumerics/Models/Lorenz1963.py [new file with mode: 0644]
src/daComposant/daNumerics/Models/TwoDimensionalInverseDistanceCS2010.py
src/daComposant/daNumerics/Models/TwoDimensionalRosenbrockFunctionR1960.py
src/daEficas/prefs_ADAO.py.in

index 6cd8b443eb61b64cfbb4b03554282d14eedef24a..a42dc853edac40ce3bee00ae9e214364ecfff3c8 100644 (file)
@@ -71,6 +71,8 @@ Dedicated tasks or study oriented cases uses
 Advanced uses
 -------------
 
+#. :ref:`subsection_tui_advanced_ex11`
+#. :ref:`subsection_tui_advanced_ex12`
 #. :ref:`section_advanced_convert_JDC`
 #. :ref:`section_advanced_YACS_tui`
 #. :ref:`section_advanced_R`
index a10feeb3933637e9db62ddafaea52c8915b61396..97907e5ae94efb066c6639cb826f2c47da93dd02 100644 (file)
Binary files a/doc/en/images/sampling_01_SampleAsnUplet.png and b/doc/en/images/sampling_01_SampleAsnUplet.png differ
index a10feeb3933637e9db62ddafaea52c8915b61396..97907e5ae94efb066c6639cb826f2c47da93dd02 100644 (file)
Binary files a/doc/en/images/sampling_02_SampleAsExplicitHyperCube.png and b/doc/en/images/sampling_02_SampleAsExplicitHyperCube.png differ
index a10feeb3933637e9db62ddafaea52c8915b61396..97907e5ae94efb066c6639cb826f2c47da93dd02 100644 (file)
Binary files a/doc/en/images/sampling_03_SampleAsMinMaxStepHyperCube.png and b/doc/en/images/sampling_03_SampleAsMinMaxStepHyperCube.png differ
index aab97d3d9bbff00bd3e5d3dcc85cac126371f692..7dd9f51d55cc0bf9d828738455a19c71efc4accd 100644 (file)
Binary files a/doc/en/images/sampling_04_SampleAsMinMaxLatinHyperCube.png and b/doc/en/images/sampling_04_SampleAsMinMaxLatinHyperCube.png differ
index 4bee257c5d184ea0a75f229721c592e0df330e90..7cbb722f343d8323396e21258714bc7274bb685a 100644 (file)
Binary files a/doc/en/images/sampling_05_SampleAsMinMaxSobolSequence.png and b/doc/en/images/sampling_05_SampleAsMinMaxSobolSequence.png differ
index 6fbfed6be16832c77dce1465f7cecaa526473b3d..44f8e7f5b5be06bba76a8368492e388acce2748c 100644 (file)
Binary files a/doc/en/images/sampling_06_SampleAsIndependantRandomVariables_normal.png and b/doc/en/images/sampling_06_SampleAsIndependantRandomVariables_normal.png differ
index a18d2d781e2c4c8a8985d72c9abd90658b234a3a..cfbbacb492050c9e4fe63d57d656800469f048a5 100644 (file)
Binary files a/doc/en/images/sampling_07_SampleAsIndependantRandomVariables_uniform.png and b/doc/en/images/sampling_07_SampleAsIndependantRandomVariables_uniform.png differ
index 4e223aaedc5fa246cc33792f45831fff7b843912..dd993b694f4e8136903da9a78954ee5abd22c8f8 100644 (file)
Binary files a/doc/en/images/sampling_08_SampleAsIndependantRandomVariables_weibull.png and b/doc/en/images/sampling_08_SampleAsIndependantRandomVariables_weibull.png differ
index 2f0f67f850f496c512b5ae75b326cd63232549a3..e935943d30cc9be1c725d6c8984838bd740106b7 100644 (file)
@@ -38,11 +38,25 @@ Briefly stated, Data Assimilation is a methodological framework to compute the
 optimal estimate of the inaccessible true value of a system state, eventually
 over time. It uses information coming from experimental measurements or
 observations, and from numerical *a priori* models, including information about
-their errors. Parts of the framework are also known under the names of
-*calibration*, *adjustment*, *state estimation*, *parameter estimation*,
-*parameter adjustment*, *inverse problems*, *inverse methods*, *Bayesian
-estimation*, *optimal interpolation*, *mathematical regularization*,
-*meta-heuristics for optimization*, *model reduction*, *data smoothing*, etc.
+their errors. Some methods that are parts of the framework are also known under
+the names of
+*adjustment*,
+*calibration*,
+*state estimation*,
+*parameter estimation*,
+*parameter adjustment*,
+*inverse problems*,
+*inverse methods*,
+*inversion*,
+*Bayesian estimation*,
+*optimal interpolation*,
+*optimal learning*,
+*mathematical regularization*,
+*meta-heuristics* for optimization,
+*model reduction*,
+*assimilation in reduced space*,
+*data smoothing*,
+etc.
 More details can be found in the section :ref:`section_theory`. The ADAO module
 currently offers more than one hundred different algorithmic methods and allows
 the study of about 400 distinct applied problems.
index 311e98753a66963c875e35d36ee1df9dc55b7786..593751f72c689e273c3c4f6b22c5fcd5d8097c13 100644 (file)
@@ -177,6 +177,8 @@ prohibitive optimization time length.
 
 .. include:: snippets/SocialAcceleration.rst
 
+.. include:: snippets/StoreInitialState.rst
+
 StoreSupplementaryCalculations
   .. index:: single: StoreSupplementaryCalculations
 
index 3ec2454f13cf43f6c15ea0c9a97a77d3c61b5e2c..8b0f45759d875f49b8c4ae4e0bb81acd5d086b10 100644 (file)
@@ -180,7 +180,7 @@ General comments on the observations
 
   When the assimilation explicitly establishes a **temporal iterative
   process**, as in state data assimilation, **the first observation is not used
-  but must be present in the data description of a ADAO case**. By convention,
+  but must be present in the data description of an ADAO case**. By convention,
   it is therefore considered to be available at the same time as the draft time
   value, and does not lead to a correction at that time. The numbering of the
   observations starts at 0 by convention, so it is only from number 1 that the
index d07e0d0999102cfe1c2bc00970f7aed643c95f7f..0abed1038f860ccd77359d7aa46a1865549edcd5 100644 (file)
@@ -51,7 +51,7 @@ output port "*algoResults*" of the calculation block):
 Templates are given hereafter as :ref:`subsection_r_o_v_Template`. In all cases,
 the post-processing of the user has in the namespace a variable whose name is
 "*ADD*", and whose only available method is named ``get``. The arguments of this
-method are an output information name, as described in the
+method are an output information name, as described in an
 :ref:`subsection_r_o_v_Inventaire`.
 
 For example, to have the optimal state after a data assimilation or optimization
index d7127cfa502baa18e79c3ff7bb3039a0e0419954..6bdb178b42b1b3890296b69b52f737348ad96a98 100644 (file)
Binary files a/doc/en/scripts/simple_3DVAR1.png and b/doc/en/scripts/simple_3DVAR1.png differ
index 143125eaed03f051c172dac87ba8046e398062fd..ae0ea24d82bbde89f94a440f66e6b922112c7f84 100644 (file)
Binary files a/doc/en/scripts/simple_3DVAR1Plus.png and b/doc/en/scripts/simple_3DVAR1Plus.png differ
index 9b96418c6ccd41faa5c9d811c1718b4dc12894d1..c1cc5c44458afd3eab9b5775debd656f45c20892 100644 (file)
Binary files a/doc/en/scripts/simple_3DVAR2_state.png and b/doc/en/scripts/simple_3DVAR2_state.png differ
index 7c0181c3e913938b5e6887ed34530e78881cfa45..9715326754d0c8922161d960feb9ef5bcdff7e0d 100644 (file)
Binary files a/doc/en/scripts/simple_3DVAR2_variance.png and b/doc/en/scripts/simple_3DVAR2_variance.png differ
index f9a01d4dce2f517417be0d80fb4fa0f5b328ce18..68524b117999baf3147d3a118d62b37b19eed009 100644 (file)
Binary files a/doc/en/scripts/simple_3DVAR3_state.png and b/doc/en/scripts/simple_3DVAR3_state.png differ
index 398823409f65f0106de8e64b315aed96b7351e12..99212a12912d3aa542a067e54b85d47c3991bc67 100644 (file)
Binary files a/doc/en/scripts/simple_3DVAR3_variance.png and b/doc/en/scripts/simple_3DVAR3_variance.png differ
index d68b0bd401b7ecc1bd468cb8d00c6324cf24dc40..9c010a5decffd6ff7b6dd1dc5bd70e4b6445c7d6 100644 (file)
Binary files a/doc/en/scripts/simple_DerivativeFreeOptimization.png and b/doc/en/scripts/simple_DerivativeFreeOptimization.png differ
index 05b4920d172479c3f29ad2b26d3be79d3b3217ea..9af81961137835fdadfb4b888e71d0d09b3bf857 100644 (file)
Binary files a/doc/en/scripts/simple_KalmanFilter1_state.png and b/doc/en/scripts/simple_KalmanFilter1_state.png differ
index de88046cf4127e76d394a964974bf8b8cfd7e0ec..c6b6603939a1bcd32dd96689d7e7a0b287ed3287 100644 (file)
Binary files a/doc/en/scripts/simple_KalmanFilter1_variance.png and b/doc/en/scripts/simple_KalmanFilter1_variance.png differ
index 05b4920d172479c3f29ad2b26d3be79d3b3217ea..9af81961137835fdadfb4b888e71d0d09b3bf857 100644 (file)
Binary files a/doc/en/scripts/simple_KalmanFilter2_state.png and b/doc/en/scripts/simple_KalmanFilter2_state.png differ
index de88046cf4127e76d394a964974bf8b8cfd7e0ec..c6b6603939a1bcd32dd96689d7e7a0b287ed3287 100644 (file)
Binary files a/doc/en/scripts/simple_KalmanFilter2_variance.png and b/doc/en/scripts/simple_KalmanFilter2_variance.png differ
index 87e62a146541a52a246d777abe759abe71dc0460..e6ec20da3cd901d0b42af02176d9100c31b1a85e 100644 (file)
Binary files a/doc/en/scripts/simple_MeasurementsOptimalPositioningTask3.png and b/doc/en/scripts/simple_MeasurementsOptimalPositioningTask3.png differ
index d68b0bd401b7ecc1bd468cb8d00c6324cf24dc40..9c010a5decffd6ff7b6dd1dc5bd70e4b6445c7d6 100644 (file)
Binary files a/doc/en/scripts/simple_NonLinearLeastSquares.png and b/doc/en/scripts/simple_NonLinearLeastSquares.png differ
index 6f7f37e03a714e7993dfea67348a32fc7e19134b..3773f44ea5c0ff63f6101253ef61ea2ed8a72236 100644 (file)
Binary files a/doc/en/scripts/simple_ParticleSwarmOptimization1.png and b/doc/en/scripts/simple_ParticleSwarmOptimization1.png differ
index 03662e74d1e04d3a2e0aaae17b8bd7ca59832ac2..964d69a622b35c1e7c41df8d14ef64f966d2a9f1 100644 (file)
Binary files a/doc/en/scripts/simple_ReducedModelingTest1.png and b/doc/en/scripts/simple_ReducedModelingTest1.png differ
index a3a333e004d9198a55cd469803c37d39e2bff59a..8601953669c3a2c919658890497fd804930ced8c 100644 (file)
@@ -2,7 +2,7 @@
 ADAO Study report
 ================================================================================
 
-Summary build with ADAO version 9.13.0
+Summary build with ADAO version 9.14.0
 
   - AlgorithmParameters command has been set with values:
         Algorithm = '3DVAR'
diff --git a/doc/en/scripts/tui_example_12.png b/doc/en/scripts/tui_example_12.png
new file mode 100644 (file)
index 0000000..9214f94
Binary files /dev/null and b/doc/en/scripts/tui_example_12.png differ
diff --git a/doc/en/scripts/tui_example_12.py b/doc/en/scripts/tui_example_12.py
new file mode 100644 (file)
index 0000000..260dc6d
--- /dev/null
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+#
+from matplotlib import pyplot as plt
+from numpy import array, set_printoptions
+from adao import adaoBuilder
+set_printoptions(precision=4, floatmode='fixed')
+#
+#-------------------------------------------------------------------------------
+#
+case = adaoBuilder.New()
+case.set( 'AlgorithmParameters',
+    Algorithm='3DVAR',
+    Parameters = {
+        "StoreSupplementaryCalculations":[
+            "CostFunctionJ",
+            "CurrentState",
+            "InnovationAtCurrentState",
+        ],
+    }
+)
+case.set( 'Background',          Vector=[0, 1, 2] )
+case.set( 'BackgroundError',     ScalarSparseMatrix=1.0 )
+case.set( 'Observation',         Vector=array([0.5, 1.5, 2.5]) )
+case.set( 'ObservationError',    DiagonalSparseMatrix='1 1 1' )
+case.set( 'ObservationOperator', Matrix='1 0 0;0 2 0;0 0 3' )
+case.set( 'Observer',
+    Variable="CurrentState",
+    Template="ValuePrinter",
+    Info="  Current state:",
+)
+#
+print("Displays current state values, at each step:")
+case.execute()
+print("")
+#
+#-------------------------------------------------------------------------------
+#
+print("Calculation-measurement deviation (or error) indicators")
+print("     (display only first 3 steps)")
+print("")
+CalculMeasureErrors = case.get("InnovationAtCurrentState")
+#
+print("===> Maximum error between calculations and measurements, at each step:")
+print("    ",array(
+    CalculMeasureErrors.maxs()
+    [0:3] ))
+print("===> Minimum error between calculations and measurements, at each step:")
+print("    ",array(
+    CalculMeasureErrors.mins()
+    [0:3] ))
+print("===> Norm of the error between calculation and measurement, at each step:")
+print("    ",array(
+    CalculMeasureErrors.norms()
+    [0:3] ))
+print("===> Mean absolute error (MAE) between calculations and measurements, at each step:")
+print("    ",array(
+    CalculMeasureErrors.maes()
+    [0:3] ))
+print("===> Mean square error (MSE) between calculations and measurements, at each step:")
+print("    ",array(
+    CalculMeasureErrors.mses()
+    [0:3] ))
+print("===> Root mean square error (RMSE) between calculations and measurements, at each step:")
+print("    ",array(
+    CalculMeasureErrors.rmses()
+    [0:3] ))
+#
+#-------------------------------------------------------------------------------
+#
+import matplotlib.pyplot as plt
+plt.rcParams['figure.figsize'] = (8, 12)
+#
+plt.figure()
+plt.suptitle('Indicators built on the current value of the calculation-measurement deviation (or error)\n', fontweight='bold')
+plt.subplot(611)
+plt.plot(CalculMeasureErrors.maxs(), 'bx--', label='Indicator at current step')
+plt.ylabel('Maximum (a.u.)')
+plt.legend()
+plt.subplot(612)
+plt.plot(CalculMeasureErrors.mins(), 'bx--', label='Indicator at current step')
+plt.ylabel('Minimum (a.u.)')
+plt.legend()
+plt.subplot(613)
+plt.plot(CalculMeasureErrors.norms(), 'bx-', label='Indicator at current step')
+plt.ylabel('Norm (a.u.)')
+plt.legend()
+plt.subplot(614)
+plt.plot(CalculMeasureErrors.maes(), 'kx-', label='Indicator at current step')
+plt.ylabel('MAE (a.u.)')
+plt.legend()
+plt.subplot(615)
+plt.plot(CalculMeasureErrors.mses(), 'gx-', label='Indicator at current step')
+plt.ylabel('MSE (a.u.)')
+plt.legend()
+plt.subplot(616)
+plt.plot(CalculMeasureErrors.rmses(), 'rx-', label='Indicator at current step')
+plt.ylabel('RMSE (a.u.)')
+plt.legend()
+plt.xlabel('Step size calculation (step number or rank)')
+plt.tight_layout()
+plt.savefig("tui_example_12.png")
diff --git a/doc/en/scripts/tui_example_12.res b/doc/en/scripts/tui_example_12.res
new file mode 100644 (file)
index 0000000..469fbd6
--- /dev/null
@@ -0,0 +1,26 @@
+Displays current state values, at each step:
+  Current state: [0.0000 1.0000 2.0000]
+  Current state: [0.0474 0.9053 1.0056]
+  Current state: [0.0905 0.8492 0.9461]
+  Current state: [0.1529 0.7984 0.9367]
+  Current state: [0.2245 0.7899 0.9436]
+  Current state: [0.2508 0.8005 0.9486]
+  Current state: [0.2500 0.7998 0.9502]
+  Current state: [0.2500 0.8000 0.9500]
+  Current state: [0.2500 0.8000 0.9500]
+
+Calculation-measurement deviation (or error) indicators
+     (display only first 3 steps)
+
+===> Maximum error between calculations and measurements, at each step:
+     [0.5000 0.4526 0.4095]
+===> Minimum error between calculations and measurements, at each step:
+     [-3.5000 -0.5169 -0.3384]
+===> Norm of the error between calculation and measurement, at each step:
+     [3.5707 0.7540 0.5670]
+===> Mean absolute error (MAE) between calculations and measurements, at each step:
+     [1.5000 0.4267 0.3154]
+===> Mean square error (MSE) between calculations and measurements, at each step:
+     [4.2500 0.1895 0.1072]
+===> Root mean square error (RMSE) between calculations and measurements, at each step:
+     [2.0616 0.4353 0.3274]
index 855e69b27030c51303cb19224f3194ae147dae92..003c36761e23661daf3f23e96c2b17acc671f90d 100644 (file)
 
     Example of TXT file for "*Observation*" variable in "*DataFile*" ::
 
-        # Fichier TXT à séparateur espace
         # TXT file with space delimiter
         # =============================
-        # Ligne de commentaires quelconques débutant par #
-        # Ligne suivante réservée au nommage des variables
+        # Comment line beginning with #
+        # The next line is dedicated to variable naming
         Alpha1 Observation Alpha2
         0.1234 5.6789 9.0123
         1.2345 2.3456 3.
index d778b79496a3a89b4e710e99eaa68b8f6122a2aa..92e3781c8fc24be49a34abe9aae48b0239d1c962 100644 (file)
@@ -7,7 +7,7 @@ variables originating from the calculation. The description of
 named ``get``, of the variable "*ADD*" of the post-processing in graphical
 interface, or of the case in textual interface. The input variables, available
 to the user at the output in order to facilitate the writing of post-processing
-procedures, are described in the :ref:`subsection_r_o_v_Inventaire`.
+procedures, are described in an :ref:`subsection_r_o_v_Inventaire`.
 
 **Permanent outputs (non conditional)**
 
index dc99912372871b53c28ca0a1c87724d5132d9818..44ddb74bf853d4bec31ae97bf5fa0338a3911270 100644 (file)
@@ -10,13 +10,15 @@ remains without guarantee. If an unusual error is encountered for previously
 running calculations, it is strongly recommended to revert to supporting tool
 versions within the range described below.
 
-.. csv-table:: Support tool verification intervals for ADAO
+.. csv-table:: Support tool verification version intervals for ADAO
    :header: "Tool", "Minimal version", "Reached version"
    :widths: 20, 10, 10
+   :align: center
 
-   Python,     3.6.5,    3.12.3
-   Numpy,      1.14.3,    1.26.4
-   Scipy,      0.19.1,    1.14.0
-   MatplotLib, 2.2.2,    3.8.4
+   Python,     3.6.5,    3.12.6
+   Numpy,      1.14.3,    2.1.2
+   Scipy,      0.19.1,    1.14.1
+   MatplotLib, 2.2.2,    3.9.2
    GnuplotPy,  1.8,    1.8
-   NLopt,      2.4.2,    2.7.1
+   NLopt,      2.4.2,    2.8.0
+   FMPy,       0.3.20,    0.3.20
index 4ef9258b4b0b71ab51b704fa61618d4ced9074c4..494a93b8a38903dde92e24de1a798dc57934390e 100644 (file)
@@ -5,9 +5,10 @@ current document. The validation versions are indicated here for information
 purposes only, knowing that, in case of doubt, the SALOME version sheet
 [Salome]_ is the official validation version.
 
-.. csv-table:: Validation versions of support tools for ADAO
+.. csv-table:: Validation versions of the support tools for ADAO
    :header: "Tool", "Version"
    :widths: 20, 10
+   :align: center
 
    ADAO,       |release|
    EFICAS,     |release|
index 6bd824c82da1905adfcb7b5c68328b9cff7d0192..d99c316f8ea531bf8a2d9b856f1ce30245de1502 100644 (file)
@@ -1 +1 @@
-    *None*
+    *None* (messages or statistics are nevertheless displayed)
diff --git a/doc/en/snippets/StoreInitialState.rst b/doc/en/snippets/StoreInitialState.rst
new file mode 100644 (file)
index 0000000..df9e7e5
--- /dev/null
@@ -0,0 +1,11 @@
+.. index:: single: StoreInitialState
+
+StoreInitialState
+  *Boolean value*. This variable defines whether the algorithm's initial state
+  is stored (with True) or not (with False, by default) as the first state in
+  the iterative sequence of found states. This makes algorithmic iterative
+  storage identical to temporal iterative storage (similar, for example, to
+  Kalman filters).
+
+  Example :
+  ``{"StoreInitialState":False}``
index 0cda0275c377dd2c154ae1eefdb604d16ccee715..54ca03307a050db8308aab4cd38bb53a929acfb9 100644 (file)
@@ -71,6 +71,7 @@ command, in the SALOME Python command window of the interface, or by the script
 execution entry of the menu) is the following:
 
 .. literalinclude:: scripts/tui_example_01.res
+    :language: none
 
 Detailed setup of an ADAO TUI calculation case
 +++++++++++++++++++++++++++++++++++++++++++++++
@@ -625,7 +626,7 @@ Get the calculation results separately
     visualization. Its argument the name of a variable "*Concept*" and returns
     back the quantity as a list (even if there is only one specimen) of this
     base variable. For a list of variables and use them, the user has to refer
-    to the :ref:`subsection_r_o_v_Inventaire` and more generally to the
+    to an :ref:`subsection_r_o_v_Inventaire` and more generally to the
     :ref:`section_ref_output_variables` and to the individual documentations of
     the algorithms.
 
@@ -634,8 +635,8 @@ Saving, loading or converting calculation case commands
 
 The saving or loading of a calculation case deals with quantities and actions
 that are linked by the previous commands, excepted case external operations
-(such as, for example, post-processing that can be developped after the
-calculation cas). The registered or loaded commands remain fully compatible
+(such as, for example, post-processing that can be developed after the
+calculation case). The registered or loaded commands remain fully compatible
 with these Python external case operations.
 
 .. index:: single: load
@@ -672,47 +673,54 @@ with these Python external case operations.
     one the commands establishing the current calculation case. Some formats
     are only available as input or as output.
 
-Obtain information on the case, the computation or the system
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Getting information about the case, the calculation or the system
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
-It's easy to obtain **aggregate information on the study case** as defined by
-the user, by using Python's "*print*" command directly on the case, at any
-stage during its completion. For example:
+There are various ways to obtain global information relating to the calculation
+case, the run or the system on which a case is run.
 
-.. literalinclude:: scripts/tui_example_07.py
-    :language: python
+*print* (*case*)
+    It's easy to obtain **aggregate information on the study case** as defined
+    by the user, by using Python's "*print*" command directly on the case, at
+    any stage during its construction. For example:
 
-which result is here:
+    .. literalinclude:: scripts/tui_example_07.py
+        :language: python
 
-.. literalinclude:: scripts/tui_example_07.res
+    which result is here:
 
-.. index:: single: callinfo
+    .. literalinclude:: scripts/tui_example_07.res
+        :language: none
 
-**Synthetic information on the number of calls to operator computations** can
-be dynamically obtained with the "**callinfo()**" command. These operator
-computations are those defined by the user in an ADAO case, for the observation
-and evolution operators. It is used after the calculation has been performed in
-the ADAO case, bearing in mind that the result of this command is simply empty
-when no calculation has been performed:
-::
+.. index:: single: callinfo
 
-    from adao import adaoBuilder
-    case = adaoBuilder.New()
-    ...
-    case.execute()
-    print(case.callinfo())
+**callinfo** ()
+    A **synthesized information on the number of calls to operator
+    calculations** can be dynamically obtained with the "**callinfo()**"
+    command. These operator calculations are those defined by the user in an
+    ADAO case, for the observation and evolution operators. It is used after
+    the case calculation has been executed, bearing in mind that the result of
+    this command is simply empty when no calculation has been performed:
+    ::
+
+        from adao import adaoBuilder
+        case = adaoBuilder.New()
+        ...
+        case.execute()
+        print(case.callinfo())
 
 .. index:: single: sysinfo
 
-Synthetic **system information** can be obtained with the "**sysinfo()**"
-command, present in every calculation case. It dynamically returns system
-information and details of Python modules useful for ADAO. It is used as
-follows:
-::
+**sysinfo** ()
+    **Synthetic system information** can be obtained with the "**sysinfo()**"
+    command, present in every ADAO calculation case. It dynamically returns system
+    information and details of Python modules useful for ADAO. It is used as
+    follows:
+    ::
 
-    from adao import adaoBuilder
-    case = adaoBuilder.New()
-    print(case.sysinfo())
+        from adao import adaoBuilder
+        case = adaoBuilder.New()
+        print(case.sysinfo())
 
 .. _subsection_tui_advanced:
 
@@ -722,6 +730,8 @@ More advanced examples of ADAO TUI calculation case
 We propose here more comprehensive examples of ADAO TUI calculation, by giving
 the purpose of the example and a set of commands that can achieve this goal.
 
+.. _subsection_tui_advanced_ex11:
+
 Independent holding of the results of a calculation case
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
@@ -750,11 +760,127 @@ Finally, the whole problem is set and solved by the following script:
 The command set execution gives the following results:
 
 .. literalinclude:: scripts/tui_example_11.res
+    :language: none
 
 As it should be in twin experiments, when we trust mainly in observations, it
 is found that we get correctly the parameters that were used to artificially
 build the observations.
 
+.. _subsection_tui_advanced_ex12:
+
+Some common numerical indicators : norm, RMS, MSE et RMSE...
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+The numerical quantities obtained from an ADAO calculation are often vectors
+(such as the analysis :math:`\mathbf{x}^a`) or matrices (such as the analysis
+covariance :math:`\mathbf{A}`). They are requested by the user through the
+standard "*StoreSupplementaryCalculations*" variable of the ADAO case
+algorithm. These quantities are available at each step of an iterative
+algorithm, and therefore take the form of a series of vectors, or a series of
+matrices.
+
+These objects support special methods for computing commonly used indicators.
+The methods are named by the name of the indicator followed by "*s*" to note
+that they apply to a series of elementary objects, and that they themselves
+return a series of values.
+
+Note: some indicators are intended to qualify, for example, a "*value
+increment*", a "*value deviation*" or a "*value difference*", rather than a
+"*value*" itself. However, there is no computational impossibility to compute
+indicators for any given quantity, so it's up to the user to check that the
+indicator he is requesting is being used as intended.
+
+.. index:: single: means
+
+**means** ()
+    Average of the quantity values, available at each step.
+
+.. index:: single: stds
+
+**stds** ()
+    Standard deviation of the quantity values, available at each step.
+
+.. index:: single: sums
+
+**sums** ()
+    Sum of the quantity values, available at each step.
+
+.. index:: single: mins
+
+**mins** ()
+    Minimum of the quantity values, available at each step.
+
+.. index:: single: maxs
+
+**maxs** ()
+    Maximum of the quantity values, available at each step.
+
+.. index:: single: norms
+
+**norms** (*_ord=None*)
+    Norm of the quantity, available at each step (*_ord*: see
+    *numpy.linalg.norm*).
+
+.. index:: single: traces
+
+**traces** (*offset=0*)
+    Trace of the quantity, available at each step (*offset*: see
+    *numpy.trace*).
+
+.. index:: single: maes
+.. index:: single: Mean Absolute Error (MAE)
+
+**maes** (*predictor=None*)
+    Mean absolute error (**MAE**). This indicator is computed as the average of
+    the absolute deviations of the quantity from the predictor, and is
+    available at each step. If the predictor is not specified, this indicator
+    theoretically applies only to an increment or a difference.
+
+.. index:: single: mses
+.. index:: single: msds
+.. index:: single: Mean-Square Error (MSE)
+.. index:: single: Mean-Square Deviation (MSD)
+
+**mses** (*predictor=None*) ou **msds** (*predictor=None*)
+    Mean square error (**MSE**) or mean-square deviation* (**MSD**). This
+    indicator is computed as the root-mean-square deviation of the quantity
+    from the predictor, and is available at each step. If the predictor is not
+    specified, this indicator theoretically applies only to an increment or
+    difference.
+
+.. index:: single: rmses
+.. index:: single: rmsds
+.. index:: single: Root-Mean-Square Error (RMSE)
+.. index:: single: Root-Mean-Square Deviation (RMSD)
+.. index:: single: Root-Mean-Square (RMS)
+
+**rmses** (*predictor=None*) or **rmsds** (*predictor=None*)
+    Root-mean-square error (**RMSE**) or root-mean-square deviation (**RMSD**).
+    This indicator is calculated as the root mean square of the deviations of
+    the quantity from the predictor, and is available at each step. If the
+    predictor is not specified, this indicator theoretically applies only to an
+    increment or a difference. In the latter case, it is a **RMS** of the
+    quantity.
+
+As a simple example, we can use the calculation example presented above:
+
+.. literalinclude:: scripts/tui_example_12.py
+    :language: python
+
+Execution of the command set gives the following results, which illustrate the
+series structure of the indicators, associated with the series of values of the
+incremental quantity "*InnovationAtCurrentState*" required:
+
+.. literalinclude:: scripts/tui_example_12.res
+    :language: none
+
+In graphical form, the indicators are displayed over all the steps:
+
+.. _tui_example_12:
+.. image:: scripts/tui_example_12.png
+  :align: center
+  :width: 90%
+
 .. [HOMARD] For more information on HOMARD, see the *HOMARD module* and its integrated help available from the main menu *Help* of the SALOME platform.
 
 .. [PARAVIS] For more information on PARAVIS, see the *PARAVIS module* and its integrated help available from the main menu *Help* of the SALOME platform.
index 076f5f3dca8d0bd592e36fb657f084c2d76363ee..d029f5181427026d7446d57370ecafb71966b189 100644 (file)
@@ -71,6 +71,8 @@ Utilisations d'algorithmes orientés tâches ou études dédiées
 Utilisations avancées
 ---------------------
 
+#. :ref:`subsection_tui_advanced_ex11`
+#. :ref:`subsection_tui_advanced_ex12`
 #. :ref:`section_advanced_convert_JDC`
 #. :ref:`section_advanced_YACS_tui`
 #. :ref:`section_advanced_R`
index e903025b78fab364cf80735e59cce699ee553a83..f53731c034d4601eea26d88149bd06532cf50acb 100644 (file)
Binary files a/doc/fr/images/sampling_01_SampleAsnUplet.png and b/doc/fr/images/sampling_01_SampleAsnUplet.png differ
index e903025b78fab364cf80735e59cce699ee553a83..f53731c034d4601eea26d88149bd06532cf50acb 100644 (file)
Binary files a/doc/fr/images/sampling_02_SampleAsExplicitHyperCube.png and b/doc/fr/images/sampling_02_SampleAsExplicitHyperCube.png differ
index e903025b78fab364cf80735e59cce699ee553a83..f53731c034d4601eea26d88149bd06532cf50acb 100644 (file)
Binary files a/doc/fr/images/sampling_03_SampleAsMinMaxStepHyperCube.png and b/doc/fr/images/sampling_03_SampleAsMinMaxStepHyperCube.png differ
index 657a4030176baa8d1247c821b3111d77c31b48a8..cc2adb73bfb396bc181f38849ab96f69b7c6433b 100644 (file)
Binary files a/doc/fr/images/sampling_04_SampleAsMinMaxLatinHyperCube.png and b/doc/fr/images/sampling_04_SampleAsMinMaxLatinHyperCube.png differ
index ad1accf5a7d76055fb7bc7c84d2f769bc5841503..30886f58c4c7aaba2b33b9de10e817fa096cf635 100644 (file)
Binary files a/doc/fr/images/sampling_05_SampleAsMinMaxSobolSequence.png and b/doc/fr/images/sampling_05_SampleAsMinMaxSobolSequence.png differ
index 265457e41c627d696fa682302182059d17563922..14c9782c146ef4be1135179ded78bf256455d9de 100644 (file)
Binary files a/doc/fr/images/sampling_06_SampleAsIndependantRandomVariables_normal.png and b/doc/fr/images/sampling_06_SampleAsIndependantRandomVariables_normal.png differ
index 894f67ff5f3ac13be2718440e903789b84957b8d..21c90848f1e2b71718110c85c43e1c4fac86f750 100644 (file)
Binary files a/doc/fr/images/sampling_07_SampleAsIndependantRandomVariables_uniform.png and b/doc/fr/images/sampling_07_SampleAsIndependantRandomVariables_uniform.png differ
index 1208a8eb5123bab9569484387ea21966e6b6c053..a8b860fed3d050acac81be88a6ee6e115e537b7c 100644 (file)
Binary files a/doc/fr/images/sampling_08_SampleAsIndependantRandomVariables_weibull.png and b/doc/fr/images/sampling_08_SampleAsIndependantRandomVariables_weibull.png differ
index 05d25e4d0cc089d94feb1e59fb76b17495bf3efe..2d8619b8079e170a5c5fa73608bee5e0bc1ab696 100644 (file)
@@ -40,14 +40,27 @@ système, éventuellement au cours du temps. Il utilise des informations
 provenant de mesures expérimentales, ou observations, et de modèles numériques
 *a priori*, y compris des informations sur leurs erreurs. Certaines des
 méthodes incluses dans ce cadre sont également connues sous les noms de
-*calage* ou *recalage*, *calibration*, *estimation d'état*, *estimation de
-paramètres*, *ajustement de paramètres*, *problèmes inverses*, *méthodes
-inverses*, *inversion*, *estimation bayésienne*, *interpolation optimale*,
-*régularisation mathématique*, *méta-heuristiques* d'optimisation, *réduction
-de modèles*, *lissage de données*, etc. De plus amples détails peuvent être
-trouvés dans la partie proposant :ref:`section_theory`. Le module ADAO offre
-actuellement plus d'une centaine de méthodes algorithmiques différentes et
-permet l'étude d'environ 400 problèmes appliqués distincts.
+*calage* ou *recalage*,
+*calibration*,
+*estimation d'état*,
+*estimation de paramètres*,
+*ajustement de paramètres*,
+*problèmes inverses*,
+*méthodes inverses*,
+*inversion*,
+*estimation bayésienne*,
+*interpolation optimale*,
+*apprentissage optimal*,
+*régularisation mathématique*,
+*méta-heuristiques* d'optimisation,
+*réduction de modèles*,
+*assimilation en espace réduit*,
+*lissage de données*,
+etc.
+De plus amples détails peuvent être trouvés dans la partie proposant
+:ref:`section_theory`. Le module ADAO offre actuellement plus d'une centaine de
+méthodes algorithmiques différentes et permet l'étude d'environ 400 problèmes
+appliqués distincts.
 
 La documentation de ce module est divisée en plusieurs grandes catégories,
 relatives à la **documentation théorique** (indiquée dans le titre de section
index 852e3426f811c2fe823648d9a2fac90c292db251..4216b7a2a7e037cebe8de79a4010d8fed471fbdd 100644 (file)
@@ -64,7 +64,7 @@ demandés **explicitement** à l'aide de la variable requise.
 
 Les résultats obtenus avec cet algorithme peuvent être utilisés pour alimenter
 un :ref:`section_ref_algorithm_MeasurementsOptimalPositioningTask`. De manière
-complémentaire, et si le but est d'évaluer l'erreur calcul-mesure, un
+complémentaire, et si le but est d'évaluer l'erreur calculs-mesures, un
 :ref:`section_ref_algorithm_SamplingTest` utilise les mêmes commandes
 d'échantillonnage pour établir un ensemble de valeurs de fonctionnelle d'erreur
 :math:`J` à partir d'observations :math:`\mathbf{y}^o`.
index 7a836fae447b6063d18d51e35f76486ccb7c7033..09113388b1bf6653bdbb412e9210979cacae97ff 100644 (file)
@@ -184,6 +184,8 @@ pour éviter une durée d'optimisation rédhibitoire.
 
 .. include:: snippets/SocialAcceleration.rst
 
+.. include:: snippets/StoreInitialState.rst
+
 StoreSupplementaryCalculations
   .. index:: single: StoreSupplementaryCalculations
 
index 829f8d96e7a8cc239b782cfb8fb8e6866f2bb7b8..76823d20cfa806c843b62a7f4ac11cdb5e170c0d 100644 (file)
@@ -52,8 +52,8 @@ Des patrons (ou "templates") sont donnés ci-après en
 :ref:`subsection_r_o_v_Template`.  Dans tous les cas, le post-processing de
 l'utilisateur dispose dans l'espace de noms d'une variable dont le nom est
 "*ADD*", et dont l'unique méthode utilisable est nommée ``get``. Les arguments
-de cette méthode sont un nom d'information de sortie, comme décrit dans
-l':ref:`subsection_r_o_v_Inventaire`.
+de cette méthode sont un nom d'information de sortie, comme décrit dans un
+:ref:`subsection_r_o_v_Inventaire`.
 
 Par exemple, pour avoir l'état optimal après un calcul d'assimilation de données
 ou d'optimisation, on utilise l'appel suivant::
index 6eb30af2e42157b422b1728f1f58576c6b8d76a0..75e7d78d2eced751052f4ecb2ccb21ed29bf92ff 100644 (file)
@@ -171,7 +171,7 @@ La commande de génération implicite d'échantillons par
 .. code-block:: python
 
     [...]
-    "SampleAsMinMaxSobolSequence":[[0, 4, 1], [0, 4, 1], [2, 25]]
+    "SampleAsMinMaxSobolSequence":[[0, 4], [0, 4], [2, 25]]
     [...]
 
 La répartition des états (il y en a ici 32 par principe de construction de la
index 50724ec43db073e6f658fe9e30c00cc827e9a565..9db9a31b3c7881e72d512f857e8859e8d88bcd68 100644 (file)
Binary files a/doc/fr/scripts/simple_3DVAR1.png and b/doc/fr/scripts/simple_3DVAR1.png differ
index d0952c5e2ac2c674a1f4c58a12999f4fc7be59f5..6546e00928e75713091ef540e795dea0b0fe4fee 100644 (file)
Binary files a/doc/fr/scripts/simple_3DVAR1Plus.png and b/doc/fr/scripts/simple_3DVAR1Plus.png differ
index f9f33ae589b3041d61062d1f608362dbd4cb4693..e368e4cec279e40e6888e5948c73b24697c0cc89 100644 (file)
Binary files a/doc/fr/scripts/simple_3DVAR2_state.png and b/doc/fr/scripts/simple_3DVAR2_state.png differ
index 8ac41b3c54e0a567e18d46ac445a3aeaff2a1a11..7225c7e8d60f3b687e9fae1454bef308d6f38226 100644 (file)
Binary files a/doc/fr/scripts/simple_3DVAR2_variance.png and b/doc/fr/scripts/simple_3DVAR2_variance.png differ
index 71077ccad1a7ca9fc44b5b329a7f4e84628aee02..4679c57620ed56ed06ba5b5e0320df572a10cedd 100644 (file)
Binary files a/doc/fr/scripts/simple_3DVAR3_state.png and b/doc/fr/scripts/simple_3DVAR3_state.png differ
index ed81dc31d57eca4998c34af1bb8de9ebc57acff0..00ea4e2f137dcf8b33a4aa48c42d2dcd5f6519e0 100644 (file)
Binary files a/doc/fr/scripts/simple_3DVAR3_variance.png and b/doc/fr/scripts/simple_3DVAR3_variance.png differ
index 74a51d88eba628b1e48fd2d423c70845879c23c5..aefecd4a02ed0bf7263f18c868a2b6e88368d0ba 100644 (file)
Binary files a/doc/fr/scripts/simple_DerivativeFreeOptimization.png and b/doc/fr/scripts/simple_DerivativeFreeOptimization.png differ
index 2d80a3dc64e5b55275952443d7b5294d1d9940b4..501ba592ba40b24d9ecf6ab0c0c24dcc47a568a4 100644 (file)
Binary files a/doc/fr/scripts/simple_KalmanFilter1_state.png and b/doc/fr/scripts/simple_KalmanFilter1_state.png differ
index 6c2d1aaa2d428b18a9e16f5e2fb78d1135e5ea32..a101a751c8af2bf3ec47362912ee2f48c06b1473 100644 (file)
Binary files a/doc/fr/scripts/simple_KalmanFilter1_variance.png and b/doc/fr/scripts/simple_KalmanFilter1_variance.png differ
index 2d80a3dc64e5b55275952443d7b5294d1d9940b4..501ba592ba40b24d9ecf6ab0c0c24dcc47a568a4 100644 (file)
Binary files a/doc/fr/scripts/simple_KalmanFilter2_state.png and b/doc/fr/scripts/simple_KalmanFilter2_state.png differ
index 6c2d1aaa2d428b18a9e16f5e2fb78d1135e5ea32..a101a751c8af2bf3ec47362912ee2f48c06b1473 100644 (file)
Binary files a/doc/fr/scripts/simple_KalmanFilter2_variance.png and b/doc/fr/scripts/simple_KalmanFilter2_variance.png differ
index bec439018e5fa907d186abd5fed1e0d06678b87a..7fa8e18f0d56430a2e09f99af8567bec4d1ad806 100644 (file)
Binary files a/doc/fr/scripts/simple_MeasurementsOptimalPositioningTask3.png and b/doc/fr/scripts/simple_MeasurementsOptimalPositioningTask3.png differ
index 74a51d88eba628b1e48fd2d423c70845879c23c5..aefecd4a02ed0bf7263f18c868a2b6e88368d0ba 100644 (file)
Binary files a/doc/fr/scripts/simple_NonLinearLeastSquares.png and b/doc/fr/scripts/simple_NonLinearLeastSquares.png differ
index 5e9f08cacc56b91fc8b685239ea0cb7d60ab664e..19a69f2e2a1c1264ba2ea1ccaadf3f3928dd2b8a 100644 (file)
Binary files a/doc/fr/scripts/simple_ParticleSwarmOptimization1.png and b/doc/fr/scripts/simple_ParticleSwarmOptimization1.png differ
index 03662e74d1e04d3a2e0aaae17b8bd7ca59832ac2..964d69a622b35c1e7c41df8d14ef64f966d2a9f1 100644 (file)
Binary files a/doc/fr/scripts/simple_ReducedModelingTest1.png and b/doc/fr/scripts/simple_ReducedModelingTest1.png differ
index a3a333e004d9198a55cd469803c37d39e2bff59a..8601953669c3a2c919658890497fd804930ced8c 100644 (file)
@@ -2,7 +2,7 @@
 ADAO Study report
 ================================================================================
 
-Summary build with ADAO version 9.13.0
+Summary build with ADAO version 9.14.0
 
   - AlgorithmParameters command has been set with values:
         Algorithm = '3DVAR'
index 452efd4930a467bc74c7a66e2ca439eaaaea95c5..cc514f87d84936bb9608017e07b593e7629d0357 100644 (file)
@@ -74,7 +74,7 @@ FX_at_optimum = case.get("SimulatedObservationAtOptimum")[-1]
 J_values      = case.get("CostFunctionJ")[:]
 #
 # =============================================================
-# EXPLOITATION DES RÉSULTATS INDÉPENDANTE
+# EXPLOITATION INDÉPENDANTE DES RÉSULTATS
 #
 print("")
 print("Nombre d'itérations internes...: %i"%len(J_values))
diff --git a/doc/fr/scripts/tui_example_12.png b/doc/fr/scripts/tui_example_12.png
new file mode 100644 (file)
index 0000000..646dadf
Binary files /dev/null and b/doc/fr/scripts/tui_example_12.png differ
diff --git a/doc/fr/scripts/tui_example_12.py b/doc/fr/scripts/tui_example_12.py
new file mode 100644 (file)
index 0000000..2415799
--- /dev/null
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+#
+from matplotlib import pyplot as plt
+from numpy import array, set_printoptions
+from adao import adaoBuilder
+set_printoptions(precision=4, floatmode='fixed')
+#
+#-------------------------------------------------------------------------------
+#
+case = adaoBuilder.New()
+case.set( 'AlgorithmParameters',
+    Algorithm='3DVAR',
+    Parameters = {
+        "StoreSupplementaryCalculations":[
+            "CostFunctionJ",
+            "CurrentState",
+            "InnovationAtCurrentState",
+        ],
+    }
+)
+case.set( 'Background',          Vector=[0, 1, 2] )
+case.set( 'BackgroundError',     ScalarSparseMatrix=1.0 )
+case.set( 'Observation',         Vector=array([0.5, 1.5, 2.5]) )
+case.set( 'ObservationError',    DiagonalSparseMatrix='1 1 1' )
+case.set( 'ObservationOperator', Matrix='1 0 0;0 2 0;0 0 3' )
+case.set( 'Observer',
+    Variable="CurrentState",
+    Template="ValuePrinter",
+    Info="  État courant :",
+)
+#
+print("Affichage des valeurs de l'état courant, à chaque pas :")
+case.execute()
+print("")
+#
+#-------------------------------------------------------------------------------
+#
+print("Indicateurs sur les écarts (ou erreurs) calculs-mesures")
+print("     (affichage des 3 premiers pas uniquement)")
+print("")
+CalculMeasureErrors = case.get("InnovationAtCurrentState")
+#
+print("===> Maximum de l'erreur entre calculs et mesures, à chaque pas :")
+print("    ",array(
+    CalculMeasureErrors.maxs()
+    [0:3] ))
+print("===> Minimum de l'erreur entre calculs et mesures, à chaque pas :")
+print("    ",array(
+    CalculMeasureErrors.mins()
+    [0:3] ))
+print("===> Norme de l'erreur entre calculs et mesures, à chaque pas :")
+print("    ",array(
+    CalculMeasureErrors.norms()
+    [0:3] ))
+print("===> Erreur absolue moyenne (MAE) entre calculs et mesures, à chaque pas :")
+print("    ",array(
+    CalculMeasureErrors.maes()
+    [0:3] ))
+print("===> Erreur quadratique moyenne (MSE) entre calculs et mesures, à chaque pas :")
+print("    ",array(
+    CalculMeasureErrors.mses()
+    [0:3] ))
+print("===> Racine de l'erreur quadratique moyenne (RMSE) entre calculs et mesures, à chaque pas :")
+print("    ",array(
+    CalculMeasureErrors.rmses()
+    [0:3] ))
+#
+#-------------------------------------------------------------------------------
+#
+import matplotlib.pyplot as plt
+plt.rcParams['figure.figsize'] = (8, 12)
+#
+plt.figure()
+plt.suptitle('Indicateurs construits sur la valeur courante des écarts (ou erreurs) calculs-mesures\n', fontweight='bold')
+plt.subplot(611)
+plt.plot(CalculMeasureErrors.maxs(), 'bx--', label='Indicateur au pas courant')
+plt.ylabel('Maximum (u.a.)')
+plt.legend()
+plt.subplot(612)
+plt.plot(CalculMeasureErrors.mins(), 'bx--', label='Indicateur au pas courant')
+plt.ylabel('Minimum (u.a.)')
+plt.legend()
+plt.subplot(613)
+plt.plot(CalculMeasureErrors.norms(), 'bx-', label='Indicateur au pas courant')
+plt.ylabel('Norme (u.a.)')
+plt.legend()
+plt.subplot(614)
+plt.plot(CalculMeasureErrors.maes(), 'kx-', label='Indicateur au pas courant')
+plt.ylabel('MAE (u.a.)')
+plt.legend()
+plt.subplot(615)
+plt.plot(CalculMeasureErrors.mses(), 'gx-', label='Indicateur au pas courant')
+plt.ylabel('MSE (u.a.)')
+plt.legend()
+plt.subplot(616)
+plt.plot(CalculMeasureErrors.rmses(), 'rx-', label='Indicateur au pas courant')
+plt.ylabel('RMSE (u.a.)')
+plt.legend()
+plt.xlabel('Pas de calcul de la grandeur (numéro ou rang du pas)')
+plt.tight_layout()
+plt.savefig("tui_example_12.png")
diff --git a/doc/fr/scripts/tui_example_12.res b/doc/fr/scripts/tui_example_12.res
new file mode 100644 (file)
index 0000000..3aac8f4
--- /dev/null
@@ -0,0 +1,26 @@
+Affichage des valeurs de l'état courant, à chaque pas :
+  État courant : [0.0000 1.0000 2.0000]
+  État courant : [0.0474 0.9053 1.0056]
+  État courant : [0.0905 0.8492 0.9461]
+  État courant : [0.1529 0.7984 0.9367]
+  État courant : [0.2245 0.7899 0.9436]
+  État courant : [0.2508 0.8005 0.9486]
+  État courant : [0.2500 0.7998 0.9502]
+  État courant : [0.2500 0.8000 0.9500]
+  État courant : [0.2500 0.8000 0.9500]
+
+Indicateurs sur les écarts (ou erreurs) calculs-mesures
+     (affichage des 3 premiers pas uniquement)
+
+===> Maximum de l'erreur entre calculs et mesures, à chaque pas :
+     [0.5000 0.4526 0.4095]
+===> Minimum de l'erreur entre calculs et mesures, à chaque pas :
+     [-3.5000 -0.5169 -0.3384]
+===> Norme de l'erreur entre calculs et mesures, à chaque pas :
+     [3.5707 0.7540 0.5670]
+===> Erreur absolue moyenne (MAE) entre calculs et mesures, à chaque pas :
+     [1.5000 0.4267 0.3154]
+===> Erreur quadratique moyenne (MSE) entre calculs et mesures, à chaque pas :
+     [4.2500 0.1895 0.1072]
+===> Racine de l'erreur quadratique moyenne (RMSE) entre calculs et mesures, à chaque pas :
+     [2.0616 0.4353 0.3274]
index 43bddd3373e276b5f63b1800d51208537806d5fd..2acc5c879189c0fa14b3d25602dc015245b378b8 100644 (file)
@@ -3,11 +3,12 @@ Informations et variables disponibles à la fin de l'algorithme
 
 En sortie, après exécution de l'algorithme, on dispose d'informations et de
 variables issues du calcul. La description des
-:ref:`section_ref_output_variables` indique la manière de les obtenir par la
-méthode nommée ``get``, de la variable "*ADD*" du post-processing en interface
-graphique, ou du cas en interface textuelle. Les variables d'entrée, mises à
-disposition de l'utilisateur en sortie pour faciliter l'écriture des procédures
-de post-processing, sont décrites dans l':ref:`subsection_r_o_v_Inventaire`.
+:ref:`section_ref_output_variables` indique la manière de les obtenir, par la
+méthode nommée ``get``, depuis la variable "*ADD*" du post-processing en
+interface graphique, ou depuis le cas en interface textuelle. Les variables
+d'entrée, mises à disposition de l'utilisateur en sortie pour faciliter
+l'écriture des procédures de post-processing, sont décrites dans un
+:ref:`subsection_r_o_v_Inventaire`.
 
 **Sorties permanentes (non conditionnelles)**
 
index e3105b3441c7690a54b665d817fd8cdcfa0ec23c..6ffafe57ae95b27a7e50cbfc55d7e68d656d56a7 100644 (file)
@@ -2,7 +2,7 @@
 
 MaximumNumberOfLocations
   *Valeur entière*. Cette clé indique le nombre maximum possible de positions
-  trouvée dans la recherche optimale. La valeur par défaut est 1. La recherche
+  trouvées dans la recherche optimale. La valeur par défaut est 1. La recherche
   optimale peut éventuellement trouver moins de positions que ce qui est requis
   par cette clé, comme par exemple dans le cas où le résidu associé à
   l'approximation est inférieur au critère et conduit à l'arrêt anticipé de la
index 04b5748adb00649619a631579bbca4cece1f0c3c..87d5674f3a53db3ffd246ea7fbc1da5866c30e21 100644 (file)
@@ -11,13 +11,15 @@ inhabituelle est rencontrée pour des calculs fonctionnant précédemment, il es
 fortement conseillé de revenir à des versions d'outils supports comprises dans
 l'étendue décrite ci-dessous.
 
-.. csv-table:: Intervalles de vérification des outils support pour ADAO
+.. csv-table:: Intervalles de version de vérification des outils support pour ADAO
    :header: "Outil", "Version minimale", "Version atteinte"
    :widths: 20, 10, 10
+   :align: center
 
-   Python,     3.6.5,    3.12.3
-   Numpy,      1.14.3,    1.26.4
-   Scipy,      0.19.1,    1.14.0
-   MatplotLib, 2.2.2,    3.8.4
+   Python,     3.6.5,    3.12.6
+   Numpy,      1.14.3,    2.1.2
+   Scipy,      0.19.1,    1.14.1
+   MatplotLib, 2.2.2,    3.9.2
    GnuplotPy,  1.8,    1.8
-   NLopt,      2.4.2,    2.7.1
+   NLopt,      2.4.2,    2.8.0
+   FMPy,       0.3.20,    0.3.20
index 55e2e0283adf0c6d08408464f0e096a27b41056e..06c12aea73d0bfbe889a2bbb1bcf20b5907af591 100644 (file)
@@ -8,6 +8,7 @@ uniquement sachant que, en cas de doute, c'est la fiche de version de SALOME
 .. csv-table:: Versions de validation des outils support pour ADAO
    :header: "Outil", "Version"
    :widths: 20, 10
+   :align: center
 
    ADAO,       |release|
    EFICAS,     |release|
index 7edf811bbc2561b9366eddccf430a0e0105df757..c82ea869913d7d605ca34182cf49668cacc7ef9d 100644 (file)
@@ -1 +1 @@
-    *Aucune*
+    *Aucune* (messages ou statistiques sont néanmoins affichés)
index 543e46c37e8255e51f142aad7e96831dab6618ae..87f7a6a55d42a836138b68189c84e654a875aa3e 100644 (file)
@@ -10,7 +10,7 @@ SampleAsIndependantRandomVariables
   'normal' de paramètres (mean,std), 'lognormal' de paramètres (mean,sigma),
   'uniform' de paramètres (low,high), ou 'weibull' de paramètre (shape). C'est
   donc une liste de la même taille que celle de l'état. Par nature, les points
-  sont inclus le domaine non borné ou borné selon les caractéristiques des
+  sont inclus dans le domaine non borné ou borné selon les caractéristiques des
   distributions choisies par variable.
 
   Exemple :
index fbe4d483027f6c2cb6f9c498a1ede3c6479edab3..b9a3ee6662ef41b369047f329ef58e2388636d6a 100644 (file)
@@ -7,7 +7,7 @@ SampleAsMinMaxLatinHyperCube
   lequel les points de calcul seront placés, sous la forme d'une paire
   *[min,max]* pour chaque composante de l'état. Les bornes inférieures sont
   incluses. Cette liste de paires, en nombre identique à la taille de l'espace
-  des états, est complétée par une paire d'entier *[dim,nbr]* comportant la
+  des états, est complétée par une paire d'entiers *[dim,nbr]* comportant la
   dimension de l'espace des états et le nombre souhaité de points
   d'échantillonnage. L'échantillonnage est ensuite construit automatiquement
   selon la méthode de l'hypercube Latin (LHS). Par nature, les points sont
index 2bd61bd32bd3b7b5c93c75639090099d21fc01fc..27e281984e9d2777b848cd307861d1f77188ae8a 100644 (file)
@@ -7,7 +7,7 @@ SampleAsMinMaxSobolSequence
   lequel les points de calcul seront placés, sous la forme d'une paire
   *[min,max]* pour chaque composante de l'état. Les bornes inférieures sont
   incluses. Cette liste de paires, en nombre identique à la taille de l'espace
-  des états, est complétée par une paire d'entier *[dim,nbr]* comportant la
+  des états, est complétée par une paire d'entiers *[dim,nbr]* comportant la
   dimension de l'espace des états et le nombre minimum souhaité de points
   d'échantillonnage (par construction, le nombre de points générés dans la
   séquence de Sobol sera la puissance de 2 immédiatement supérieure à ce nombre
diff --git a/doc/fr/snippets/StoreInitialState.rst b/doc/fr/snippets/StoreInitialState.rst
new file mode 100644 (file)
index 0000000..c301580
--- /dev/null
@@ -0,0 +1,11 @@
+.. index:: single: StoreInitialState
+
+StoreInitialState
+  *Valeur booléenne*. Cette variable définit le stockage (avec True) ou pas
+  (avec False, par défaut) de l'état initial de l'algorithme comme étant le
+  premier état dans la suite itérative des états trouvés. Cela rend le stockage
+  algorithmique itératif identique au stockage temporel itératif (de manière
+  par exemple similaire aux filtres de Kalman).
+
+  Exemple :
+  ``{"StoreInitialState":False}``
index d2ddce96b4cc32f1878716098f8bc174a722fcd2..b82996d8cec1800b747ff851d0543b3d6e373da9 100644 (file)
@@ -73,6 +73,7 @@ commande "*shell*" de SALOME, dans une console Python SALOME de l'interface, ou
 par le menu d'exécution d'un script) est le suivant :
 
 .. literalinclude:: scripts/tui_example_01.res
+    :language: none
 
 Création détaillée d'un cas de calcul TUI ADAO
 ++++++++++++++++++++++++++++++++++++++++++++++
@@ -655,8 +656,8 @@ Obtenir séparément les résultats de calcul
     variable dans "*Concept*", et renvoie en retour la grandeur sous la forme
     d'une liste (même s'il n'y en a qu'un exemplaire) de cette variable de
     base. Pour connaître la liste des variables et les utiliser, on se
-    reportera à l':ref:`subsection_r_o_v_Inventaire`, et plus généralement à la
-    fois aux :ref:`section_ref_output_variables` et aux documentations
+    reportera à un :ref:`subsection_r_o_v_Inventaire`, et plus généralement à
+    la fois aux :ref:`section_ref_output_variables` et aux documentations
     individuelles des algorithmes.
 
 Enregistrer, charger ou convertir les commandes de cas de calcul
@@ -707,45 +708,53 @@ externes au cas.
 Obtenir des informations sur le cas, le calcul ou le système
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
-On peut obtenir de manière simple une **information agrégée sur le cas
-d'étude** tel que défini par l'utilisateur, en utilisant directement la
-commande "*print*" de Python sur le cas, à n'importe quelle étape lors de sa
-construction. Par exemple :
+Il existe plusieurs manières d'obtenir des informations globales relatives
+au cas de calcul, à l'exécution ou au système sur lequel est exécuté un cas.
 
-.. literalinclude:: scripts/tui_example_07.py
-    :language: python
+*print* (*cas*)
+    On peut obtenir de manière simple une **information agrégée sur le cas
+    d'étude** tel que défini par l'utilisateur, en utilisant directement la
+    commande "*print*" de Python sur le cas, à n'importe quelle étape lors de sa
+    construction. Par exemple :
 
-dont le résultat est ici :
+    .. literalinclude:: scripts/tui_example_07.py
+        :language: python
 
-.. literalinclude:: scripts/tui_example_07.res
+    dont le résultat est ici :
 
-.. index:: single: callinfo
+    .. literalinclude:: scripts/tui_example_07.res
+        :language: none
 
-Une **information synthétique sur le nombre d'appels aux calculs d'opérateurs**
-peut être dynamiquement obtenue par la commande "**callinfo()**". Ces calculs
-d'opérateurs sont ceux définis par l'utilisateur dans un cas ADAO, pour les
-opérateurs d'observation et d'évolution. Elle s'utilise après l'exécution du
-calcul dans le cas ADAO, sachant que le résultat de cette commande est
-simplement vide lorsqu'aucun calcul n'a été effectué :
-::
+.. index:: single: callinfo
 
-    from adao import adaoBuilder
-    case = adaoBuilder.New()
-    ...
-    case.execute()
-    print(case.callinfo())
+**callinfo** ()
+    Une **information synthétique sur le nombre d'appels aux calculs
+    d'opérateurs** peut être dynamiquement obtenue par la commande
+    "**callinfo()**". Ces calculs d'opérateurs sont ceux définis par
+    l'utilisateur dans un cas ADAO, pour les opérateurs d'observation et
+    d'évolution. Elle s'utilise après l'exécution du calcul du cas, sachant que
+    le résultat de cette commande est simplement vide lorsqu'aucun calcul n'a
+    été effectué :
+    ::
+
+        from adao import adaoBuilder
+        case = adaoBuilder.New()
+        ...
+        case.execute()
+        print(case.callinfo())
 
 .. index:: single: sysinfo
 
-Une **information synthétique sur le système** peut être obtenue par la
-commande "**sysinfo()**", présente dans chaque cas de calcul ADAO. Elle
-retourne dynamiquement des informations système et des détails sur les modules
-Python utiles pour ADAO. Elle s'utilise de la manière suivante :
-::
+**sysinfo** ()
+    Une **information synthétique sur le système** peut être obtenue par la
+    commande "**sysinfo()**", présente dans chaque cas de calcul ADAO. Elle
+    retourne dynamiquement des informations système et des détails sur les
+    modules Python utiles pour ADAO. Elle s'utilise de la manière suivante :
+    ::
 
-    from adao import adaoBuilder
-    case = adaoBuilder.New()
-    print(case.sysinfo())
+        from adao import adaoBuilder
+        case = adaoBuilder.New()
+        print(case.sysinfo())
 
 .. _subsection_tui_advanced:
 
@@ -756,6 +765,8 @@ On propose ici des exemples plus complets de cas de calcul TUI ADAO, en donnant
 l'objectif de l'exemple et un jeu de commandes qui permet de parvenir à cet
 objectif.
 
+.. _subsection_tui_advanced_ex11:
+
 Exploitation indépendante des résultats d'un cas de calcul
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
@@ -785,11 +796,132 @@ script suivant :
 L'exécution de jeu de commandes donne les résultats suivants :
 
 .. literalinclude:: scripts/tui_example_11.res
+    :language: none
 
 Comme il se doit en expériences jumelles, avec une confiance majoritairement
 placée dans les observations, on constate que l'on retrouve bien les paramètres
 qui ont servi à construire artificiellement les observations.
 
+.. _subsection_tui_advanced_ex12:
+
+Quelques indicateurs numériques particuliers : norme, RMS, MSE et RMSE...
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Les grandeurs numériques obtenues à l'issue d'un calcul ADAO sont souvent des
+vecteurs (comme l'analyse :math:`\mathbf{x}^a`) ou des matrices (comme la
+covariance d'analyse :math:`\mathbf{A}`). Elles sont requises par l'utilisateur
+à travers la variable standard "*StoreSupplementaryCalculations*" de
+l'algorithme du cas ADAO. Ces grandeurs sont disponible à chaque étape d'un
+algorithme itératif, et se présentent donc sous la forme d'une série de
+vecteurs, ou d'une série de matrices.
+
+Les objets portant ces grandeurs supportent des méthodes particulières pour
+calculer des indicateurs courants. Les méthodes sont nommées par le nom de
+l'indicateur suivi de "*s*" pour noter qu'elle s'appliquent à une série d'objets
+élémentaires, et qu'elles renvoient elles-mêmes une série de valeurs.
+
+Remarque : certains indicateurs sont destinés à qualifier par exemple un
+"*incrément de valeur*", un "*écart de valeur*" ou une "*différence de
+valeur*", plutôt qu'une "*valeur*" elle-même. Informatiquement, il n'y a
+néanmoins pas d'impossibilité à calculer les indicateurs quelle que soit la
+grandeur considérée, c'est donc à l'utilisateur de bien vérifier que
+l'indicateur dont il demande le calcul est utilisé de manière licite.
+
+.. index:: single: means
+
+**means** ()
+    Moyenne des valeurs de la grandeur, disponible à chaque pas.
+
+.. index:: single: stds
+
+**stds** ()
+    Écart-type des valeurs de la grandeur, disponible à chaque pas.
+
+.. index:: single: sums
+
+**sums** ()
+    Somme des valeurs de la grandeur, disponible à chaque pas.
+
+.. index:: single: mins
+
+**mins** ()
+    Minimum des valeurs de la grandeur, disponible à chaque pas.
+
+.. index:: single: maxs
+
+**maxs** ()
+    Maximum des valeurs de la grandeur, disponible à chaque pas.
+
+.. index:: single: norms
+
+**norms** (*_ord=None*)
+    Norme de la grandeur, disponible à chaque pas (*_ord* : voir
+    *numpy.linalg.norm*).
+
+.. index:: single: traces
+
+**traces** (*offset=0*)
+    Trace de la grandeur, disponible à chaque pas (*offset* : voir
+    *numpy.trace*).
+
+.. index:: single: maes
+.. index:: single: Mean Absolute Error (MAE)
+
+**maes** (*predictor=None*)
+    Erreur ou écart moyen absolu (*Mean Absolute Error* (**MAE**)). Cet
+    indicateur est calculé comme la moyenne des écarts en valeur absolue de la
+    grandeur par rapport au prédicteur, et l'indicateur est disponible à chaque
+    pas. Si le prédicteur est non renseigné, cet indicateur ne s'applique
+    théoriquement qu'à un incrément ou une différence.
+
+.. index:: single: mses
+.. index:: single: msds
+.. index:: single: Mean-Square Error (MSE)
+.. index:: single: Mean-Square Deviation (MSD)
+
+**mses** (*predictor=None*) ou **msds** (*predictor=None*)
+    Erreur ou écart quadratique moyen (*Mean-Square Error* (**MSE**) ou
+    *Mean-Square Deviation* (**MSD**)). Cet indicateur est calculé comme la
+    moyenne quadratique des écarts de la grandeur par rapport au prédicteur, et
+    l'indicateur est disponible à chaque pas. Si le prédicteur est non
+    renseigné, cet indicateur ne s'applique théoriquement qu'à un incrément ou
+    une différence.
+
+.. index:: single: rmses
+.. index:: single: rmsds
+.. index:: single: Root-Mean-Square Error (RMSE)
+.. index:: single: Root-Mean-Square Deviation (RMSD)
+.. index:: single: Root-Mean-Square (RMS)
+
+**rmses** (*predictor=None*) ou **rmsds** (*predictor=None*)
+    Racine de l'erreur ou de l'écart quadratique moyen (*Root-Mean-Square
+    Error* (**RMSE**) ou *Root-Mean-Square Deviation* (**RMSD**)). Cet
+    indicateur est calculé comme la racine de la moyenne quadratique des écarts
+    de la grandeur par rapport au prédicteur, et l'indicateur est disponible à
+    chaque pas. Si le prédicteur est non renseigné, cet indicateur ne
+    s'applique théoriquement qu'à un incrément ou une différence. Dans ce
+    dernier cas, c'est une **RMS** de la grandeur.
+
+À titre d'exemple simple, on peut reprendre le cas de calcul déjà présenté plus
+haut :
+
+.. literalinclude:: scripts/tui_example_12.py
+    :language: python
+
+L'exécution de jeu de commandes donne les résultats suivants, qui illustrent la
+structure en série des indicateurs, associés à la série de valeurs de la
+grandeur incrémentale "*InnovationAtCurrentState*" requise :
+
+.. literalinclude:: scripts/tui_example_12.res
+    :language: none
+
+Sous forme graphique, on observe les indicateurs sur l'ensemble des pas :
+
+.. _tui_example_12:
+.. image:: scripts/tui_example_12.png
+  :align: center
+  :width: 90%
+
 .. Réconciliation de courbes à l'aide de MedCoupling
 .. +++++++++++++++++++++++++++++++++++++++++++++++++
 
index 285e5d9ee1a939f1d0e26323bafb94bbadfaf6e0..6d49bf752595f2681158acdbcd838467e0c920f0 100644 (file)
@@ -110,6 +110,15 @@ def ecwapso(selfA, Xb, Y, HO, R, B):
     #
     nbfct = 1  # Nb d'évaluations
     JXini, JbXini, JoXini = CostFunction(Xini, selfA._parameters["QualityCriterion"])
+    if selfA._parameters["StoreInitialState"]:
+        selfA.StoredVariables["CurrentIterationNumber"].store( len(selfA.StoredVariables["CostFunctionJ"]) )
+        selfA.StoredVariables["CostFunctionJ" ].store( JXini  )
+        selfA.StoredVariables["CostFunctionJb"].store( JbXini )
+        selfA.StoredVariables["CostFunctionJo"].store( JoXini )
+        if selfA._toStore("CurrentState"):
+            selfA.StoredVariables["CurrentState"].store( Xini )
+        if selfA._toStore("SimulatedObservationAtCurrentState"):
+            selfA.StoredVariables["SimulatedObservationAtCurrentState"].store( Hm( Xini ) )
     #
     Swarm  = numpy.zeros((__nbI, 4, __nbP))  # 4 car (x,v,gbest,lbest)
     for __p in range(__nbP):
@@ -157,6 +166,7 @@ def ecwapso(selfA, Xb, Y, HO, R, B):
     step = 0
     while KeepRunningCondition(step, nbfct):
         step += 1
+        #
         for __i in range(__nbI):
             __rct = rand(size=__nbP)
             __rst = rand(size=__nbP)
index 807056013f1afc154f4f03fb587dd82c7aadfe96..6d90f74fc10c926d4acdd430c181750584e0a372 100644 (file)
@@ -108,6 +108,15 @@ def ecwnpso(selfA, Xb, Y, HO, R, B):
     #
     nbfct = 1  # Nb d'évaluations
     JXini, JbXini, JoXini = CostFunction(Xini, selfA._parameters["QualityCriterion"])
+    if selfA._parameters["StoreInitialState"]:
+        selfA.StoredVariables["CurrentIterationNumber"].store( len(selfA.StoredVariables["CostFunctionJ"]) )
+        selfA.StoredVariables["CostFunctionJ" ].store( JXini  )
+        selfA.StoredVariables["CostFunctionJb"].store( JbXini )
+        selfA.StoredVariables["CostFunctionJo"].store( JoXini )
+        if selfA._toStore("CurrentState"):
+            selfA.StoredVariables["CurrentState"].store( Xini )
+        if selfA._toStore("SimulatedObservationAtCurrentState"):
+            selfA.StoredVariables["SimulatedObservationAtCurrentState"].store( Hm( Xini ) )
     #
     Swarm  = numpy.zeros((__nbI, 4, __nbP))  # 4 car (x,v,xbest,lbest)
     for __p in range(__nbP):
@@ -150,6 +159,7 @@ def ecwnpso(selfA, Xb, Y, HO, R, B):
     step = 0
     while KeepRunningCondition(step, nbfct):
         step += 1
+        #
         for __i in range(__nbI):
             rct = rand(size=__nbP)
             rst = rand(size=__nbP)
index af4eaf5552d930134d80d2a0dc5c2ba95a1f2851..3846c2aa660cd62e3a30c256c5762bb60a42647a 100644 (file)
@@ -108,6 +108,15 @@ def ecwopso(selfA, Xb, Y, HO, R, B):
     #
     nbfct = 1  # Nb d'évaluations
     JXini, JbXini, JoXini = CostFunction(Xini, selfA._parameters["QualityCriterion"])
+    if selfA._parameters["StoreInitialState"]:
+        selfA.StoredVariables["CurrentIterationNumber"].store( len(selfA.StoredVariables["CostFunctionJ"]) )
+        selfA.StoredVariables["CostFunctionJ" ].store( JXini  )
+        selfA.StoredVariables["CostFunctionJb"].store( JbXini )
+        selfA.StoredVariables["CostFunctionJo"].store( JoXini )
+        if selfA._toStore("CurrentState"):
+            selfA.StoredVariables["CurrentState"].store( Xini )
+        if selfA._toStore("SimulatedObservationAtCurrentState"):
+            selfA.StoredVariables["SimulatedObservationAtCurrentState"].store( Hm( Xini ) )
     #
     Swarm  = numpy.zeros((__nbI, 3, __nbP))  # 3 car (x,v,xbest)
     for __p in range(__nbP):
@@ -150,6 +159,7 @@ def ecwopso(selfA, Xb, Y, HO, R, B):
     step = 0
     while KeepRunningCondition(step, nbfct):
         step += 1
+        #
         for __i in range(__nbI):
             for __p in range(__nbP):
                 # Vitesse
index c7f3aa2256c1d490751f71fd58450e7a6716fcbb..d2e5154593807724092619c05ef38c69e7b683c7 100644 (file)
@@ -111,6 +111,15 @@ def ecwpspso(selfA, Xb, Y, HO, R, B):
     nbfct = 1  # Nb d'évaluations
     HX = Hm( Xini )
     JXini, JbXini, JoXini = CostFunction(Xini, HX, selfA._parameters["QualityCriterion"])
+    if selfA._parameters["StoreInitialState"]:
+        selfA.StoredVariables["CurrentIterationNumber"].store( len(selfA.StoredVariables["CostFunctionJ"]) )
+        selfA.StoredVariables["CostFunctionJ" ].store( JXini  )
+        selfA.StoredVariables["CostFunctionJb"].store( JbXini )
+        selfA.StoredVariables["CostFunctionJo"].store( JoXini )
+        if selfA._toStore("CurrentState"):
+            selfA.StoredVariables["CurrentState"].store( Xini )
+        if selfA._toStore("SimulatedObservationAtCurrentState"):
+            selfA.StoredVariables["SimulatedObservationAtCurrentState"].store( HX )
     #
     Swarm  = numpy.zeros((__nbI, 4, __nbP))  # 4 car (x,v,gbest,lbest)
     for __p in range(__nbP):
index d757cd5415eac7eead78290228de967fe21d57e4..fc4ffe69c29352ef326e62fecf69eac9036e33d8 100644 (file)
@@ -110,6 +110,15 @@ def ecwspso(selfA, Xb, Y, HO, R, B):
     #
     nbfct = 1  # Nb d'évaluations
     JXini, JbXini, JoXini = CostFunction(Xini, selfA._parameters["QualityCriterion"])
+    if selfA._parameters["StoreInitialState"]:
+        selfA.StoredVariables["CurrentIterationNumber"].store( len(selfA.StoredVariables["CostFunctionJ"]) )
+        selfA.StoredVariables["CostFunctionJ" ].store( JXini  )
+        selfA.StoredVariables["CostFunctionJb"].store( JbXini )
+        selfA.StoredVariables["CostFunctionJo"].store( JoXini )
+        if selfA._toStore("CurrentState"):
+            selfA.StoredVariables["CurrentState"].store( Xini )
+        if selfA._toStore("SimulatedObservationAtCurrentState"):
+            selfA.StoredVariables["SimulatedObservationAtCurrentState"].store( Hm( Xini ) )
     #
     Swarm  = numpy.zeros((__nbI, 4, __nbP))  # 4 car (x,v,gbest,lbest)
     for __p in range(__nbP):
index 6fb36329a02b016badabfc7ef4f01b73d519520a..6173089350d589f5e6a1f83f192017f6ef7cb97c 100644 (file)
@@ -91,8 +91,8 @@ def incr3dvar(selfA, Xb, Y, U, HO, CM, R, B, __storeState = False):
             if selfA._toStore("InnovationAtCurrentState"):
                 selfA.StoredVariables["InnovationAtCurrentState"].store( _dInnovation )
             #
-            Jb  = vfloat( 0.5 * _dX.T * (BI * _dX) )
-            Jo  = vfloat( 0.5 * _dInnovation.T * (RI * _dInnovation) )
+            Jb  = vfloat( 0.5 * _dX.T @ (BI @ _dX) )
+            Jo  = vfloat( 0.5 * _dInnovation.T @ (RI @ _dInnovation) )
             J   = Jb + Jo
             #
             selfA.StoredVariables["CurrentIterationNumber"].store( len(selfA.StoredVariables["CostFunctionJ"]) )
index db77218b8ff32d5007223450c4ae83797cc7921f..bba2d1feee27d5e419598d135837c128c500dc0b 100644 (file)
@@ -77,8 +77,8 @@ def std3dvar(selfA, Xb, Y, U, HO, CM, R, B, __storeState = False):
         if selfA._toStore("InnovationAtCurrentState"):
             selfA.StoredVariables["InnovationAtCurrentState"].store( _Innovation )
         #
-        Jb  = vfloat( 0.5 * (_X - Xb).T * (BI * (_X - Xb)) )
-        Jo  = vfloat( 0.5 * _Innovation.T * (RI * _Innovation) )
+        Jb  = vfloat( 0.5 * (_X - Xb).T @ (BI @ (_X - Xb)) )
+        Jo  = vfloat( 0.5 * _Innovation.T @ (RI @ _Innovation) )
         J   = Jb + Jo
         #
         selfA.StoredVariables["CurrentIterationNumber"].store( len(selfA.StoredVariables["CostFunctionJ"]) )
index b743fff937ad90ada7dd257261ef63f9900597c3..af568cf0fe66a05970040f1b20b16865cf3ba33b 100644 (file)
@@ -84,8 +84,8 @@ def van3dvar(selfA, Xb, Y, U, HO, CM, R, B, __storeState = False):
         if selfA._toStore("InnovationAtCurrentState"):
             selfA.StoredVariables["InnovationAtCurrentState"].store( _Innovation )
         #
-        Jb  = vfloat( 0.5 * _V.T * (BT * _V) )
-        Jo  = vfloat( 0.5 * _Innovation.T * (RI * _Innovation) )
+        Jb  = vfloat( 0.5 * _V.T @ (BT @ _V) )
+        Jo  = vfloat( 0.5 * _Innovation.T @ (RI @ _Innovation) )
         J   = Jb + Jo
         #
         selfA.StoredVariables["CurrentIterationNumber"].store( len(selfA.StoredVariables["CostFunctionJ"]) )
index e15ae80ae4bead169ffdd3e1926fcff80e25dd77..f5909e73050ee061d208784b4161d41d203d8445 100644 (file)
@@ -37,7 +37,7 @@ class ElementaryAlgorithm(BasicObjects.Algorithm):
         self.defineRequiredParameter(
             name     = "OptimalLocations",
             default  = [],
-            typecast = tuple,
+            typecast = numpy.array,
             message  = "Liste des indices ou noms de positions optimales de mesure selon l'ordre interne d'un vecteur de base",  # noqa: E501
         )
         self.defineRequiredParameter(
index 843d04a0573bea5e524fac7a8299d8e861875e42..c8ac7b68cc86293297a2b6abc1768117bb6e0930 100644 (file)
@@ -139,6 +139,12 @@ class ElementaryAlgorithm(BasicObjects.Algorithm):
             typecast = bool,
             message  = "Stockage des variables internes ou intermédiaires du calcul",
         )
+        self.defineRequiredParameter(
+            name     = "StoreInitialState",
+            default  = False,
+            typecast = bool,
+            message  = "Stockage du premier état à la manière des algorithmes récursifs",
+        )
         self.defineRequiredParameter(
             name     = "StoreSupplementaryCalculations",
             default  = [],
index 91dd08669b8d4410fe269accfb52f3c42a332626..1ee77b91b7ecb306bf7b1f46dc54e307386b4ee6 100644 (file)
@@ -29,7 +29,7 @@ __all__ = ["Aidsm"]
 import os
 import sys
 import inspect
-#
+
 from daCore.BasicObjects import State, Covariance, FullOperator, Operator
 from daCore.BasicObjects import AlgorithmAndParameters, DataObserver
 from daCore.BasicObjects import RegulationAndParameters, CaseLogger
@@ -38,24 +38,34 @@ from daCore import PlatformInfo
 from daCore import version
 
 from daCore import ExtendedLogging
+
 ExtendedLogging.ExtendedLogging()  # A importer en premier
 import logging  # noqa: E402
 
+
 # ==============================================================================
 class Aidsm(object):
-    """ ADAO Internal Data Structure Model """
+    """ADAO Internal Data Structure Model"""
+
     __slots__ = (
-        "__name", "__objname", "__directory", "__case", "__parent",
-        "__adaoObject", "__StoredInputs", "__PostAnalysis", "__Concepts",
+        "__name",
+        "__objname",
+        "__directory",
+        "__case",
+        "__parent",
+        "__adaoObject",
+        "__StoredInputs",
+        "__PostAnalysis",
+        "__Concepts",
     )
 
     def __init__(self, name="", addViewers=None):
-        self.__name         = str(name)
-        self.__objname      = None
-        self.__directory    = None
+        self.__name = str(name)
+        self.__objname = None
+        self.__directory = None
         self.__case = CaseLogger(self.__name, "case", addViewers)
         #
-        self.__adaoObject   = {}
+        self.__adaoObject = {}
         self.__StoredInputs = {}
         self.__PostAnalysis = []
         #
@@ -86,11 +96,11 @@ class Aidsm(object):
         for ename in ("ObservationOperator", "EvolutionModel", "ControlModel"):
             self.__adaoObject[ename] = {}
         for ename in ("BackgroundError", "ObservationError"):
-            self.__adaoObject[ename] = Covariance(ename, asEyeByScalar = 1.)
+            self.__adaoObject[ename] = Covariance(ename, asEyeByScalar=1.0)
         for ename in ("EvolutionError",):
-            self.__adaoObject[ename] = Covariance(ename, asEyeByScalar = 1.e-16)
+            self.__adaoObject[ename] = Covariance(ename, asEyeByScalar=1.0e-16)
         for ename in ("Observer", "UserPostAnalysis"):
-            self.__adaoObject[ename]   = []
+            self.__adaoObject[ename] = []
             self.__StoredInputs[ename] = []  # Vide par defaut
         self.__StoredInputs["Name"] = self.__name
         self.__StoredInputs["Directory"] = self.__directory
@@ -100,53 +110,78 @@ class Aidsm(object):
         # qui est activée dans Persistence)
         self.__parent = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
         sys.path.insert(0, self.__parent)
-        sys.path = PlatformInfo.uniq( sys.path )  # Conserve en unique exemplaire chaque chemin
-
-    def set(self,
-            Concept              = None,  # Premier argument
-            Algorithm            = None,
-            AppliedInXb          = None,
-            Checked              = False,
-            ColMajor             = False,
-            ColNames             = None,
-            CrossObs             = False,
-            DataFile             = None,
-            DiagonalSparseMatrix = None,
-            ExtraArguments       = None,
-            Info                 = None,
-            InputFunctionAsMulti = False,
-            Matrix               = None,
-            ObjectFunction       = None,
-            ObjectMatrix         = None,
-            OneFunction          = None,
-            Parameters           = None,
-            PerformanceProfile   = None,
-            ScalarSparseMatrix   = None,
-            Scheduler            = None,
-            Script               = None,
-            Stored               = False,
-            String               = None,
-            SyncObs              = True,
-            Template             = None,
-            ThreeFunctions       = None,
-            Variable             = None,
-            Vector               = None,
-            VectorSerie          = None,
-            ):
+        sys.path = PlatformInfo.uniq(
+            sys.path
+        )  # Conserve en unique exemplaire chaque chemin
+
+    def set(
+        self,
+        Concept=None,  # Premier argument
+        Algorithm=None,
+        AppliedInXb=None,
+        Checked=False,
+        ColMajor=False,
+        ColNames=None,
+        CrossObs=False,
+        DataFile=None,
+        DiagonalSparseMatrix=None,
+        ExtraArguments=None,
+        Info=None,
+        InputFunctionAsMulti=False,
+        Matrix=None,
+        ObjectFunction=None,
+        ObjectMatrix=None,
+        OneFunction=None,
+        Parameters=None,
+        PerformanceProfile=None,
+        ScalarSparseMatrix=None,
+        Scheduler=None,
+        Script=None,
+        Stored=False,
+        String=None,
+        SyncObs=True,
+        Template=None,
+        ThreeFunctions=None,
+        Variable=None,
+        Vector=None,
+        VectorSerie=None,
+    ):
         "Interface unique de définition de variables d'entrées par argument"
         self.__case.register("set", dir(), locals(), None, True)
         try:
-            if Concept in ("Background", "CheckingPoint", "ControlInput", "Observation"):
+            if Concept in (
+                "Background",
+                "CheckingPoint",
+                "ControlInput",
+                "Observation",
+            ):
                 commande = getattr(self, "set" + Concept)
-                commande(Vector, VectorSerie, Script, DataFile, ColNames, ColMajor, Stored, Scheduler, Checked )
+                commande(
+                    Vector,
+                    VectorSerie,
+                    Script,
+                    DataFile,
+                    ColNames,
+                    ColMajor,
+                    Stored,
+                    Scheduler,
+                    Checked,
+                )
             elif Concept in ("BackgroundError", "ObservationError", "EvolutionError"):
                 commande = getattr(self, "set" + Concept)
-                commande(Matrix, ScalarSparseMatrix, DiagonalSparseMatrix,
-                         Script, Stored, ObjectMatrix, Checked )
+                commande(
+                    Matrix,
+                    ScalarSparseMatrix,
+                    DiagonalSparseMatrix,
+                    Script,
+                    Stored,
+                    ObjectMatrix,
+                    Checked,
+                )
             elif Concept == "AlgorithmParameters":
-                self.setAlgorithmParameters( Algorithm, Parameters, Script )
+                self.setAlgorithmParameters(Algorithm, Parameters, Script)
             elif Concept == "RegulationParameters":
-                self.setRegulationParameters( Algorithm, Parameters, Script )
+                self.setRegulationParameters(Algorithm, Parameters, Script)
             elif Concept == "Name":
                 self.setName(String)
             elif Concept == "Directory":
@@ -157,326 +192,368 @@ class Aidsm(object):
                 self.setNoDebug()
             elif Concept == "Observer":
                 self.setObserver(
-                    Variable, Template, String, Script, Info,
-                    ObjectFunction, CrossObs, SyncObs, Scheduler )
+                    Variable,
+                    Template,
+                    String,
+                    Script,
+                    Info,
+                    ObjectFunction,
+                    CrossObs,
+                    SyncObs,
+                    Scheduler,
+                )
             elif Concept == "UserPostAnalysis":
-                self.setUserPostAnalysis( Template, String, Script )
+                self.setUserPostAnalysis(Template, String, Script)
             elif Concept == "SupplementaryParameters":
-                self.setSupplementaryParameters( Parameters, Script )
+                self.setSupplementaryParameters(Parameters, Script)
             elif Concept == "ObservationOperator":
                 self.setObservationOperator(
-                    Matrix, OneFunction, ThreeFunctions, AppliedInXb,
-                    Parameters, Script, ExtraArguments,
-                    Stored, PerformanceProfile, InputFunctionAsMulti, Checked )
+                    Matrix,
+                    OneFunction,
+                    ThreeFunctions,
+                    AppliedInXb,
+                    Parameters,
+                    Script,
+                    ExtraArguments,
+                    Stored,
+                    PerformanceProfile,
+                    InputFunctionAsMulti,
+                    Checked,
+                )
             elif Concept in ("EvolutionModel", "ControlModel"):
                 commande = getattr(self, "set" + Concept)
                 commande(
-                    Matrix, OneFunction, ThreeFunctions,
-                    Parameters, Script, Scheduler, ExtraArguments,
-                    Stored, PerformanceProfile, InputFunctionAsMulti, Checked )
+                    Matrix,
+                    OneFunction,
+                    ThreeFunctions,
+                    Parameters,
+                    Script,
+                    Scheduler,
+                    ExtraArguments,
+                    Stored,
+                    PerformanceProfile,
+                    InputFunctionAsMulti,
+                    Checked,
+                )
             else:
-                raise ValueError("the variable named '%s' is not allowed."%str(Concept))
+                raise ValueError(
+                    "the variable named '%s' is not allowed." % str(Concept)
+                )
         except Exception as e:
             if isinstance(e, SyntaxError):
-                msg = " at %s: %s"%(e.offset, e.text)
+                msg = " at %s: %s" % (e.offset, e.text)
             else:
                 msg = ""
-            raise ValueError((
-                "during settings, the following error occurs:\n" + \
-                "\n%s%s\n\nSee also the potential messages, " + \
-                "which can show the origin of the above error, " + \
-                "in the launching terminal.")%(str(e), msg))
+            raise ValueError(
+                (
+                    "during settings, the following error occurs:\n"
+                    + "\n%s%s\n\nSee also the potential messages, "
+                    + "which can show the origin of the above error, "
+                    + "in the launching terminal."
+                )
+                % (str(e), msg)
+            )
 
     # -----------------------------------------------------------
 
     def setBackground(
-            self,
-            Vector         = None,
-            VectorSerie    = None,
-            Script         = None,
-            DataFile       = None,
-            ColNames       = None,
-            ColMajor       = False,
-            Stored         = False,
-            Scheduler      = None,
-            Checked        = False ):
+        self,
+        Vector=None,
+        VectorSerie=None,
+        Script=None,
+        DataFile=None,
+        ColNames=None,
+        ColMajor=False,
+        Stored=False,
+        Scheduler=None,
+        Checked=False,
+    ):
         "Définition d'un concept de calcul"
         Concept = "Background"
         self.__case.register("set" + Concept, dir(), locals())
         self.__adaoObject[Concept] = State(
-            name               = Concept,
-            asVector           = Vector,
-            asPersistentVector = VectorSerie,
-            asScript           = self.__with_directory(Script),
-            asDataFile         = DataFile,
-            colNames           = ColNames,
-            colMajor           = ColMajor,
-            scheduledBy        = Scheduler,
-            toBeChecked        = Checked,
+            name=Concept,
+            asVector=Vector,
+            asPersistentVector=VectorSerie,
+            asScript=self.__with_directory(Script),
+            asDataFile=DataFile,
+            colNames=ColNames,
+            colMajor=ColMajor,
+            scheduledBy=Scheduler,
+            toBeChecked=Checked,
         )
         if Stored:
             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
         return 0
 
     def setCheckingPoint(
-            self,
-            Vector         = None,
-            VectorSerie    = None,
-            Script         = None,
-            DataFile       = None,
-            ColNames       = None,
-            ColMajor       = False,
-            Stored         = False,
-            Scheduler      = None,
-            Checked        = False ):
+        self,
+        Vector=None,
+        VectorSerie=None,
+        Script=None,
+        DataFile=None,
+        ColNames=None,
+        ColMajor=False,
+        Stored=False,
+        Scheduler=None,
+        Checked=False,
+    ):
         "Définition d'un concept de calcul"
         Concept = "CheckingPoint"
         self.__case.register("set" + Concept, dir(), locals())
         self.__adaoObject[Concept] = State(
-            name               = Concept,
-            asVector           = Vector,
-            asPersistentVector = VectorSerie,
-            asScript           = self.__with_directory(Script),
-            asDataFile         = DataFile,
-            colNames           = ColNames,
-            colMajor           = ColMajor,
-            scheduledBy        = Scheduler,
-            toBeChecked        = Checked,
+            name=Concept,
+            asVector=Vector,
+            asPersistentVector=VectorSerie,
+            asScript=self.__with_directory(Script),
+            asDataFile=DataFile,
+            colNames=ColNames,
+            colMajor=ColMajor,
+            scheduledBy=Scheduler,
+            toBeChecked=Checked,
         )
         if Stored:
             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
         return 0
 
     def setControlInput(
-            self,
-            Vector         = None,
-            VectorSerie    = None,
-            Script         = None,
-            DataFile       = None,
-            ColNames       = None,
-            ColMajor       = False,
-            Stored         = False,
-            Scheduler      = None,
-            Checked        = False ):
+        self,
+        Vector=None,
+        VectorSerie=None,
+        Script=None,
+        DataFile=None,
+        ColNames=None,
+        ColMajor=False,
+        Stored=False,
+        Scheduler=None,
+        Checked=False,
+    ):
         "Définition d'un concept de calcul"
         Concept = "ControlInput"
         self.__case.register("set" + Concept, dir(), locals())
         self.__adaoObject[Concept] = State(
-            name               = Concept,
-            asVector           = Vector,
-            asPersistentVector = VectorSerie,
-            asScript           = self.__with_directory(Script),
-            asDataFile         = DataFile,
-            colNames           = ColNames,
-            colMajor           = ColMajor,
-            scheduledBy        = Scheduler,
-            toBeChecked        = Checked,
+            name=Concept,
+            asVector=Vector,
+            asPersistentVector=VectorSerie,
+            asScript=self.__with_directory(Script),
+            asDataFile=DataFile,
+            colNames=ColNames,
+            colMajor=ColMajor,
+            scheduledBy=Scheduler,
+            toBeChecked=Checked,
         )
         if Stored:
             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
         return 0
 
     def setObservation(
-            self,
-            Vector         = None,
-            VectorSerie    = None,
-            Script         = None,
-            DataFile       = None,
-            ColNames       = None,
-            ColMajor       = False,
-            Stored         = False,
-            Scheduler      = None,
-            Checked        = False ):
+        self,
+        Vector=None,
+        VectorSerie=None,
+        Script=None,
+        DataFile=None,
+        ColNames=None,
+        ColMajor=False,
+        Stored=False,
+        Scheduler=None,
+        Checked=False,
+    ):
         "Définition d'un concept de calcul"
         Concept = "Observation"
         self.__case.register("set" + Concept, dir(), locals())
         self.__adaoObject[Concept] = State(
-            name               = Concept,
-            asVector           = Vector,
-            asPersistentVector = VectorSerie,
-            asScript           = self.__with_directory(Script),
-            asDataFile         = DataFile,
-            colNames           = ColNames,
-            colMajor           = ColMajor,
-            scheduledBy        = Scheduler,
-            toBeChecked        = Checked,
+            name=Concept,
+            asVector=Vector,
+            asPersistentVector=VectorSerie,
+            asScript=self.__with_directory(Script),
+            asDataFile=DataFile,
+            colNames=ColNames,
+            colMajor=ColMajor,
+            scheduledBy=Scheduler,
+            toBeChecked=Checked,
         )
         if Stored:
             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
         return 0
 
     def setBackgroundError(
-            self,
-            Matrix               = None,
-            ScalarSparseMatrix   = None,
-            DiagonalSparseMatrix = None,
-            Script               = None,
-            Stored               = False,
-            ObjectMatrix         = None,
-            Checked              = False ):
+        self,
+        Matrix=None,
+        ScalarSparseMatrix=None,
+        DiagonalSparseMatrix=None,
+        Script=None,
+        Stored=False,
+        ObjectMatrix=None,
+        Checked=False,
+    ):
         "Définition d'un concept de calcul"
         Concept = "BackgroundError"
         self.__case.register("set" + Concept, dir(), locals())
         self.__adaoObject[Concept] = Covariance(
-            name          = Concept,
-            asCovariance  = Matrix,
-            asEyeByScalar = ScalarSparseMatrix,
-            asEyeByVector = DiagonalSparseMatrix,
-            asCovObject   = ObjectMatrix,
-            asScript      = self.__with_directory(Script),
-            toBeChecked   = Checked,
+            name=Concept,
+            asCovariance=Matrix,
+            asEyeByScalar=ScalarSparseMatrix,
+            asEyeByVector=DiagonalSparseMatrix,
+            asCovObject=ObjectMatrix,
+            asScript=self.__with_directory(Script),
+            toBeChecked=Checked,
         )
         if Stored:
             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
         return 0
 
     def setObservationError(
-            self,
-            Matrix               = None,
-            ScalarSparseMatrix   = None,
-            DiagonalSparseMatrix = None,
-            Script               = None,
-            Stored               = False,
-            ObjectMatrix         = None,
-            Checked              = False ):
+        self,
+        Matrix=None,
+        ScalarSparseMatrix=None,
+        DiagonalSparseMatrix=None,
+        Script=None,
+        Stored=False,
+        ObjectMatrix=None,
+        Checked=False,
+    ):
         "Définition d'un concept de calcul"
         Concept = "ObservationError"
         self.__case.register("set" + Concept, dir(), locals())
         self.__adaoObject[Concept] = Covariance(
-            name          = Concept,
-            asCovariance  = Matrix,
-            asEyeByScalar = ScalarSparseMatrix,
-            asEyeByVector = DiagonalSparseMatrix,
-            asCovObject   = ObjectMatrix,
-            asScript      = self.__with_directory(Script),
-            toBeChecked   = Checked,
+            name=Concept,
+            asCovariance=Matrix,
+            asEyeByScalar=ScalarSparseMatrix,
+            asEyeByVector=DiagonalSparseMatrix,
+            asCovObject=ObjectMatrix,
+            asScript=self.__with_directory(Script),
+            toBeChecked=Checked,
         )
         if Stored:
             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
         return 0
 
     def setEvolutionError(
-            self,
-            Matrix               = None,
-            ScalarSparseMatrix   = None,
-            DiagonalSparseMatrix = None,
-            Script               = None,
-            Stored               = False,
-            ObjectMatrix         = None,
-            Checked              = False ):
+        self,
+        Matrix=None,
+        ScalarSparseMatrix=None,
+        DiagonalSparseMatrix=None,
+        Script=None,
+        Stored=False,
+        ObjectMatrix=None,
+        Checked=False,
+    ):
         "Définition d'un concept de calcul"
         Concept = "EvolutionError"
         self.__case.register("set" + Concept, dir(), locals())
         self.__adaoObject[Concept] = Covariance(
-            name          = Concept,
-            asCovariance  = Matrix,
-            asEyeByScalar = ScalarSparseMatrix,
-            asEyeByVector = DiagonalSparseMatrix,
-            asCovObject   = ObjectMatrix,
-            asScript      = self.__with_directory(Script),
-            toBeChecked   = Checked,
+            name=Concept,
+            asCovariance=Matrix,
+            asEyeByScalar=ScalarSparseMatrix,
+            asEyeByVector=DiagonalSparseMatrix,
+            asCovObject=ObjectMatrix,
+            asScript=self.__with_directory(Script),
+            toBeChecked=Checked,
         )
         if Stored:
             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
         return 0
 
     def setObservationOperator(
-            self,
-            Matrix               = None,
-            OneFunction          = None,
-            ThreeFunctions       = None,
-            AppliedInXb          = None,
-            Parameters           = None,
-            Script               = None,
-            ExtraArguments       = None,
-            Stored               = False,
-            PerformanceProfile   = None,
-            InputFunctionAsMulti = False,
-            Checked              = False ):
+        self,
+        Matrix=None,
+        OneFunction=None,
+        ThreeFunctions=None,
+        AppliedInXb=None,
+        Parameters=None,
+        Script=None,
+        ExtraArguments=None,
+        Stored=False,
+        PerformanceProfile=None,
+        InputFunctionAsMulti=False,
+        Checked=False,
+    ):
         "Définition d'un concept de calcul"
         Concept = "ObservationOperator"
         self.__case.register("set" + Concept, dir(), locals())
         self.__adaoObject[Concept] = FullOperator(
-            name             = Concept,
-            asMatrix         = Matrix,
-            asOneFunction    = OneFunction,
-            asThreeFunctions = ThreeFunctions,
-            asScript         = self.__with_directory(Script),
-            asDict           = Parameters,
-            appliedInX       = AppliedInXb,
-            extraArguments   = ExtraArguments,
-            performancePrf   = PerformanceProfile,
-            inputAsMF        = InputFunctionAsMulti,
-            scheduledBy      = None,
-            toBeChecked      = Checked,
+            name=Concept,
+            asMatrix=Matrix,
+            asOneFunction=OneFunction,
+            asThreeFunctions=ThreeFunctions,
+            asScript=self.__with_directory(Script),
+            asDict=Parameters,
+            appliedInX=AppliedInXb,
+            extraArguments=ExtraArguments,
+            performancePrf=PerformanceProfile,
+            inputAsMF=InputFunctionAsMulti,
+            scheduledBy=None,
+            toBeChecked=Checked,
         )
         if Stored:
             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
         return 0
 
     def setEvolutionModel(
-            self,
-            Matrix               = None,
-            OneFunction          = None,
-            ThreeFunctions       = None,
-            Parameters           = None,
-            Script               = None,
-            Scheduler            = None,
-            ExtraArguments       = None,
-            Stored               = False,
-            PerformanceProfile   = None,
-            InputFunctionAsMulti = False,
-            Checked              = False ):
+        self,
+        Matrix=None,
+        OneFunction=None,
+        ThreeFunctions=None,
+        Parameters=None,
+        Script=None,
+        Scheduler=None,
+        ExtraArguments=None,
+        Stored=False,
+        PerformanceProfile=None,
+        InputFunctionAsMulti=False,
+        Checked=False,
+    ):
         "Définition d'un concept de calcul"
         Concept = "EvolutionModel"
         self.__case.register("set" + Concept, dir(), locals())
         self.__adaoObject[Concept] = FullOperator(
-            name             = Concept,
-            asMatrix         = Matrix,
-            asOneFunction    = OneFunction,
-            asThreeFunctions = ThreeFunctions,
-            asScript         = self.__with_directory(Script),
-            asDict           = Parameters,
-            appliedInX       = None,
-            extraArguments   = ExtraArguments,
-            performancePrf   = PerformanceProfile,
-            inputAsMF        = InputFunctionAsMulti,
-            scheduledBy      = Scheduler,
-            toBeChecked      = Checked,
+            name=Concept,
+            asMatrix=Matrix,
+            asOneFunction=OneFunction,
+            asThreeFunctions=ThreeFunctions,
+            asScript=self.__with_directory(Script),
+            asDict=Parameters,
+            appliedInX=None,
+            extraArguments=ExtraArguments,
+            performancePrf=PerformanceProfile,
+            inputAsMF=InputFunctionAsMulti,
+            scheduledBy=Scheduler,
+            toBeChecked=Checked,
         )
         if Stored:
             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
         return 0
 
     def setControlModel(
-            self,
-            Matrix               = None,
-            OneFunction          = None,
-            ThreeFunctions       = None,
-            Parameters           = None,
-            Script               = None,
-            Scheduler            = None,
-            ExtraArguments       = None,
-            Stored               = False,
-            PerformanceProfile   = None,
-            InputFunctionAsMulti = False,
-            Checked              = False ):
+        self,
+        Matrix=None,
+        OneFunction=None,
+        ThreeFunctions=None,
+        Parameters=None,
+        Script=None,
+        Scheduler=None,
+        ExtraArguments=None,
+        Stored=False,
+        PerformanceProfile=None,
+        InputFunctionAsMulti=False,
+        Checked=False,
+    ):
         "Définition d'un concept de calcul"
         Concept = "ControlModel"
         self.__case.register("set" + Concept, dir(), locals())
         self.__adaoObject[Concept] = FullOperator(
-            name             = Concept,
-            asMatrix         = Matrix,
-            asOneFunction    = OneFunction,
-            asThreeFunctions = ThreeFunctions,
-            asScript         = self.__with_directory(Script),
-            asDict           = Parameters,
-            appliedInX       = None,
-            extraArguments   = ExtraArguments,
-            performancePrf   = PerformanceProfile,
-            inputAsMF        = InputFunctionAsMulti,
-            scheduledBy      = Scheduler,
-            toBeChecked      = Checked,
+            name=Concept,
+            asMatrix=Matrix,
+            asOneFunction=OneFunction,
+            asThreeFunctions=ThreeFunctions,
+            asScript=self.__with_directory(Script),
+            asDict=Parameters,
+            appliedInX=None,
+            extraArguments=ExtraArguments,
+            performancePrf=PerformanceProfile,
+            inputAsMF=InputFunctionAsMulti,
+            scheduledBy=Scheduler,
+            toBeChecked=Checked,
         )
         if Stored:
             self.__StoredInputs[Concept] = self.__adaoObject[Concept].getO()
@@ -500,13 +577,15 @@ class Aidsm(object):
             self.__directory = None
         self.__StoredInputs["Directory"] = self.__directory
 
-    def setDebug(self, __level = 10):
+    def setDebug(self, __level=10):
         "NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50"
         self.__case.register("setDebug", dir(), locals())
         log = logging.getLogger()
-        log.setLevel( __level )
-        logging.debug("Mode debug initialisé avec %s %s"%(version.name, version.version))
-        self.__StoredInputs["Debug"]   = __level
+        log.setLevel(__level)
+        logging.debug(
+            "Mode debug initialisé avec %s %s" % (version.name, version.version)
+        )
+        self.__StoredInputs["Debug"] = __level
         self.__StoredInputs["NoDebug"] = False
         return 0
 
@@ -514,200 +593,232 @@ class Aidsm(object):
         "NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50"
         self.__case.register("setNoDebug", dir(), locals())
         log = logging.getLogger()
-        log.setLevel( logging.WARNING )
-        self.__StoredInputs["Debug"]   = logging.WARNING
+        log.setLevel(logging.WARNING)
+        self.__StoredInputs["Debug"] = logging.WARNING
         self.__StoredInputs["NoDebug"] = True
         return 0
 
-    def setAlgorithmParameters(
-            self,
-            Algorithm  = None,
-            Parameters = None,
-            Script     = None ):
+    def setAlgorithmParameters(self, Algorithm=None, Parameters=None, Script=None):
         "Définition d'un concept de calcul"
         Concept = "AlgorithmParameters"
         self.__case.register("set" + Concept, dir(), locals())
         self.__adaoObject[Concept] = AlgorithmAndParameters(
-            name          = Concept,
-            asAlgorithm   = Algorithm,
-            asDict        = Parameters,
-            asScript      = self.__with_directory(Script),
+            name=Concept,
+            asAlgorithm=Algorithm,
+            asDict=Parameters,
+            asScript=self.__with_directory(Script),
         )
         return 0
 
-    def updateAlgorithmParameters(
-            self,
-            Parameters = None,
-            Script     = None ):
+    def updateAlgorithmParameters(self, Parameters=None, Script=None):
         "Mise à jour d'un concept de calcul"
         Concept = "AlgorithmParameters"
         if Concept not in self.__adaoObject or self.__adaoObject[Concept] is None:
-            raise ValueError("\n\nNo algorithm registred, set one before updating parameters or executing\n")
+            raise ValueError(
+                "\n\nNo algorithm registred, set one before updating parameters or executing\n"
+            )
         self.__adaoObject[Concept].updateParameters(
-            asDict        = Parameters,
-            asScript      = self.__with_directory(Script),
+            asDict=Parameters,
+            asScript=self.__with_directory(Script),
         )
         # RaJ du register
         return 0
 
-    def setRegulationParameters(
-            self,
-            Algorithm  = None,
-            Parameters = None,
-            Script     = None ):
+    def setRegulationParameters(self, Algorithm=None, Parameters=None, Script=None):
         "Définition d'un concept de calcul"
         Concept = "RegulationParameters"
         self.__case.register("set" + Concept, dir(), locals())
         self.__adaoObject[Concept] = RegulationAndParameters(
-            name        = Concept,
-            asAlgorithm = Algorithm,
-            asDict      = Parameters,
-            asScript    = self.__with_directory(Script),
+            name=Concept,
+            asAlgorithm=Algorithm,
+            asDict=Parameters,
+            asScript=self.__with_directory(Script),
         )
         return 0
 
-    def setSupplementaryParameters(
-            self,
-            Parameters = None,
-            Script     = None ):
+    def setSupplementaryParameters(self, Parameters=None, Script=None):
         "Définition d'un concept de calcul"
         Concept = "SupplementaryParameters"
         self.__case.register("set" + Concept, dir(), locals())
         self.__adaoObject[Concept] = ExternalParameters(
-            name     = Concept,
-            asDict   = Parameters,
-            asScript = self.__with_directory(Script),
+            name=Concept,
+            asDict=Parameters,
+            asScript=self.__with_directory(Script),
         )
         return 0
 
-    def updateSupplementaryParameters(
-            self,
-            Parameters = None,
-            Script     = None ):
+    def updateSupplementaryParameters(self, Parameters=None, Script=None):
         "Mise à jour d'un concept de calcul"
         Concept = "SupplementaryParameters"
         if Concept not in self.__adaoObject or self.__adaoObject[Concept] is None:
-            self.__adaoObject[Concept] = ExternalParameters(name = Concept)
+            self.__adaoObject[Concept] = ExternalParameters(name=Concept)
         self.__adaoObject[Concept].updateParameters(
-            asDict   = Parameters,
-            asScript = self.__with_directory(Script),
+            asDict=Parameters,
+            asScript=self.__with_directory(Script),
         )
         return 0
 
     def setObserver(
-            self,
-            Variable       = None,
-            Template       = None,
-            String         = None,
-            Script         = None,
-            Info           = None,
-            ObjectFunction = None,
-            CrossObs       = False,
-            SyncObs        = True,
-            Scheduler      = None ):
+        self,
+        Variable=None,
+        Template=None,
+        String=None,
+        Script=None,
+        Info=None,
+        ObjectFunction=None,
+        CrossObs=False,
+        SyncObs=True,
+        Scheduler=None,
+    ):
         "Définition d'un concept de calcul"
         Concept = "Observer"
         self.__case.register("set" + Concept, dir(), locals())
-        self.__adaoObject[Concept].append( DataObserver(
-            name        = Concept,
-            onVariable  = Variable,
-            asTemplate  = Template,
-            asString    = String,
-            asScript    = self.__with_directory(Script),
-            asObsObject = ObjectFunction,
-            withInfo    = Info,
-            crossObs    = CrossObs,
-            syncObs     = SyncObs,
-            scheduledBy = Scheduler,
-            withAlgo    = self.__adaoObject["AlgorithmParameters"]
-        ))
+        self.__adaoObject[Concept].append(
+            DataObserver(
+                name=Concept,
+                onVariable=Variable,
+                asTemplate=Template,
+                asString=String,
+                asScript=self.__with_directory(Script),
+                asObsObject=ObjectFunction,
+                withInfo=Info,
+                crossObs=CrossObs,
+                syncObs=SyncObs,
+                scheduledBy=Scheduler,
+                withAlgo=self.__adaoObject["AlgorithmParameters"],
+            )
+        )
         return 0
 
-    def removeObserver(
-            self,
-            Variable       = None,
-            ObjectFunction = None ):
+    def removeObserver(self, Variable=None, ObjectFunction=None):
         "Permet de retirer un observer à une ou des variable nommées"
         if "AlgorithmParameters" not in self.__adaoObject:
-            raise ValueError("No algorithm registred, ask for one before removing observers")
+            raise ValueError(
+                "No algorithm registred, ask for one before removing observers"
+            )
         #
         # Vérification du nom de variable et typage
         # -----------------------------------------
         if isinstance(Variable, str):
             VariableNames = (Variable,)
         elif isinstance(Variable, list):
-            VariableNames = tuple(map( str, Variable ))
+            VariableNames = tuple(map(str, Variable))
         else:
-            raise ValueError("The observer requires a name or a list of names of variables.")
+            raise ValueError(
+                "The observer requires a name or a list of names of variables."
+            )
         #
         # Association interne de l'observer à la variable
         # -----------------------------------------------
         for ename in VariableNames:
             if ename not in self.__adaoObject["AlgorithmParameters"]:
-                raise ValueError("An observer requires to be removed on a variable named %s which does not exist."%ename)
+                raise ValueError(
+                    "An observer requires to be removed on a variable named %s which does not exist."
+                    % ename
+                )
             else:
-                return self.__adaoObject["AlgorithmParameters"].removeObserver( ename, ObjectFunction )
+                return self.__adaoObject["AlgorithmParameters"].removeObserver(
+                    ename, ObjectFunction
+                )
 
-    def setUserPostAnalysis(
-            self,
-            Template       = None,
-            String         = None,
-            Script         = None ):
+    def setUserPostAnalysis(self, Template=None, String=None, Script=None):
         "Définition d'un concept de calcul"
         Concept = "UserPostAnalysis"
         self.__case.register("set" + Concept, dir(), locals())
-        self.__adaoObject[Concept].append( repr(UserScript(
-            name        = Concept,
-            asTemplate  = Template,
-            asString    = String,
-            asScript    = self.__with_directory(Script),
-        )))
+        self.__adaoObject[Concept].append(
+            repr(
+                UserScript(
+                    name=Concept,
+                    asTemplate=Template,
+                    asString=String,
+                    asScript=self.__with_directory(Script),
+                )
+            )
+        )
         return 0
 
     # -----------------------------------------------------------
 
-    def get(self, Concept=None, noDetails=True ):
+    def get(self, Concept=None, noDetails=True):
         "Récupération d'une sortie du calcul"
         if Concept is not None:
             try:
-                self.__case.register("get", dir(), locals(), Concept)  # Break pickle in Python 2
+                self.__case.register(
+                    "get", dir(), locals(), Concept
+                )  # Break pickle in Python 2
             except Exception:
                 pass
             if Concept in self.__StoredInputs:
                 return self.__StoredInputs[Concept]
                 #
-            elif self.__adaoObject["AlgorithmParameters"] is not None and Concept == "AlgorithmParameters":
+            elif (
+                self.__adaoObject["AlgorithmParameters"] is not None
+                and Concept == "AlgorithmParameters"
+            ):
                 return self.__adaoObject["AlgorithmParameters"].get()
                 #
-            elif self.__adaoObject["AlgorithmParameters"] is not None and Concept in self.__adaoObject["AlgorithmParameters"]:
-                return self.__adaoObject["AlgorithmParameters"].get( Concept )
+            elif (
+                self.__adaoObject["AlgorithmParameters"] is not None
+                and Concept in self.__adaoObject["AlgorithmParameters"]
+            ):
+                return self.__adaoObject["AlgorithmParameters"].get(Concept)
                 #
-            elif Concept == "AlgorithmRequiredParameters" and self.__adaoObject["AlgorithmParameters"] is not None:
-                return self.__adaoObject["AlgorithmParameters"].getAlgorithmRequiredParameters(noDetails)
+            elif (
+                Concept == "AlgorithmRequiredParameters"
+                and self.__adaoObject["AlgorithmParameters"] is not None
+            ):
+                return self.__adaoObject[
+                    "AlgorithmParameters"
+                ].getAlgorithmRequiredParameters(noDetails)
                 #
-            elif Concept == "AlgorithmRequiredInputs" and self.__adaoObject["AlgorithmParameters"] is not None:
-                return self.__adaoObject["AlgorithmParameters"].getAlgorithmInputArguments()
+            elif (
+                Concept == "AlgorithmRequiredInputs"
+                and self.__adaoObject["AlgorithmParameters"] is not None
+            ):
+                return self.__adaoObject[
+                    "AlgorithmParameters"
+                ].getAlgorithmInputArguments()
                 #
-            elif Concept == "AlgorithmAttributes" and self.__adaoObject["AlgorithmParameters"] is not None:
+            elif (
+                Concept == "AlgorithmAttributes"
+                and self.__adaoObject["AlgorithmParameters"] is not None
+            ):
                 return self.__adaoObject["AlgorithmParameters"].getAlgorithmAttributes()
                 #
-            elif self.__adaoObject["SupplementaryParameters"] is not None and Concept == "SupplementaryParameters":
+            elif (
+                self.__adaoObject["SupplementaryParameters"] is not None
+                and Concept == "SupplementaryParameters"
+            ):
                 return self.__adaoObject["SupplementaryParameters"].get()
                 #
-            elif self.__adaoObject["SupplementaryParameters"] is not None and Concept in self.__adaoObject["SupplementaryParameters"]:
-                return self.__adaoObject["SupplementaryParameters"].get( Concept )
+            elif (
+                self.__adaoObject["SupplementaryParameters"] is not None
+                and Concept in self.__adaoObject["SupplementaryParameters"]
+            ):
+                return self.__adaoObject["SupplementaryParameters"].get(Concept)
                 #
             else:
-                raise ValueError("The requested key \"%s\" does not exists as an input or a stored variable."%Concept)
+                raise ValueError(
+                    'The requested key "%s" does not exists as an input or a stored variable.'
+                    % Concept
+                )
         else:
             allvariables = {}
-            allvariables.update( {"AlgorithmParameters": self.__adaoObject["AlgorithmParameters"].get()} )
+            allvariables.update(
+                {"AlgorithmParameters": self.__adaoObject["AlgorithmParameters"].get()}
+            )
             if self.__adaoObject["SupplementaryParameters"] is not None:
-                allvariables.update( {"SupplementaryParameters": self.__adaoObject["SupplementaryParameters"].get()} )
+                allvariables.update(
+                    {
+                        "SupplementaryParameters": self.__adaoObject[
+                            "SupplementaryParameters"
+                        ].get()
+                    }
+                )
             # allvariables.update( self.__adaoObject["AlgorithmParameters"].get() )
-            allvariables.update( self.__StoredInputs )
-            allvariables.pop('Observer', None)
-            allvariables.pop('UserPostAnalysis', None)
+            allvariables.update(self.__StoredInputs)
+            allvariables.pop("Observer", None)
+            allvariables.pop("UserPostAnalysis", None)
             return allvariables
 
     # -----------------------------------------------------------
@@ -719,20 +830,26 @@ class Aidsm(object):
         identifiés par les chaînes de caractères. L'algorithme doit avoir été
         préalablement choisi sinon la méthode renvoie "None".
         """
-        if len(list(self.__adaoObject["AlgorithmParameters"].keys())) == 0 and \
-                len(list(self.__StoredInputs.keys())) == 0:
+        if (
+            len(list(self.__adaoObject["AlgorithmParameters"].keys())) == 0
+            and len(list(self.__StoredInputs.keys())) == 0
+        ):
             return None
         else:
             variables = []
             if len(list(self.__adaoObject["AlgorithmParameters"].keys())) > 0:
                 variables.extend(list(self.__adaoObject["AlgorithmParameters"].keys()))
-            if self.__adaoObject["SupplementaryParameters"] is not None and \
-                    len(list(self.__adaoObject["SupplementaryParameters"].keys())) > 0:
-                variables.extend(list(self.__adaoObject["SupplementaryParameters"].keys()))
+            if (
+                self.__adaoObject["SupplementaryParameters"] is not None
+                and len(list(self.__adaoObject["SupplementaryParameters"].keys())) > 0
+            ):
+                variables.extend(
+                    list(self.__adaoObject["SupplementaryParameters"].keys())
+                )
             if len(list(self.__StoredInputs.keys())) > 0:
-                variables.extend( list(self.__StoredInputs.keys()) )
-            variables.remove('Observer')
-            variables.remove('UserPostAnalysis')
+                variables.extend(list(self.__StoredInputs.keys()))
+            variables.remove("Observer")
+            variables.remove("UserPostAnalysis")
             variables.sort()
             return variables
 
@@ -752,7 +869,7 @@ class Aidsm(object):
                             continue
                         with open(os.path.join(trypath, fname)) as fc:
                             iselal = bool("class ElementaryAlgorithm" in fc.read())
-                            if iselal and ext == '.py' and root != '__init__':
+                            if iselal and ext == ".py" and root != "__init__":
                                 files.append(root)
         files.sort()
         return files
@@ -769,13 +886,25 @@ class Aidsm(object):
         se trouve un sous-répertoire "daAlgorithms"
         """
         if not os.path.isdir(Path):
-            raise ValueError("The given " + Path + " argument must exist as a directory")
+            raise ValueError(
+                "The given " + Path + " argument must exist as a directory"
+            )
         if not os.path.isdir(os.path.join(Path, "daAlgorithms")):
-            raise ValueError("The given \"" + Path + "\" argument must contain a subdirectory named \"daAlgorithms\"")
+            raise ValueError(
+                'The given "'
+                + Path
+                + '" argument must contain a subdirectory named "daAlgorithms"'
+            )
         if not os.path.isfile(os.path.join(Path, "daAlgorithms", "__init__.py")):
-            raise ValueError("The given \"" + Path + "/daAlgorithms\" path must contain a file named \"__init__.py\"")
+            raise ValueError(
+                'The given "'
+                + Path
+                + '/daAlgorithms" path must contain a file named "__init__.py"'
+            )
         sys.path.insert(0, os.path.abspath(Path))
-        sys.path = PlatformInfo.uniq( sys.path )  # Conserve en unique exemplaire chaque chemin
+        sys.path = PlatformInfo.uniq(
+            sys.path
+        )  # Conserve en unique exemplaire chaque chemin
         return 0
 
     # -----------------------------------------------------------
@@ -788,39 +917,56 @@ class Aidsm(object):
             Operator.CM.clearCache()
         try:
             if Executor == "YACS":
-                self.__executeYACSScheme( SaveCaseInFile )
+                self.__executeYACSScheme(SaveCaseInFile)
             else:
-                self.__executePythonScheme( SaveCaseInFile )
+                self.__executePythonScheme(SaveCaseInFile)
         except Exception as e:
             if isinstance(e, SyntaxError):
-                msg = "at %s: %s"%(e.offset, e.text)
+                msg = "at %s: %s" % (e.offset, e.text)
             else:
                 msg = ""
-            raise ValueError((
-                "during execution, the following error occurs:\n" + \
-                "\n%s %s\n\nSee also the potential messages, " + \
-                "which can show the origin of the above error, " + \
-                "in the launching terminal.\n")%(str(e), msg))
+            raise ValueError(
+                (
+                    "during execution, the following error occurs:\n"
+                    + "\n%s %s\n\nSee also the potential messages, "
+                    + "which can show the origin of the above error, "
+                    + "in the launching terminal.\n"
+                )
+                % (str(e), msg)
+            )
         return 0
 
     def __executePythonScheme(self, FileName=None):
         "Lancement du calcul"
         self.__case.register("executePythonScheme", dir(), locals())
         if FileName is not None:
-            self.dump( FileName, "TUI")
-        self.__adaoObject["AlgorithmParameters"].executePythonScheme( self.__adaoObject )
-        if "UserPostAnalysis" in self.__adaoObject and len(self.__adaoObject["UserPostAnalysis"]) > 0:
+            self.dump(FileName, "TUI")
+        self.__adaoObject["AlgorithmParameters"].executePythonScheme(self.__adaoObject)
+        if (
+            "UserPostAnalysis" in self.__adaoObject
+            and len(self.__adaoObject["UserPostAnalysis"]) > 0
+        ):
             self.__objname = self.__retrieve_objname()
             for __UpaOne in self.__adaoObject["UserPostAnalysis"]:
                 __UpaOne = eval(str(__UpaOne))
-                exec(__UpaOne, {}, {'self': self, 'ADD': self, 'case': self, 'adaopy': self, self.__objname: self})
+                exec(
+                    __UpaOne,
+                    {},
+                    {
+                        "self": self,
+                        "ADD": self,
+                        "case": self,
+                        "adaopy": self,
+                        self.__objname: self,
+                    },
+                )
         return 0
 
     def __executeYACSScheme(self, FileName=None):
         "Lancement du calcul"
         self.__case.register("executeYACSScheme", dir(), locals())
-        self.dump( FileName, "YACS")
-        self.__adaoObject["AlgorithmParameters"].executeYACSScheme( FileName )
+        self.dump(FileName, "YACS")
+        self.__adaoObject["AlgorithmParameters"].executeYACSScheme(FileName)
         return 0
 
     # -----------------------------------------------------------
@@ -834,22 +980,32 @@ class Aidsm(object):
         "Chargement normalisé des commandes"
         __commands = self.__case.load(FileName, Content, Object, Formater)
         from numpy import array, matrix  # noqa: F401
+
         for __command in __commands:
-            if (__command.find("set") > -1 and __command.find("set_") < 0) or 'UserPostAnalysis' in __command:
+            if (
+                __command.find("set") > -1 and __command.find("set_") < 0
+            ) or "UserPostAnalysis" in __command:
                 exec("self." + __command, {}, locals())
             else:
                 self.__PostAnalysis.append(__command)
         return self
 
-    def convert(self,
-                FileNameFrom=None, ContentFrom=None, ObjectFrom=None, FormaterFrom="TUI",
-                FileNameTo=None, FormaterTo="TUI" ):
+    def convert(
+        self,
+        FileNameFrom=None,
+        ContentFrom=None,
+        ObjectFrom=None,
+        FormaterFrom="TUI",
+        FileNameTo=None,
+        FormaterTo="TUI",
+    ):
         "Conversion normalisée des commandes"
         return self.load(
-            FileName=FileNameFrom, Content=ContentFrom, Object=ObjectFrom, Formater=FormaterFrom
-        ).dump(
-            FileName=FileNameTo, Formater=FormaterTo
-        )
+            FileName=FileNameFrom,
+            Content=ContentFrom,
+            Object=ObjectFrom,
+            Formater=FormaterFrom,
+        ).dump(FileName=FileNameTo, Formater=FormaterTo)
 
     def clear(self):
         "Effacement du contenu du cas en cours"
@@ -868,12 +1024,14 @@ class Aidsm(object):
 
     def __retrieve_objname(self):
         "Ne pas utiliser dans le __init__, la variable appelante n'existe pas encore"
-        __names  = []
+        __names = []
         for level in reversed(inspect.stack()):
-            __names += [name for name, value in level.frame.f_locals.items() if value is self]
+            __names += [
+                name for name, value in level.frame.f_locals.items() if value is self
+            ]
         __names += [name for name, value in globals().items() if value is self]
-        while 'self' in __names:
-            __names.remove('self')  # Devrait toujours être trouvé, donc pas d'erreur
+        while "self" in __names:
+            __names.remove("self")  # Devrait toujours être trouvé, donc pas d'erreur
         if len(__names) > 0:
             self.__objname = __names[0]
         else:
@@ -882,11 +1040,20 @@ class Aidsm(object):
 
     def __dir__(self):
         "Clarifie la visibilité des méthodes"
-        return ['set', 'get', 'execute', 'dump', 'load', '__doc__', '__init__', '__module__']
+        return [
+            "set",
+            "get",
+            "execute",
+            "dump",
+            "load",
+            "__doc__",
+            "__init__",
+            "__module__",
+        ]
 
     def __str__(self):
         "Représentation pour impression (mais pas repr)"
-        msg  = self.dump(None, "SimpleReportInPlainTxt")
+        msg = self.dump(None, "SimpleReportInPlainTxt")
         return msg
 
     def sysinfo(self, title=""):
@@ -894,36 +1061,50 @@ class Aidsm(object):
         return msg
 
     def callinfo(self, __prefix="  "):
-        msg  = ""
+        msg = ""
         for oname in ["ObservationOperator", "EvolutionModel"]:
             if hasattr(self.__adaoObject[oname], "nbcalls"):
                 ostats = self.__adaoObject[oname].nbcalls()
-                msg += "\n%sNumber of calls for the %s:"%(__prefix, oname)
+                msg += "\n%sNumber of calls for the %s:" % (__prefix, oname)
                 for otype in ["Direct", "Tangent", "Adjoint"]:
                     if otype in ostats:
-                        msg += "\n%s%30s : %s"%(__prefix, "%s evaluation"%(otype,), ostats[otype][0])
+                        msg += "\n%s%30s : %s" % (
+                            __prefix,
+                            "%s evaluation" % (otype,),
+                            ostats[otype][0],
+                        )
                 msg += "\n"
         return msg
 
     def prepare_to_pickle(self):
         "Retire les variables non pickelisables, avec recopie efficace"
-        if self.__adaoObject['AlgorithmParameters'] is not None:
-            for k in self.__adaoObject['AlgorithmParameters'].keys():
+        if self.__adaoObject["AlgorithmParameters"] is not None:
+            for k in self.__adaoObject["AlgorithmParameters"].keys():
                 if k == "Algorithm":
                     continue
                 if k in self.__StoredInputs:
-                    raise ValueError("The key \"%s\" to be transfered for pickling will overwrite an existing one."%(k,))
-                if self.__adaoObject['AlgorithmParameters'].hasObserver( k ):
-                    self.__adaoObject['AlgorithmParameters'].removeObserver( k, "", True )
-                self.__StoredInputs[k] = self.__adaoObject['AlgorithmParameters'].pop(k, None)
+                    raise ValueError(
+                        'The key "%s" to be transfered for pickling will overwrite an existing one.'
+                        % (k,)
+                    )
+                if self.__adaoObject["AlgorithmParameters"].hasObserver(k):
+                    self.__adaoObject["AlgorithmParameters"].removeObserver(k, "", True)
+                self.__StoredInputs[k] = self.__adaoObject["AlgorithmParameters"].pop(
+                    k, None
+                )
         if sys.version_info[0] == 2:
-            del self.__adaoObject  # Because it breaks pickle in Python 2. Not required for Python 3
-            del self.__case        # Because it breaks pickle in Python 2. Not required for Python 3
+            del (
+                self.__adaoObject
+            )  # Because it breaks pickle in Python 2. Not required for Python 3
+            del (
+                self.__case
+            )  # Because it breaks pickle in Python 2. Not required for Python 3
         if sys.version_info.major < 3:
             return 0
         else:
             return self.__StoredInputs
 
+
 # ==============================================================================
 if __name__ == "__main__":
     print("\n AUTODIAGNOSTIC\n")
index aa92bb16cbb3036f142cac235bfa48f603f4e5d9..60030ec34b9bb98e761f9d10564d79ba23f916cf 100644 (file)
@@ -28,16 +28,19 @@ __all__ = ["AssimilationStudy"]
 
 from daCore.Aidsm import Aidsm as _Aidsm
 
+
 # ==============================================================================
 class AssimilationStudy(_Aidsm):
     """
     Generic ADAO TUI builder
     """
+
     __slots__ = ()
 
-    def __init__(self, name = ""):
+    def __init__(self, name=""):
         _Aidsm.__init__(self, name)
 
+
 # ==============================================================================
 if __name__ == "__main__":
     print("\n AUTODIAGNOSTIC\n")
index 03cfe56904962bb37f57869f4d7d1b09565d93db..f5c9466ff820cf954ccdedd93034904cebc582a4 100644 (file)
@@ -39,55 +39,63 @@ from daCore import PlatformInfo
 from daCore import Interfaces
 from daCore import Templates
 
+
 # ==============================================================================
 class CacheManager(object):
     """
     Classe générale de gestion d'un cache de calculs
     """
+
     __slots__ = (
-        "__tolerBP", "__lengthOR", "__initlnOR", "__seenNames", "__enabled",
+        "__tolerBP",
+        "__lengthOR",
+        "__initlnOR",
+        "__seenNames",
+        "__enabled",
         "__listOPCV",
     )
 
-    def __init__(self,
-                 toleranceInRedundancy = 1.e-18,
-                 lengthOfRedundancy    = -1 ):
+    def __init__(self, toleranceInRedundancy=1.0e-18, lengthOfRedundancy=-1):
         """
         Les caractéristiques de tolérance peuvent être modifiées à la création.
         """
-        self.__tolerBP   = float(toleranceInRedundancy)
-        self.__lengthOR  = int(lengthOfRedundancy)
-        self.__initlnOR  = self.__lengthOR
+        self.__tolerBP = float(toleranceInRedundancy)
+        self.__lengthOR = int(lengthOfRedundancy)
+        self.__initlnOR = self.__lengthOR
         self.__seenNames = []
-        self.__enabled   = True
+        self.__enabled = True
         self.clearCache()
 
     def clearCache(self):
         "Vide le cache"
-        self.__listOPCV  = []
+        self.__listOPCV = []
         self.__seenNames = []
 
-    def wasCalculatedIn(self, xValue, oName="" ):
+    def wasCalculatedIn(self, xValue, oName=""):
         "Vérifie l'existence d'un calcul correspondant à la valeur"
         __alc = False
         __HxV = None
         if self.__enabled:
             for i in range(min(len(self.__listOPCV), self.__lengthOR) - 1, -1, -1):
-                if not hasattr(xValue, 'size'):
+                if not hasattr(xValue, "size"):
                     pass
-                elif (str(oName) != self.__listOPCV[i][3]):
+                elif str(oName) != self.__listOPCV[i][3]:
                     pass
-                elif (xValue.size != self.__listOPCV[i][0].size):
+                elif xValue.size != self.__listOPCV[i][0].size:
                     pass
-                elif (numpy.ravel(xValue)[0] - self.__listOPCV[i][0][0]) > (self.__tolerBP * self.__listOPCV[i][2] / self.__listOPCV[i][0].size):
+                elif (numpy.ravel(xValue)[0] - self.__listOPCV[i][0][0]) > (
+                    self.__tolerBP * self.__listOPCV[i][2] / self.__listOPCV[i][0].size
+                ):
                     pass
-                elif numpy.linalg.norm(numpy.ravel(xValue) - self.__listOPCV[i][0]) < (self.__tolerBP * self.__listOPCV[i][2]):
-                    __alc  = True
+                elif numpy.linalg.norm(numpy.ravel(xValue) - self.__listOPCV[i][0]) < (
+                    self.__tolerBP * self.__listOPCV[i][2]
+                ):
+                    __alc = True
                     __HxV = self.__listOPCV[i][1]
                     break
         return __alc, __HxV
 
-    def storeValueInX(self, xValue, HxValue, oName="" ):
+    def storeValueInX(self, xValue, HxValue, oName=""):
         "Stocke pour un opérateur o un calcul Hx correspondant à la valeur x"
         if self.__lengthOR < 0:
             self.__lengthOR = 2 * min(numpy.size(xValue), 50) + 2
@@ -99,33 +107,46 @@ class CacheManager(object):
             self.__seenNames.append(str(oName))
         while len(self.__listOPCV) > self.__lengthOR:
             self.__listOPCV.pop(0)
-        self.__listOPCV.append((
-            copy.copy(numpy.ravel(xValue)),  # 0 Previous point
-            copy.copy(HxValue),              # 1 Previous value
-            numpy.linalg.norm(xValue),       # 2 Norm
-            str(oName),                      # 3 Operator name
-        ))
+        self.__listOPCV.append(
+            (
+                copy.copy(numpy.ravel(xValue)),  # 0 Previous point
+                copy.copy(HxValue),  # 1 Previous value
+                numpy.linalg.norm(xValue),  # 2 Norm
+                str(oName),  # 3 Operator name
+            )
+        )
 
     def disable(self):
         "Inactive le cache"
         self.__initlnOR = self.__lengthOR
         self.__lengthOR = 0
-        self.__enabled  = False
+        self.__enabled = False
 
     def enable(self):
         "Active le cache"
         self.__lengthOR = self.__initlnOR
-        self.__enabled  = True
+        self.__enabled = True
+
 
 # ==============================================================================
 class Operator(object):
     """
     Classe générale d'interface de type opérateur simple
     """
+
     __slots__ = (
-        "__name", "__NbCallsAsMatrix", "__NbCallsAsMethod",
-        "__NbCallsOfCached", "__reduceM", "__avoidRC", "__inputAsMF",
-        "__mpEnabled", "__extraArgs", "__Method", "__Matrix", "__Type",
+        "__name",
+        "__NbCallsAsMatrix",
+        "__NbCallsAsMethod",
+        "__NbCallsOfCached",
+        "__reduceM",
+        "__avoidRC",
+        "__inputAsMF",
+        "__mpEnabled",
+        "__extraArgs",
+        "__Method",
+        "__Matrix",
+        "__Type",
     )
     #
     NbCallsAsMatrix = 0
@@ -133,15 +154,17 @@ class Operator(object):
     NbCallsOfCached = 0
     CM = CacheManager()
 
-    def __init__(self,
-                 name                 = "GenericOperator",
-                 fromMethod           = None,
-                 fromMatrix           = None,
-                 avoidingRedundancy   = True,
-                 reducingMemoryUse    = False,
-                 inputAsMultiFunction = False,
-                 enableMultiProcess   = False,
-                 extraArguments       = None ):
+    def __init__(
+        self,
+        name="GenericOperator",
+        fromMethod=None,
+        fromMatrix=None,
+        avoidingRedundancy=True,
+        reducingMemoryUse=False,
+        inputAsMultiFunction=False,
+        enableMultiProcess=False,
+        extraArguments=None,
+    ):
         """
         On construit un objet de ce type en fournissant, à l'aide de l'un des
         deux mots-clé, soit une fonction ou un multi-fonction python, soit une
@@ -158,31 +181,33 @@ class Operator(object):
         - extraArguments : arguments supplémentaires passés à la fonction de
           base et ses dérivées (tuple ou dictionnaire)
         """
-        self.__name      = str(name)
+        self.__name = str(name)
         self.__NbCallsAsMatrix, self.__NbCallsAsMethod, self.__NbCallsOfCached = 0, 0, 0
-        self.__reduceM   = bool( reducingMemoryUse )
-        self.__avoidRC   = bool( avoidingRedundancy )
-        self.__inputAsMF = bool( inputAsMultiFunction )
-        self.__mpEnabled = bool( enableMultiProcess )
+        self.__reduceM = bool(reducingMemoryUse)
+        self.__avoidRC = bool(avoidingRedundancy)
+        self.__inputAsMF = bool(inputAsMultiFunction)
+        self.__mpEnabled = bool(enableMultiProcess)
         self.__extraArgs = extraArguments
         if fromMethod is not None and self.__inputAsMF:
             self.__Method = fromMethod  # logtimer(fromMethod)
             self.__Matrix = None
-            self.__Type   = "Method"
+            self.__Type = "Method"
         elif fromMethod is not None and not self.__inputAsMF:
-            self.__Method = partial( MultiFonction, _sFunction=fromMethod, _mpEnabled=self.__mpEnabled)
+            self.__Method = partial(
+                MultiFonction, _sFunction=fromMethod, _mpEnabled=self.__mpEnabled
+            )
             self.__Matrix = None
-            self.__Type   = "Method"
+            self.__Type = "Method"
         elif fromMatrix is not None:
             self.__Method = None
             if isinstance(fromMatrix, str):
-                fromMatrix = PlatformInfo.strmatrix2liststr( fromMatrix )
-            self.__Matrix = numpy.asarray( fromMatrix, dtype=float )
-            self.__Type   = "Matrix"
+                fromMatrix = PlatformInfo.strmatrix2liststr(fromMatrix)
+            self.__Matrix = numpy.asarray(fromMatrix, dtype=float)
+            self.__Type = "Matrix"
         else:
             self.__Method = None
             self.__Matrix = None
-            self.__Type   = None
+            self.__Type = None
 
     def disableAvoidingRedundancy(self):
         "Inactive le cache"
@@ -199,7 +224,9 @@ class Operator(object):
         "Renvoie le type"
         return self.__Type
 
-    def appliedTo(self, xValue, HValue = None, argsAsSerie = False, returnSerieAsArrayMatrix = False):
+    def appliedTo(
+        self, xValue, HValue=None, argsAsSerie=False, returnSerieAsArrayMatrix=False
+    ):
         """
         Permet de restituer le résultat de l'application de l'opérateur à une
         série d'arguments xValue. Cette méthode se contente d'appliquer, chaque
@@ -219,13 +246,15 @@ class Operator(object):
                 _HValue = (HValue,)
             else:
                 _HValue = HValue
-        PlatformInfo.isIterable( _xValue, True, " in Operator.appliedTo" )
+        PlatformInfo.isIterable(_xValue, True, " in Operator.appliedTo")
         #
         if _HValue is not None:
-            assert len(_xValue) == len(_HValue), "Incompatible number of elements in xValue and HValue"
+            assert len(_xValue) == len(
+                _HValue
+            ), "Incompatible number of elements in xValue and HValue"
             _HxValue = []
             for i in range(len(_HValue)):
-                _HxValue.append( _HValue[i] )
+                _HxValue.append(_HValue[i])
                 if self.__avoidRC:
                     Operator.CM.storeValueInX(_xValue[i], _HxValue[-1], self.__name)
         else:
@@ -234,7 +263,9 @@ class Operator(object):
             _hindex = []
             for i, xv in enumerate(_xValue):
                 if self.__avoidRC:
-                    __alreadyCalculated, __HxV = Operator.CM.wasCalculatedIn(xv, self.__name)
+                    __alreadyCalculated, __HxV = Operator.CM.wasCalculatedIn(
+                        xv, self.__name
+                    )
                 else:
                     __alreadyCalculated = False
                 #
@@ -247,21 +278,22 @@ class Operator(object):
                         _hv = self.__Matrix @ numpy.ravel(xv)
                     else:
                         self.__addOneMethodCall()
-                        _xserie.append( xv )
-                        _hindex.append(  i )
+                        _xserie.append(xv)
+                        _hindex.append(i)
                         _hv = None
-                _HxValue.append( _hv )
+                _HxValue.append(_hv)
             #
             if len(_xserie) > 0 and self.__Matrix is None:
                 if self.__extraArgs is None:
-                    _hserie = self.__Method( _xserie )  # Calcul MF
+                    _hserie = self.__Method(_xserie)  # Calcul MF
                 else:
-                    _hserie = self.__Method( _xserie, self.__extraArgs )  # Calcul MF
+                    _hserie = self.__Method(_xserie, self.__extraArgs)  # Calcul MF
                 if not hasattr(_hserie, "pop"):
                     raise TypeError(
-                        "The user input multi-function doesn't seem to return a" + \
-                        " result sequence, behaving like a mono-function. It has" + \
-                        " to be checked." )
+                        "The user input multi-function doesn't seem to return a"
+                        + " result sequence, behaving like a mono-function. It has"
+                        + " to be checked."
+                    )
                 for i in _hindex:
                     _xv = _xserie.pop(0)
                     _hv = _hserie.pop(0)
@@ -272,10 +304,14 @@ class Operator(object):
         if returnSerieAsArrayMatrix:
             _HxValue = numpy.stack([numpy.ravel(_hv) for _hv in _HxValue], axis=1)
         #
-        if argsAsSerie: return _HxValue      # noqa: E701
-        else:           return _HxValue[-1]  # noqa: E241,E272,E701
+        if argsAsSerie:
+            return _HxValue
+        else:
+            return _HxValue[-1]
 
-    def appliedControledFormTo(self, paires, argsAsSerie = False, returnSerieAsArrayMatrix = False):
+    def appliedControledFormTo(
+        self, paires, argsAsSerie=False, returnSerieAsArrayMatrix=False
+    ):
         """
         Permet de restituer le résultat de l'application de l'opérateur à des
         paires (xValue, uValue). Cette méthode se contente d'appliquer, son
@@ -287,37 +323,41 @@ class Operator(object):
             - uValue : argument U adapté pour appliquer l'opérateur
         - argsAsSerie : indique si l'argument est une mono ou multi-valeur
         """
-        if argsAsSerie: _xuValue = paires     # noqa: E701
-        else:           _xuValue = (paires,)  # noqa: E241,E272,E701
-        PlatformInfo.isIterable( _xuValue, True, " in Operator.appliedControledFormTo" )
+        if argsAsSerie:
+            _xuValue = paires
+        else:
+            _xuValue = (paires,)
+        PlatformInfo.isIterable(_xuValue, True, " in Operator.appliedControledFormTo")
         #
         if self.__Matrix is not None:
             _HxValue = []
             for paire in _xuValue:
                 _xValue, _uValue = paire
                 self.__addOneMatrixCall()
-                _HxValue.append( self.__Matrix @ numpy.ravel(_xValue) )
+                _HxValue.append(self.__Matrix @ numpy.ravel(_xValue))
         else:
             _xuArgs = []
             for paire in _xuValue:
                 _xValue, _uValue = paire
                 if _uValue is not None:
-                    _xuArgs.append( paire )
+                    _xuArgs.append(paire)
                 else:
-                    _xuArgs.append( _xValue )
-            self.__addOneMethodCall( len(_xuArgs) )
+                    _xuArgs.append(_xValue)
+            self.__addOneMethodCall(len(_xuArgs))
             if self.__extraArgs is None:
-                _HxValue = self.__Method( _xuArgs )  # Calcul MF
+                _HxValue = self.__Method(_xuArgs)  # Calcul MF
             else:
-                _HxValue = self.__Method( _xuArgs, self.__extraArgs )  # Calcul MF
+                _HxValue = self.__Method(_xuArgs, self.__extraArgs)  # Calcul MF
         #
         if returnSerieAsArrayMatrix:
             _HxValue = numpy.stack([numpy.ravel(_hv) for _hv in _HxValue], axis=1)
         #
-        if argsAsSerie: return _HxValue      # noqa: E701
-        else:           return _HxValue[-1]  # noqa: E241,E272,E701
+        if argsAsSerie:
+            return _HxValue
+        else:
+            return _HxValue[-1]
 
-    def appliedInXTo(self, paires, argsAsSerie = False, returnSerieAsArrayMatrix = False):
+    def appliedInXTo(self, paires, argsAsSerie=False, returnSerieAsArrayMatrix=False):
         """
         Permet de restituer le résultat de l'application de l'opérateur à une
         série d'arguments xValue, sachant que l'opérateur est valable en
@@ -333,50 +373,63 @@ class Operator(object):
             - xValue : série d'arguments adaptés pour appliquer l'opérateur
         - argsAsSerie : indique si l'argument est une mono ou multi-valeur
         """
-        if argsAsSerie: _nxValue = paires     # noqa: E701
-        else:           _nxValue = (paires,)  # noqa: E241,E272,E701
-        PlatformInfo.isIterable( _nxValue, True, " in Operator.appliedInXTo" )
+        if argsAsSerie:
+            _nxValue = paires
+        else:
+            _nxValue = (paires,)
+        PlatformInfo.isIterable(_nxValue, True, " in Operator.appliedInXTo")
         #
         if self.__Matrix is not None:
             _HxValue = []
             for paire in _nxValue:
                 _xNominal, _xValue = paire
                 self.__addOneMatrixCall()
-                _HxValue.append( self.__Matrix @ numpy.ravel(_xValue) )
+                _HxValue.append(self.__Matrix @ numpy.ravel(_xValue))
         else:
-            self.__addOneMethodCall( len(_nxValue) )
+            self.__addOneMethodCall(len(_nxValue))
             if self.__extraArgs is None:
-                _HxValue = self.__Method( _nxValue )  # Calcul MF
+                _HxValue = self.__Method(_nxValue)  # Calcul MF
             else:
-                _HxValue = self.__Method( _nxValue, self.__extraArgs )  # Calcul MF
+                _HxValue = self.__Method(_nxValue, self.__extraArgs)  # Calcul MF
         #
         if returnSerieAsArrayMatrix:
             _HxValue = numpy.stack([numpy.ravel(_hv) for _hv in _HxValue], axis=1)
         #
-        if argsAsSerie: return _HxValue      # noqa: E701
-        else:           return _HxValue[-1]  # noqa: E241,E272,E701
+        if argsAsSerie:
+            return _HxValue
+        else:
+            return _HxValue[-1]
 
-    def asMatrix(self, ValueForMethodForm = "UnknownVoidValue", argsAsSerie = False):
+    def asMatrix(self, ValueForMethodForm="UnknownVoidValue", argsAsSerie=False):
         """
         Permet de renvoyer l'opérateur sous la forme d'une matrice
         """
         if self.__Matrix is not None:
             self.__addOneMatrixCall()
-            mValue = [self.__Matrix,]
-        elif not isinstance(ValueForMethodForm, str) or ValueForMethodForm != "UnknownVoidValue":  # Ne pas utiliser "None"
+            mValue = [
+                self.__Matrix,
+            ]
+        elif (
+            not isinstance(ValueForMethodForm, str)
+            or ValueForMethodForm != "UnknownVoidValue"
+        ):  # Ne pas utiliser "None"
             mValue = []
             if argsAsSerie:
-                self.__addOneMethodCall( len(ValueForMethodForm) )
+                self.__addOneMethodCall(len(ValueForMethodForm))
                 for _vfmf in ValueForMethodForm:
-                    mValue.append( self.__Method(((_vfmf, None),)) )
+                    mValue.append(self.__Method(((_vfmf, None),)))
             else:
                 self.__addOneMethodCall()
                 mValue = self.__Method(((ValueForMethodForm, None),))
         else:
-            raise ValueError("Matrix form of the operator defined as a function/method requires to give an operating point.")
+            raise ValueError(
+                "Matrix form of the operator defined as a function/method requires to give an operating point."
+            )
         #
-        if argsAsSerie: return mValue      # noqa: E701
-        else:           return mValue[-1]  # noqa: E241,E272,E701
+        if argsAsSerie:
+            return mValue
+        else:
+            return mValue[-1]
 
     def shape(self):
         """
@@ -386,7 +439,9 @@ class Operator(object):
         if self.__Matrix is not None:
             return self.__Matrix.shape
         else:
-            raise ValueError("Matrix form of the operator is not available, nor the shape")
+            raise ValueError(
+                "Matrix form of the operator is not available, nor the shape"
+            )
 
     def nbcalls(self, which=None):
         """
@@ -402,83 +457,96 @@ class Operator(object):
             Operator.NbCallsAsMethod,
             Operator.NbCallsOfCached,
         )
-        if which is None: return __nbcalls         # noqa: E701
-        else:             return __nbcalls[which]  # noqa: E241,E272,E701
+        if which is None:
+            return __nbcalls
+        else:
+            return __nbcalls[which]
 
     def __addOneMatrixCall(self):
         "Comptabilise un appel"
-        self.__NbCallsAsMatrix   += 1  # Decompte local
+        self.__NbCallsAsMatrix += 1  # Decompte local
         Operator.NbCallsAsMatrix += 1  # Decompte global
 
-    def __addOneMethodCall(self, nb = 1):
+    def __addOneMethodCall(self, nb=1):
         "Comptabilise un appel"
-        self.__NbCallsAsMethod   += nb  # Decompte local
+        self.__NbCallsAsMethod += nb  # Decompte local
         Operator.NbCallsAsMethod += nb  # Decompte global
 
     def __addOneCacheCall(self):
         "Comptabilise un appel"
-        self.__NbCallsOfCached   += 1  # Décompte local
+        self.__NbCallsOfCached += 1  # Décompte local
         Operator.NbCallsOfCached += 1  # Décompte global
 
+
 # ==============================================================================
 class FullOperator(object):
     """
     Classe générale d'interface de type opérateur complet
     (Direct, Linéaire Tangent, Adjoint)
     """
+
     __slots__ = (
-        "__name", "__check", "__extraArgs", "__FO", "__T",
+        "__name",
+        "__check",
+        "__extraArgs",
+        "__FO",
+        "__T",
     )
 
-    def __init__(self,
-                 name             = "GenericFullOperator",
-                 asMatrix         = None,
-                 asOneFunction    = None,   # 1 Fonction
-                 asThreeFunctions = None,   # 3 Fonctions in a dictionary
-                 asScript         = None,   # 1 or 3 Fonction(s) by script
-                 asDict           = None,   # Parameters
-                 appliedInX       = None,
-                 extraArguments   = None,
-                 performancePrf   = None,
-                 inputAsMF        = False,  # Fonction(s) as Multi-Functions
-                 scheduledBy      = None,
-                 toBeChecked      = False ):
-        ""
-        self.__name      = str(name)
-        self.__check     = bool(toBeChecked)
+    def __init__(
+        self,
+        name="GenericFullOperator",
+        asMatrix=None,
+        asOneFunction=None,  # 1 Fonction
+        asThreeFunctions=None,  # 3 Fonctions in a dictionary
+        asScript=None,  # 1 or 3 Fonction(s) by script
+        asDict=None,  # Parameters
+        appliedInX=None,
+        extraArguments=None,
+        performancePrf=None,
+        inputAsMF=False,  # Fonction(s) as Multi-Functions
+        scheduledBy=None,
+        toBeChecked=False,
+    ):
+        """"""
+        self.__name = str(name)
+        self.__check = bool(toBeChecked)
         self.__extraArgs = extraArguments
         #
-        self.__FO        = {}
+        self.__FO = {}
         #
         __Parameters = {}
         if (asDict is not None) and isinstance(asDict, dict):
-            __Parameters.update( asDict )  # Copie mémoire
+            __Parameters.update(asDict)  # Copie mémoire
         # Deprecated parameters
         __Parameters = self.__deprecateOpt(
-            collection = __Parameters,
-            oldn = "EnableMultiProcessing",
-            newn = "EnableWiseParallelism",
+            collection=__Parameters,
+            oldn="EnableMultiProcessing",
+            newn="EnableWiseParallelism",
         )
         __Parameters = self.__deprecateOpt(
-            collection = __Parameters,
-            oldn = "EnableMultiProcessingInEvaluation",
-            newn = "EnableParallelEvaluations",
+            collection=__Parameters,
+            oldn="EnableMultiProcessingInEvaluation",
+            newn="EnableParallelEvaluations",
         )
         __Parameters = self.__deprecateOpt(
-            collection = __Parameters,
-            oldn = "EnableMultiProcessingInDerivatives",
-            newn = "EnableParallelDerivatives",
+            collection=__Parameters,
+            oldn="EnableMultiProcessingInDerivatives",
+            newn="EnableParallelDerivatives",
         )
         # Priorité à EnableParallelDerivatives=True
-        if "EnableWiseParallelism" in __Parameters and __Parameters["EnableWiseParallelism"]:
+        if (
+            "EnableWiseParallelism" in __Parameters
+            and __Parameters["EnableWiseParallelism"]
+        ):
             __Parameters["EnableParallelDerivatives"] = True
-            __Parameters["EnableParallelEvaluations"]  = False
+            __Parameters["EnableParallelEvaluations"] = False
         if "EnableParallelDerivatives" not in __Parameters:
-            __Parameters["EnableParallelDerivatives"]  = False
+            __Parameters["EnableParallelDerivatives"] = False
         if __Parameters["EnableParallelDerivatives"]:
-            __Parameters["EnableParallelEvaluations"]  = False
+            __Parameters["EnableParallelEvaluations"] = False
         if "EnableParallelEvaluations" not in __Parameters:
-            __Parameters["EnableParallelEvaluations"]  = False
+            __Parameters["EnableParallelEvaluations"] = False
         if "withIncrement" in __Parameters:  # Temporaire
             __Parameters["DifferentialIncrement"] = __Parameters["withIncrement"]
         #
@@ -496,16 +564,26 @@ class FullOperator(object):
         if asScript is not None:
             __Matrix, __Function = None, None
             if asMatrix:
-                __Matrix = Interfaces.ImportFromScript(asScript).getvalue( self.__name )
+                __Matrix = Interfaces.ImportFromScript(asScript).getvalue(self.__name)
             elif asOneFunction:
-                __Function = { "Direct": Interfaces.ImportFromScript(asScript).getvalue( "DirectOperator" ) }
+                __Function = {
+                    "Direct": Interfaces.ImportFromScript(asScript).getvalue(
+                        "DirectOperator"
+                    )
+                }
                 __Function.update({"useApproximatedDerivatives": True})
                 __Function.update(__Parameters)
             elif asThreeFunctions:
                 __Function = {
-                    "Direct": Interfaces.ImportFromScript(asScript).getvalue( "DirectOperator" ),
-                    "Tangent": Interfaces.ImportFromScript(asScript).getvalue( "TangentOperator" ),
-                    "Adjoint": Interfaces.ImportFromScript(asScript).getvalue( "AdjointOperator" ),
+                    "Direct": Interfaces.ImportFromScript(asScript).getvalue(
+                        "DirectOperator"
+                    ),
+                    "Tangent": Interfaces.ImportFromScript(asScript).getvalue(
+                        "TangentOperator"
+                    ),
+                    "Adjoint": Interfaces.ImportFromScript(asScript).getvalue(
+                        "AdjointOperator"
+                    ),
                 }
                 __Function.update(__Parameters)
         else:
@@ -515,26 +593,39 @@ class FullOperator(object):
                     if asOneFunction["Direct"] is not None:
                         __Function = asOneFunction
                     else:
-                        raise ValueError("The function has to be given in a dictionnary which have 1 key (\"Direct\")")
+                        raise ValueError(
+                            'The function has to be given in a dictionnary which have 1 key ("Direct")'
+                        )
                 else:
-                    __Function = { "Direct": asOneFunction }
+                    __Function = {"Direct": asOneFunction}
                 __Function.update({"useApproximatedDerivatives": True})
                 __Function.update(__Parameters)
             elif asThreeFunctions is not None:
-                if isinstance(asThreeFunctions, dict) and \
-                        ("Tangent" in asThreeFunctions) and (asThreeFunctions["Tangent"] is not None) and \
-                        ("Adjoint" in asThreeFunctions) and (asThreeFunctions["Adjoint"] is not None) and \
-                        (("useApproximatedDerivatives" not in asThreeFunctions) or not bool(asThreeFunctions["useApproximatedDerivatives"])):
+                if (
+                    isinstance(asThreeFunctions, dict)
+                    and ("Tangent" in asThreeFunctions)
+                    and (asThreeFunctions["Tangent"] is not None)
+                    and ("Adjoint" in asThreeFunctions)
+                    and (asThreeFunctions["Adjoint"] is not None)
+                    and (
+                        ("useApproximatedDerivatives" not in asThreeFunctions)
+                        or not bool(asThreeFunctions["useApproximatedDerivatives"])
+                    )
+                ):
                     __Function = asThreeFunctions
-                elif isinstance(asThreeFunctions, dict) and \
-                        ("Direct" in asThreeFunctions) and (asThreeFunctions["Direct"] is not None):
+                elif (
+                    isinstance(asThreeFunctions, dict)
+                    and ("Direct" in asThreeFunctions)
+                    and (asThreeFunctions["Direct"] is not None)
+                ):
                     __Function = asThreeFunctions
                     __Function.update({"useApproximatedDerivatives": True})
                 else:
                     raise ValueError(
-                        "The functions has to be given in a dictionnary which have either" + \
-                        " 1 key (\"Direct\") or" + \
-                        " 3 keys (\"Direct\" (optionnal), \"Tangent\" and \"Adjoint\")")
+                        "The functions has to be given in a dictionnary which have either"
+                        + ' 1 key ("Direct") or'
+                        + ' 3 keys ("Direct" (optionnal), "Tangent" and "Adjoint")'
+                    )
                 if "Direct" not in asThreeFunctions:
                     __Function["Direct"] = asThreeFunctions["Tangent"]
                 __Function.update(__Parameters)
@@ -551,121 +642,153 @@ class FullOperator(object):
         if scheduledBy is not None:
             self.__T = scheduledBy
         #
-        if isinstance(__Function, dict) and \
-                ("useApproximatedDerivatives" in __Function) and bool(__Function["useApproximatedDerivatives"]) and \
-                ("Direct" in __Function) and (__Function["Direct"] is not None):
-            if "CenteredFiniteDifference"           not in __Function: __Function["CenteredFiniteDifference"]           = False      # noqa: E272,E701
-            if "DifferentialIncrement"              not in __Function: __Function["DifferentialIncrement"]              = 0.01       # noqa: E272,E701
-            if "withdX"                             not in __Function: __Function["withdX"]                             = None       # noqa: E272,E701
-            if "withReducingMemoryUse"              not in __Function: __Function["withReducingMemoryUse"]              = __reduceM  # noqa: E272,E701
-            if "withAvoidingRedundancy"             not in __Function: __Function["withAvoidingRedundancy"]             = __avoidRC  # noqa: E272,E701
-            if "withToleranceInRedundancy"          not in __Function: __Function["withToleranceInRedundancy"]          = 1.e-18     # noqa: E272,E701
-            if "withLengthOfRedundancy"             not in __Function: __Function["withLengthOfRedundancy"]             = -1         # noqa: E272,E701
-            if "NumberOfProcesses"                  not in __Function: __Function["NumberOfProcesses"]                  = None       # noqa: E272,E701
-            if "withmfEnabled"                      not in __Function: __Function["withmfEnabled"]                      = inputAsMF  # noqa: E272,E701
+        if (
+            isinstance(__Function, dict)
+            and ("useApproximatedDerivatives" in __Function)
+            and bool(__Function["useApproximatedDerivatives"])
+            and ("Direct" in __Function)
+            and (__Function["Direct"] is not None)
+        ):
+            if "CenteredFiniteDifference" not in __Function:
+                __Function["CenteredFiniteDifference"] = False
+            if "DifferentialIncrement" not in __Function:
+                __Function["DifferentialIncrement"] = 0.01
+            if "withdX" not in __Function:
+                __Function["withdX"] = None
+            if "withReducingMemoryUse" not in __Function:
+                __Function["withReducingMemoryUse"] = __reduceM
+            if "withAvoidingRedundancy" not in __Function:
+                __Function["withAvoidingRedundancy"] = __avoidRC
+            if "withToleranceInRedundancy" not in __Function:
+                __Function["withToleranceInRedundancy"] = 1.0e-18
+            if "withLengthOfRedundancy" not in __Function:
+                __Function["withLengthOfRedundancy"] = -1
+            if "NumberOfProcesses" not in __Function:
+                __Function["NumberOfProcesses"] = None
+            if "withmfEnabled" not in __Function:
+                __Function["withmfEnabled"] = inputAsMF
             from daCore import NumericObjects
+
             FDA = NumericObjects.FDApproximation(
-                name                  = self.__name,
-                Function              = __Function["Direct"],
-                centeredDF            = __Function["CenteredFiniteDifference"],
-                increment             = __Function["DifferentialIncrement"],
-                dX                    = __Function["withdX"],
-                extraArguments        = self.__extraArgs,
-                reducingMemoryUse     = __Function["withReducingMemoryUse"],
-                avoidingRedundancy    = __Function["withAvoidingRedundancy"],
-                toleranceInRedundancy = __Function["withToleranceInRedundancy"],
-                lengthOfRedundancy    = __Function["withLengthOfRedundancy"],
-                mpEnabled             = __Function["EnableParallelDerivatives"],
-                mpWorkers             = __Function["NumberOfProcesses"],
-                mfEnabled             = __Function["withmfEnabled"],
-            )
-            self.__FO["Direct"]  = Operator(
-                name = self.__name,
-                fromMethod = FDA.DirectOperator,
-                reducingMemoryUse = __reduceM,
-                avoidingRedundancy = __avoidRC,
-                inputAsMultiFunction = inputAsMF,
-                extraArguments = self.__extraArgs,
-                enableMultiProcess = __Parameters["EnableParallelEvaluations"] )
+                name=self.__name,
+                Function=__Function["Direct"],
+                centeredDF=__Function["CenteredFiniteDifference"],
+                increment=__Function["DifferentialIncrement"],
+                dX=__Function["withdX"],
+                extraArguments=self.__extraArgs,
+                reducingMemoryUse=__Function["withReducingMemoryUse"],
+                avoidingRedundancy=__Function["withAvoidingRedundancy"],
+                toleranceInRedundancy=__Function["withToleranceInRedundancy"],
+                lengthOfRedundancy=__Function["withLengthOfRedundancy"],
+                mpEnabled=__Function["EnableParallelDerivatives"],
+                mpWorkers=__Function["NumberOfProcesses"],
+                mfEnabled=__Function["withmfEnabled"],
+            )
+            self.__FO["Direct"] = Operator(
+                name=self.__name,
+                fromMethod=FDA.DirectOperator,
+                reducingMemoryUse=__reduceM,
+                avoidingRedundancy=__avoidRC,
+                inputAsMultiFunction=inputAsMF,
+                extraArguments=self.__extraArgs,
+                enableMultiProcess=__Parameters["EnableParallelEvaluations"],
+            )
             self.__FO["Tangent"] = Operator(
-                name = self.__name + "Tangent",
-                fromMethod = FDA.TangentOperator,
-                reducingMemoryUse = __reduceM,
-                avoidingRedundancy = __avoidRC,
-                inputAsMultiFunction = inputAsMF,
-                extraArguments = self.__extraArgs )
+                name=self.__name + "Tangent",
+                fromMethod=FDA.TangentOperator,
+                reducingMemoryUse=__reduceM,
+                avoidingRedundancy=__avoidRC,
+                inputAsMultiFunction=inputAsMF,
+                extraArguments=self.__extraArgs,
+            )
             self.__FO["Adjoint"] = Operator(
-                name = self.__name + "Adjoint",
-                fromMethod = FDA.AdjointOperator,
-                reducingMemoryUse = __reduceM,
-                avoidingRedundancy = __avoidRC,
-                inputAsMultiFunction = inputAsMF,
-                extraArguments = self.__extraArgs )
+                name=self.__name + "Adjoint",
+                fromMethod=FDA.AdjointOperator,
+                reducingMemoryUse=__reduceM,
+                avoidingRedundancy=__avoidRC,
+                inputAsMultiFunction=inputAsMF,
+                extraArguments=self.__extraArgs,
+            )
             self.__FO["DifferentialIncrement"] = __Function["DifferentialIncrement"]
-        elif isinstance(__Function, dict) and \
-                ("Direct" in __Function) and ("Tangent" in __Function) and ("Adjoint" in __Function) and \
-                (__Function["Direct"] is not None) and (__Function["Tangent"] is not None) and (__Function["Adjoint"] is not None):
-            self.__FO["Direct"]  = Operator(
-                name = self.__name,
-                fromMethod = __Function["Direct"],
-                reducingMemoryUse = __reduceM,
-                avoidingRedundancy = __avoidRC,
-                inputAsMultiFunction = inputAsMF,
-                extraArguments = self.__extraArgs,
-                enableMultiProcess = __Parameters["EnableParallelEvaluations"] )
+        elif (
+            isinstance(__Function, dict)
+            and ("Direct" in __Function)
+            and ("Tangent" in __Function)
+            and ("Adjoint" in __Function)
+            and (__Function["Direct"] is not None)
+            and (__Function["Tangent"] is not None)
+            and (__Function["Adjoint"] is not None)
+        ):
+            self.__FO["Direct"] = Operator(
+                name=self.__name,
+                fromMethod=__Function["Direct"],
+                reducingMemoryUse=__reduceM,
+                avoidingRedundancy=__avoidRC,
+                inputAsMultiFunction=inputAsMF,
+                extraArguments=self.__extraArgs,
+                enableMultiProcess=__Parameters["EnableParallelEvaluations"],
+            )
             self.__FO["Tangent"] = Operator(
-                name = self.__name + "Tangent",
-                fromMethod = __Function["Tangent"],
-                reducingMemoryUse = __reduceM,
-                avoidingRedundancy = __avoidRC,
-                inputAsMultiFunction = inputAsMF,
-                extraArguments = self.__extraArgs )
+                name=self.__name + "Tangent",
+                fromMethod=__Function["Tangent"],
+                reducingMemoryUse=__reduceM,
+                avoidingRedundancy=__avoidRC,
+                inputAsMultiFunction=inputAsMF,
+                extraArguments=self.__extraArgs,
+            )
             self.__FO["Adjoint"] = Operator(
-                name = self.__name + "Adjoint",
-                fromMethod = __Function["Adjoint"],
-                reducingMemoryUse = __reduceM,
-                avoidingRedundancy = __avoidRC,
-                inputAsMultiFunction = inputAsMF,
-                extraArguments = self.__extraArgs )
+                name=self.__name + "Adjoint",
+                fromMethod=__Function["Adjoint"],
+                reducingMemoryUse=__reduceM,
+                avoidingRedundancy=__avoidRC,
+                inputAsMultiFunction=inputAsMF,
+                extraArguments=self.__extraArgs,
+            )
             self.__FO["DifferentialIncrement"] = None
         elif asMatrix is not None:
             if isinstance(__Matrix, str):
-                __Matrix = PlatformInfo.strmatrix2liststr( __Matrix )
-            __matrice = numpy.asarray( __Matrix, dtype=float )
-            self.__FO["Direct"]  = Operator(
-                name = self.__name,
-                fromMatrix = __matrice,
-                reducingMemoryUse = __reduceM,
-                avoidingRedundancy = __avoidRC,
-                inputAsMultiFunction = inputAsMF,
-                enableMultiProcess = __Parameters["EnableParallelEvaluations"] )
+                __Matrix = PlatformInfo.strmatrix2liststr(__Matrix)
+            __matrice = numpy.asarray(__Matrix, dtype=float)
+            self.__FO["Direct"] = Operator(
+                name=self.__name,
+                fromMatrix=__matrice,
+                reducingMemoryUse=__reduceM,
+                avoidingRedundancy=__avoidRC,
+                inputAsMultiFunction=inputAsMF,
+                enableMultiProcess=__Parameters["EnableParallelEvaluations"],
+            )
             self.__FO["Tangent"] = Operator(
-                name = self.__name + "Tangent",
-                fromMatrix = __matrice,
-                reducingMemoryUse = __reduceM,
-                avoidingRedundancy = __avoidRC,
-                inputAsMultiFunction = inputAsMF )
+                name=self.__name + "Tangent",
+                fromMatrix=__matrice,
+                reducingMemoryUse=__reduceM,
+                avoidingRedundancy=__avoidRC,
+                inputAsMultiFunction=inputAsMF,
+            )
             self.__FO["Adjoint"] = Operator(
-                name = self.__name + "Adjoint",
-                fromMatrix = __matrice.T,
-                reducingMemoryUse = __reduceM,
-                avoidingRedundancy = __avoidRC,
-                inputAsMultiFunction = inputAsMF )
+                name=self.__name + "Adjoint",
+                fromMatrix=__matrice.T,
+                reducingMemoryUse=__reduceM,
+                avoidingRedundancy=__avoidRC,
+                inputAsMultiFunction=inputAsMF,
+            )
             del __matrice
             self.__FO["DifferentialIncrement"] = None
         else:
             raise ValueError(
-                "The %s object is improperly defined or undefined,"%self.__name + \
-                " it requires at minima either a matrix, a Direct operator for" + \
-                " approximate derivatives or a Tangent/Adjoint operators pair." + \
-                " Please check your operator input.")
+                "The %s object is improperly defined or undefined," % self.__name
+                + " it requires at minima either a matrix, a Direct operator for"
+                + " approximate derivatives or a Tangent/Adjoint operators pair."
+                + " Please check your operator input."
+            )
         #
         if __appliedInX is not None:
             self.__FO["AppliedInX"] = {}
             for key in __appliedInX:
                 if isinstance(__appliedInX[key], str):
-                    __appliedInX[key] = PlatformInfo.strvect2liststr( __appliedInX[key] )
-                self.__FO["AppliedInX"][key] = numpy.ravel( __appliedInX[key] ).reshape((-1, 1))
+                    __appliedInX[key] = PlatformInfo.strvect2liststr(__appliedInX[key])
+                self.__FO["AppliedInX"][key] = numpy.ravel(__appliedInX[key]).reshape(
+                    (-1, 1)
+                )
         else:
             self.__FO["AppliedInX"] = None
 
@@ -697,12 +820,13 @@ class FullOperator(object):
         if oldn in collection:
             collection[newn] = collection[oldn]
             del collection[oldn]
-            __msg  = "the parameter \"%s\" used in this case is"%(oldn,)
-            __msg += " deprecated and has to be replaced by \"%s\"."%(newn,)
+            __msg = 'the parameter "%s" used in this case is' % (oldn,)
+            __msg += ' deprecated and has to be replaced by "%s".' % (newn,)
             __msg += " Please update your code."
             warnings.warn(__msg, FutureWarning, stacklevel=50)
         return collection
 
+
 # ==============================================================================
 class Algorithm(object):
     """
@@ -714,10 +838,17 @@ class Algorithm(object):
 
     Une classe élémentaire d'algorithme doit implémenter la méthode "run".
     """
+
     __slots__ = (
-        "_name", "_parameters", "__internal_state", "__required_parameters",
-        "_m", "__variable_names_not_public", "__canonical_parameter_name",
-        "__canonical_stored_name", "__replace_by_the_new_name",
+        "_name",
+        "_parameters",
+        "__internal_state",
+        "__required_parameters",
+        "_m",
+        "__variable_names_not_public",
+        "__canonical_parameter_name",
+        "__canonical_stored_name",
+        "__replace_by_the_new_name",
         "StoredVariables",
     )
 
@@ -785,7 +916,7 @@ class Algorithm(object):
         logging.debug("%s Initialisation", str(name))
         self._m = PlatformInfo.SystemUsage()
         #
-        self._name = str( name )
+        self._name = str(name)
         self._parameters = {"StoreSupplementaryCalculations": []}
         self.__internal_state = {}
         self.__required_parameters = {}
@@ -794,69 +925,167 @@ class Algorithm(object):
             "AttributesTags": [],
             "AttributesFeatures": [],
         }
-        self.__variable_names_not_public = {"nextStep": False}  # Duplication dans AlgorithmAndParameters
+        self.__variable_names_not_public = {
+            "nextStep": False
+        }  # Duplication dans AlgorithmAndParameters
         self.__canonical_parameter_name = {}  # Correspondance "lower"->"correct"
-        self.__canonical_stored_name = {}     # Correspondance "lower"->"correct"
-        self.__replace_by_the_new_name = {}   # Nouveau nom à partir d'un nom ancien
+        self.__canonical_stored_name = {}  # Correspondance "lower"->"correct"
+        self.__replace_by_the_new_name = {}  # Nouveau nom à partir d'un nom ancien
         #
         self.StoredVariables = {}
-        self.StoredVariables["APosterioriCorrelations"]               = Persistence.OneMatrix(name = "APosterioriCorrelations")
-        self.StoredVariables["APosterioriCovariance"]                 = Persistence.OneMatrix(name = "APosterioriCovariance")
-        self.StoredVariables["APosterioriStandardDeviations"]         = Persistence.OneVector(name = "APosterioriStandardDeviations")
-        self.StoredVariables["APosterioriVariances"]                  = Persistence.OneVector(name = "APosterioriVariances")
-        self.StoredVariables["Analysis"]                              = Persistence.OneVector(name = "Analysis")
-        self.StoredVariables["BMA"]                                   = Persistence.OneVector(name = "BMA")
-        self.StoredVariables["CostFunctionJ"]                         = Persistence.OneScalar(name = "CostFunctionJ")
-        self.StoredVariables["CostFunctionJAtCurrentOptimum"]         = Persistence.OneScalar(name = "CostFunctionJAtCurrentOptimum")
-        self.StoredVariables["CostFunctionJb"]                        = Persistence.OneScalar(name = "CostFunctionJb")
-        self.StoredVariables["CostFunctionJbAtCurrentOptimum"]        = Persistence.OneScalar(name = "CostFunctionJbAtCurrentOptimum")
-        self.StoredVariables["CostFunctionJo"]                        = Persistence.OneScalar(name = "CostFunctionJo")
-        self.StoredVariables["CostFunctionJoAtCurrentOptimum"]        = Persistence.OneScalar(name = "CostFunctionJoAtCurrentOptimum")
-        self.StoredVariables["CurrentEnsembleState"]                  = Persistence.OneMatrix(name = "CurrentEnsembleState")
-        self.StoredVariables["CurrentIterationNumber"]                = Persistence.OneIndex(name  = "CurrentIterationNumber")
-        self.StoredVariables["CurrentOptimum"]                        = Persistence.OneVector(name = "CurrentOptimum")
-        self.StoredVariables["CurrentState"]                          = Persistence.OneVector(name = "CurrentState")
-        self.StoredVariables["CurrentStepNumber"]                     = Persistence.OneIndex(name  = "CurrentStepNumber")
-        self.StoredVariables["EnsembleOfSimulations"]                 = Persistence.OneMatrice(name = "EnsembleOfSimulations")
-        self.StoredVariables["EnsembleOfSnapshots"]                   = Persistence.OneMatrice(name = "EnsembleOfSnapshots")
-        self.StoredVariables["EnsembleOfStates"]                      = Persistence.OneMatrice(name = "EnsembleOfStates")
-        self.StoredVariables["ExcludedPoints"]                        = Persistence.OneVector(name = "ExcludedPoints")
-        self.StoredVariables["ForecastCovariance"]                    = Persistence.OneMatrix(name = "ForecastCovariance")
-        self.StoredVariables["ForecastState"]                         = Persistence.OneVector(name = "ForecastState")
-        self.StoredVariables["GradientOfCostFunctionJ"]               = Persistence.OneVector(name = "GradientOfCostFunctionJ")
-        self.StoredVariables["GradientOfCostFunctionJb"]              = Persistence.OneVector(name = "GradientOfCostFunctionJb")
-        self.StoredVariables["GradientOfCostFunctionJo"]              = Persistence.OneVector(name = "GradientOfCostFunctionJo")
-        self.StoredVariables["IndexOfOptimum"]                        = Persistence.OneIndex(name  = "IndexOfOptimum")
-        self.StoredVariables["Innovation"]                            = Persistence.OneVector(name = "Innovation")
-        self.StoredVariables["InnovationAtCurrentAnalysis"]           = Persistence.OneVector(name = "InnovationAtCurrentAnalysis")
-        self.StoredVariables["InnovationAtCurrentState"]              = Persistence.OneVector(name = "InnovationAtCurrentState")
-        self.StoredVariables["InternalCostFunctionJ"]                 = Persistence.OneVector(name = "InternalCostFunctionJ")
-        self.StoredVariables["InternalCostFunctionJb"]                = Persistence.OneVector(name = "InternalCostFunctionJb")
-        self.StoredVariables["InternalCostFunctionJo"]                = Persistence.OneVector(name = "InternalCostFunctionJo")
-        self.StoredVariables["InternalStates"]                        = Persistence.OneMatrix(name = "InternalStates")
-        self.StoredVariables["JacobianMatrixAtBackground"]            = Persistence.OneMatrix(name = "JacobianMatrixAtBackground")
-        self.StoredVariables["JacobianMatrixAtCurrentState"]          = Persistence.OneMatrix(name = "JacobianMatrixAtCurrentState")
-        self.StoredVariables["JacobianMatrixAtOptimum"]               = Persistence.OneMatrix(name = "JacobianMatrixAtOptimum")
-        self.StoredVariables["KalmanGainAtOptimum"]                   = Persistence.OneMatrix(name = "KalmanGainAtOptimum")
-        self.StoredVariables["MahalanobisConsistency"]                = Persistence.OneScalar(name = "MahalanobisConsistency")
-        self.StoredVariables["OMA"]                                   = Persistence.OneVector(name = "OMA")
-        self.StoredVariables["OMB"]                                   = Persistence.OneVector(name = "OMB")
-        self.StoredVariables["OptimalPoints"]                         = Persistence.OneVector(name = "OptimalPoints")
-        self.StoredVariables["ReducedBasis"]                          = Persistence.OneMatrix(name = "ReducedBasis")
-        self.StoredVariables["ReducedBasisMus"]                       = Persistence.OneVector(name = "ReducedBasisMus")
-        self.StoredVariables["ReducedCoordinates"]                    = Persistence.OneVector(name = "ReducedCoordinates")
-        self.StoredVariables["Residu"]                                = Persistence.OneScalar(name = "Residu")
-        self.StoredVariables["Residus"]                               = Persistence.OneVector(name = "Residus")
-        self.StoredVariables["SampledStateForQuantiles"]              = Persistence.OneMatrix(name = "SampledStateForQuantiles")
-        self.StoredVariables["SigmaBck2"]                             = Persistence.OneScalar(name = "SigmaBck2")
-        self.StoredVariables["SigmaObs2"]                             = Persistence.OneScalar(name = "SigmaObs2")
-        self.StoredVariables["SimulatedObservationAtBackground"]      = Persistence.OneVector(name = "SimulatedObservationAtBackground")
-        self.StoredVariables["SimulatedObservationAtCurrentAnalysis"] = Persistence.OneVector(name = "SimulatedObservationAtCurrentAnalysis")
-        self.StoredVariables["SimulatedObservationAtCurrentOptimum"]  = Persistence.OneVector(name = "SimulatedObservationAtCurrentOptimum")
-        self.StoredVariables["SimulatedObservationAtCurrentState"]    = Persistence.OneVector(name = "SimulatedObservationAtCurrentState")
-        self.StoredVariables["SimulatedObservationAtOptimum"]         = Persistence.OneVector(name = "SimulatedObservationAtOptimum")
-        self.StoredVariables["SimulationQuantiles"]                   = Persistence.OneMatrix(name = "SimulationQuantiles")
-        self.StoredVariables["SingularValues"]                        = Persistence.OneVector(name = "SingularValues")
+        self.StoredVariables["APosterioriCorrelations"] = Persistence.OneMatrix(
+            name="APosterioriCorrelations"
+        )
+        self.StoredVariables["APosterioriCovariance"] = Persistence.OneMatrix(
+            name="APosterioriCovariance"
+        )
+        self.StoredVariables["APosterioriStandardDeviations"] = Persistence.OneVector(
+            name="APosterioriStandardDeviations"
+        )
+        self.StoredVariables["APosterioriVariances"] = Persistence.OneVector(
+            name="APosterioriVariances"
+        )
+        self.StoredVariables["Analysis"] = Persistence.OneVector(name="Analysis")
+        self.StoredVariables["BMA"] = Persistence.OneVector(name="BMA")
+        self.StoredVariables["CostFunctionJ"] = Persistence.OneScalar(
+            name="CostFunctionJ"
+        )
+        self.StoredVariables["CostFunctionJAtCurrentOptimum"] = Persistence.OneScalar(
+            name="CostFunctionJAtCurrentOptimum"
+        )
+        self.StoredVariables["CostFunctionJb"] = Persistence.OneScalar(
+            name="CostFunctionJb"
+        )
+        self.StoredVariables["CostFunctionJbAtCurrentOptimum"] = Persistence.OneScalar(
+            name="CostFunctionJbAtCurrentOptimum"
+        )
+        self.StoredVariables["CostFunctionJo"] = Persistence.OneScalar(
+            name="CostFunctionJo"
+        )
+        self.StoredVariables["CostFunctionJoAtCurrentOptimum"] = Persistence.OneScalar(
+            name="CostFunctionJoAtCurrentOptimum"
+        )
+        self.StoredVariables["CurrentEnsembleState"] = Persistence.OneMatrix(
+            name="CurrentEnsembleState"
+        )
+        self.StoredVariables["CurrentIterationNumber"] = Persistence.OneIndex(
+            name="CurrentIterationNumber"
+        )
+        self.StoredVariables["CurrentOptimum"] = Persistence.OneVector(
+            name="CurrentOptimum"
+        )
+        self.StoredVariables["CurrentState"] = Persistence.OneVector(
+            name="CurrentState"
+        )
+        self.StoredVariables["CurrentStepNumber"] = Persistence.OneIndex(
+            name="CurrentStepNumber"
+        )
+        self.StoredVariables["EnsembleOfSimulations"] = Persistence.OneMatrice(
+            name="EnsembleOfSimulations"
+        )
+        self.StoredVariables["EnsembleOfSnapshots"] = Persistence.OneMatrice(
+            name="EnsembleOfSnapshots"
+        )
+        self.StoredVariables["EnsembleOfStates"] = Persistence.OneMatrice(
+            name="EnsembleOfStates"
+        )
+        self.StoredVariables["ExcludedPoints"] = Persistence.OneVector(
+            name="ExcludedPoints"
+        )
+        self.StoredVariables["ForecastCovariance"] = Persistence.OneMatrix(
+            name="ForecastCovariance"
+        )
+        self.StoredVariables["ForecastState"] = Persistence.OneVector(
+            name="ForecastState"
+        )
+        self.StoredVariables["GradientOfCostFunctionJ"] = Persistence.OneVector(
+            name="GradientOfCostFunctionJ"
+        )
+        self.StoredVariables["GradientOfCostFunctionJb"] = Persistence.OneVector(
+            name="GradientOfCostFunctionJb"
+        )
+        self.StoredVariables["GradientOfCostFunctionJo"] = Persistence.OneVector(
+            name="GradientOfCostFunctionJo"
+        )
+        self.StoredVariables["IndexOfOptimum"] = Persistence.OneIndex(
+            name="IndexOfOptimum"
+        )
+        self.StoredVariables["Innovation"] = Persistence.OneVector(name="Innovation")
+        self.StoredVariables["InnovationAtCurrentAnalysis"] = Persistence.OneVector(
+            name="InnovationAtCurrentAnalysis"
+        )
+        self.StoredVariables["InnovationAtCurrentState"] = Persistence.OneVector(
+            name="InnovationAtCurrentState"
+        )
+        self.StoredVariables["InternalCostFunctionJ"] = Persistence.OneVector(
+            name="InternalCostFunctionJ"
+        )
+        self.StoredVariables["InternalCostFunctionJb"] = Persistence.OneVector(
+            name="InternalCostFunctionJb"
+        )
+        self.StoredVariables["InternalCostFunctionJo"] = Persistence.OneVector(
+            name="InternalCostFunctionJo"
+        )
+        self.StoredVariables["InternalStates"] = Persistence.OneMatrix(
+            name="InternalStates"
+        )
+        self.StoredVariables["JacobianMatrixAtBackground"] = Persistence.OneMatrix(
+            name="JacobianMatrixAtBackground"
+        )
+        self.StoredVariables["JacobianMatrixAtCurrentState"] = Persistence.OneMatrix(
+            name="JacobianMatrixAtCurrentState"
+        )
+        self.StoredVariables["JacobianMatrixAtOptimum"] = Persistence.OneMatrix(
+            name="JacobianMatrixAtOptimum"
+        )
+        self.StoredVariables["KalmanGainAtOptimum"] = Persistence.OneMatrix(
+            name="KalmanGainAtOptimum"
+        )
+        self.StoredVariables["MahalanobisConsistency"] = Persistence.OneScalar(
+            name="MahalanobisConsistency"
+        )
+        self.StoredVariables["OMA"] = Persistence.OneVector(name="OMA")
+        self.StoredVariables["OMB"] = Persistence.OneVector(name="OMB")
+        self.StoredVariables["OptimalPoints"] = Persistence.OneVector(
+            name="OptimalPoints"
+        )
+        self.StoredVariables["ReducedBasis"] = Persistence.OneMatrix(
+            name="ReducedBasis"
+        )
+        self.StoredVariables["ReducedBasisMus"] = Persistence.OneVector(
+            name="ReducedBasisMus"
+        )
+        self.StoredVariables["ReducedCoordinates"] = Persistence.OneVector(
+            name="ReducedCoordinates"
+        )
+        self.StoredVariables["Residu"] = Persistence.OneScalar(name="Residu")
+        self.StoredVariables["Residus"] = Persistence.OneVector(name="Residus")
+        self.StoredVariables["SampledStateForQuantiles"] = Persistence.OneMatrix(
+            name="SampledStateForQuantiles"
+        )
+        self.StoredVariables["SigmaBck2"] = Persistence.OneScalar(name="SigmaBck2")
+        self.StoredVariables["SigmaObs2"] = Persistence.OneScalar(name="SigmaObs2")
+        self.StoredVariables["SimulatedObservationAtBackground"] = (
+            Persistence.OneVector(name="SimulatedObservationAtBackground")
+        )
+        self.StoredVariables["SimulatedObservationAtCurrentAnalysis"] = (
+            Persistence.OneVector(name="SimulatedObservationAtCurrentAnalysis")
+        )
+        self.StoredVariables["SimulatedObservationAtCurrentOptimum"] = (
+            Persistence.OneVector(name="SimulatedObservationAtCurrentOptimum")
+        )
+        self.StoredVariables["SimulatedObservationAtCurrentState"] = (
+            Persistence.OneVector(name="SimulatedObservationAtCurrentState")
+        )
+        self.StoredVariables["SimulatedObservationAtOptimum"] = Persistence.OneVector(
+            name="SimulatedObservationAtOptimum"
+        )
+        self.StoredVariables["SimulationQuantiles"] = Persistence.OneMatrix(
+            name="SimulationQuantiles"
+        )
+        self.StoredVariables["SingularValues"] = Persistence.OneVector(
+            name="SingularValues"
+        )
         #
         for k in self.StoredVariables:
             self.__canonical_stored_name[k.lower()] = k
@@ -864,12 +1093,29 @@ class Algorithm(object):
         for k, v in self.__variable_names_not_public.items():
             self.__canonical_parameter_name[k.lower()] = k
         self.__canonical_parameter_name["algorithm"] = "Algorithm"
-        self.__canonical_parameter_name["storesupplementarycalculations"] = "StoreSupplementaryCalculations"
+        self.__canonical_parameter_name["storesupplementarycalculations"] = (
+            "StoreSupplementaryCalculations"
+        )
 
-    def _pre_run(self, Parameters, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None ):
+    def _pre_run(
+        self,
+        Parameters,
+        Xb=None,
+        Y=None,
+        U=None,
+        HO=None,
+        EM=None,
+        CM=None,
+        R=None,
+        B=None,
+        Q=None,
+    ):
         "Pré-calcul"
         logging.debug("%s Lancement", self._name)
-        logging.debug("%s Taille mémoire utilisée de %.0f Mio"%(self._name, self._m.getUsedMemory("Mio")))
+        logging.debug(
+            "%s Taille mémoire utilisée de %.0f Mio"
+            % (self._name, self._m.getUsedMemory("Mio"))
+        )
         self._getTimeState(reset=True)
         #
         # Mise à jour des paramètres internes avec le contenu de Parameters, en
@@ -877,130 +1123,242 @@ class Algorithm(object):
         self.__setParameters(Parameters, reset=True)  # Copie mémoire
         for k, v in self.__variable_names_not_public.items():
             if k not in self._parameters:
-                self.__setParameters( {k: v} )
+                self.__setParameters({k: v})
 
         def __test_vvalue(argument, variable, argname, symbol=None):
             "Corrections et compléments des vecteurs"
             if symbol is None:
                 symbol = variable
             if argument is None:
-                if variable in self.__required_inputs["RequiredInputValues"]["mandatory"]:
-                    raise ValueError("%s %s vector %s is not set and has to be properly defined!"%(self._name, argname, symbol))
-                elif variable in self.__required_inputs["RequiredInputValues"]["optional"]:
-                    logging.debug("%s %s vector %s is not set, but is optional."%(self._name, argname, symbol))
+                if (
+                    variable
+                    in self.__required_inputs["RequiredInputValues"]["mandatory"]
+                ):
+                    raise ValueError(
+                        "%s %s vector %s is not set and has to be properly defined!"
+                        % (self._name, argname, symbol)
+                    )
+                elif (
+                    variable
+                    in self.__required_inputs["RequiredInputValues"]["optional"]
+                ):
+                    logging.debug(
+                        "%s %s vector %s is not set, but is optional."
+                        % (self._name, argname, symbol)
+                    )
                 else:
-                    logging.debug("%s %s vector %s is not set, but is not required."%(self._name, argname, symbol))
+                    logging.debug(
+                        "%s %s vector %s is not set, but is not required."
+                        % (self._name, argname, symbol)
+                    )
             else:
-                if variable in self.__required_inputs["RequiredInputValues"]["mandatory"]:
+                if (
+                    variable
+                    in self.__required_inputs["RequiredInputValues"]["mandatory"]
+                ):
                     logging.debug(
-                        "%s %s vector %s is required and set, and its full size is %i." \
-                        % (self._name, argname, symbol, numpy.array(argument).size))
-                elif variable in self.__required_inputs["RequiredInputValues"]["optional"]:
+                        "%s %s vector %s is required and set, and its full size is %i."
+                        % (self._name, argname, symbol, numpy.array(argument).size)
+                    )
+                elif (
+                    variable
+                    in self.__required_inputs["RequiredInputValues"]["optional"]
+                ):
                     logging.debug(
-                        "%s %s vector %s is optional and set, and its full size is %i." \
-                        % (self._name, argname, symbol, numpy.array(argument).size))
+                        "%s %s vector %s is optional and set, and its full size is %i."
+                        % (self._name, argname, symbol, numpy.array(argument).size)
+                    )
                 else:
                     logging.debug(
-                        "%s %s vector %s is set although neither required nor optional, and its full size is %i." \
-                        % (self._name, argname, symbol, numpy.array(argument).size))
+                        "%s %s vector %s is set although neither required nor optional, and its full size is %i."
+                        % (self._name, argname, symbol, numpy.array(argument).size)
+                    )
             return 0
-        __test_vvalue( Xb, "Xb", "Background or initial state" )
-        __test_vvalue( Y, "Y", "Observation" )
-        __test_vvalue( U, "U", "Control" )
+
+        __test_vvalue(Xb, "Xb", "Background or initial state")
+        __test_vvalue(Y, "Y", "Observation")
+        __test_vvalue(U, "U", "Control")
 
         def __test_cvalue(argument, variable, argname, symbol=None):
             "Corrections et compléments des covariances"
             if symbol is None:
                 symbol = variable
             if argument is None:
-                if variable in self.__required_inputs["RequiredInputValues"]["mandatory"]:
-                    raise ValueError("%s %s error covariance matrix %s is not set and has to be properly defined!"%(self._name, argname, symbol))
-                elif variable in self.__required_inputs["RequiredInputValues"]["optional"]:
-                    logging.debug("%s %s error covariance matrix %s is not set, but is optional."%(self._name, argname, symbol))
+                if (
+                    variable
+                    in self.__required_inputs["RequiredInputValues"]["mandatory"]
+                ):
+                    raise ValueError(
+                        "%s %s error covariance matrix %s is not set and has to be properly defined!"
+                        % (self._name, argname, symbol)
+                    )
+                elif (
+                    variable
+                    in self.__required_inputs["RequiredInputValues"]["optional"]
+                ):
+                    logging.debug(
+                        "%s %s error covariance matrix %s is not set, but is optional."
+                        % (self._name, argname, symbol)
+                    )
                 else:
-                    logging.debug("%s %s error covariance matrix %s is not set, but is not required."%(self._name, argname, symbol))
+                    logging.debug(
+                        "%s %s error covariance matrix %s is not set, but is not required."
+                        % (self._name, argname, symbol)
+                    )
             else:
-                if variable in self.__required_inputs["RequiredInputValues"]["mandatory"]:
-                    logging.debug("%s %s error covariance matrix %s is required and set."%(self._name, argname, symbol))
-                elif variable in self.__required_inputs["RequiredInputValues"]["optional"]:
-                    logging.debug("%s %s error covariance matrix %s is optional and set."%(self._name, argname, symbol))
+                if (
+                    variable
+                    in self.__required_inputs["RequiredInputValues"]["mandatory"]
+                ):
+                    logging.debug(
+                        "%s %s error covariance matrix %s is required and set."
+                        % (self._name, argname, symbol)
+                    )
+                elif (
+                    variable
+                    in self.__required_inputs["RequiredInputValues"]["optional"]
+                ):
+                    logging.debug(
+                        "%s %s error covariance matrix %s is optional and set."
+                        % (self._name, argname, symbol)
+                    )
                 else:
                     logging.debug(
-                        "%s %s error covariance matrix %s is set although neither required nor optional." \
-                        % (self._name, argname, symbol))
+                        "%s %s error covariance matrix %s is set although neither required nor optional."
+                        % (self._name, argname, symbol)
+                    )
             return 0
-        __test_cvalue( B, "B", "Background" )
-        __test_cvalue( R, "R", "Observation" )
-        __test_cvalue( Q, "Q", "Evolution" )
+
+        __test_cvalue(B, "B", "Background")
+        __test_cvalue(R, "R", "Observation")
+        __test_cvalue(Q, "Q", "Evolution")
 
         def __test_ovalue(argument, variable, argname, symbol=None):
             "Corrections et compléments des opérateurs"
             if symbol is None:
                 symbol = variable
             if argument is None or (isinstance(argument, dict) and len(argument) == 0):
-                if variable in self.__required_inputs["RequiredInputValues"]["mandatory"]:
-                    raise ValueError("%s %s operator %s is not set and has to be properly defined!"%(self._name, argname, symbol))
-                elif variable in self.__required_inputs["RequiredInputValues"]["optional"]:
-                    logging.debug("%s %s operator %s is not set, but is optional."%(self._name, argname, symbol))
+                if (
+                    variable
+                    in self.__required_inputs["RequiredInputValues"]["mandatory"]
+                ):
+                    raise ValueError(
+                        "%s %s operator %s is not set and has to be properly defined!"
+                        % (self._name, argname, symbol)
+                    )
+                elif (
+                    variable
+                    in self.__required_inputs["RequiredInputValues"]["optional"]
+                ):
+                    logging.debug(
+                        "%s %s operator %s is not set, but is optional."
+                        % (self._name, argname, symbol)
+                    )
                 else:
-                    logging.debug("%s %s operator %s is not set, but is not required."%(self._name, argname, symbol))
+                    logging.debug(
+                        "%s %s operator %s is not set, but is not required."
+                        % (self._name, argname, symbol)
+                    )
             else:
-                if variable in self.__required_inputs["RequiredInputValues"]["mandatory"]:
-                    logging.debug("%s %s operator %s is required and set."%(self._name, argname, symbol))
-                elif variable in self.__required_inputs["RequiredInputValues"]["optional"]:
-                    logging.debug("%s %s operator %s is optional and set."%(self._name, argname, symbol))
+                if (
+                    variable
+                    in self.__required_inputs["RequiredInputValues"]["mandatory"]
+                ):
+                    logging.debug(
+                        "%s %s operator %s is required and set."
+                        % (self._name, argname, symbol)
+                    )
+                elif (
+                    variable
+                    in self.__required_inputs["RequiredInputValues"]["optional"]
+                ):
+                    logging.debug(
+                        "%s %s operator %s is optional and set."
+                        % (self._name, argname, symbol)
+                    )
                 else:
-                    logging.debug("%s %s operator %s is set although neither required nor optional."%(self._name, argname, symbol))
+                    logging.debug(
+                        "%s %s operator %s is set although neither required nor optional."
+                        % (self._name, argname, symbol)
+                    )
             return 0
-        __test_ovalue( HO, "HO", "Observation", "H" )
-        __test_ovalue( EM, "EM", "Evolution", "M" )
-        __test_ovalue( CM, "CM", "Control Model", "C" )
+
+        __test_ovalue(HO, "HO", "Observation", "H")
+        __test_ovalue(EM, "EM", "Evolution", "M")
+        __test_ovalue(CM, "CM", "Control Model", "C")
         #
         # Corrections et compléments des bornes
-        if ("Bounds" in self._parameters) \
-                and isinstance(self._parameters["Bounds"], (list, tuple)):
-            if (len(self._parameters["Bounds"]) > 0):
-                logging.debug("%s Bounds taken into account"%(self._name,))
+        if ("Bounds" in self._parameters) and isinstance(
+            self._parameters["Bounds"], (list, tuple)
+        ):
+            if len(self._parameters["Bounds"]) > 0:
+                logging.debug("%s Bounds taken into account" % (self._name,))
             else:
                 self._parameters["Bounds"] = None
-        elif ("Bounds" in self._parameters) \
-                and isinstance(self._parameters["Bounds"], (numpy.ndarray, numpy.matrix)):
-            self._parameters["Bounds"] = numpy.ravel(self._parameters["Bounds"]).reshape((-1, 2)).tolist()
-            if (len(self._parameters["Bounds"]) > 0):
-                logging.debug("%s Bounds for states taken into account"%(self._name,))
+        elif ("Bounds" in self._parameters) and isinstance(
+            self._parameters["Bounds"], (numpy.ndarray, numpy.matrix)
+        ):
+            self._parameters["Bounds"] = (
+                numpy.ravel(self._parameters["Bounds"]).reshape((-1, 2)).tolist()
+            )
+            if len(self._parameters["Bounds"]) > 0:
+                logging.debug("%s Bounds for states taken into account" % (self._name,))
             else:
                 self._parameters["Bounds"] = None
         else:
             self._parameters["Bounds"] = None
         if self._parameters["Bounds"] is None:
-            logging.debug("%s There are no bounds for states to take into account"%(self._name,))
-        #
-        if ("StateBoundsForQuantiles" in self._parameters) \
-                and isinstance(self._parameters["StateBoundsForQuantiles"], (list, tuple)) \
-                and (len(self._parameters["StateBoundsForQuantiles"]) > 0):
-            logging.debug("%s Bounds for quantiles states taken into account"%(self._name,))
-        elif ("StateBoundsForQuantiles" in self._parameters) \
-                and isinstance(self._parameters["StateBoundsForQuantiles"], (numpy.ndarray, numpy.matrix)):
-            self._parameters["StateBoundsForQuantiles"] = numpy.ravel(self._parameters["StateBoundsForQuantiles"]).reshape((-1, 2)).tolist()
-            if (len(self._parameters["StateBoundsForQuantiles"]) > 0):
-                logging.debug("%s Bounds for quantiles states taken into account"%(self._name,))
+            logging.debug(
+                "%s There are no bounds for states to take into account" % (self._name,)
+            )
+        #
+        if (
+            ("StateBoundsForQuantiles" in self._parameters)
+            and isinstance(self._parameters["StateBoundsForQuantiles"], (list, tuple))
+            and (len(self._parameters["StateBoundsForQuantiles"]) > 0)
+        ):
+            logging.debug(
+                "%s Bounds for quantiles states taken into account" % (self._name,)
+            )
+        elif ("StateBoundsForQuantiles" in self._parameters) and isinstance(
+            self._parameters["StateBoundsForQuantiles"], (numpy.ndarray, numpy.matrix)
+        ):
+            self._parameters["StateBoundsForQuantiles"] = (
+                numpy.ravel(self._parameters["StateBoundsForQuantiles"])
+                .reshape((-1, 2))
+                .tolist()
+            )
+            if len(self._parameters["StateBoundsForQuantiles"]) > 0:
+                logging.debug(
+                    "%s Bounds for quantiles states taken into account" % (self._name,)
+                )
             # Attention : contrairement à Bounds, il n'y a pas de défaut à None,
             #             sinon on ne peut pas être sans bornes
         #
         # Corrections et compléments de l'initialisation en X
         if "InitializationPoint" in self._parameters:
             if Xb is not None:
-                if self._parameters["InitializationPoint"] is not None and hasattr(self._parameters["InitializationPoint"], 'size'):
-                    if self._parameters["InitializationPoint"].size != numpy.ravel(Xb).size:
+                if self._parameters["InitializationPoint"] is not None and hasattr(
+                    self._parameters["InitializationPoint"], "size"
+                ):
+                    if (
+                        self._parameters["InitializationPoint"].size
+                        != numpy.ravel(Xb).size
+                    ):
                         raise ValueError(
-                            "Incompatible size %i of forced initial point that have to replace the background of size %i" \
-                            % (self._parameters["InitializationPoint"].size, numpy.ravel(Xb).size))
+                            "Incompatible size %i of forced initial point that"
+                            % self._parameters["InitializationPoint"].size
+                            + " have to replace the background of size %i"
+                            % numpy.ravel(Xb).size
+                        )
                     # Obtenu par typecast : numpy.ravel(self._parameters["InitializationPoint"])
                 else:
                     self._parameters["InitializationPoint"] = numpy.ravel(Xb)
             else:
                 if self._parameters["InitializationPoint"] is None:
-                    raise ValueError("Forced initial point can not be set without any given Background or required value")
+                    raise ValueError(
+                        "Forced initial point can not be set without any given Background or required value"
+                    )
         #
         # Correction pour pallier a un bug de TNC sur le retour du Minimum
         if "Minimizer" in self._parameters and self._parameters["Minimizer"] == "TNC":
@@ -1018,33 +1376,82 @@ class Algorithm(object):
 
     def _post_run(self, _oH=None, _oM=None):
         "Post-calcul"
-        if ("StoreSupplementaryCalculations" in self._parameters) and \
-                "APosterioriCovariance" in self._parameters["StoreSupplementaryCalculations"]:
+        if (
+            "StoreSupplementaryCalculations" in self._parameters
+        ) and "APosterioriCovariance" in self._parameters[
+            "StoreSupplementaryCalculations"
+        ]:
             for _A in self.StoredVariables["APosterioriCovariance"]:
-                if "APosterioriVariances" in self._parameters["StoreSupplementaryCalculations"]:
-                    self.StoredVariables["APosterioriVariances"].store( numpy.diag(_A) )
-                if "APosterioriStandardDeviations" in self._parameters["StoreSupplementaryCalculations"]:
-                    self.StoredVariables["APosterioriStandardDeviations"].store( numpy.sqrt(numpy.diag(_A)) )
-                if "APosterioriCorrelations" in self._parameters["StoreSupplementaryCalculations"]:
-                    _EI = numpy.diag(1. / numpy.sqrt(numpy.diag(_A)))
+                if (
+                    "APosterioriVariances"
+                    in self._parameters["StoreSupplementaryCalculations"]
+                ):
+                    self.StoredVariables["APosterioriVariances"].store(numpy.diag(_A))
+                if (
+                    "APosterioriStandardDeviations"
+                    in self._parameters["StoreSupplementaryCalculations"]
+                ):
+                    self.StoredVariables["APosterioriStandardDeviations"].store(
+                        numpy.sqrt(numpy.diag(_A))
+                    )
+                if (
+                    "APosterioriCorrelations"
+                    in self._parameters["StoreSupplementaryCalculations"]
+                ):
+                    _EI = numpy.diag(1.0 / numpy.sqrt(numpy.diag(_A)))
                     _C = numpy.dot(_EI, numpy.dot(_A, _EI))
-                    self.StoredVariables["APosterioriCorrelations"].store( _C )
-        if _oH is not None and "Direct" in _oH and "Tangent" in _oH and "Adjoint" in _oH:
+                    self.StoredVariables["APosterioriCorrelations"].store(_C)
+        if (
+            _oH is not None
+            and "Direct" in _oH
+            and "Tangent" in _oH
+            and "Adjoint" in _oH
+        ):
             logging.debug(
                 "%s Nombre d'évaluation(s) de l'opérateur d'observation direct/tangent/adjoint.: %i/%i/%i",
-                self._name, _oH["Direct"].nbcalls(0), _oH["Tangent"].nbcalls(0), _oH["Adjoint"].nbcalls(0))
+                self._name,
+                _oH["Direct"].nbcalls(0),
+                _oH["Tangent"].nbcalls(0),
+                _oH["Adjoint"].nbcalls(0),
+            )
             logging.debug(
                 "%s Nombre d'appels au cache d'opérateur d'observation direct/tangent/adjoint..: %i/%i/%i",
-                self._name, _oH["Direct"].nbcalls(3), _oH["Tangent"].nbcalls(3), _oH["Adjoint"].nbcalls(3))
-        if _oM is not None and "Direct" in _oM and "Tangent" in _oM and "Adjoint" in _oM:
+                self._name,
+                _oH["Direct"].nbcalls(3),
+                _oH["Tangent"].nbcalls(3),
+                _oH["Adjoint"].nbcalls(3),
+            )
+        if (
+            _oM is not None
+            and "Direct" in _oM
+            and "Tangent" in _oM
+            and "Adjoint" in _oM
+        ):
             logging.debug(
                 "%s Nombre d'évaluation(s) de l'opérateur d'évolution direct/tangent/adjoint.: %i/%i/%i",
-                self._name, _oM["Direct"].nbcalls(0), _oM["Tangent"].nbcalls(0), _oM["Adjoint"].nbcalls(0))
+                self._name,
+                _oM["Direct"].nbcalls(0),
+                _oM["Tangent"].nbcalls(0),
+                _oM["Adjoint"].nbcalls(0),
+            )
             logging.debug(
                 "%s Nombre d'appels au cache d'opérateur d'évolution direct/tangent/adjoint..: %i/%i/%i",
-                self._name, _oM["Direct"].nbcalls(3), _oM["Tangent"].nbcalls(3), _oM["Adjoint"].nbcalls(3))
-        logging.debug("%s Taille mémoire utilisée de %.0f Mio", self._name, self._m.getUsedMemory("Mio"))
-        logging.debug("%s Durées d'utilisation CPU de %.1fs et elapsed de %.1fs", self._name, self._getTimeState()[0], self._getTimeState()[1])
+                self._name,
+                _oM["Direct"].nbcalls(3),
+                _oM["Tangent"].nbcalls(3),
+                _oM["Adjoint"].nbcalls(3),
+            )
+        logging.debug(
+            "%s Taille mémoire utilisée de %.0f Mio",
+            self._name,
+            self._m.getUsedMemory("Mio"),
+        )
+        logging.debug(
+            "%s Durées d'utilisation CPU de %.1fs et elapsed de %.1fs",
+            self._name,
+            self._getTimeState()[0],
+            self._getTimeState()[1],
+        )
         logging.debug("%s Terminé", self._name)
         return 0
 
@@ -1081,11 +1488,14 @@ class Algorithm(object):
 
     def pop(self, k, d):
         "D.pop(k[,d]) -> v, remove specified key and return the corresponding value"
-        if hasattr(self, "StoredVariables") and k.lower() in self.__canonical_stored_name:
+        if (
+            hasattr(self, "StoredVariables")
+            and k.lower() in self.__canonical_stored_name
+        ):
             return self.StoredVariables.pop(self.__canonical_stored_name[k.lower()], d)
         else:
             try:
-                msg = "'%s'"%k
+                msg = "'%s'" % k
             except Exception:
                 raise TypeError("pop expected at least 1 arguments, got 0")
             "If key is not found, d is returned if given, otherwise KeyError is raised"
@@ -1094,23 +1504,38 @@ class Algorithm(object):
             except Exception:
                 raise KeyError(msg)
 
-    def run(self, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None, Parameters=None):
+    def run(
+        self,
+        Xb=None,
+        Y=None,
+        U=None,
+        HO=None,
+        EM=None,
+        CM=None,
+        R=None,
+        B=None,
+        Q=None,
+        Parameters=None,
+    ):
         """
         Doit implémenter l'opération élémentaire de calcul algorithmique.
         """
-        raise NotImplementedError("Mathematical algorithmic calculation has not been implemented!")
+        raise NotImplementedError(
+            "Mathematical algorithmic calculation has not been implemented!"
+        )
 
     def defineRequiredParameter(
-            self,
-            name     = None,
-            default  = None,
-            typecast = None,
-            message  = None,
-            minval   = None,
-            maxval   = None,
-            listval  = None,
-            listadv  = None,
-            oldname  = None ):
+        self,
+        name=None,
+        default=None,
+        typecast=None,
+        message=None,
+        minval=None,
+        maxval=None,
+        listval=None,
+        listadv=None,
+        oldname=None,
+    ):
         """
         Permet de définir dans l'algorithme des paramètres requis et leurs
         caractéristiques par défaut.
@@ -1119,20 +1544,25 @@ class Algorithm(object):
             raise ValueError("A name is mandatory to define a required parameter.")
         #
         self.__required_parameters[name] = {
-            "default"  : default,   # noqa: E203
-            "typecast" : typecast,  # noqa: E203
-            "minval"   : minval,    # noqa: E203
-            "maxval"   : maxval,    # noqa: E203
-            "listval"  : listval,   # noqa: E203
-            "listadv"  : listadv,   # noqa: E203
-            "message"  : message,   # noqa: E203
-            "oldname"  : oldname,   # noqa: E203
+            "default": default,
+            "typecast": typecast,
+            "minval": minval,
+            "maxval": maxval,
+            "listval": listval,
+            "listadv": listadv,
+            "message": message,
+            "oldname": oldname,
         }
         self.__canonical_parameter_name[name.lower()] = name
         if oldname is not None:
             self.__canonical_parameter_name[oldname.lower()] = name  # Conversion
             self.__replace_by_the_new_name[oldname.lower()] = name
-        logging.debug("%s %s (valeur par défaut = %s)", self._name, message, self.setParameterValue(name))
+        logging.debug(
+            "%s %s (valeur par défaut = %s)",
+            self._name,
+            message,
+            self.setParameterValue(name),
+        )
 
     def getRequiredParameters(self, noDetails=True):
         """
@@ -1149,12 +1579,12 @@ class Algorithm(object):
         Renvoie la valeur d'un paramètre requis de manière contrôlée
         """
         __k = self.__canonical_parameter_name[name.lower()]
-        default  = self.__required_parameters[__k]["default"]
+        default = self.__required_parameters[__k]["default"]
         typecast = self.__required_parameters[__k]["typecast"]
-        minval   = self.__required_parameters[__k]["minval"]
-        maxval   = self.__required_parameters[__k]["maxval"]
-        listval  = self.__required_parameters[__k]["listval"]
-        listadv  = self.__required_parameters[__k]["listadv"]
+        minval = self.__required_parameters[__k]["minval"]
+        maxval = self.__required_parameters[__k]["maxval"]
+        listval = self.__required_parameters[__k]["listval"]
+        listadv = self.__required_parameters[__k]["listadv"]
         #
         if value is None and default is None:
             __val = None
@@ -1162,33 +1592,57 @@ class Algorithm(object):
             if typecast is None:
                 __val = default
             else:
-                __val = typecast( default )
+                __val = typecast(default)
         else:
             if typecast is None:
                 __val = value
             else:
                 try:
-                    __val = typecast( value )
+                    __val = typecast(value)
                 except Exception:
-                    raise ValueError("The value '%s' for the parameter named '%s' can not be correctly evaluated with type '%s'."%(value, __k, typecast))
+                    raise ValueError(
+                        "The value '%s' for the parameter named '%s' can not be correctly evaluated with type '%s'."
+                        % (value, __k, typecast)
+                    )
         #
         if minval is not None and (numpy.array(__val, float) < minval).any():
-            raise ValueError("The parameter named '%s' of value '%s' can not be less than %s."%(__k, __val, minval))
+            raise ValueError(
+                "The parameter named '%s' of value '%s' can not be less than %s."
+                % (__k, __val, minval)
+            )
         if maxval is not None and (numpy.array(__val, float) > maxval).any():
-            raise ValueError("The parameter named '%s' of value '%s' can not be greater than %s."%(__k, __val, maxval))
+            raise ValueError(
+                "The parameter named '%s' of value '%s' can not be greater than %s."
+                % (__k, __val, maxval)
+            )
         if listval is not None or listadv is not None:
-            if typecast is list or typecast is tuple or isinstance(__val, list) or isinstance(__val, tuple):
+            if (
+                typecast is list
+                or typecast is tuple
+                or isinstance(__val, list)
+                or isinstance(__val, tuple)
+            ):
                 for v in __val:
                     if listval is not None and v in listval:
                         continue
                     elif listadv is not None and v in listadv:
                         continue
                     else:
-                        raise ValueError("The value '%s' is not allowed for the parameter named '%s', it has to be in the list %s."%(v, __k, listval))
-            elif not (listval is not None and __val in listval) and not (listadv is not None and __val in listadv):
-                raise ValueError("The value '%s' is not allowed for the parameter named '%s', it has to be in the list %s."%(__val, __k, listval))
+                        raise ValueError(
+                            "The value '%s' is not allowed for the parameter named '%s', it has to be in the list %s."
+                            % (v, __k, listval)
+                        )
+            elif not (listval is not None and __val in listval) and not (
+                listadv is not None and __val in listadv
+            ):
+                raise ValueError(
+                    "The value '%s' is not allowed for the parameter named '%s', it has to be in the list %s."
+                    % (__val, __k, listval)
+                )
         #
-        if __k in ["SetSeed",]:
+        if __k in [
+            "SetSeed",
+        ]:
             __val = value
         #
         return __val
@@ -1197,29 +1651,35 @@ class Algorithm(object):
         """
         Permet d'imposer des arguments de calcul requis en entrée.
         """
-        self.__required_inputs["RequiredInputValues"]["mandatory"] = tuple( mandatory )
-        self.__required_inputs["RequiredInputValues"]["optional"]  = tuple( optional )
+        self.__required_inputs["RequiredInputValues"]["mandatory"] = tuple(mandatory)
+        self.__required_inputs["RequiredInputValues"]["optional"] = tuple(optional)
 
     def getInputArguments(self):
         """
         Permet d'obtenir les listes des arguments de calcul requis en entrée.
         """
-        return self.__required_inputs["RequiredInputValues"]["mandatory"], self.__required_inputs["RequiredInputValues"]["optional"]
+        return (
+            self.__required_inputs["RequiredInputValues"]["mandatory"],
+            self.__required_inputs["RequiredInputValues"]["optional"],
+        )
 
     def setAttributes(self, tags=(), features=()):
         """
         Permet d'adjoindre des attributs comme les tags de classification.
         Renvoie la liste actuelle dans tous les cas.
         """
-        self.__required_inputs["AttributesTags"].extend( tags )
-        self.__required_inputs["AttributesFeatures"].extend( features )
-        return (self.__required_inputs["AttributesTags"], self.__required_inputs["AttributesFeatures"])
+        self.__required_inputs["AttributesTags"].extend(tags)
+        self.__required_inputs["AttributesFeatures"].extend(features)
+        return (
+            self.__required_inputs["AttributesTags"],
+            self.__required_inputs["AttributesFeatures"],
+        )
 
     def __setParameters(self, fromDico={}, reset=False):
         """
         Permet de stocker les paramètres reçus dans le dictionnaire interne.
         """
-        self._parameters.update( fromDico )
+        self._parameters.update(fromDico)
         __inverse_fromDico_keys = {}
         for k in fromDico.keys():
             if k.lower() in self.__canonical_parameter_name:
@@ -1230,23 +1690,46 @@ class Algorithm(object):
         for k in __inverse_fromDico_keys.values():
             if k.lower() in self.__replace_by_the_new_name:
                 __newk = self.__replace_by_the_new_name[k.lower()]
-                __msg  = "the parameter \"%s\" used in \"%s\" algorithm case is deprecated and has to be replaced by \"%s\"."%(k, self._name, __newk)
+                __msg = (
+                    'the parameter "%s" used in "%s" algorithm case is deprecated and has to be replaced by "%s".'
+                    % (k, self._name, __newk)
+                )
                 __msg += " Please update your code."
                 warnings.warn(__msg, FutureWarning, stacklevel=50)
         #
         for k in self.__required_parameters.keys():
             if k in __canonic_fromDico_keys:
-                self._parameters[k] = self.setParameterValue(k, fromDico[__inverse_fromDico_keys[k]])
+                self._parameters[k] = self.setParameterValue(
+                    k, fromDico[__inverse_fromDico_keys[k]]
+                )
             elif reset:
                 self._parameters[k] = self.setParameterValue(k)
             else:
                 pass
             if hasattr(self._parameters[k], "size") and self._parameters[k].size > 100:
-                logging.debug("%s %s d'une taille totale de %s", self._name, self.__required_parameters[k]["message"], self._parameters[k].size)
-            elif hasattr(self._parameters[k], "__len__") and len(self._parameters[k]) > 100:
-                logging.debug("%s %s de longueur %s", self._name, self.__required_parameters[k]["message"], len(self._parameters[k]))
+                logging.debug(
+                    "%s %s d'une taille totale de %s",
+                    self._name,
+                    self.__required_parameters[k]["message"],
+                    self._parameters[k].size,
+                )
+            elif (
+                hasattr(self._parameters[k], "__len__")
+                and len(self._parameters[k]) > 100
+            ):
+                logging.debug(
+                    "%s %s de longueur %s",
+                    self._name,
+                    self.__required_parameters[k]["message"],
+                    len(self._parameters[k]),
+                )
             else:
-                logging.debug("%s %s : %s", self._name, self.__required_parameters[k]["message"], self._parameters[k])
+                logging.debug(
+                    "%s %s : %s",
+                    self._name,
+                    self.__required_parameters[k]["message"],
+                    self._parameters[k],
+                )
 
     def _setInternalState(self, key=None, value=None, fromDico={}, reset=False):
         """
@@ -1256,7 +1739,7 @@ class Algorithm(object):
             self.__internal_state = {}
         if key is not None and value is not None:
             self.__internal_state[key] = value
-        self.__internal_state.update( dict(fromDico) )
+        self.__internal_state.update(dict(fromDico))
 
     def _getInternalState(self, key=None):
         """
@@ -1272,21 +1755,33 @@ class Algorithm(object):
         Initialise ou restitue le temps de calcul (cpu/elapsed) à la seconde
         """
         if reset:
-            self.__initial_cpu_time      = time.process_time()
-            self.__initial_elapsed_time  = time.perf_counter()
-            return 0., 0.
+            self.__initial_cpu_time = time.process_time()
+            self.__initial_elapsed_time = time.perf_counter()
+            return 0.0, 0.0
         else:
-            self.__cpu_time     = time.process_time() - self.__initial_cpu_time
+            self.__cpu_time = time.process_time() - self.__initial_cpu_time
             self.__elapsed_time = time.perf_counter() - self.__initial_elapsed_time
             return self.__cpu_time, self.__elapsed_time
 
     def _StopOnTimeLimit(self, X=None, withReason=False):
         "Stop criteria on time limit: True/False [+ Reason]"
         c, e = self._getTimeState()
-        if "MaximumCpuTime" in self._parameters and c > self._parameters["MaximumCpuTime"]:
-            __SC, __SR = True, "Reached maximum CPU time (%.1fs > %.1fs)"%(c, self._parameters["MaximumCpuTime"])
-        elif "MaximumElapsedTime" in self._parameters and e > self._parameters["MaximumElapsedTime"]:
-            __SC, __SR = True, "Reached maximum elapsed time (%.1fs > %.1fs)"%(e, self._parameters["MaximumElapsedTime"])
+        if (
+            "MaximumCpuTime" in self._parameters
+            and c > self._parameters["MaximumCpuTime"]
+        ):
+            __SC, __SR = True, "Reached maximum CPU time (%.1fs > %.1fs)" % (
+                c,
+                self._parameters["MaximumCpuTime"],
+            )
+        elif (
+            "MaximumElapsedTime" in self._parameters
+            and e > self._parameters["MaximumElapsedTime"]
+        ):
+            __SC, __SR = True, "Reached maximum elapsed time (%.1fs > %.1fs)" % (
+                e,
+                self._parameters["MaximumElapsedTime"],
+            )
         else:
             __SC, __SR = False, ""
         if withReason:
@@ -1294,6 +1789,7 @@ class Algorithm(object):
         else:
             return __SC
 
+
 # ==============================================================================
 class PartialAlgorithm(object):
     """
@@ -1301,21 +1797,35 @@ class PartialAlgorithm(object):
     action avancée comme la vérification . Pour les méthodes reprises ici,
     le fonctionnement est identique à celles de la classe "Algorithm".
     """
+
     __slots__ = (
-        "_name", "_parameters", "StoredVariables", "__canonical_stored_name",
+        "_name",
+        "_parameters",
+        "StoredVariables",
+        "__canonical_stored_name",
     )
 
     def __init__(self, name):
-        self._name = str( name )
+        self._name = str(name)
         self._parameters = {"StoreSupplementaryCalculations": []}
         #
         self.StoredVariables = {}
-        self.StoredVariables["Analysis"]                             = Persistence.OneVector(name = "Analysis")
-        self.StoredVariables["CostFunctionJ"]                        = Persistence.OneScalar(name = "CostFunctionJ")
-        self.StoredVariables["CostFunctionJb"]                       = Persistence.OneScalar(name = "CostFunctionJb")
-        self.StoredVariables["CostFunctionJo"]                       = Persistence.OneScalar(name = "CostFunctionJo")
-        self.StoredVariables["CurrentIterationNumber"]               = Persistence.OneIndex(name  = "CurrentIterationNumber")
-        self.StoredVariables["CurrentStepNumber"]                    = Persistence.OneIndex(name  = "CurrentStepNumber")
+        self.StoredVariables["Analysis"] = Persistence.OneVector(name="Analysis")
+        self.StoredVariables["CostFunctionJ"] = Persistence.OneScalar(
+            name="CostFunctionJ"
+        )
+        self.StoredVariables["CostFunctionJb"] = Persistence.OneScalar(
+            name="CostFunctionJb"
+        )
+        self.StoredVariables["CostFunctionJo"] = Persistence.OneScalar(
+            name="CostFunctionJo"
+        )
+        self.StoredVariables["CurrentIterationNumber"] = Persistence.OneIndex(
+            name="CurrentIterationNumber"
+        )
+        self.StoredVariables["CurrentStepNumber"] = Persistence.OneIndex(
+            name="CurrentStepNumber"
+        )
         #
         self.__canonical_stored_name = {}
         for k in self.StoredVariables:
@@ -1338,76 +1848,107 @@ class PartialAlgorithm(object):
         else:
             return self.StoredVariables
 
+
 # ==============================================================================
 class AlgorithmAndParameters(object):
     """
     Classe générale d'interface d'action pour l'algorithme et ses paramètres
     """
+
     __slots__ = (
-        "__name", "__algorithm", "__algorithmFile", "__algorithmName", "__A",
-        "__P", "__Xb", "__Y", "__U", "__HO", "__EM", "__CM", "__B", "__R",
-        "__Q", "__variable_names_not_public",
+        "__name",
+        "__algorithm",
+        "__algorithmFile",
+        "__algorithmName",
+        "__A",
+        "__P",
+        "__Xb",
+        "__Y",
+        "__U",
+        "__HO",
+        "__EM",
+        "__CM",
+        "__B",
+        "__R",
+        "__Q",
+        "__variable_names_not_public",
     )
 
-    def __init__(self,
-                 name               = "GenericAlgorithm",
-                 asAlgorithm        = None,
-                 asDict             = None,
-                 asScript           = None ):
-        """
-        """
-        self.__name       = str(name)
-        self.__A          = None
-        self.__P          = {}
+    def __init__(
+        self, name="GenericAlgorithm", asAlgorithm=None, asDict=None, asScript=None
+    ):
+        """ """
+        self.__name = str(name)
+        self.__A = None
+        self.__P = {}
         #
-        self.__algorithm         = {}
-        self.__algorithmFile     = None
-        self.__algorithmName     = None
+        self.__algorithm = {}
+        self.__algorithmFile = None
+        self.__algorithmName = None
         #
-        self.updateParameters( asDict, asScript )
+        self.updateParameters(asDict, asScript)
         #
         if asAlgorithm is None and asScript is not None:
-            __Algo = Interfaces.ImportFromScript(asScript).getvalue( "Algorithm" )
+            __Algo = Interfaces.ImportFromScript(asScript).getvalue("Algorithm")
         else:
             __Algo = asAlgorithm
         #
         if __Algo is not None:
             self.__A = str(__Algo)
-            self.__P.update( {"Algorithm": self.__A} )
+            self.__P.update({"Algorithm": self.__A})
         #
-        self.__setAlgorithm( self.__A )
+        self.__setAlgorithm(self.__A)
         #
-        self.__variable_names_not_public = {"nextStep": False}  # Duplication dans Algorithm
+        self.__variable_names_not_public = {
+            "nextStep": False
+        }  # Duplication dans Algorithm
 
-    def updateParameters(self, asDict = None, asScript = None ):
+    def updateParameters(self, asDict=None, asScript=None):
         "Mise à jour des paramètres"
         if asDict is None and asScript is not None:
-            __Dict = Interfaces.ImportFromScript(asScript).getvalue( self.__name, "Parameters" )
+            __Dict = Interfaces.ImportFromScript(asScript).getvalue(
+                self.__name, "Parameters"
+            )
         else:
             __Dict = asDict
         #
         if __Dict is not None:
-            self.__P.update( dict(__Dict) )
+            self.__P.update(dict(__Dict))
 
-    def executePythonScheme(self, asDictAO = None):
+    def executePythonScheme(self, asDictAO=None):
         "Permet de lancer le calcul d'assimilation"
         Operator.CM.clearCache()
         #
         if not isinstance(asDictAO, dict):
-            raise ValueError("The objects for algorithm calculation have to be given together as a dictionnary, and they are not")
-        if hasattr(asDictAO["Background"], "getO"):          self.__Xb = asDictAO["Background"].getO()           # noqa: E241,E701
-        elif hasattr(asDictAO["CheckingPoint"], "getO"):     self.__Xb = asDictAO["CheckingPoint"].getO()        # noqa: E241,E701
-        else:                                                self.__Xb = None                                    # noqa: E241,E701
-        if hasattr(asDictAO["Observation"], "getO"):         self.__Y  = asDictAO["Observation"].getO()          # noqa: E241,E701
-        else:                                                self.__Y  = asDictAO["Observation"]                 # noqa: E241,E701
-        if hasattr(asDictAO["ControlInput"], "getO"):        self.__U  = asDictAO["ControlInput"].getO()         # noqa: E241,E701
-        else:                                                self.__U  = asDictAO["ControlInput"]                # noqa: E241,E701
-        if hasattr(asDictAO["ObservationOperator"], "getO"): self.__HO = asDictAO["ObservationOperator"].getO()  # noqa: E241,E701
-        else:                                                self.__HO = asDictAO["ObservationOperator"]         # noqa: E241,E701
-        if hasattr(asDictAO["EvolutionModel"], "getO"):      self.__EM = asDictAO["EvolutionModel"].getO()       # noqa: E241,E701
-        else:                                                self.__EM = asDictAO["EvolutionModel"]              # noqa: E241,E701
-        if hasattr(asDictAO["ControlModel"], "getO"):        self.__CM = asDictAO["ControlModel"].getO()         # noqa: E241,E701
-        else:                                                self.__CM = asDictAO["ControlModel"]                # noqa: E241,E701
+            raise ValueError(
+                "The objects for algorithm calculation have to be given together as a dictionnary, and they are not"
+            )
+        if hasattr(asDictAO["Background"], "getO"):
+            self.__Xb = asDictAO["Background"].getO()
+        elif hasattr(asDictAO["CheckingPoint"], "getO"):
+            self.__Xb = asDictAO["CheckingPoint"].getO()
+        else:
+            self.__Xb = None
+        if hasattr(asDictAO["Observation"], "getO"):
+            self.__Y = asDictAO["Observation"].getO()
+        else:
+            self.__Y = asDictAO["Observation"]
+        if hasattr(asDictAO["ControlInput"], "getO"):
+            self.__U = asDictAO["ControlInput"].getO()
+        else:
+            self.__U = asDictAO["ControlInput"]
+        if hasattr(asDictAO["ObservationOperator"], "getO"):
+            self.__HO = asDictAO["ObservationOperator"].getO()
+        else:
+            self.__HO = asDictAO["ObservationOperator"]
+        if hasattr(asDictAO["EvolutionModel"], "getO"):
+            self.__EM = asDictAO["EvolutionModel"].getO()
+        else:
+            self.__EM = asDictAO["EvolutionModel"]
+        if hasattr(asDictAO["ControlModel"], "getO"):
+            self.__CM = asDictAO["ControlModel"].getO()
+        else:
+            self.__CM = asDictAO["ControlModel"]
         self.__B = asDictAO["BackgroundError"]
         self.__R = asDictAO["ObservationError"]
         self.__Q = asDictAO["EvolutionError"]
@@ -1415,16 +1956,16 @@ class AlgorithmAndParameters(object):
         self.__shape_validate()
         #
         self.__algorithm.run(
-            Xb         = self.__Xb,
-            Y          = self.__Y,
-            U          = self.__U,
-            HO         = self.__HO,
-            EM         = self.__EM,
-            CM         = self.__CM,
-            R          = self.__R,
-            B          = self.__B,
-            Q          = self.__Q,
-            Parameters = self.__P,
+            Xb=self.__Xb,
+            Y=self.__Y,
+            U=self.__U,
+            HO=self.__HO,
+            EM=self.__EM,
+            CM=self.__CM,
+            R=self.__R,
+            B=self.__B,
+            Q=self.__Q,
+            Parameters=self.__P,
         )
         return 0
 
@@ -1433,19 +1974,23 @@ class AlgorithmAndParameters(object):
         if FileName is None or not os.path.exists(FileName):
             raise ValueError("a YACS file name has to be given for YACS execution.\n")
         else:
-            __file    = os.path.abspath(FileName)
-            logging.debug("The YACS file name is \"%s\"."%__file)
-        if not PlatformInfo.has_salome or \
-                not PlatformInfo.has_yacs or \
-                not PlatformInfo.has_adao:
+            __file = os.path.abspath(FileName)
+            logging.debug('The YACS file name is "%s".' % __file)
+        if (
+            not PlatformInfo.has_salome
+            or not PlatformInfo.has_yacs
+            or not PlatformInfo.has_adao
+        ):
             raise ImportError(
-                "\n\n" + \
-                "Unable to get SALOME, YACS or ADAO environnement variables.\n" + \
-                "Please load the right environnement before trying to use it.\n" )
+                "\n\n"
+                + "Unable to get SALOME, YACS or ADAO environnement variables.\n"
+                + "Please load the right environnement before trying to use it.\n"
+            )
         #
         import pilot
         import SALOMERuntime
         import loader
+
         SALOMERuntime.RuntimeSALOME_setRuntime()
 
         r = pilot.getRuntime()
@@ -1460,7 +2005,7 @@ class AlgorithmAndParameters(object):
         try:
             p = xmlLoader.load(__file)
         except IOError as ex:
-            print("The YACS XML schema file can not be loaded: %s"%(ex,))
+            print("The YACS XML schema file can not be loaded: %s" % (ex,))
 
         logger = p.getLogger("parser")
         if not logger.isEmpty():
@@ -1484,10 +2029,10 @@ class AlgorithmAndParameters(object):
         #
         return 0
 
-    def get(self, key = None):
+    def get(self, key=None):
         "Vérifie l'existence d'une clé de variable ou de paramètres"
         if key in self.__algorithm:
-            return self.__algorithm.get( key )
+            return self.__algorithm.get(key)
         elif key in self.__P:
             return self.__P[key]
         else:
@@ -1514,50 +2059,84 @@ class AlgorithmAndParameters(object):
 
     def setObserver(self, __V, __O, __I, __A, __S):
         "Associe un observer à une variable unique"
-        if self.__algorithm is None \
-                or isinstance(self.__algorithm, dict) \
-                or not hasattr(self.__algorithm, "StoredVariables"):
+        if (
+            self.__algorithm is None
+            or isinstance(self.__algorithm, dict)
+            or not hasattr(self.__algorithm, "StoredVariables")
+        ):
             raise ValueError("No observer can be build before choosing an algorithm.")
         if __V not in self.__algorithm:
-            raise ValueError("An observer requires to be set on a variable named %s which does not exist."%__V)
+            raise ValueError(
+                "An observer requires to be set on a variable named %s which does not exist."
+                % __V
+            )
         else:
-            self.__algorithm.StoredVariables[ __V ].setDataObserver( HookFunction = __O, HookParameters = __I, Scheduler = __S )
+            self.__algorithm.StoredVariables[__V].setDataObserver(
+                HookFunction=__O, HookParameters=__I, Scheduler=__S
+            )
 
     def setCrossObserver(self, __V, __O, __I, __A, __S):
         "Associe un observer à une collection ordonnée de variables"
-        if self.__algorithm is None \
-                or isinstance(self.__algorithm, dict) \
-                or not hasattr(self.__algorithm, "StoredVariables"):
+        if (
+            self.__algorithm is None
+            or isinstance(self.__algorithm, dict)
+            or not hasattr(self.__algorithm, "StoredVariables")
+        ):
             raise ValueError("No observer can be build before choosing an algorithm.")
         if not isinstance(__V, (list, tuple)):
-            raise ValueError("A cross observer requires to be set on a variable series which is not the case of %s."%__V)
+            raise ValueError(
+                "A cross observer requires to be set on a variable series which"
+                + " is not the case of %s." % __V
+            )
         if len(__V) != len(__I):
-            raise ValueError("The number of information fields has to be the same than the number of variables on which to set the observer.")
+            raise ValueError(
+                "The number of information fields has to be the same than the"
+                + " number of variables on which to set the observer."
+            )
         #
         for __eV in __V:
             if __eV not in self.__algorithm:
-                raise ValueError("An observer requires to be set on a variable named %s which does not exist."%__eV)
+                raise ValueError(
+                    "An observer requires to be set on a variable named %s which does not exist."
+                    % __eV
+                )
             else:
-                self.__algorithm.StoredVariables[ __eV ].setDataObserver( HookFunction = __O, HookParameters = __I, Scheduler = __S, Order = __V, OSync = __A, DOVar = self.__algorithm.StoredVariables )
-
-    def removeObserver(self, __V, __O, __A = False):
-        if self.__algorithm is None \
-                or isinstance(self.__algorithm, dict) \
-                or not hasattr(self.__algorithm, "StoredVariables"):
+                self.__algorithm.StoredVariables[__eV].setDataObserver(
+                    HookFunction=__O,
+                    HookParameters=__I,
+                    Scheduler=__S,
+                    Order=__V,
+                    OSync=__A,
+                    DOVar=self.__algorithm.StoredVariables,
+                )
+
+    def removeObserver(self, __V, __O, __A=False):
+        if (
+            self.__algorithm is None
+            or isinstance(self.__algorithm, dict)
+            or not hasattr(self.__algorithm, "StoredVariables")
+        ):
             raise ValueError("No observer can be removed before choosing an algorithm.")
         if __V not in self.__algorithm:
-            raise ValueError("An observer requires to be removed on a variable named %s which does not exist."%__V)
+            raise ValueError(
+                "An observer requires to be removed on a variable named %s which does not exist."
+                % __V
+            )
         else:
-            return self.__algorithm.StoredVariables[ __V ].removeDataObserver( HookFunction = __O, AllObservers = __A )
+            return self.__algorithm.StoredVariables[__V].removeDataObserver(
+                HookFunction=__O, AllObservers=__A
+            )
 
     def hasObserver(self, __V):
-        if self.__algorithm is None \
-                or isinstance(self.__algorithm, dict) \
-                or not hasattr(self.__algorithm, "StoredVariables"):
+        if (
+            self.__algorithm is None
+            or isinstance(self.__algorithm, dict)
+            or not hasattr(self.__algorithm, "StoredVariables")
+        ):
             return False
         if __V not in self.__algorithm:
             return False
-        return self.__algorithm.StoredVariables[ __V ].hasDataObserver()
+        return self.__algorithm.StoredVariables[__V].hasDataObserver()
 
     def keys(self):
         __allvariables = list(self.__algorithm.keys()) + list(self.__P.keys())
@@ -1578,7 +2157,7 @@ class AlgorithmAndParameters(object):
         "x.__str__() <==> str(x)"
         return str(self.__A) + ", " + str(self.__P)
 
-    def __setAlgorithm(self, choice = None ):
+    def __setAlgorithm(self, choice=None):
         """
         Permet de sélectionner l'algorithme à utiliser pour mener à bien l'étude
         d'assimilation. L'argument est un champ caractère se rapportant au nom
@@ -1587,18 +2166,26 @@ class AlgorithmAndParameters(object):
         if choice is None:
             raise ValueError("Error: algorithm choice has to be given")
         if self.__algorithmName is not None:
-            raise ValueError("Error: algorithm choice has already been done as \"%s\", it can't be changed."%self.__algorithmName)
+            raise ValueError(
+                'Error: algorithm choice has already been done as "%s", it can\'t be changed.'
+                % self.__algorithmName
+            )
         daDirectory = "daAlgorithms"
         #
         # Recherche explicitement le fichier complet
         # ------------------------------------------
         module_path = None
         for directory in sys.path:
-            if os.path.isfile(os.path.join(directory, daDirectory, str(choice) + '.py')):
+            if os.path.isfile(
+                os.path.join(directory, daDirectory, str(choice) + ".py")
+            ):
                 module_path = os.path.abspath(os.path.join(directory, daDirectory))
         if module_path is None:
             raise ImportError(
-                "No algorithm module named \"%s\" has been found in the search path.\n             The search path is %s"%(choice, sys.path))
+                'No algorithm module named "%s" has been found in the search path.'
+                % choice
+                + "\n             The search path is %s" % sys.path
+            )
         #
         # Importe le fichier complet comme un module
         # ------------------------------------------
@@ -1607,13 +2194,18 @@ class AlgorithmAndParameters(object):
             sys.path.insert(0, module_path)
             self.__algorithmFile = __import__(str(choice), globals(), locals(), [])
             if not hasattr(self.__algorithmFile, "ElementaryAlgorithm"):
-                raise ImportError("this module does not define a valid elementary algorithm.")
+                raise ImportError(
+                    "this module does not define a valid elementary algorithm."
+                )
             self.__algorithmName = str(choice)
             sys.path = sys_path_tmp
             del sys_path_tmp
         except ImportError as e:
             raise ImportError(
-                "The module named \"%s\" was found, but is incorrect at the import stage.\n             The import error message is: %s"%(choice, e))
+                'The module named "%s" was found, but is incorrect at the import stage.'
+                % choice
+                + "\n             The import error message is: %s" % e
+            )
         #
         # Instancie un objet du type élémentaire du fichier
         # -------------------------------------------------
@@ -1625,232 +2217,394 @@ class AlgorithmAndParameters(object):
         Validation de la correspondance correcte des tailles des variables et
         des matrices s'il y en a.
         """
-        if self.__Xb is None:                      __Xb_shape = (0,)                                                # noqa: E241,E701
-        elif hasattr(self.__Xb, "size"):           __Xb_shape = (self.__Xb.size,)                                   # noqa: E241,E701
+        if self.__Xb is None:
+            __Xb_shape = (0,)
+        elif hasattr(self.__Xb, "size"):
+            __Xb_shape = (self.__Xb.size,)
         elif hasattr(self.__Xb, "shape"):
-            if isinstance(self.__Xb.shape, tuple): __Xb_shape = self.__Xb.shape                                     # noqa: E241,E701
-            else:                                  __Xb_shape = self.__Xb.shape()                                   # noqa: E241,E701
-        else: raise TypeError("The background (Xb) has no attribute of shape: problem !")                           # noqa: E701
+            if isinstance(self.__Xb.shape, tuple):
+                __Xb_shape = self.__Xb.shape
+            else:
+                __Xb_shape = self.__Xb.shape()
+        else:
+            raise TypeError("The background (Xb) has no attribute of shape: problem!")
         #
-        if self.__Y is None:                       __Y_shape = (0,)                                                 # noqa: E241,E701
-        elif hasattr(self.__Y, "size"):            __Y_shape = (self.__Y.size,)                                     # noqa: E241,E701
+        if self.__Y is None:
+            __Y_shape = (0,)
+        elif hasattr(self.__Y, "size"):
+            __Y_shape = (self.__Y.size,)
         elif hasattr(self.__Y, "shape"):
-            if isinstance(self.__Y.shape, tuple):  __Y_shape = self.__Y.shape                                       # noqa: E241,E701
-            else:                                  __Y_shape = self.__Y.shape()                                     # noqa: E241,E701
-        else: raise TypeError("The observation (Y) has no attribute of shape: problem !")                           # noqa: E701
+            if isinstance(self.__Y.shape, tuple):
+                __Y_shape = self.__Y.shape
+            else:
+                __Y_shape = self.__Y.shape()
+        else:
+            raise TypeError("The observation (Y) has no attribute of shape: problem!")
         #
-        if self.__U is None:                       __U_shape = (0,)                                                 # noqa: E241,E701
-        elif hasattr(self.__U, "size"):            __U_shape = (self.__U.size,)                                     # noqa: E241,E701
+        if self.__U is None:
+            __U_shape = (0,)
+        elif hasattr(self.__U, "size"):
+            __U_shape = (self.__U.size,)
         elif hasattr(self.__U, "shape"):
-            if isinstance(self.__U.shape, tuple):  __U_shape = self.__U.shape                                       # noqa: E241,E701
-            else:                                  __U_shape = self.__U.shape()                                     # noqa: E241,E701
-        else: raise TypeError("The control (U) has no attribute of shape: problem !")                               # noqa: E701
+            if isinstance(self.__U.shape, tuple):
+                __U_shape = self.__U.shape
+            else:
+                __U_shape = self.__U.shape()
+        else:
+            raise TypeError("The control (U) has no attribute of shape: problem!")
         #
-        if self.__B is None:                       __B_shape = (0, 0)                                               # noqa: E241,E701
+        if self.__B is None:
+            __B_shape = (0, 0)
         elif hasattr(self.__B, "shape"):
-            if isinstance(self.__B.shape, tuple):  __B_shape = self.__B.shape                                       # noqa: E241,E701
-            else:                                  __B_shape = self.__B.shape()                                     # noqa: E241,E701
-        else: raise TypeError("The a priori errors covariance matrix (B) has no attribute of shape: problem !")     # noqa: E701
+            if isinstance(self.__B.shape, tuple):
+                __B_shape = self.__B.shape
+            else:
+                __B_shape = self.__B.shape()
+        else:
+            raise TypeError(
+                "The a priori errors covariance matrix (B) has no attribute of shape: problem!"
+            )
         #
-        if self.__R is None:                       __R_shape = (0, 0)                                               # noqa: E241,E701
+        if self.__R is None:
+            __R_shape = (0, 0)
         elif hasattr(self.__R, "shape"):
-            if isinstance(self.__R.shape, tuple):  __R_shape = self.__R.shape                                       # noqa: E241,E701
-            else:                                  __R_shape = self.__R.shape()                                     # noqa: E241,E701
-        else: raise TypeError("The observation errors covariance matrix (R) has no attribute of shape: problem !")  # noqa: E701
+            if isinstance(self.__R.shape, tuple):
+                __R_shape = self.__R.shape
+            else:
+                __R_shape = self.__R.shape()
+        else:
+            raise TypeError(
+                "The observation errors covariance matrix (R) has no attribute of shape: problem!"
+            )
         #
-        if self.__Q is None:                       __Q_shape = (0, 0)                                               # noqa: E241,E701
+        if self.__Q is None:
+            __Q_shape = (0, 0)
         elif hasattr(self.__Q, "shape"):
-            if isinstance(self.__Q.shape, tuple):  __Q_shape = self.__Q.shape                                       # noqa: E241,E701
-            else:                                  __Q_shape = self.__Q.shape()                                     # noqa: E241,E701
-        else: raise TypeError("The evolution errors covariance matrix (Q) has no attribute of shape: problem !")    # noqa: E701
+            if isinstance(self.__Q.shape, tuple):
+                __Q_shape = self.__Q.shape
+            else:
+                __Q_shape = self.__Q.shape()
+        else:
+            raise TypeError(
+                "The evolution errors covariance matrix (Q) has no attribute of shape: problem!"
+            )
         #
-        if len(self.__HO) == 0:                              __HO_shape = (0, 0)                                    # noqa: E241,E701
-        elif isinstance(self.__HO, dict):                    __HO_shape = (0, 0)                                    # noqa: E241,E701
+        if len(self.__HO) == 0:
+            __HO_shape = (0, 0)
+        elif isinstance(self.__HO, dict):
+            __HO_shape = (0, 0)
         elif hasattr(self.__HO["Direct"], "shape"):
-            if isinstance(self.__HO["Direct"].shape, tuple): __HO_shape = self.__HO["Direct"].shape                 # noqa: E241,E701
-            else:                                            __HO_shape = self.__HO["Direct"].shape()               # noqa: E241,E701
-        else: raise TypeError("The observation operator (H) has no attribute of shape: problem !")                  # noqa: E701
+            if isinstance(self.__HO["Direct"].shape, tuple):
+                __HO_shape = self.__HO["Direct"].shape
+            else:
+                __HO_shape = self.__HO["Direct"].shape()
+        else:
+            raise TypeError(
+                "The observation operator (H) has no attribute of shape: problem!"
+            )
         #
-        if len(self.__EM) == 0:                              __EM_shape = (0, 0)                                    # noqa: E241,E701
-        elif isinstance(self.__EM, dict):                    __EM_shape = (0, 0)                                    # noqa: E241,E701
+        if len(self.__EM) == 0:
+            __EM_shape = (0, 0)
+        elif isinstance(self.__EM, dict):
+            __EM_shape = (0, 0)
         elif hasattr(self.__EM["Direct"], "shape"):
-            if isinstance(self.__EM["Direct"].shape, tuple): __EM_shape = self.__EM["Direct"].shape                 # noqa: E241,E701
-            else:                                            __EM_shape = self.__EM["Direct"].shape()               # noqa: E241,E701
-        else: raise TypeError("The evolution model (EM) has no attribute of shape: problem !")                      # noqa: E241,E70
+            if isinstance(self.__EM["Direct"].shape, tuple):
+                __EM_shape = self.__EM["Direct"].shape
+            else:
+                __EM_shape = self.__EM["Direct"].shape()
+        else:
+            raise TypeError(
+                "The evolution model (EM) has no attribute of shape: problem!"
+            )
         #
-        if len(self.__CM) == 0:                              __CM_shape = (0, 0)                                    # noqa: E241,E701
-        elif isinstance(self.__CM, dict):                    __CM_shape = (0, 0)                                    # noqa: E241,E701
+        if len(self.__CM) == 0:
+            __CM_shape = (0, 0)
+        elif isinstance(self.__CM, dict):
+            __CM_shape = (0, 0)
         elif hasattr(self.__CM["Direct"], "shape"):
-            if isinstance(self.__CM["Direct"].shape, tuple): __CM_shape = self.__CM["Direct"].shape                 # noqa: E241,E701
-            else:                                            __CM_shape = self.__CM["Direct"].shape()               # noqa: E241,E701
-        else: raise TypeError("The control model (CM) has no attribute of shape: problem !")                        # noqa: E701
+            if isinstance(self.__CM["Direct"].shape, tuple):
+                __CM_shape = self.__CM["Direct"].shape
+            else:
+                __CM_shape = self.__CM["Direct"].shape()
+        else:
+            raise TypeError(
+                "The control model (CM) has no attribute of shape: problem!"
+            )
         #
         # Vérification des conditions
         # ---------------------------
-        if not ( len(__Xb_shape) == 1 or min(__Xb_shape) == 1 ):
-            raise ValueError("Shape characteristic of background (Xb) is incorrect: \"%s\"."%(__Xb_shape,))
-        if not ( len(__Y_shape) == 1 or min(__Y_shape) == 1 ):
-            raise ValueError("Shape characteristic of observation (Y) is incorrect: \"%s\"."%(__Y_shape,))
-        #
-        if not ( min(__B_shape) == max(__B_shape) ):
-            raise ValueError("Shape characteristic of a priori errors covariance matrix (B) is incorrect: \"%s\"."%(__B_shape,))
-        if not ( min(__R_shape) == max(__R_shape) ):
-            raise ValueError("Shape characteristic of observation errors covariance matrix (R) is incorrect: \"%s\"."%(__R_shape,))
-        if not ( min(__Q_shape) == max(__Q_shape) ):
-            raise ValueError("Shape characteristic of evolution errors covariance matrix (Q) is incorrect: \"%s\"."%(__Q_shape,))
-        if not ( min(__EM_shape) == max(__EM_shape) ):
-            raise ValueError("Shape characteristic of evolution operator (EM) is incorrect: \"%s\"."%(__EM_shape,))
-        #
-        if len(self.__HO) > 0 and not isinstance(self.__HO, dict) and not ( __HO_shape[1] == max(__Xb_shape) ):
+        if not (len(__Xb_shape) == 1 or min(__Xb_shape) == 1):
             raise ValueError(
-                "Shape characteristic of observation operator (H)" + \
-                " \"%s\" and state (X) \"%s\" are incompatible."%(__HO_shape, __Xb_shape))
-        if len(self.__HO) > 0 and not isinstance(self.__HO, dict) and not ( __HO_shape[0] == max(__Y_shape) ):
+                'Shape characteristic of background (Xb) is incorrect: "%s".'
+                % (__Xb_shape,)
+            )
+        if not (len(__Y_shape) == 1 or min(__Y_shape) == 1):
+            raise ValueError(
+                'Shape characteristic of observation (Y) is incorrect: "%s".'
+                % (__Y_shape,)
+            )
+        #
+        if not (min(__B_shape) == max(__B_shape)):
             raise ValueError(
-                "Shape characteristic of observation operator (H)" + \
-                " \"%s\" and observation (Y) \"%s\" are incompatible."%(__HO_shape, __Y_shape))
-        if len(self.__HO) > 0 and not isinstance(self.__HO, dict) and len(self.__B) > 0 and not ( __HO_shape[1] == __B_shape[0] ):
+                'Shape characteristic of a priori errors covariance matrix (B) is incorrect: "%s".'
+                % (__B_shape,)
+            )
+        if not (min(__R_shape) == max(__R_shape)):
             raise ValueError(
-                "Shape characteristic of observation operator (H)" + \
-                " \"%s\" and a priori errors covariance matrix (B) \"%s\" are incompatible."%(__HO_shape, __B_shape))
-        if len(self.__HO) > 0 and not isinstance(self.__HO, dict) and len(self.__R) > 0 and not ( __HO_shape[0] == __R_shape[1] ):
+                'Shape characteristic of observation errors covariance matrix (R) is incorrect: "%s".'
+                % (__R_shape,)
+            )
+        if not (min(__Q_shape) == max(__Q_shape)):
             raise ValueError(
-                "Shape characteristic of observation operator (H)" + \
-                " \"%s\" and observation errors covariance matrix (R) \"%s\" are incompatible."%(__HO_shape, __R_shape))
+                'Shape characteristic of evolution errors covariance matrix (Q) is incorrect: "%s".'
+                % (__Q_shape,)
+            )
+        if not (min(__EM_shape) == max(__EM_shape)):
+            raise ValueError(
+                'Shape characteristic of evolution operator (EM) is incorrect: "%s".'
+                % (__EM_shape,)
+            )
+        #
+        if (
+            len(self.__HO) > 0
+            and not isinstance(self.__HO, dict)
+            and not (__HO_shape[1] == max(__Xb_shape))
+        ):
+            raise ValueError(
+                "Shape characteristic of observation operator (H)"
+                + ' "%s" and state (X) "%s" are incompatible.'
+                % (__HO_shape, __Xb_shape)
+            )
+        if (
+            len(self.__HO) > 0
+            and not isinstance(self.__HO, dict)
+            and not (__HO_shape[0] == max(__Y_shape))
+        ):
+            raise ValueError(
+                "Shape characteristic of observation operator (H)"
+                + ' "%s" and observation (Y) "%s" are incompatible.'
+                % (__HO_shape, __Y_shape)
+            )
+        if (
+            len(self.__HO) > 0
+            and not isinstance(self.__HO, dict)
+            and len(self.__B) > 0
+            and not (__HO_shape[1] == __B_shape[0])
+        ):
+            raise ValueError(
+                "Shape characteristic of observation operator (H)"
+                + ' "%s" and a priori errors covariance matrix (B) "%s" are incompatible.'
+                % (__HO_shape, __B_shape)
+            )
+        if (
+            len(self.__HO) > 0
+            and not isinstance(self.__HO, dict)
+            and len(self.__R) > 0
+            and not (__HO_shape[0] == __R_shape[1])
+        ):
+            raise ValueError(
+                "Shape characteristic of observation operator (H)"
+                + ' "%s" and observation errors covariance matrix (R) "%s" are incompatible.'
+                % (__HO_shape, __R_shape)
+            )
         #
-        if self.__B is not None and len(self.__B) > 0 and not ( __B_shape[1] == max(__Xb_shape) ):
-            if self.__algorithmName in ["EnsembleBlue",]:
+        if (
+            self.__B is not None
+            and len(self.__B) > 0
+            and not (__B_shape[1] == max(__Xb_shape))
+        ):
+            if self.__algorithmName in [
+                "EnsembleBlue",
+            ]:
                 asPersistentVector = self.__Xb.reshape((-1, min(__B_shape)))
                 self.__Xb = Persistence.OneVector("Background")
                 for member in asPersistentVector:
-                    self.__Xb.store( numpy.asarray(member, dtype=float) )
+                    self.__Xb.store(numpy.asarray(member, dtype=float))
                 __Xb_shape = min(__B_shape)
             else:
                 raise ValueError(
-                    "Shape characteristic of a priori errors covariance matrix (B)" + \
-                    " \"%s\" and background vector (Xb) \"%s\" are incompatible."%(__B_shape, __Xb_shape))
-        #
-        if self.__R is not None and len(self.__R) > 0 and not ( __R_shape[1] == max(__Y_shape) ):
+                    "Shape characteristic of a priori errors covariance matrix (B)"
+                    + ' "%s" and background vector (Xb) "%s" are incompatible.'
+                    % (__B_shape, __Xb_shape)
+                )
+        #
+        if (
+            self.__R is not None
+            and len(self.__R) > 0
+            and not (__R_shape[1] == max(__Y_shape))
+        ):
             raise ValueError(
-                "Shape characteristic of observation errors covariance matrix (R)" + \
-                " \"%s\" and observation vector (Y) \"%s\" are incompatible."%(__R_shape, __Y_shape))
+                "Shape characteristic of observation errors covariance matrix (R)"
+                + ' "%s" and observation vector (Y) "%s" are incompatible.'
+                % (__R_shape, __Y_shape)
+            )
         #
-        if self.__EM is not None and len(self.__EM) > 0 and not isinstance(self.__EM, dict) and not ( __EM_shape[1] == max(__Xb_shape) ):
+        if (
+            self.__EM is not None
+            and len(self.__EM) > 0
+            and not isinstance(self.__EM, dict)
+            and not (__EM_shape[1] == max(__Xb_shape))
+        ):
             raise ValueError(
-                "Shape characteristic of evolution model (EM)" + \
-                " \"%s\" and state (X) \"%s\" are incompatible."%(__EM_shape, __Xb_shape))
+                "Shape characteristic of evolution model (EM)"
+                + ' "%s" and state (X) "%s" are incompatible.'
+                % (__EM_shape, __Xb_shape)
+            )
         #
-        if self.__CM is not None and len(self.__CM) > 0 and not isinstance(self.__CM, dict) and not ( __CM_shape[1] == max(__U_shape) ):
+        if (
+            self.__CM is not None
+            and len(self.__CM) > 0
+            and not isinstance(self.__CM, dict)
+            and not (__CM_shape[1] == max(__U_shape))
+        ):
             raise ValueError(
-                "Shape characteristic of control model (CM)" + \
-                " \"%s\" and control (U) \"%s\" are incompatible."%(__CM_shape, __U_shape))
+                "Shape characteristic of control model (CM)"
+                + ' "%s" and control (U) "%s" are incompatible.'
+                % (__CM_shape, __U_shape)
+            )
         #
-        if ("Bounds" in self.__P) \
-                and isinstance(self.__P["Bounds"], (list, tuple)) \
-                and (len(self.__P["Bounds"]) != max(__Xb_shape)):
+        if (
+            ("Bounds" in self.__P)
+            and isinstance(self.__P["Bounds"], (list, tuple))
+            and (len(self.__P["Bounds"]) != max(__Xb_shape))
+        ):
             if len(self.__P["Bounds"]) > 0:
-                raise ValueError("The number '%s' of bound pairs for the state components is different from the size '%s' of the state (X) itself." \
-                                 % (len(self.__P["Bounds"]), max(__Xb_shape)))
+                raise ValueError(
+                    "The number '%s' of bound pairs for the state components"
+                    % len(self.__P["Bounds"])
+                    + " is different from the size '%s' of the state (X) itself."
+                    % max(__Xb_shape)
+                )
             else:
                 self.__P["Bounds"] = None
-        if ("Bounds" in self.__P) \
-                and isinstance(self.__P["Bounds"], (numpy.ndarray, numpy.matrix)) \
-                and (self.__P["Bounds"].shape[0] != max(__Xb_shape)):
+        if (
+            ("Bounds" in self.__P)
+            and isinstance(self.__P["Bounds"], (numpy.ndarray, numpy.matrix))
+            and (self.__P["Bounds"].shape[0] != max(__Xb_shape))
+        ):
             if self.__P["Bounds"].size > 0:
-                raise ValueError("The number '%s' of bound pairs for the state components is different from the size '%s' of the state (X) itself." \
-                                 % (self.__P["Bounds"].shape[0], max(__Xb_shape)))
+                raise ValueError(
+                    "The number '%s' of bound pairs for the state components"
+                    % self.__P["Bounds"].shape[0]
+                    + " is different from the size '%s' of the state (X) itself."
+                    % max(__Xb_shape)
+                )
             else:
                 self.__P["Bounds"] = None
         #
-        if ("BoxBounds" in self.__P) \
-                and isinstance(self.__P["BoxBounds"], (list, tuple)) \
-                and (len(self.__P["BoxBounds"]) != max(__Xb_shape)):
-            raise ValueError("The number '%s' of bound pairs for the state box components is different from the size '%s' of the state (X) itself." \
-                             % (len(self.__P["BoxBounds"]), max(__Xb_shape)))
-        if ("BoxBounds" in self.__P) \
-                and isinstance(self.__P["BoxBounds"], (numpy.ndarray, numpy.matrix)) \
-                and (self.__P["BoxBounds"].shape[0] != max(__Xb_shape)):
-            raise ValueError("The number '%s' of bound pairs for the state box components is different from the size '%s' of the state (X) itself." \
-                             % (self.__P["BoxBounds"].shape[0], max(__Xb_shape)))
-        #
-        if ("StateBoundsForQuantiles" in self.__P) \
-                and isinstance(self.__P["StateBoundsForQuantiles"], (list, tuple)) \
-                and (len(self.__P["StateBoundsForQuantiles"]) != max(__Xb_shape)):
-            raise ValueError("The number '%s' of bound pairs for the quantile state components is different from the size '%s' of the state (X) itself." \
-                             % (len(self.__P["StateBoundsForQuantiles"]), max(__Xb_shape)))
+        if (
+            ("BoxBounds" in self.__P)
+            and isinstance(self.__P["BoxBounds"], (list, tuple))
+            and (len(self.__P["BoxBounds"]) != max(__Xb_shape))
+        ):
+            raise ValueError(
+                "The number '%s' of bound pairs for the state box components"
+                % len(self.__P["BoxBounds"])
+                + " is different from the size '%s' of the state (X) itself."
+                % max(__Xb_shape)
+            )
+        if (
+            ("BoxBounds" in self.__P)
+            and isinstance(self.__P["BoxBounds"], (numpy.ndarray, numpy.matrix))
+            and (self.__P["BoxBounds"].shape[0] != max(__Xb_shape))
+        ):
+            raise ValueError(
+                "The number '%s' of bound pairs for the state box components"
+                % self.__P["BoxBounds"].shape[0]
+                + " is different from the size '%s' of the state (X) itself."
+                % max(__Xb_shape)
+            )
+        #
+        if (
+            ("StateBoundsForQuantiles" in self.__P)
+            and isinstance(self.__P["StateBoundsForQuantiles"], (list, tuple))
+            and (len(self.__P["StateBoundsForQuantiles"]) != max(__Xb_shape))
+        ):
+            raise ValueError(
+                "The number '%s' of bound pairs for the quantile state components"
+                % len(self.__P["StateBoundsForQuantiles"])
+                + " is different from the size '%s' of the state (X) itself."
+                % max(__Xb_shape)
+            )
         #
         return 1
 
+
 # ==============================================================================
 class RegulationAndParameters(object):
     """
     Classe générale d'interface d'action pour la régulation et ses paramètres
     """
+
     __slots__ = ("__name", "__P")
 
-    def __init__(self,
-                 name        = "GenericRegulation",
-                 asAlgorithm = None,
-                 asDict      = None,
-                 asScript    = None ):
-        """
-        """
-        self.__name       = str(name)
-        self.__P          = {}
+    def __init__(
+        self, name="GenericRegulation", asAlgorithm=None, asDict=None, asScript=None
+    ):
+        """ """
+        self.__name = str(name)
+        self.__P = {}
         #
         if asAlgorithm is None and asScript is not None:
-            __Algo = Interfaces.ImportFromScript(asScript).getvalue( "Algorithm" )
+            __Algo = Interfaces.ImportFromScript(asScript).getvalue("Algorithm")
         else:
             __Algo = asAlgorithm
         #
         if asDict is None and asScript is not None:
-            __Dict = Interfaces.ImportFromScript(asScript).getvalue( self.__name, "Parameters" )
+            __Dict = Interfaces.ImportFromScript(asScript).getvalue(
+                self.__name, "Parameters"
+            )
         else:
             __Dict = asDict
         #
         if __Dict is not None:
-            self.__P.update( dict(__Dict) )
+            self.__P.update(dict(__Dict))
         #
         if __Algo is not None:
-            self.__P.update( {"Algorithm": str(__Algo)} )
+            self.__P.update({"Algorithm": str(__Algo)})
 
-    def get(self, key = None):
+    def get(self, key=None):
         "Vérifie l'existence d'une clé de variable ou de paramètres"
         if key in self.__P:
             return self.__P[key]
         else:
             return self.__P
 
+
 # ==============================================================================
 class DataObserver(object):
     """
     Classe générale d'interface de type observer
     """
+
     __slots__ = ("__name", "__V", "__O", "__I")
 
-    def __init__(self,
-                 name        = "GenericObserver",
-                 onVariable  = None,
-                 asTemplate  = None,
-                 asString    = None,
-                 asScript    = None,
-                 asObsObject = None,
-                 withInfo    = None,
-                 crossObs    = False,
-                 syncObs     = True,
-                 scheduledBy = None,
-                 withAlgo    = None ):
-        """
-        """
-        self.__name       = str(name)
-        self.__V          = None
-        self.__O          = None
-        self.__I          = None
+    def __init__(
+        self,
+        name="GenericObserver",
+        onVariable=None,
+        asTemplate=None,
+        asString=None,
+        asScript=None,
+        asObsObject=None,
+        withInfo=None,
+        crossObs=False,
+        syncObs=True,
+        scheduledBy=None,
+        withAlgo=None,
+    ):
+        """ """
+        self.__name = str(name)
+        self.__V = None
+        self.__O = None
+        self.__I = None
         #
         if onVariable is None:
-            raise ValueError("setting an observer has to be done over a variable name or a list of variable names, not over None.")
+            raise ValueError(
+                "setting an observer has to be done over a variable name or a list of variable names, not over None."
+            )
         elif isinstance(onVariable, (tuple, list)):
-            self.__V = tuple(map( str, onVariable ))
+            self.__V = tuple(map(str, onVariable))
             if withInfo is None:
                 self.__I = self.__V
             elif crossObs or isinstance(withInfo, (tuple, list)):
@@ -1864,24 +2618,33 @@ class DataObserver(object):
             else:
                 self.__I = (str(withInfo),)
         else:
-            raise ValueError("setting an observer has to be done over a variable name or a list of variable names.")
+            raise ValueError(
+                "setting an observer has to be done over a variable name or a list of variable names."
+            )
         #
         if asObsObject is not None:
             self.__O = asObsObject
         else:
-            __FunctionText = str(UserScript('Observer', asTemplate, asString, asScript))
+            __FunctionText = str(UserScript("Observer", asTemplate, asString, asScript))
             __Function = Observer2Func(__FunctionText)
             self.__O = __Function.getfunc()
         #
         for k in range(len(self.__V)):
             if self.__V[k] not in withAlgo:
-                raise ValueError("An observer is asked to be set on a variable named %s which does not exist."%self.__V[k])
+                raise ValueError(
+                    "An observer is asked to be set on a variable named %s which does not exist."
+                    % self.__V[k]
+                )
         #
         if bool(crossObs):
-            withAlgo.setCrossObserver(self.__V, self.__O, self.__I, syncObs, scheduledBy)
+            withAlgo.setCrossObserver(
+                self.__V, self.__O, self.__I, syncObs, scheduledBy
+            )
         else:
             for k in range(len(self.__V)):
-                withAlgo.setObserver(self.__V[k], self.__O, self.__I[k], syncObs, scheduledBy)
+                withAlgo.setObserver(
+                    self.__V[k], self.__O, self.__I[k], syncObs, scheduledBy
+                )
 
     def __repr__(self):
         "x.__repr__() <==> repr(x)"
@@ -1891,27 +2654,34 @@ class DataObserver(object):
         "x.__str__() <==> str(x)"
         return str(self.__V) + "\n" + str(self.__O)
 
+
 # ==============================================================================
 class UserScript(object):
     """
     Classe générale d'interface de type texte de script utilisateur
     """
+
     __slots__ = ("__name", "__F")
 
-    def __init__(self,
-                 name       = "GenericUserScript",
-                 asTemplate = None,
-                 asString   = None,
-                 asScript   = None ):
-        """
-        """
-        self.__name       = str(name)
+    def __init__(
+        self, name="GenericUserScript", asTemplate=None, asString=None, asScript=None
+    ):
+        """ """
+        self.__name = str(name)
         #
         if asString is not None:
             self.__F = asString
-        elif self.__name == "UserPostAnalysis" and (asTemplate is not None) and (asTemplate in Templates.UserPostAnalysisTemplates):
+        elif (
+            self.__name == "UserPostAnalysis"
+            and (asTemplate is not None)
+            and (asTemplate in Templates.UserPostAnalysisTemplates)
+        ):
             self.__F = Templates.UserPostAnalysisTemplates[asTemplate]
-        elif self.__name == "Observer" and (asTemplate is not None) and (asTemplate in Templates.ObserverTemplates):
+        elif (
+            self.__name == "Observer"
+            and (asTemplate is not None)
+            and (asTemplate in Templates.ObserverTemplates)
+        ):
             self.__F = Templates.ObserverTemplates[asTemplate]
         elif asScript is not None:
             self.__F = Interfaces.ImportFromScript(asScript).getstring()
@@ -1926,35 +2696,35 @@ class UserScript(object):
         "x.__str__() <==> str(x)"
         return str(self.__F)
 
+
 # ==============================================================================
 class ExternalParameters(object):
     """
     Classe générale d'interface pour le stockage des paramètres externes
     """
+
     __slots__ = ("__name", "__P")
 
-    def __init__(self,
-                 name     = "GenericExternalParameters",
-                 asDict   = None,
-                 asScript = None ):
-        """
-        """
+    def __init__(self, name="GenericExternalParameters", asDict=None, asScript=None):
+        """ """
         self.__name = str(name)
-        self.__P    = {}
+        self.__P = {}
         #
-        self.updateParameters( asDict, asScript )
+        self.updateParameters(asDict, asScript)
 
-    def updateParameters(self, asDict = None, asScript = None ):
+    def updateParameters(self, asDict=None, asScript=None):
         "Mise à jour des paramètres"
         if asDict is None and asScript is not None:
-            __Dict = Interfaces.ImportFromScript(asScript).getvalue( self.__name, "ExternalParameters" )
+            __Dict = Interfaces.ImportFromScript(asScript).getvalue(
+                self.__name, "ExternalParameters"
+            )
         else:
             __Dict = asDict
         #
         if __Dict is not None:
-            self.__P.update( dict(__Dict) )
+            self.__P.update(dict(__Dict))
 
-    def get(self, key = None):
+    def get(self, key=None):
         if key in self.__P:
             return self.__P[key]
         else:
@@ -1973,26 +2743,36 @@ class ExternalParameters(object):
         "D.__contains__(k) -> True if D has a key k, else False"
         return key in self.__P
 
+
 # ==============================================================================
 class State(object):
     """
     Classe générale d'interface de type état
     """
+
     __slots__ = (
-        "__name", "__check", "__V", "__T", "__is_vector", "__is_series",
-        "shape", "size",
+        "__name",
+        "__check",
+        "__V",
+        "__T",
+        "__is_vector",
+        "__is_series",
+        "shape",
+        "size",
     )
 
-    def __init__(self,
-                 name               = "GenericVector",
-                 asVector           = None,
-                 asPersistentVector = None,
-                 asScript           = None,
-                 asDataFile         = None,
-                 colNames           = None,
-                 colMajor           = False,
-                 scheduledBy        = None,
-                 toBeChecked        = False ):
+    def __init__(
+        self,
+        name="GenericVector",
+        asVector=None,
+        asPersistentVector=None,
+        asScript=None,
+        asDataFile=None,
+        colNames=None,
+        colMajor=False,
+        scheduledBy=None,
+        toBeChecked=False,
+    ):
         """
         Permet de définir un vecteur :
         - asVector : entrée des données, comme un vecteur compatible avec le
@@ -2013,74 +2793,97 @@ class State(object):
           défaut) ou "asPersistentVector" selon que l'une de ces variables est
           placée à "True".
         """
-        self.__name       = str(name)
-        self.__check      = bool(toBeChecked)
+        self.__name = str(name)
+        self.__check = bool(toBeChecked)
         #
-        self.__V          = None
-        self.__T          = None
-        self.__is_vector  = False
-        self.__is_series  = False
+        self.__V = None
+        self.__T = None
+        self.__is_vector = False
+        self.__is_series = False
         #
         if asScript is not None:
             __Vector, __Series = None, None
             if asPersistentVector:
-                __Series = Interfaces.ImportFromScript(asScript).getvalue( self.__name )
+                __Series = Interfaces.ImportFromScript(asScript).getvalue(self.__name)
             else:
-                __Vector = Interfaces.ImportFromScript(asScript).getvalue( self.__name )
+                __Vector = Interfaces.ImportFromScript(asScript).getvalue(self.__name)
         elif asDataFile is not None:
             __Vector, __Series = None, None
             if asPersistentVector:
                 if colNames is not None:
-                    __Series = Interfaces.ImportFromFile(asDataFile).getvalue( colNames )[1]
+                    __Series = Interfaces.ImportFromFile(asDataFile).getvalue(colNames)[
+                        1
+                    ]
                 else:
-                    __Series = Interfaces.ImportFromFile(asDataFile).getvalue( [self.__name,] )[1]
-                if bool(colMajor) and not Interfaces.ImportFromFile(asDataFile).getformat() == "application/numpy.npz":
+                    __Series = Interfaces.ImportFromFile(asDataFile).getvalue(
+                        [
+                            self.__name,
+                        ]
+                    )[1]
+                if (
+                    bool(colMajor)
+                    and not Interfaces.ImportFromFile(asDataFile).getformat()
+                    == "application/numpy.npz"
+                ):
                     __Series = numpy.transpose(__Series)
-                elif not bool(colMajor) and Interfaces.ImportFromFile(asDataFile).getformat() == "application/numpy.npz":
+                elif (
+                    not bool(colMajor)
+                    and Interfaces.ImportFromFile(asDataFile).getformat()
+                    == "application/numpy.npz"
+                ):
                     __Series = numpy.transpose(__Series)
             else:
                 if colNames is not None:
-                    __Vector = Interfaces.ImportFromFile(asDataFile).getvalue( colNames )[1]
+                    __Vector = Interfaces.ImportFromFile(asDataFile).getvalue(colNames)[
+                        1
+                    ]
                 else:
-                    __Vector = Interfaces.ImportFromFile(asDataFile).getvalue( [self.__name,] )[1]
+                    __Vector = Interfaces.ImportFromFile(asDataFile).getvalue(
+                        [
+                            self.__name,
+                        ]
+                    )[1]
                 if bool(colMajor):
-                    __Vector = numpy.ravel(__Vector, order = "F")
+                    __Vector = numpy.ravel(__Vector, order="F")
                 else:
-                    __Vector = numpy.ravel(__Vector, order = "C")
+                    __Vector = numpy.ravel(__Vector, order="C")
         else:
             __Vector, __Series = asVector, asPersistentVector
         #
         if __Vector is not None:
             self.__is_vector = True
             if isinstance(__Vector, str):
-                __Vector = PlatformInfo.strvect2liststr( __Vector )
-            self.__V         = numpy.ravel(numpy.asarray( __Vector, dtype=float )).reshape((-1, 1))
-            self.shape       = self.__V.shape
-            self.size        = self.__V.size
+                __Vector = PlatformInfo.strvect2liststr(__Vector)
+            self.__V = numpy.ravel(numpy.asarray(__Vector, dtype=float)).reshape(
+                (-1, 1)
+            )
+            self.shape = self.__V.shape
+            self.size = self.__V.size
         elif __Series is not None:
-            self.__is_series  = True
+            self.__is_series = True
             if isinstance(__Series, (tuple, list, numpy.ndarray, numpy.matrix, str)):
                 self.__V = Persistence.OneVector(self.__name)
                 if isinstance(__Series, str):
                     __Series = PlatformInfo.strmatrix2liststr(__Series)
                 for member in __Series:
                     if isinstance(member, str):
-                        member = PlatformInfo.strvect2liststr( member )
-                    self.__V.store(numpy.asarray( member, dtype=float ))
+                        member = PlatformInfo.strvect2liststr(member)
+                    self.__V.store(numpy.asarray(member, dtype=float))
             else:
                 self.__V = __Series
             if isinstance(self.__V.shape, (tuple, list)):
-                self.shape       = self.__V.shape
+                self.shape = self.__V.shape
             else:
-                self.shape       = self.__V.shape()
+                self.shape = self.__V.shape()
             if len(self.shape) == 1:
-                self.shape       = (self.shape[0], 1)
-            self.size            = self.shape[0] * self.shape[1]
+                self.shape = (self.shape[0], 1)
+            self.size = self.shape[0] * self.shape[1]
         else:
             raise ValueError(
-                "The %s object is improperly defined or undefined,"%self.__name + \
-                " it requires at minima either a vector, a list/tuple of" + \
-                " vectors or a persistent object. Please check your vector input.")
+                "The %s object is improperly defined or undefined," % self.__name
+                + " it requires at minima either a vector, a list/tuple of"
+                + " vectors or a persistent object. Please check your vector input."
+            )
         #
         if scheduledBy is not None:
             self.__T = scheduledBy
@@ -2109,24 +2912,35 @@ class State(object):
         "x.__str__() <==> str(x)"
         return str(self.__V)
 
+
 # ==============================================================================
 class Covariance(object):
     """
     Classe générale d'interface de type covariance
     """
+
     __slots__ = (
-        "__name", "__check", "__C", "__is_scalar", "__is_vector", "__is_matrix",
-        "__is_object", "shape", "size",
+        "__name",
+        "__check",
+        "__C",
+        "__is_scalar",
+        "__is_vector",
+        "__is_matrix",
+        "__is_object",
+        "shape",
+        "size",
     )
 
-    def __init__(self,
-                 name          = "GenericCovariance",
-                 asCovariance  = None,
-                 asEyeByScalar = None,
-                 asEyeByVector = None,
-                 asCovObject   = None,
-                 asScript      = None,
-                 toBeChecked   = False ):
+    def __init__(
+        self,
+        name="GenericCovariance",
+        asCovariance=None,
+        asEyeByScalar=None,
+        asEyeByVector=None,
+        asCovObject=None,
+        asScript=None,
+        toBeChecked=False,
+    ):
         """
         Permet de définir une covariance :
         - asCovariance : entrée des données, comme une matrice compatible avec
@@ -2144,68 +2958,90 @@ class Covariance(object):
         - toBeChecked : booléen indiquant si le caractère SDP de la matrice
           pleine doit être vérifié
         """
-        self.__name       = str(name)
-        self.__check      = bool(toBeChecked)
+        self.__name = str(name)
+        self.__check = bool(toBeChecked)
         #
-        self.__C          = None
-        self.__is_scalar  = False
-        self.__is_vector  = False
-        self.__is_matrix  = False
-        self.__is_object  = False
+        self.__C = None
+        self.__is_scalar = False
+        self.__is_vector = False
+        self.__is_matrix = False
+        self.__is_object = False
         #
         if asScript is not None:
             __Matrix, __Scalar, __Vector, __Object = None, None, None, None
             if asEyeByScalar:
-                __Scalar = Interfaces.ImportFromScript(asScript).getvalue( self.__name )
+                __Scalar = Interfaces.ImportFromScript(asScript).getvalue(self.__name)
             elif asEyeByVector:
-                __Vector = Interfaces.ImportFromScript(asScript).getvalue( self.__name )
+                __Vector = Interfaces.ImportFromScript(asScript).getvalue(self.__name)
             elif asCovObject:
-                __Object = Interfaces.ImportFromScript(asScript).getvalue( self.__name )
+                __Object = Interfaces.ImportFromScript(asScript).getvalue(self.__name)
             else:
-                __Matrix = Interfaces.ImportFromScript(asScript).getvalue( self.__name )
+                __Matrix = Interfaces.ImportFromScript(asScript).getvalue(self.__name)
         else:
-            __Matrix, __Scalar, __Vector, __Object = asCovariance, asEyeByScalar, asEyeByVector, asCovObject
+            __Matrix, __Scalar, __Vector, __Object = (
+                asCovariance,
+                asEyeByScalar,
+                asEyeByVector,
+                asCovObject,
+            )
         #
         if __Scalar is not None:
             if isinstance(__Scalar, str):
-                __Scalar = PlatformInfo.strvect2liststr( __Scalar )
+                __Scalar = PlatformInfo.strvect2liststr(__Scalar)
                 if len(__Scalar) > 0:
                     __Scalar = __Scalar[0]
             if numpy.array(__Scalar).size != 1:
                 raise ValueError(
-                    "  The diagonal multiplier given to define a sparse matrix is" + \
-                    " not a unique scalar value.\n  Its actual measured size is" + \
-                    " %i. Please check your scalar input."%numpy.array(__Scalar).size)
+                    "  The diagonal multiplier given to define a sparse matrix is"
+                    + " not a unique scalar value.\n  Its actual measured size is"
+                    + " %i. Please check your scalar input."
+                    % numpy.array(__Scalar).size
+                )
             self.__is_scalar = True
-            self.__C         = numpy.abs( float(__Scalar) )
-            self.shape       = (0, 0)
-            self.size        = 0
+            self.__C = numpy.abs(float(__Scalar))
+            self.shape = (0, 0)
+            self.size = 0
         elif __Vector is not None:
             if isinstance(__Vector, str):
-                __Vector = PlatformInfo.strvect2liststr( __Vector )
+                __Vector = PlatformInfo.strvect2liststr(__Vector)
             self.__is_vector = True
-            self.__C         = numpy.abs( numpy.ravel(numpy.asarray( __Vector, dtype=float )) )
-            self.shape       = (self.__C.size, self.__C.size)
-            self.size        = self.__C.size**2
+            self.__C = numpy.abs(numpy.ravel(numpy.asarray(__Vector, dtype=float)))
+            self.shape = (self.__C.size, self.__C.size)
+            self.size = self.__C.size**2
         elif __Matrix is not None:
             self.__is_matrix = True
-            self.__C         = numpy.matrix( __Matrix, float )
-            self.shape       = self.__C.shape
-            self.size        = self.__C.size
+            self.__C = numpy.matrix(__Matrix, float)
+            self.shape = self.__C.shape
+            self.size = self.__C.size
         elif __Object is not None:
             self.__is_object = True
-            self.__C         = __Object
-            for at in ("getT", "getI", "diag", "trace", "__add__", "__sub__", "__neg__", "__matmul__", "__mul__", "__rmatmul__", "__rmul__"):
+            self.__C = __Object
+            for at in (
+                "getT",
+                "getI",
+                "diag",
+                "trace",
+                "__add__",
+                "__sub__",
+                "__neg__",
+                "__matmul__",
+                "__mul__",
+                "__rmatmul__",
+                "__rmul__",
+            ):
                 if not hasattr(self.__C, at):
-                    raise ValueError("The matrix given for %s as an object has no attribute \"%s\". Please check your object input."%(self.__name, at))
+                    raise ValueError(
+                        'The matrix given for %s as an object has no attribute "%s". Please check your object input.'
+                        % (self.__name, at)
+                    )
             if hasattr(self.__C, "shape"):
-                self.shape       = self.__C.shape
+                self.shape = self.__C.shape
             else:
-                self.shape       = (0, 0)
+                self.shape = (0, 0)
             if hasattr(self.__C, "size"):
-                self.size        = self.__C.size
+                self.size = self.__C.size
             else:
-                self.size        = 0
+                self.size = 0
         else:
             pass
         #
@@ -2214,25 +3050,49 @@ class Covariance(object):
     def __validate(self):
         "Validation"
         if self.__C is None:
-            raise UnboundLocalError("%s covariance matrix value has not been set!"%(self.__name,))
+            raise UnboundLocalError(
+                "%s covariance matrix value has not been set!" % (self.__name,)
+            )
         if self.ismatrix() and min(self.shape) != max(self.shape):
-            raise ValueError("The given matrix for %s is not a square one, its shape is %s. Please check your matrix input."%(self.__name, self.shape))
+            raise ValueError(
+                "The given matrix for %s is not a square one, its shape is %s. Please check your matrix input."
+                % (self.__name, self.shape)
+            )
         if self.isobject() and min(self.shape) != max(self.shape):
-            raise ValueError("The matrix given for \"%s\" is not a square one, its shape is %s. Please check your object input."%(self.__name, self.shape))
+            raise ValueError(
+                'The matrix given for "%s" is not a square one, its shape is %s. Please check your object input.'
+                % (self.__name, self.shape)
+            )
         if self.isscalar() and self.__C <= 0:
-            raise ValueError("The \"%s\" covariance matrix is not positive-definite. Please check your scalar input %s."%(self.__name, self.__C))
+            raise ValueError(
+                'The "%s" covariance matrix is not positive-definite. Please check your scalar input %s.'
+                % (self.__name, self.__C)
+            )
         if self.isvector() and (self.__C <= 0).any():
-            raise ValueError("The \"%s\" covariance matrix is not positive-definite. Please check your vector input."%(self.__name,))
-        if self.ismatrix() and (self.__check or logging.getLogger().level < logging.WARNING):
+            raise ValueError(
+                'The "%s" covariance matrix is not positive-definite. Please check your vector input.'
+                % (self.__name,)
+            )
+        if self.ismatrix() and (
+            self.__check or logging.getLogger().level < logging.WARNING
+        ):
             try:
-                numpy.linalg.cholesky( self.__C )
+                numpy.linalg.cholesky(self.__C)
             except Exception:
-                raise ValueError("The %s covariance matrix is not symmetric positive-definite. Please check your matrix input."%(self.__name,))
-        if self.isobject() and (self.__check or logging.getLogger().level < logging.WARNING):
+                raise ValueError(
+                    "The %s covariance matrix is not symmetric positive-definite. Please check your matrix input."
+                    % (self.__name,)
+                )
+        if self.isobject() and (
+            self.__check or logging.getLogger().level < logging.WARNING
+        ):
             try:
                 self.__C.cholesky()
             except Exception:
-                raise ValueError("The %s covariance object is not symmetric positive-definite. Please check your matrix input."%(self.__name,))
+                raise ValueError(
+                    "The %s covariance object is not symmetric positive-definite. Please check your matrix input."
+                    % (self.__name,)
+                )
 
     def isscalar(self):
         "Vérification du type interne"
@@ -2253,82 +3113,114 @@ class Covariance(object):
     def getI(self):
         "Inversion"
         if self.ismatrix():
-            return Covariance(self.__name + "I", asCovariance  = numpy.linalg.inv(self.__C) )
+            return Covariance(
+                self.__name + "I", asCovariance=numpy.linalg.inv(self.__C)
+            )
         elif self.isvector():
-            return Covariance(self.__name + "I", asEyeByVector = 1. / self.__C )
+            return Covariance(self.__name + "I", asEyeByVector=1.0 / self.__C)
         elif self.isscalar():
-            return Covariance(self.__name + "I", asEyeByScalar = 1. / self.__C )
+            return Covariance(self.__name + "I", asEyeByScalar=1.0 / self.__C)
         elif self.isobject() and hasattr(self.__C, "getI"):
-            return Covariance(self.__name + "I", asCovObject   = self.__C.getI() )
+            return Covariance(self.__name + "I", asCovObject=self.__C.getI())
         else:
             return None  # Indispensable
 
     def getT(self):
         "Transposition"
         if self.ismatrix():
-            return Covariance(self.__name + "T", asCovariance  = self.__C.T )
+            return Covariance(self.__name + "T", asCovariance=self.__C.T)
         elif self.isvector():
-            return Covariance(self.__name + "T", asEyeByVector = self.__C )
+            return Covariance(self.__name + "T", asEyeByVector=self.__C)
         elif self.isscalar():
-            return Covariance(self.__name + "T", asEyeByScalar = self.__C )
+            return Covariance(self.__name + "T", asEyeByScalar=self.__C)
         elif self.isobject() and hasattr(self.__C, "getT"):
-            return Covariance(self.__name + "T", asCovObject   = self.__C.getT() )
+            return Covariance(self.__name + "T", asCovObject=self.__C.getT())
         else:
-            raise AttributeError("the %s covariance matrix has no getT attribute."%(self.__name,))
+            raise AttributeError(
+                "the %s covariance matrix has no getT attribute." % (self.__name,)
+            )
 
     def cholesky(self):
         "Décomposition de Cholesky"
         if self.ismatrix():
-            return Covariance(self.__name + "C", asCovariance  = numpy.linalg.cholesky(self.__C) )
+            return Covariance(
+                self.__name + "C", asCovariance=numpy.linalg.cholesky(self.__C)
+            )
         elif self.isvector():
-            return Covariance(self.__name + "C", asEyeByVector = numpy.sqrt( self.__C ) )
+            return Covariance(self.__name + "C", asEyeByVector=numpy.sqrt(self.__C))
         elif self.isscalar():
-            return Covariance(self.__name + "C", asEyeByScalar = numpy.sqrt( self.__C ) )
+            return Covariance(self.__name + "C", asEyeByScalar=numpy.sqrt(self.__C))
         elif self.isobject() and hasattr(self.__C, "cholesky"):
-            return Covariance(self.__name + "C", asCovObject   = self.__C.cholesky() )
+            return Covariance(self.__name + "C", asCovObject=self.__C.cholesky())
         else:
-            raise AttributeError("the %s covariance matrix has no cholesky attribute."%(self.__name,))
+            raise AttributeError(
+                "the %s covariance matrix has no cholesky attribute." % (self.__name,)
+            )
 
     def choleskyI(self):
         "Inversion de la décomposition de Cholesky"
         if self.ismatrix():
-            return Covariance(self.__name + "H", asCovariance  = numpy.linalg.inv(numpy.linalg.cholesky(self.__C)) )
+            return Covariance(
+                self.__name + "H",
+                asCovariance=numpy.linalg.inv(numpy.linalg.cholesky(self.__C)),
+            )
         elif self.isvector():
-            return Covariance(self.__name + "H", asEyeByVector = 1.0 / numpy.sqrt( self.__C ) )
+            return Covariance(
+                self.__name + "H", asEyeByVector=1.0 / numpy.sqrt(self.__C)
+            )
         elif self.isscalar():
-            return Covariance(self.__name + "H", asEyeByScalar = 1.0 / numpy.sqrt( self.__C ) )
+            return Covariance(
+                self.__name + "H", asEyeByScalar=1.0 / numpy.sqrt(self.__C)
+            )
         elif self.isobject() and hasattr(self.__C, "choleskyI"):
-            return Covariance(self.__name + "H", asCovObject   = self.__C.choleskyI() )
+            return Covariance(self.__name + "H", asCovObject=self.__C.choleskyI())
         else:
-            raise AttributeError("the %s covariance matrix has no choleskyI attribute."%(self.__name,))
+            raise AttributeError(
+                "the %s covariance matrix has no choleskyI attribute." % (self.__name,)
+            )
 
     def sqrtm(self):
         "Racine carrée matricielle"
         if self.ismatrix():
             import scipy
-            return Covariance(self.__name + "C", asCovariance  = numpy.real(scipy.linalg.sqrtm(self.__C)) )
+
+            return Covariance(
+                self.__name + "C", asCovariance=numpy.real(scipy.linalg.sqrtm(self.__C))
+            )
         elif self.isvector():
-            return Covariance(self.__name + "C", asEyeByVector = numpy.sqrt( self.__C ) )
+            return Covariance(self.__name + "C", asEyeByVector=numpy.sqrt(self.__C))
         elif self.isscalar():
-            return Covariance(self.__name + "C", asEyeByScalar = numpy.sqrt( self.__C ) )
+            return Covariance(self.__name + "C", asEyeByScalar=numpy.sqrt(self.__C))
         elif self.isobject() and hasattr(self.__C, "sqrtm"):
-            return Covariance(self.__name + "C", asCovObject   = self.__C.sqrtm() )
+            return Covariance(self.__name + "C", asCovObject=self.__C.sqrtm())
         else:
-            raise AttributeError("the %s covariance matrix has no sqrtm attribute."%(self.__name,))
+            raise AttributeError(
+                "the %s covariance matrix has no sqrtm attribute." % (self.__name,)
+            )
 
     def sqrtmI(self):
         "Inversion de la racine carrée matricielle"
         if self.ismatrix():
             import scipy
-            return Covariance(self.__name + "H", asCovariance  = numpy.linalg.inv(numpy.real(scipy.linalg.sqrtm(self.__C))) )
+
+            return Covariance(
+                self.__name + "H",
+                asCovariance=numpy.linalg.inv(numpy.real(scipy.linalg.sqrtm(self.__C))),
+            )
         elif self.isvector():
-            return Covariance(self.__name + "H", asEyeByVector = 1.0 / numpy.sqrt( self.__C ) )
+            return Covariance(
+                self.__name + "H", asEyeByVector=1.0 / numpy.sqrt(self.__C)
+            )
         elif self.isscalar():
-            return Covariance(self.__name + "H", asEyeByScalar = 1.0 / numpy.sqrt( self.__C ) )
+            return Covariance(
+                self.__name + "H", asEyeByScalar=1.0 / numpy.sqrt(self.__C)
+            )
         elif self.isobject() and hasattr(self.__C, "sqrtmI"):
-            return Covariance(self.__name + "H", asCovObject   = self.__C.sqrtmI() )
+            return Covariance(self.__name + "H", asCovObject=self.__C.sqrtmI())
         else:
-            raise AttributeError("the %s covariance matrix has no sqrtmI attribute."%(self.__name,))
+            raise AttributeError(
+                "the %s covariance matrix has no sqrtmI attribute." % (self.__name,)
+            )
 
     def diag(self, msize=None):
         "Diagonale de la matrice"
@@ -2338,13 +3230,19 @@ class Covariance(object):
             return self.__C
         elif self.isscalar():
             if msize is None:
-                raise ValueError("the size of the %s covariance matrix has to be given in case of definition as a scalar over the diagonal."%(self.__name,))
+                raise ValueError(
+                    "the size of the %s covariance matrix has to be given in"
+                    % (self.__name,)
+                    + " case of definition as a scalar over the diagonal."
+                )
             else:
                 return self.__C * numpy.ones(int(msize))
         elif self.isobject() and hasattr(self.__C, "diag"):
             return self.__C.diag()
         else:
-            raise AttributeError("the %s covariance matrix has no diag attribute."%(self.__name,))
+            raise AttributeError(
+                "the %s covariance matrix has no diag attribute." % (self.__name,)
+            )
 
     def trace(self, msize=None):
         "Trace de la matrice"
@@ -2354,29 +3252,42 @@ class Covariance(object):
             return float(numpy.sum(self.__C))
         elif self.isscalar():
             if msize is None:
-                raise ValueError("the size of the %s covariance matrix has to be given in case of definition as a scalar over the diagonal."%(self.__name,))
+                raise ValueError(
+                    "the size of the %s covariance matrix has to be given in"
+                    % (self.__name,)
+                    + " case of definition as a scalar over the diagonal."
+                )
             else:
                 return self.__C * int(msize)
         elif self.isobject():
             return self.__C.trace()
         else:
-            raise AttributeError("the %s covariance matrix has no trace attribute."%(self.__name,))
+            raise AttributeError(
+                "the %s covariance matrix has no trace attribute." % (self.__name,)
+            )
 
     def asfullmatrix(self, msize=None):
         "Matrice pleine"
         if self.ismatrix():
             return numpy.asarray(self.__C, dtype=float)
         elif self.isvector():
-            return numpy.asarray( numpy.diag(self.__C), dtype=float )
+            return numpy.asarray(numpy.diag(self.__C), dtype=float)
         elif self.isscalar():
             if msize is None:
-                raise ValueError("the size of the %s covariance matrix has to be given in case of definition as a scalar over the diagonal."%(self.__name,))
+                raise ValueError(
+                    "the size of the %s covariance matrix has to be given in"
+                    % (self.__name,)
+                    + " case of definition as a scalar over the diagonal."
+                )
             else:
-                return numpy.asarray( self.__C * numpy.eye(int(msize)), dtype=float )
+                return numpy.asarray(self.__C * numpy.eye(int(msize)), dtype=float)
         elif self.isobject() and hasattr(self.__C, "asfullmatrix"):
             return self.__C.asfullmatrix()
         else:
-            raise AttributeError("the %s covariance matrix has no asfullmatrix attribute."%(self.__name,))
+            raise AttributeError(
+                "the %s covariance matrix has no asfullmatrix attribute."
+                % (self.__name,)
+            )
 
     def assparsematrix(self):
         "Valeur sparse"
@@ -2405,12 +3316,15 @@ class Covariance(object):
             if len(_A.shape) == 1:
                 _A.reshape((-1, 1))[::2] += self.__C
             else:
-                _A.reshape(_A.size)[::_A.shape[1] + 1] += self.__C
+                _A.reshape(_A.size)[:: _A.shape[1] + 1] += self.__C
             return numpy.asmatrix(_A)
 
     def __radd__(self, other):
         "x.__radd__(y) <==> y+x"
-        raise NotImplementedError("%s covariance matrix __radd__ method not available for %s type!"%(self.__name, type(other)))
+        raise NotImplementedError(
+            "%s covariance matrix __radd__ method not available for %s type!"
+            % (self.__name, type(other))
+        )
 
     def __sub__(self, other):
         "x.__sub__(y) <==> x-y"
@@ -2418,46 +3332,68 @@ class Covariance(object):
             return self.__C - numpy.asmatrix(other)
         elif self.isvector() or self.isscalar():
             _A = numpy.asarray(other)
-            _A.reshape(_A.size)[::_A.shape[1] + 1] = self.__C - _A.reshape(_A.size)[::_A.shape[1] + 1]
+            _A.reshape(_A.size)[:: _A.shape[1] + 1] = (
+                self.__C - _A.reshape(_A.size)[:: _A.shape[1] + 1]
+            )
             return numpy.asmatrix(_A)
 
     def __rsub__(self, other):
         "x.__rsub__(y) <==> y-x"
-        raise NotImplementedError("%s covariance matrix __rsub__ method not available for %s type!"%(self.__name, type(other)))
+        raise NotImplementedError(
+            "%s covariance matrix __rsub__ method not available for %s type!"
+            % (self.__name, type(other))
+        )
 
     def __neg__(self):
         "x.__neg__() <==> -x"
-        return - self.__C
+        return -self.__C
 
     def __matmul__(self, other):
         "x.__mul__(y) <==> x@y"
         if self.ismatrix() and isinstance(other, (int, float)):
             return numpy.asarray(self.__C) * other
-        elif self.ismatrix() and isinstance(other, (list, numpy.matrix, numpy.ndarray, tuple)):
+        elif self.ismatrix() and isinstance(
+            other, (list, numpy.matrix, numpy.ndarray, tuple)
+        ):
             if numpy.ravel(other).size == self.shape[1]:  # Vecteur
                 return numpy.ravel(self.__C @ numpy.ravel(other))
             elif numpy.asarray(other).shape[0] == self.shape[1]:  # Matrice
                 return numpy.asarray(self.__C) @ numpy.asarray(other)
             else:
-                raise ValueError("operands could not be broadcast together with shapes %s %s in %s matrix"%(self.shape, numpy.asarray(other).shape, self.__name))
-        elif self.isvector() and isinstance(other, (list, numpy.matrix, numpy.ndarray, tuple)):
+                raise ValueError(
+                    "operands could not be broadcast together with shapes %s %s in %s matrix"
+                    % (self.shape, numpy.asarray(other).shape, self.__name)
+                )
+        elif self.isvector() and isinstance(
+            other, (list, numpy.matrix, numpy.ndarray, tuple)
+        ):
             if numpy.ravel(other).size == self.shape[1]:  # Vecteur
                 return numpy.ravel(self.__C) * numpy.ravel(other)
             elif numpy.asarray(other).shape[0] == self.shape[1]:  # Matrice
                 return numpy.ravel(self.__C).reshape((-1, 1)) * numpy.asarray(other)
             else:
-                raise ValueError("operands could not be broadcast together with shapes %s %s in %s matrix"%(self.shape, numpy.ravel(other).shape, self.__name))
+                raise ValueError(
+                    "operands could not be broadcast together with shapes %s %s in %s matrix"
+                    % (self.shape, numpy.ravel(other).shape, self.__name)
+                )
         elif self.isscalar() and isinstance(other, numpy.matrix):
             return numpy.asarray(self.__C * other)
         elif self.isscalar() and isinstance(other, (list, numpy.ndarray, tuple)):
-            if len(numpy.asarray(other).shape) == 1 or numpy.asarray(other).shape[1] == 1 or numpy.asarray(other).shape[0] == 1:
+            if (
+                len(numpy.asarray(other).shape) == 1
+                or numpy.asarray(other).shape[1] == 1
+                or numpy.asarray(other).shape[0] == 1
+            ):
                 return self.__C * numpy.ravel(other)
             else:
                 return self.__C * numpy.asarray(other)
         elif self.isobject():
             return self.__C.__matmul__(other)
         else:
-            raise NotImplementedError("%s covariance matrix __matmul__ method not available for %s type!"%(self.__name, type(other)))
+            raise NotImplementedError(
+                "%s covariance matrix __matmul__ method not available for %s type!"
+                % (self.__name, type(other))
+            )
 
     def __mul__(self, other):
         "x.__mul__(y) <==> x*y"
@@ -2470,19 +3406,31 @@ class Covariance(object):
                 return self.__C * numpy.asmatrix(other)
             else:
                 raise ValueError(
-                    "operands could not be broadcast together with shapes %s %s in %s matrix"%(self.shape, numpy.asmatrix(other).shape, self.__name))
-        elif self.isvector() and isinstance(other, (list, numpy.matrix, numpy.ndarray, tuple)):
+                    "operands could not be broadcast together with shapes %s %s in %s matrix"
+                    % (self.shape, numpy.asmatrix(other).shape, self.__name)
+                )
+        elif self.isvector() and isinstance(
+            other, (list, numpy.matrix, numpy.ndarray, tuple)
+        ):
             if numpy.ravel(other).size == self.shape[1]:  # Vecteur
                 return numpy.asmatrix(self.__C * numpy.ravel(other)).T
             elif numpy.asmatrix(other).shape[0] == self.shape[1]:  # Matrice
-                return numpy.asmatrix((self.__C * (numpy.asarray(other).transpose())).transpose())
+                return numpy.asmatrix(
+                    (self.__C * (numpy.asarray(other).transpose())).transpose()
+                )
             else:
                 raise ValueError(
-                    "operands could not be broadcast together with shapes %s %s in %s matrix"%(self.shape, numpy.ravel(other).shape, self.__name))
+                    "operands could not be broadcast together with shapes %s %s in %s matrix"
+                    % (self.shape, numpy.ravel(other).shape, self.__name)
+                )
         elif self.isscalar() and isinstance(other, numpy.matrix):
             return self.__C * other
         elif self.isscalar() and isinstance(other, (list, numpy.ndarray, tuple)):
-            if len(numpy.asarray(other).shape) == 1 or numpy.asarray(other).shape[1] == 1 or numpy.asarray(other).shape[0] == 1:
+            if (
+                len(numpy.asarray(other).shape) == 1
+                or numpy.asarray(other).shape[1] == 1
+                or numpy.asarray(other).shape[0] == 1
+            ):
                 return self.__C * numpy.asmatrix(numpy.ravel(other)).T
             else:
                 return self.__C * numpy.asmatrix(other)
@@ -2490,7 +3438,9 @@ class Covariance(object):
             return self.__C.__mul__(other)
         else:
             raise NotImplementedError(
-                "%s covariance matrix __mul__ method not available for %s type!"%(self.__name, type(other)))
+                "%s covariance matrix __mul__ method not available for %s type!"
+                % (self.__name, type(other))
+            )
 
     def __rmatmul__(self, other):
         "x.__rmul__(y) <==> y@x"
@@ -2503,7 +3453,9 @@ class Covariance(object):
                 return numpy.asmatrix(other) * self.__C
             else:
                 raise ValueError(
-                    "operands could not be broadcast together with shapes %s %s in %s matrix"%(numpy.asmatrix(other).shape, self.shape, self.__name))
+                    "operands could not be broadcast together with shapes %s %s in %s matrix"
+                    % (numpy.asmatrix(other).shape, self.shape, self.__name)
+                )
         elif self.isvector() and isinstance(other, numpy.matrix):
             if numpy.ravel(other).size == self.shape[0]:  # Vecteur
                 return numpy.asmatrix(numpy.ravel(other) * self.__C)
@@ -2511,14 +3463,18 @@ class Covariance(object):
                 return numpy.asmatrix(numpy.array(other) * self.__C)
             else:
                 raise ValueError(
-                    "operands could not be broadcast together with shapes %s %s in %s matrix"%(numpy.ravel(other).shape, self.shape, self.__name))
+                    "operands could not be broadcast together with shapes %s %s in %s matrix"
+                    % (numpy.ravel(other).shape, self.shape, self.__name)
+                )
         elif self.isscalar() and isinstance(other, numpy.matrix):
             return other * self.__C
         elif self.isobject():
             return self.__C.__rmatmul__(other)
         else:
             raise NotImplementedError(
-                "%s covariance matrix __rmatmul__ method not available for %s type!"%(self.__name, type(other)))
+                "%s covariance matrix __rmatmul__ method not available for %s type!"
+                % (self.__name, type(other))
+            )
 
     def __rmul__(self, other):
         "x.__rmul__(y) <==> y*x"
@@ -2531,7 +3487,9 @@ class Covariance(object):
                 return numpy.asmatrix(other) * self.__C
             else:
                 raise ValueError(
-                    "operands could not be broadcast together with shapes %s %s in %s matrix"%(numpy.asmatrix(other).shape, self.shape, self.__name))
+                    "operands could not be broadcast together with shapes %s %s in %s matrix"
+                    % (numpy.asmatrix(other).shape, self.shape, self.__name)
+                )
         elif self.isvector() and isinstance(other, numpy.matrix):
             if numpy.ravel(other).size == self.shape[0]:  # Vecteur
                 return numpy.asmatrix(numpy.ravel(other) * self.__C)
@@ -2539,7 +3497,9 @@ class Covariance(object):
                 return numpy.asmatrix(numpy.array(other) * self.__C)
             else:
                 raise ValueError(
-                    "operands could not be broadcast together with shapes %s %s in %s matrix"%(numpy.ravel(other).shape, self.shape, self.__name))
+                    "operands could not be broadcast together with shapes %s %s in %s matrix"
+                    % (numpy.ravel(other).shape, self.shape, self.__name)
+                )
         elif self.isscalar() and isinstance(other, numpy.matrix):
             return other * self.__C
         elif self.isscalar() and isinstance(other, float):
@@ -2548,18 +3508,345 @@ class Covariance(object):
             return self.__C.__rmul__(other)
         else:
             raise NotImplementedError(
-                "%s covariance matrix __rmul__ method not available for %s type!"%(self.__name, type(other)))
+                "%s covariance matrix __rmul__ method not available for %s type!"
+                % (self.__name, type(other))
+            )
 
     def __len__(self):
         "x.__len__() <==> len(x)"
         return self.shape[0]
 
+
+# ==============================================================================
+class DynamicalSimulator(object):
+    """
+    Classe de simulateur ODE d'ordre 1 pour modèles dynamiques :
+
+        dy / dt = F_µ(t, y)
+
+    avec y = f(t) et µ les paramètres intrinsèques. t est couramment le temps,
+    mais il peut être une variable quelconque non temporelle.
+
+    Paramètres d'initialisation :
+    - mu         : paramètres intrinsèques du modèle
+    - integrator : intégrateur choisi pour intégrer l'ODE
+    - dt         : pas de temps d'intégration
+    - t0         : temps initial d'intégration
+    - tf         : temps final
+    - y0         : condition initiale
+    """
+
+    __integrator_list = ["euler", "rk1", "rk2", "rk3", "rk4", "odeint", "solve_ivp"]
+    __slots__ = (
+        "_autonomous",
+        "_mu",
+        "_integrator",
+        "_dt",
+        "_do",
+        "_t0",
+        "_tf",
+        "_y0",
+    )
+
+    def __init__(
+        self,
+        mu=None,
+        integrator=None,
+        dt=None,
+        t0=None,
+        tf=None,
+        y0=None,
+        autonomous=None,
+    ):
+        "None default values are mandatory to allow overriding"
+        self.set_canonical_description()
+        self.set_description(mu, integrator, dt, t0, tf, y0, autonomous)
+
+    # --------------------------------------------------------------------------
+    # User defined ODE model
+
+    def ODEModel(self, t, y):
+        """
+        ODE : return dy / dt = F_µ(t, y)
+        """
+        raise NotImplementedError()
+
+    def set_canonical_description(self):
+        """
+        User settings for default or recommended EDO description
+
+        Setters that >>> can <<< be used:
+            - self.set_mu
+            - self.set_integrator
+            - self.set_dt
+            - self.set_t0
+            - self.set_tf
+            - self.set_y0
+            - self.set_autonomous
+        """
+        pass
+
+    # --------------------------------------------------------------------------
+
+    def set_description(
+        self,
+        mu=None,
+        integrator=None,
+        dt=None,
+        t0=None,
+        tf=None,
+        y0=None,
+        autonomous=False,
+    ):
+        "Explicit setting of EDO description"
+        self.set_mu(mu)
+        self.set_integrator(integrator)
+        self.set_dt(dt)
+        self.set_t0(t0)
+        self.set_tf(tf)
+        self.set_y0(y0)
+        self.set_autonomous(autonomous)
+
+    def set_mu(self, mu=None):
+        "Set EDO intrinsic parameters µ"
+        if mu is not None:
+            self._mu = numpy.ravel(mu)
+        return self._mu
+
+    def set_integrator(self, integrator=None):
+        "Set integration scheme name"
+        if integrator is None:
+            pass
+        elif not (integrator in self.__integrator_list):
+            raise ValueError(
+                "Wrong value %s for integrator in set_integrator call. \nAvailable integrators are: %s"
+                % (integrator, self.__integrator_list)
+            )
+        else:
+            self._integrator = str(integrator)
+        return self._integrator
+
+    def set_dt(self, value=None):
+        "Set integration step size dt"
+        if value is not None:
+            self._dt = max(2.0e-16, abs(float(value)))
+        return self._dt
+
+    def set_t0(self, value=None):
+        "Set initial integration time"
+        if value is not None:
+            self._t0 = float(value)
+            if hasattr(self, "_tf") and self._t0 > self._tf:
+                raise ValueError("Initial time has to remain less than final time")
+        return self._t0
+
+    def set_tf(self, value=None):
+        "Set final integration time"
+        if value is not None:
+            self._tf = float(value)
+            if hasattr(self, "_t0") and self._t0 > self._tf:
+                raise ValueError("Initial time has to remain less than final time")
+        return self._tf
+
+    def set_y0(self, value):
+        "Set integration initial condition"
+        if value is not None:
+            self._y0 = numpy.ravel(value)
+        return self._y0
+
+    def set_autonomous(self, value=None):
+        "Declare the system to be autonomous"
+        if value is not None:
+            self._autonomous = bool(value)
+        return self._autonomous
+
+    def set_do(self, value=None):
+        "Set observation step size do"
+        if value is not None:
+            self._do = max(2.0e-16, abs(float(value)))
+        return self._do
+
+    # --------------------------------------------------------------------------
+
+    def _rk1_step(self, t, y, h, F):
+        "Euler integration schema"
+        y = y + h * F(t, y)
+        t = t + h
+        return [t, y]
+
+    def _rk2_step(self, t, y, h, F):
+        "Runge-Kutta integration schema of order 2 (RK2)"
+        k1 = h * F(t, y)
+        k2 = h * F(t + h / 2.0, y + k1 / 2.0)
+        #
+        y = y + k2
+        t = t + h
+        return [t, y]
+
+    def _rk3_step(self, t, y, h, F):
+        "Runge-Kutta integration schema of order 3 (RK3)"
+        k1 = h * F(t, y)
+        k2 = h * F(t + h / 2.0, y + k1 / 2.0)
+        k3 = h * F(t + h, y - k1 + 2.0 * k2)
+        #
+        y = y + (k1 + 4.0 * k2 + k3) / 6.0
+        t = t + h
+        return [t, y]
+
+    def _rk4_step(self, t, y, h, F):
+        "Runge-Kutta integration schema of order 4 (RK4)"
+        k1 = h * F(t, y)
+        k2 = h * F(t + h / 2.0, y + k1 / 2.0)
+        k3 = h * F(t + h / 2.0, y + k2 / 2.0)
+        k4 = h * F(t + h, y + k3)
+        #
+        y = y + (k1 + 2.0 * k2 + 2.0 * k3 + k4) / 6.0
+        t = t + h
+        return [t, y]
+
+    _euler_step = _rk1_step
+
+    def Integration(self, y0=None, t0=None, tf=None, mu=None):
+        """
+        Exécute l'intégration du modèle entre t0 et tf, en partant de y0,
+        via le schéma d'intégration choisi
+        """
+        if y0 is not None:
+            self.set_y0(y0)
+        if t0 is not None:
+            self.set_t0(t0)
+        if tf is not None:
+            self.set_tf(tf)
+        if mu is not None:
+            self.set_mu(mu)
+        if (
+            (self._mu is None)
+            or (self._integrator is None)
+            or (self._dt is None)
+            or (self._t0 is None)
+            or (self._tf is None)
+            or (self._y0 is None)
+        ):
+            raise ValueError(
+                "Some integration input information are None and not defined\n(%s, %s, %s, %s, %s, %s)"
+                % (
+                    self._mu,
+                    self._integrator,
+                    self._dt,
+                    self._t0,
+                    self._tf,
+                    self._y0,
+                )
+            )
+        #
+        ODE = self.ODEModel
+        times = numpy.arange(self._t0, self._tf + self._dt / 2, self._dt)
+        if self._integrator == "odeint":
+            # intégration 'automatique' dans le cas d'un système pouvant être
+            # problématique avec rk4 ou euler (comme Van Der Pol)
+            from scipy.integrate import odeint
+
+            trajectory = odeint(
+                ODE,
+                numpy.array(self._y0, dtype=float),
+                times,
+                tfirst=True,
+            )
+        elif self._integrator == "solve_ivp":
+            # intégration 'automatique' dans le cas d'un système pouvant être
+            # problématique avec rk4 ou euler (comme Van Der Pol)
+            from scipy.integrate import solve_ivp
+
+            sol = solve_ivp(
+                ODE,
+                (self._t0, self._tf),
+                numpy.array(self._y0, dtype=float),
+                t_eval=times,
+            )
+            trajectory = sol.y.T
+        else:
+            if hasattr(self, "_%s_step" % self._integrator):
+                integration_step = getattr(self, "_%s_step" % self._integrator)
+            else:
+                raise ValueError(
+                    "Error in setting the integrator method (no _%s_step method)"
+                    % self._integrator
+                )
+            #
+            t = self._t0
+            y = self._y0
+            trajectory = numpy.array([self._y0])
+            #
+            while t < self._tf - self._dt / 2:
+                [t, y] = integration_step(t, y, self._dt, ODE)
+                trajectory = numpy.concatenate((trajectory, numpy.array([y])), axis=0)
+        #
+        return [times, trajectory]
+
+    def ForecastedPath(self, y1=None, t1=None, t2=None, mu=None):
+        "Trajectoire de t1 à t2, en partant de yn, pour un paramètre donné mu"
+        #
+        _, trajectory_from_t1_to_t2 = self.Integration(y1, t1, t2, mu)
+        #
+        return trajectory_from_t1_to_t2
+
+    def ForecastedState(self, y1=None, t1=None, t2=None, mu=None):
+        "État à t2 en intégrant à partir de t1, y1, pour un paramètre donné mu"
+        #
+        _, trajectory_from_t1_to_t2 = self.Integration(y1, t1, t2, mu)
+        #
+        return trajectory_from_t1_to_t2[-1, :]
+
+    def StateTransition(self, y1=None):
+        "État y[n+1] intégré depuis y[n] sur pas constant ou non"
+        if self.set_autonomous():
+            if not hasattr(self, "_do") or self._do is None:
+                raise ValueError(
+                    "    StateTransition requires an observation step size to be given"
+                )
+            return self.ForecastedState(y1, t1=0.0, t2=self.set_do())
+        else:
+            raise NotImplementedError(
+                "    StateTransition has to be provided by the user in case of non-autonomous ODE"
+            )
+
+    def HistoryBoard(self, t_s, i_s, y_s, filename="history_board_of_trajectory.pdf"):
+        """
+        t_s : série des instants t
+        i_s : série des indices i des variables
+        y_s : série des valeurs 1D des variables du système dynamique, pour
+              chaque pas de temps, sous forme d'un tableau 2D de type:
+              SDyn(i,t) = SDyn[i][t] = [SDyn[i] pour chaque t]
+        """
+        import matplotlib
+        import matplotlib.pyplot as plt
+        from matplotlib.ticker import MaxNLocator
+
+        levels = MaxNLocator(nbins=25).tick_values(
+            numpy.ravel(y_s).min(), numpy.ravel(y_s).max()
+        )
+        fig, ax = plt.subplots(figsize=(15, 5))
+        fig.subplots_adjust(bottom=0.1, left=0.05, right=0.95, top=0.9)
+        im = plt.contourf(
+            t_s, i_s, y_s, levels=levels, cmap=plt.get_cmap("gist_gray_r")
+        )
+        fig.colorbar(im, ax=ax)
+        plt.title("Model trajectory with %i variables" % len(y_s[:, 0]))
+        plt.xlabel("Time")
+        plt.ylabel("State variables")
+        if filename is None:
+            plt.show()
+        else:
+            plt.savefig(filename)
+
+
 # ==============================================================================
 class Observer2Func(object):
     """
     Création d'une fonction d'observateur a partir de son texte
     """
-    __slots__ = ("__corps")
+
+    __slots__ = ("__corps",)
 
     def __init__(self, corps=""):
         self.__corps = corps
@@ -2572,19 +3859,27 @@ class Observer2Func(object):
         "Restitution du pointeur de fonction dans l'objet"
         return self.func
 
+
 # ==============================================================================
 class CaseLogger(object):
     """
     Conservation des commandes de création d'un cas
     """
+
     __slots__ = (
-        "__name", "__objname", "__logSerie", "__switchoff", "__viewers",
+        "__name",
+        "__objname",
+        "__logSerie",
+        "__switchoff",
+        "__viewers",
         "__loaders",
     )
 
-    def __init__(self, __name="", __objname="case", __addViewers=None, __addLoaders=None):
-        self.__name     = str(__name)
-        self.__objname  = str(__objname)
+    def __init__(
+        self, __name="", __objname="case", __addViewers=None, __addLoaders=None
+    ):
+        self.__name = str(__name)
+        self.__objname = str(__objname)
         self.__logSerie = []
         self.__switchoff = False
         self.__viewers = {
@@ -2604,12 +3899,21 @@ class CaseLogger(object):
         if __addLoaders is not None:
             self.__loaders.update(dict(__addLoaders))
 
-    def register(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
+    def register(
+        self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False
+    ):
         "Enregistrement d'une commande individuelle"
-        if __command is not None and __keys is not None and __local is not None and not self.__switchoff:
+        if (
+            __command is not None
+            and __keys is not None
+            and __local is not None
+            and not self.__switchoff
+        ):
             if "self" in __keys:
                 __keys.remove("self")
-            self.__logSerie.append( (str(__command), __keys, __local, __pre, __switchoff) )
+            self.__logSerie.append(
+                (str(__command), __keys, __local, __pre, __switchoff)
+            )
             if __switchoff:
                 self.__switchoff = True
         if not __switchoff:
@@ -2618,9 +3922,11 @@ class CaseLogger(object):
     def dump(self, __filename=None, __format="TUI", __upa=""):
         "Restitution normalisée des commandes"
         if __format in self.__viewers:
-            __formater = self.__viewers[__format](self.__name, self.__objname, self.__logSerie)
+            __formater = self.__viewers[__format](
+                self.__name, self.__objname, self.__logSerie
+            )
         else:
-            raise ValueError("Dumping as \"%s\" is not available"%__format)
+            raise ValueError('Dumping as "%s" is not available' % __format)
         return __formater.dump(__filename, __upa)
 
     def load(self, __filename=None, __content=None, __object=None, __format="TUI"):
@@ -2628,24 +3934,28 @@ class CaseLogger(object):
         if __format in self.__loaders:
             __formater = self.__loaders[__format]()
         else:
-            raise ValueError("Loading as \"%s\" is not available"%__format)
+            raise ValueError('Loading as "%s" is not available' % __format)
         return __formater.load(__filename, __content, __object)
 
+
 # ==============================================================================
 def MultiFonction(
-        __xserie,
-        _extraArguments = None,
-        _sFunction      = lambda x: x,
-        _mpEnabled      = False,
-        _mpWorkers      = None ):
+    __xserie,
+    _extraArguments=None,
+    _sFunction=lambda x: x,
+    _mpEnabled=False,
+    _mpWorkers=None,
+):
     """
     Pour une liste ordonnée de vecteurs en entrée, renvoie en sortie la liste
     correspondante de valeurs de la fonction en argument
     """
     # Vérifications et définitions initiales
     # logging.debug("MULTF Internal multifonction calculations begin with function %s"%(_sFunction.__name__,))
-    if not PlatformInfo.isIterable( __xserie ):
-        raise TypeError("MultiFonction not iterable unkown input type: %s"%(type(__xserie),))
+    if not PlatformInfo.isIterable(__xserie):
+        raise TypeError(
+            "MultiFonction not iterable unkown input type: %s" % (type(__xserie),)
+        )
     if _mpEnabled:
         if (_mpWorkers is None) or (_mpWorkers is not None and _mpWorkers < 1):
             __mpWorkers = None
@@ -2653,6 +3963,7 @@ def MultiFonction(
             __mpWorkers = int(_mpWorkers)
         try:
             import multiprocessing
+
             __mpEnabled = True
         except ImportError:
             __mpEnabled = False
@@ -2665,7 +3976,7 @@ def MultiFonction(
         _jobs = __xserie
         # logging.debug("MULTF Internal multiprocessing calculations begin : evaluation of %i point(s)"%(len(_jobs),))
         with multiprocessing.Pool(__mpWorkers) as pool:
-            __multiHX = pool.map( _sFunction, _jobs )
+            __multiHX = pool.map(_sFunction, _jobs)
             pool.close()
             pool.join()
         # logging.debug("MULTF Internal multiprocessing calculation end")
@@ -2674,20 +3985,26 @@ def MultiFonction(
         __multiHX = []
         if _extraArguments is None:
             for __xvalue in __xserie:
-                __multiHX.append( _sFunction( __xvalue ) )
-        elif _extraArguments is not None and isinstance(_extraArguments, (list, tuple, map)):
+                __multiHX.append(_sFunction(__xvalue))
+        elif _extraArguments is not None and isinstance(
+            _extraArguments, (list, tuple, map)
+        ):
             for __xvalue in __xserie:
-                __multiHX.append( _sFunction( __xvalue, *_extraArguments ) )
+                __multiHX.append(_sFunction(__xvalue, *_extraArguments))
         elif _extraArguments is not None and isinstance(_extraArguments, dict):
             for __xvalue in __xserie:
-                __multiHX.append( _sFunction( __xvalue, **_extraArguments ) )
+                __multiHX.append(_sFunction(__xvalue, **_extraArguments))
         else:
-            raise TypeError("MultiFonction extra arguments unkown input type: %s"%(type(_extraArguments),))
+            raise TypeError(
+                "MultiFonction extra arguments unkown input type: %s"
+                % (type(_extraArguments),)
+            )
         # logging.debug("MULTF Internal monoprocessing calculation end")
     #
     # logging.debug("MULTF Internal multifonction calculations end")
     return __multiHX
 
+
 # ==============================================================================
 if __name__ == "__main__":
     print("\n AUTODIAGNOSTIC\n")
index 5918581c5d1a2e0d6b3f9ae1b9f55f4f73363057..fb765bae5c74e26528e1050381f01afafbe360ce 100644 (file)
@@ -81,13 +81,15 @@ from daCore import PlatformInfo
 
 LOGFILE = os.path.join(os.path.abspath(os.curdir), "AdaoOutputLogfile.log")
 
+
 # ==============================================================================
 class ExtendedLogging(object):
     """
     Logger général pour disposer conjointement de la sortie standard et de la
     sortie sur fichier
     """
-    __slots__ = ("__logfile")
+
+    __slots__ = ("__logfile",)
 
     def __init__(self, level=logging.WARNING):
         """
@@ -96,22 +98,24 @@ class ExtendedLogging(object):
         if sys.version_info.major <= 3 and sys.version_info.minor < 8:
             if logging.getLogger().hasHandlers():
                 while logging.getLogger().hasHandlers():
-                    logging.getLogger().removeHandler( logging.getLogger().handlers[-1] )
+                    logging.getLogger().removeHandler(logging.getLogger().handlers[-1])
                 __sys_stdout = logging.StreamHandler(sys.stdout)
-                __sys_stdout.setFormatter(logging.Formatter('%(levelname)-8s %(message)s'))
+                __sys_stdout.setFormatter(
+                    logging.Formatter("%(levelname)-8s %(message)s")
+                )
                 logging.getLogger().addHandler(__sys_stdout)
             else:
                 logging.basicConfig(
-                    format = '%(levelname)-8s %(message)s',
-                    level  = level,
-                    stream = sys.stdout,
+                    format="%(levelname)-8s %(message)s",
+                    level=level,
+                    stream=sys.stdout,
                 )
         else:  # Actif lorsque Python > 3.7
             logging.basicConfig(
-                format = '%(levelname)-8s %(message)s',
-                level  = level,
-                stream = sys.stdout,
-                force  = True,
+                format="%(levelname)-8s %(message)s",
+                level=level,
+                stream=sys.stdout,
+                force=True,
             )
         self.__logfile = None
         #
@@ -119,26 +123,26 @@ class ExtendedLogging(object):
         # ---------------------------------
         lpi = PlatformInfo.PlatformInfo()
         #
-        logging.info( "--------------------------------------------------" )
-        logging.info( lpi.getName() + " version " + lpi.getVersion() )
-        logging.info( "--------------------------------------------------" )
-        logging.info( "Library availability:" )
-        logging.info( "- Python.......: True" )
-        logging.info( "- Numpy........: " + str(lpi.has_numpy) )
-        logging.info( "- Scipy........: " + str(lpi.has_scipy) )
-        logging.info( "- Matplotlib...: " + str(lpi.has_matplotlib) )
-        logging.info( "- Gnuplot......: " + str(lpi.has_gnuplot) )
-        logging.info( "- Sphinx.......: " + str(lpi.has_sphinx) )
-        logging.info( "- Nlopt........: " + str(lpi.has_nlopt) )
-        logging.info( "Library versions:" )
-        logging.info( "- Python.......: " + lpi.getPythonVersion() )
-        logging.info( "- Numpy........: " + lpi.getNumpyVersion() )
-        logging.info( "- Scipy........: " + lpi.getScipyVersion() )
-        logging.info( "- Matplotlib...: " + lpi.getMatplotlibVersion() )
-        logging.info( "- Gnuplot......: " + lpi.getGnuplotVersion() )
-        logging.info( "- Sphinx.......: " + lpi.getSphinxVersion() )
-        logging.info( "- Nlopt........: " + lpi.getNloptVersion() )
-        logging.info( "" )
+        logging.info("--------------------------------------------------")
+        logging.info(lpi.getName() + " version " + lpi.getVersion())
+        logging.info("--------------------------------------------------")
+        logging.info("Library availability:")
+        logging.info("- Python.......: True")
+        logging.info("- Numpy........: " + str(lpi.has_numpy))
+        logging.info("- Scipy........: " + str(lpi.has_scipy))
+        logging.info("- Matplotlib...: " + str(lpi.has_matplotlib))
+        logging.info("- Gnuplot......: " + str(lpi.has_gnuplot))
+        logging.info("- Sphinx.......: " + str(lpi.has_sphinx))
+        logging.info("- Nlopt........: " + str(lpi.has_nlopt))
+        logging.info("Library versions:")
+        logging.info("- Python.......: " + lpi.getPythonVersion())
+        logging.info("- Numpy........: " + lpi.getNumpyVersion())
+        logging.info("- Scipy........: " + lpi.getScipyVersion())
+        logging.info("- Matplotlib...: " + lpi.getMatplotlibVersion())
+        logging.info("- Gnuplot......: " + lpi.getGnuplotVersion())
+        logging.info("- Sphinx.......: " + lpi.getSphinxVersion())
+        logging.info("- Nlopt........: " + lpi.getNloptVersion())
+        logging.info("")
 
     def setLogfile(self, filename=LOGFILE, filemode="w", level=logging.NOTSET):
         """
@@ -150,11 +154,13 @@ class ExtendedLogging(object):
         self.__logfile = logging.FileHandler(filename, filemode)
         self.__logfile.setLevel(level)
         self.__logfile.setFormatter(
-            logging.Formatter('%(asctime)s %(levelname)-8s %(message)s',
-                              '%d %b %Y %H:%M:%S'))
+            logging.Formatter(
+                "%(asctime)s %(levelname)-8s %(message)s", "%d %b %Y %H:%M:%S"
+            )
+        )
         logging.getLogger().addHandler(self.__logfile)
 
-    def setLogfileLevel(self, level=logging.NOTSET ):
+    def setLogfileLevel(self, level=logging.NOTSET):
         """
         Permet de changer le niveau des messages stockés en fichier. Il ne sera
         pris en compte que s'il est supérieur au niveau global.
@@ -165,20 +171,23 @@ class ExtendedLogging(object):
         """
         Renvoie le niveau de logging sous forme texte
         """
-        return logging.getLevelName( logging.getLogger().getEffectiveLevel() )
+        return logging.getLevelName(logging.getLogger().getEffectiveLevel())
+
 
 # ==============================================================================
 def logtimer(f):
     @functools.wraps(f)
     def wrapper(*args, **kwargs):
-        start  = time.clock()  # time.time()
+        start = time.clock()  # time.time()
         result = f(*args, **kwargs)
-        end    = time.clock()  # time.time()
-        msg    = 'TIMER Durée elapsed de la fonction utilisateur "{}": {:.3f}s'
+        end = time.clock()  # time.time()
+        msg = 'TIMER Durée elapsed de la fonction utilisateur "{}": {:.3f}s'
         logging.debug(msg.format(f.__name__, end - start))
         return result
+
     return wrapper
 
+
 # ==============================================================================
 if __name__ == "__main__":
     print("\n AUTODIAGNOSTIC\n")
index abc4f516272c10944f1764bcbb841305756b589b..33f4b2f2fad7b7a53ad8fc188ef99ef455eeb69b 100644 (file)
@@ -37,28 +37,41 @@ from daCore import PlatformInfo
 from daCore import Templates
 from daCore import Reporting
 from daCore import version
+
 lpi = PlatformInfo.PlatformInfo()
 
+
 # ==============================================================================
 class GenericCaseViewer(object):
     """
     Gestion des commandes de création d'une vue de cas
     """
+
     __slots__ = (
-        "_name", "_objname", "_lineSerie", "_switchoff", "_content",
-        "_numobservers", "_object", "_missing",
+        "_name",
+        "_objname",
+        "_lineSerie",
+        "_switchoff",
+        "_content",
+        "_numobservers",
+        "_object",
+        "_missing",
     )
 
     def __init__(self, __name="", __objname="case", __content=None, __object=None):
         "Initialisation et enregistrement de l'entete"
-        self._name         = str(__name)
-        self._objname      = str(__objname)
-        self._lineSerie    = []
-        self._switchoff    = False
+        self._name = str(__name)
+        self._objname = str(__objname)
+        self._lineSerie = []
+        self._switchoff = False
         self._numobservers = 2
-        self._content      = __content
-        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# """
+        self._content = __content
+        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 d'une commande individuelle en un enregistrement"
@@ -71,12 +84,12 @@ class GenericCaseViewer(object):
     def _initialize(self, __multilines):
         "Permet des pré-conversions automatiques simples de commandes ou clés"
         __translation = {
-            "Study_name"           : "StudyName",                  # noqa: E203
-            "Study_repertory"      : "StudyRepertory",             # noqa: E203
-            "MaximumNumberOfSteps" : "MaximumNumberOfIterations",  # noqa: E203
+            "Study_name": "StudyName",
+            "Study_repertory": "StudyRepertory",
+            "MaximumNumberOfSteps": "MaximumNumberOfIterations",
             "EnableMultiProcessing": "EnableWiseParallelism",
-            "FunctionDict"         : "ScriptWithSwitch",           # noqa: E203
-            "FUNCTIONDICT_FILE"    : "SCRIPTWITHSWITCH_FILE",      # noqa: E203
+            "FunctionDict": "ScriptWithSwitch",
+            "FUNCTIONDICT_FILE": "SCRIPTWITHSWITCH_FILE",
         }
         for k, v in __translation.items():
             __multilines = __multilines.replace(k, v)
@@ -86,10 +99,10 @@ class GenericCaseViewer(object):
         "Enregistrement du final"
         __hasNotExecute = True
         for __l in self._lineSerie:
-            if "%s.execute"%(self._objname,) in __l:
+            if "%s.execute" % (self._objname,) in __l:
                 __hasNotExecute = False
         if __hasNotExecute:
-            self._lineSerie.append("%s.execute()"%(self._objname,))
+            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)
@@ -116,7 +129,7 @@ class GenericCaseViewer(object):
     def load(self, __filename=None, __content=None, __object=None):
         "Chargement normalisé des commandes"
         if __filename is not None and os.path.exists(__filename):
-            self._content = open(__filename, 'r').read()
+            self._content = open(__filename, "r").read()
             self._content = self._initialize(self._content)
         elif __content is not None and type(__content) is str:
             self._content = self._initialize(__content)
@@ -127,10 +140,12 @@ class GenericCaseViewer(object):
         __commands = self._extract(self._content, self._object)
         return __commands
 
+
 class _TUIViewer(GenericCaseViewer):
     """
     Établissement des commandes d'un cas ADAO TUI (Cas<->TUI)
     """
+
     __slots__ = ()
 
     def __init__(self, __name="", __objname="case", __content=None, __object=None):
@@ -141,47 +156,62 @@ class _TUIViewer(GenericCaseViewer):
         self._addLine("import numpy as np")
         self._addLine("from numpy import array, matrix")
         self._addLine("from adao import adaoBuilder")
-        self._addLine("%s = adaoBuilder.New('%s')"%(self._objname, self._name))
+        self._addLine("%s = adaoBuilder.New('%s')" % (self._objname, self._name))
         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):
+    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  = ""
+                logging.debug("TUI Order processed: %s" % (__local["Concept"],))
+            __text = ""
             if __pre is not None:
-                __text += "%s = "%__pre
-            __text += "%s.%s( "%(self._objname, str(__command))
+                __text += "%s = " % __pre
+            __text += "%s.%s( " % (self._objname, str(__command))
             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                           # noqa: E701
+                if k not in __local:
+                    continue
                 __v = __local[k]
-                if __v is None: continue                                # noqa: E701
-                if   k == "Checked"              and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "ColMajor"             and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "CrossObs"             and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "SyncObs"              and     __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "InputFunctionAsMulti" and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "PerformanceProfile"   and     __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "Stored"               and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "nextStep"             and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "noDetails":                        continue  # noqa: E241,E271,E272,E701
+                if __v is None:
+                    continue
+                if k == "Checked" and not __v:
+                    continue
+                if k == "ColMajor" and not __v:
+                    continue
+                if k == "CrossObs" and not __v:
+                    continue
+                if k == "SyncObs" and __v:
+                    continue
+                if k == "InputFunctionAsMulti" and not __v:
+                    continue
+                if k == "PerformanceProfile" and __v:
+                    continue
+                if k == "Stored" and not __v:
+                    continue
+                if k == "nextStep" and not __v:
+                    continue
+                if k == "noDetails":
+                    continue
                 if isinstance(__v, Persistence.Persistence):
                     __v = __v.values()
                 if callable(__v):
-                    __text = self._missing%__v.__name__ + __text
+                    __text = self._missing % __v.__name__ + __text
                 if isinstance(__v, dict):
                     for val in __v.values():
                         if callable(val):
-                            __text = self._missing%val.__name__ + __text
-                numpy.set_printoptions(precision=15, threshold=1000000, linewidth=1000 * 15)
-                __text += "%s=%s, "%(k, repr(__v))
+                            __text = self._missing % val.__name__ + __text
+                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 = __text.rstrip(", ")
             __text += " )"
@@ -196,19 +226,23 @@ class _TUIViewer(GenericCaseViewer):
             if "adaoBuilder.New" in line and "=" in line:
                 self._objname = line.split("=")[0].strip()
                 __is_case = True
-                logging.debug("TUI Extracting commands of '%s' object..."%(self._objname,))
+                logging.debug(
+                    "TUI Extracting commands of '%s' object..." % (self._objname,)
+                )
             if not __is_case:
                 continue
             else:
                 if self._objname + ".set" in line:
-                    __commands.append( line.replace(self._objname + ".", "", 1) )
-                    logging.debug("TUI Extracted command: %s"%(__commands[-1],))
+                    __commands.append(line.replace(self._objname + ".", "", 1))
+                    logging.debug("TUI Extracted command: %s" % (__commands[-1],))
         return __commands
 
+
 class _COMViewer(GenericCaseViewer):
     """
     Établissement des commandes d'un cas COMM (Eficas Native Format/Cas<-COM)
     """
+
     __slots__ = ("_observerIndex", "_objdata")
 
     def __init__(self, __name="", __objname="case", __content=None, __object=None):
@@ -220,7 +254,7 @@ class _COMViewer(GenericCaseViewer):
         self._addLine("import numpy as np")
         self._addLine("from numpy import array, matrix")
         self._addLine("#")
-        self._addLine("%s = {}"%__objname)
+        self._addLine("%s = {}" % __objname)
         if self._content is not None:
             for command in self._content:
                 self._append(*command)
@@ -229,19 +263,22 @@ class _COMViewer(GenericCaseViewer):
         "Transformation d'enregistrement(s) en commande(s) individuelle(s)"
         __suppparameters = {}
         if __multilines is not None:
-            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 "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"})
+                __suppparameters.update({"StudyType": "ASSIMILATION_STUDY"})
                 __multilines = __multilines.replace("ASSIMILATION_STUDY", "dict")
             elif "OPTIMIZATION_STUDY" in __multilines:
-                __suppparameters.update({'StudyType': "ASSIMILATION_STUDY"})
+                __suppparameters.update({"StudyType": "ASSIMILATION_STUDY"})
                 __multilines = __multilines.replace("OPTIMIZATION_STUDY", "dict")
             elif "REDUCTION_STUDY" in __multilines:
-                __suppparameters.update({'StudyType': "ASSIMILATION_STUDY"})
+                __suppparameters.update({"StudyType": "ASSIMILATION_STUDY"})
                 __multilines = __multilines.replace("REDUCTION_STUDY", "dict")
             elif "CHECKING_STUDY" in __multilines:
-                __suppparameters.update({'StudyType': "CHECKING_STUDY"})
+                __suppparameters.update({"StudyType": "CHECKING_STUDY"})
                 __multilines = __multilines.replace("CHECKING_STUDY", "dict")
             else:
                 __multilines = __multilines.replace("ASSIMILATION_STUDY", "dict")
@@ -258,138 +295,193 @@ class _COMViewer(GenericCaseViewer):
         self._objdata = None
         exec("self._objdata = " + __multilines)
         #
-        if self._objdata is None or not (type(self._objdata) is dict) or not ('AlgorithmParameters' in self._objdata):
-            raise ValueError("Impossible to load given content as an ADAO COMM one (no dictionnary or no 'AlgorithmParameters' key found).")
+        if (
+            self._objdata is None
+            or not (type(self._objdata) is dict)
+            or not ("AlgorithmParameters" in self._objdata)
+        ):
+            raise ValueError(
+                "Impossible to load given content as an ADAO COMM one"
+                + " (no dictionnary or no 'AlgorithmParameters' key found)."
+            )
         # ----------------------------------------------------------------------
-        logging.debug("COMM Extracting commands of '%s' object..."%(self._objname,))
+        logging.debug("COMM Extracting commands of '%s' object..." % (self._objname,))
         __commands = []
         __UserPostAnalysis = ""
         for k, r in self._objdata.items():
             __command = k
-            logging.debug("COMM Extracted command: %s:%s"%(k, r))
-            if __command   == "StudyName" and len(str(r)) > 0:
-                __commands.append( "set( Concept='Name', String='%s')"%(str(r),) )
+            logging.debug("COMM Extracted command: %s:%s" % (k, r))
+            if __command == "StudyName" and len(str(r)) > 0:
+                __commands.append("set( Concept='Name', String='%s')" % (str(r),))
             elif __command == "StudyRepertory":
-                __commands.append( "set( Concept='Directory', String='%s')"%(str(r),) )
+                __commands.append("set( Concept='Directory', String='%s')" % (str(r),))
             elif __command == "Debug" and str(r) == "0":
-                __commands.append( "set( Concept='NoDebug' )" )
+                __commands.append("set( Concept='NoDebug' )")
             elif __command == "Debug" and str(r) == "1":
-                __commands.append( "set( Concept='Debug' )" )
+                __commands.append("set( Concept='Debug' )")
             elif __command == "ExecuteInContainer":
-                __suppparameters.update({'ExecuteInContainer': r})
+                __suppparameters.update({"ExecuteInContainer": r})
             #
             elif __command == "UserPostAnalysis" and type(r) is dict:
-                if 'STRING' in r:
-                    __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()
-                    __commands.append( "set( Concept='UserPostAnalysis', Script='%s' )"%(r['SCRIPT_FILE'],) )
-                elif 'Template' in r and 'ValueTemplate' not in r:
+                if "STRING" in r:
+                    __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()
+                    __commands.append(
+                        "set( Concept='UserPostAnalysis', Script='%s' )"
+                        % (r["SCRIPT_FILE"],)
+                    )
+                elif "Template" in r and "ValueTemplate" not in r:
                     # AnalysisPrinter...
-                    if r['Template'] not in Templates.UserPostAnalysisTemplates:
-                        raise ValueError("User post-analysis template \"%s\" does not exist."%(r['Template'],))
+                    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:
+                        __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,) )
+                    __UserPostAnalysis = r["ValueTemplate"]
+                    __commands.append(
+                        'set( Concept=\'UserPostAnalysis\', String="""%s""" )'
+                        % (__UserPostAnalysis,)
+                    )
                 else:
                     __UserPostAnalysis = ""
             #
-            elif __command == "AlgorithmParameters" and type(r) is dict and 'Algorithm' in r:
-                if 'data' in r and r['Parameters'] == 'Dict':
-                    __from = r['data']
-                    if 'STRING' in __from:
-                        __parameters = ", Parameters=%s"%(repr(eval(__from['STRING'])),)
-                    elif 'SCRIPT_FILE' in __from:  # Pas de test d'existence du fichier pour accepter un fichier relatif
-                        __parameters = ", Script='%s'"%(__from['SCRIPT_FILE'],)
+            elif (
+                __command == "AlgorithmParameters"
+                and type(r) is dict
+                and "Algorithm" in r
+            ):
+                if "data" in r and r["Parameters"] == "Dict":
+                    __from = r["data"]
+                    if "STRING" in __from:
+                        __parameters = ", Parameters=%s" % (
+                            repr(eval(__from["STRING"])),
+                        )
+                    elif (
+                        "SCRIPT_FILE" in __from
+                    ):  # Pas de test d'existence du fichier pour accepter un fichier relatif
+                        __parameters = ", Script='%s'" % (__from["SCRIPT_FILE"],)
                 else:  # if 'Parameters' in r and r['Parameters'] == 'Defaults':
                     __Dict = copy.deepcopy(r)
-                    __Dict.pop('Algorithm', '')
-                    __Dict.pop('Parameters', '')
-                    if 'SetSeed' in __Dict:
-                        __Dict['SetSeed'] = int(__Dict['SetSeed'])
-                    if 'Bounds' in __Dict and type(__Dict['Bounds']) is str:
-                        __Dict['Bounds'] = eval(__Dict['Bounds'])
-                    if 'BoxBounds' in __Dict and type(__Dict['BoxBounds']) is str:
-                        __Dict['BoxBounds'] = eval(__Dict['BoxBounds'])
+                    __Dict.pop("Algorithm", "")
+                    __Dict.pop("Parameters", "")
+                    if "SetSeed" in __Dict:
+                        __Dict["SetSeed"] = int(__Dict["SetSeed"])
+                    if "Bounds" in __Dict and type(__Dict["Bounds"]) is str:
+                        __Dict["Bounds"] = eval(__Dict["Bounds"])
+                    if "BoxBounds" in __Dict and type(__Dict["BoxBounds"]) is str:
+                        __Dict["BoxBounds"] = eval(__Dict["BoxBounds"])
                     if len(__Dict) > 0:
-                        __parameters = ', Parameters=%s'%(repr(__Dict),)
+                        __parameters = ", Parameters=%s" % (repr(__Dict),)
                     else:
                         __parameters = ""
-                __commands.append( "set( Concept='AlgorithmParameters', Algorithm='%s'%s )"%(r['Algorithm'], __parameters) )
+                __commands.append(
+                    "set( Concept='AlgorithmParameters', Algorithm='%s'%s )"
+                    % (r["Algorithm"], __parameters)
+                )
             #
-            elif __command == "Observers" and type(r) is dict and 'SELECTION' in r:
-                if type(r['SELECTION']) is str:
-                    __selection = (r['SELECTION'],)
+            elif __command == "Observers" and type(r) is dict and "SELECTION" in r:
+                if type(r["SELECTION"]) is str:
+                    __selection = (r["SELECTION"],)
                 else:
-                    __selection = tuple(r['SELECTION'])
+                    __selection = tuple(r["SELECTION"])
                 for sk in __selection:
-                    __idata = r['%s_data'%sk]
-                    if __idata['NodeType'] == 'Template' and 'Template' in __idata:
-                        __template = __idata['Template']
-                        if 'Info' in __idata:
-                            __info = ", Info=\"\"\"%s\"\"\""%(__idata['Info'],)
+                    __idata = r["%s_data" % sk]
+                    if __idata["NodeType"] == "Template" and "Template" in __idata:
+                        __template = __idata["Template"]
+                        if "Info" in __idata:
+                            __info = ', Info="""%s"""' % (__idata["Info"],)
                         else:
                             __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\', 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)
+                        )
             #
             # Background, ObservationError, ObservationOperator...
             elif type(r) is dict:
                 __argumentsList = []
-                if 'Stored' in r and bool(r['Stored']):
-                    __argumentsList.append(['Stored', True])
-                if 'INPUT_TYPE' in r and 'data' in r:
+                if "Stored" in r and bool(r["Stored"]):
+                    __argumentsList.append(["Stored", True])
+                if "INPUT_TYPE" in r and "data" in r:
                     # Vector, Matrix, ScalarSparseMatrix, DiagonalSparseMatrix, Function
-                    __itype = r['INPUT_TYPE']
-                    __idata = r['data']
-                    if 'FROM' in __idata:
+                    __itype = r["INPUT_TYPE"]
+                    __idata = r["data"]
+                    if "FROM" in __idata:
                         # String, Script, DataFile, Template, ScriptWithOneFunction, ScriptWithFunctions
-                        __ifrom = __idata['FROM']
-                        __idata.pop('FROM', '')
-                        if __ifrom == 'String' or __ifrom == 'Template':
-                            __argumentsList.append([__itype, __idata['STRING']])
-                        if __ifrom == 'Script':
+                        __ifrom = __idata["FROM"]
+                        __idata.pop("FROM", "")
+                        if __ifrom == "String" or __ifrom == "Template":
+                            __argumentsList.append([__itype, __idata["STRING"]])
+                        if __ifrom == "Script":
                             __argumentsList.append([__itype, True])
-                            __argumentsList.append(['Script', __idata['SCRIPT_FILE']])
-                        if __ifrom == 'DataFile':
+                            __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')])
+                            __argumentsList.append(["DataFile", __idata["DATA_FILE"]])
+                        if __ifrom == "ScriptWithOneFunction":
+                            __argumentsList.append(["OneFunction", True])
+                            __argumentsList.append(
+                                ["Script", __idata.pop("SCRIPTWITHONEFUNCTION_FILE")]
+                            )
                             if len(__idata) > 0:
-                                __argumentsList.append(['Parameters', __idata])
-                        if __ifrom == 'ScriptWithFunctions':
-                            __argumentsList.append(['ThreeFunctions', True])
-                            __argumentsList.append(['Script', __idata.pop('SCRIPTWITHFUNCTIONS_FILE')])
+                                __argumentsList.append(["Parameters", __idata])
+                        if __ifrom == "ScriptWithFunctions":
+                            __argumentsList.append(["ThreeFunctions", True])
+                            __argumentsList.append(
+                                ["Script", __idata.pop("SCRIPTWITHFUNCTIONS_FILE")]
+                            )
                             if len(__idata) > 0:
-                                __argumentsList.append(['Parameters', __idata])
-                __arguments = ["%s = %s"%(k, repr(v)) for k, v in __argumentsList]
-                __commands.append( "set( Concept='%s', %s )"%(__command, ", ".join(__arguments)))
+                                __argumentsList.append(["Parameters", __idata])
+                __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.append(
+            "set( Concept='%s', Parameters=%s )"
+            % ("SupplementaryParameters", repr(__suppparameters))
+        )
         #
         # ----------------------------------------------------------------------
         __commands.sort()  # Pour commencer par 'AlgorithmParameters'
         __commands.append(__UserPostAnalysis)
         return __commands
 
+
 class _SCDViewer(GenericCaseViewer):
     """
     É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
     """
+
     __slots__ = (
-        "__DebugCommandNotSet", "__ObserverCommandNotSet",
-        "__UserPostAnalysisNotSet", "__hasAlgorithm")
+        "__DebugCommandNotSet",
+        "__ObserverCommandNotSet",
+        "__UserPostAnalysisNotSet",
+        "__hasAlgorithm",
+    )
 
     def __init__(self, __name="", __objname="case", __content=None, __object=None):
         "Initialisation et enregistrement de l'entête"
@@ -401,7 +493,7 @@ class _SCDViewer(GenericCaseViewer):
                     __command = command[2]["Concept"]
                 else:
                     __command = command[0].replace("set", "", 1)
-                if __command == 'Name':
+                if __command == "Name":
                     self._name = command[2]["String"]
         #
         self.__DebugCommandNotSet = True
@@ -412,7 +504,7 @@ class _SCDViewer(GenericCaseViewer):
         self._addLine("#\n# Input for ADAO converter to SCD\n#")
         self._addLine("#")
         self._addLine("study_config = {}")
-        self._addLine("study_config['Name'] = '%s'"%self._name)
+        self._addLine("study_config['Name'] = '%s'" % self._name)
         self._addLine("#")
         self._addLine("inputvariables_config = {}")
         self._addLine("inputvariables_config['Order'] =['adao_default']")
@@ -427,67 +519,102 @@ class _SCDViewer(GenericCaseViewer):
             for command in __content:
                 self._append(*command)
 
-    def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False):
+    def _append(
+        self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False
+    ):
         "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))
+        logging.debug("SCD Order processed: %s" % (__command))
         #
-        __text  = None
-        if __command in (None, 'execute', 'executePythonScheme', 'executeYACSScheme', 'get', 'Name'):
+        __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'"
+        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'"
+        elif __command in ["NoDebug", "setNoDebug"]:
+            __text = "#\nstudy_config['Debug'] = '0'"
             self.__DebugCommandNotSet = False
-        elif __command in ['Observer', 'setObserver']:
+        elif __command in ["Observer", "setObserver"]:
             if self.__ObserverCommandNotSet:
                 self._addLine("observers = {}")
                 self._addLine("study_config['Observers'] = observers")
                 self.__ObserverCommandNotSet = False
-            __obs   = __local['Variable']
+            __obs = __local["Variable"]
             self._numobservers += 1
-            __text  = "#\n"
-            __text += "observers['%s'] = {}\n"%__obs
-            if __local['String'] is not None:
-                __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
-                __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, __local['String'])
-            if __local['Script'] is not None:
-                __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'Script')
-                __text += "observers['%s']['Script'] = \"%s\"\n"%(__obs, __local['Script'])
-            if __local['Template'] is not None and __local['Template'] in Templates.ObserverTemplates:
-                __text += "observers['%s']['nodetype'] = '%s'\n"%(__obs, 'String')
-                __text += "observers['%s']['String'] = \"\"\"%s\"\"\"\n"%(__obs, Templates.ObserverTemplates[__local['Template']])
-            if __local['Info'] is not None:
-                __text += "observers['%s']['info'] = \"\"\"%s\"\"\"\n"%(__obs, __local['Info'])
+            __text = "#\n"
+            __text += "observers['%s'] = {}\n" % __obs
+            if __local["String"] is not None:
+                __text += "observers['%s']['nodetype'] = '%s'\n" % (__obs, "String")
+                __text += 'observers[\'%s\'][\'String\'] = """%s"""\n' % (
+                    __obs,
+                    __local["String"],
+                )
+            if __local["Script"] is not None:
+                __text += "observers['%s']['nodetype'] = '%s'\n" % (__obs, "Script")
+                __text += "observers['%s']['Script'] = \"%s\"\n" % (
+                    __obs,
+                    __local["Script"],
+                )
+            if (
+                __local["Template"] is not None
+                and __local["Template"] in Templates.ObserverTemplates
+            ):
+                __text += "observers['%s']['nodetype'] = '%s'\n" % (__obs, "String")
+                __text += 'observers[\'%s\'][\'String\'] = """%s"""\n' % (
+                    __obs,
+                    Templates.ObserverTemplates[__local["Template"]],
+                )
+            if __local["Info"] is not None:
+                __text += 'observers[\'%s\'][\'info\'] = """%s"""\n' % (
+                    __obs,
+                    __local["Info"],
+                )
             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 += '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:
+            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[\'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[\'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 += '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', '')
+            __text = "#\n"
+            __text += "%s_config = {}\n" % __command
+            __local.pop("self", "")
             __to_be_removed = []
             __vectorIsDataFile = False
             __vectorIsScript = False
@@ -499,91 +626,160 @@ class _SCDViewer(GenericCaseViewer):
             for __k, __v in __local.items():
                 if __k == "Concept":
                     continue
-                if __k in ['ScalarSparseMatrix', 'DiagonalSparseMatrix', 'Matrix', 'OneFunction', 'ThreeFunctions'] \
-                        and 'Script' in __local \
-                        and __local['Script'] is not None:
+                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:
+                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']):
+                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'
+                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']:
+                    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 += "%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'
+                elif __k == "Script":
+                    __k = "Vector"
+                    __f = "Script"
                     __v = "'" + repr(__v) + "'"
-                    for __lk in ['ScalarSparseMatrix', 'DiagonalSparseMatrix', 'Matrix']:
+                    for __lk in [
+                        "ScalarSparseMatrix",
+                        "DiagonalSparseMatrix",
+                        "Matrix",
+                    ]:
                         if __lk in __local and __local[__lk]:
                             __k = __lk
                     if __command == "AlgorithmParameters":
                         __k = "Dict"
-                    if 'OneFunction' in __local and __local['OneFunction']:
-                        __text += "%s_ScriptWithOneFunction = {}\n"%(__command,)
-                        __text += "%s_ScriptWithOneFunction['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
-                        __text += "%s_ScriptWithOneFunction['Script'] = {}\n"%(__command,)
-                        __text += "%s_ScriptWithOneFunction['Script']['Direct'] = %s\n"%(__command, __v)
-                        __text += "%s_ScriptWithOneFunction['Script']['Tangent'] = %s\n"%(__command, __v)
-                        __text += "%s_ScriptWithOneFunction['Script']['Adjoint'] = %s\n"%(__command, __v)
-                        __text += "%s_ScriptWithOneFunction['DifferentialIncrement'] = 1e-06\n"%(__command,)
-                        __text += "%s_ScriptWithOneFunction['CenteredFiniteDifference'] = 0\n"%(__command,)
-                        __k = 'Function'
-                        __f = 'ScriptWithOneFunction'
-                        __v = '%s_ScriptWithOneFunction'%(__command,)
-                    if 'ThreeFunctions' in __local and __local['ThreeFunctions']:
-                        __text += "%s_ScriptWithFunctions = {}\n"%(__command,)
-                        __text += "%s_ScriptWithFunctions['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"%(__command,)
-                        __text += "%s_ScriptWithFunctions['Script'] = {}\n"%(__command,)
-                        __text += "%s_ScriptWithFunctions['Script']['Direct'] = %s\n"%(__command, __v)
-                        __text += "%s_ScriptWithFunctions['Script']['Tangent'] = %s\n"%(__command, __v)
-                        __text += "%s_ScriptWithFunctions['Script']['Adjoint'] = %s\n"%(__command, __v)
-                        __k = 'Function'
-                        __f = 'ScriptWithFunctions'
-                        __v = '%s_ScriptWithFunctions'%(__command,)
-                    __text += "%s_config['Type'] = '%s'\n"%(__command, __k)
-                    __text += "%s_config['From'] = '%s'\n"%(__command, __f)
-                    __text += "%s_config['Data'] = %s\n"%(__command, __v)
+                    if "OneFunction" in __local and __local["OneFunction"]:
+                        __text += "%s_ScriptWithOneFunction = {}\n" % (__command,)
+                        __text += (
+                            "%s_ScriptWithOneFunction['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"
+                            % (__command,)
+                        )
+                        __text += "%s_ScriptWithOneFunction['Script'] = {}\n" % (
+                            __command,
+                        )
+                        __text += (
+                            "%s_ScriptWithOneFunction['Script']['Direct'] = %s\n"
+                            % (__command, __v)
+                        )
+                        __text += (
+                            "%s_ScriptWithOneFunction['Script']['Tangent'] = %s\n"
+                            % (__command, __v)
+                        )
+                        __text += (
+                            "%s_ScriptWithOneFunction['Script']['Adjoint'] = %s\n"
+                            % (__command, __v)
+                        )
+                        __text += (
+                            "%s_ScriptWithOneFunction['DifferentialIncrement'] = 1e-06\n"
+                            % (__command,)
+                        )
+                        __text += (
+                            "%s_ScriptWithOneFunction['CenteredFiniteDifference'] = 0\n"
+                            % (__command,)
+                        )
+                        __k = "Function"
+                        __f = "ScriptWithOneFunction"
+                        __v = "%s_ScriptWithOneFunction" % (__command,)
+                    if "ThreeFunctions" in __local and __local["ThreeFunctions"]:
+                        __text += "%s_ScriptWithFunctions = {}\n" % (__command,)
+                        __text += (
+                            "%s_ScriptWithFunctions['Function'] = ['Direct', 'Tangent', 'Adjoint']\n"
+                            % (__command,)
+                        )
+                        __text += "%s_ScriptWithFunctions['Script'] = {}\n" % (
+                            __command,
+                        )
+                        __text += (
+                            "%s_ScriptWithFunctions['Script']['Direct'] = %s\n"
+                            % (__command, __v)
+                        )
+                        __text += (
+                            "%s_ScriptWithFunctions['Script']['Tangent'] = %s\n"
+                            % (__command, __v)
+                        )
+                        __text += (
+                            "%s_ScriptWithFunctions['Script']['Adjoint'] = %s\n"
+                            % (__command, __v)
+                        )
+                        __k = "Function"
+                        __f = "ScriptWithFunctions"
+                        __v = "%s_ScriptWithFunctions" % (__command,)
+                    __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("''", "'")
                     __vectorIsScript = True
-                elif __k in ('Stored', 'Checked', 'ColMajor', 'CrossObs', 'InputFunctionAsMulti', 'nextStep'):
+                elif __k in (
+                    "Stored",
+                    "Checked",
+                    "ColMajor",
+                    "CrossObs",
+                    "InputFunctionAsMulti",
+                    "nextStep",
+                ):
                     if bool(__v):
-                        __text += "%s_config['%s'] = '%s'\n"%(__command, __k, int(bool(__v)))
-                elif __k in ('PerformanceProfile', 'SyncObs', 'noDetails'):
+                        __text += "%s_config['%s'] = '%s'\n" % (
+                            __command,
+                            __k,
+                            int(bool(__v)),
+                        )
+                elif __k in ("PerformanceProfile", "SyncObs", "noDetails"):
                     if not bool(__v):
-                        __text += "%s_config['%s'] = '%s'\n"%(__command, __k, int(bool(__v)))
+                        __text += "%s_config['%s'] = '%s'\n" % (
+                            __command,
+                            __k,
+                            int(bool(__v)),
+                        )
                 else:
-                    if __k == 'Vector' and __vectorIsScript:
+                    if __k == "Vector" and __vectorIsScript:
                         continue
-                    if __k == 'Vector' and __vectorIsDataFile:
+                    if __k == "Vector" and __vectorIsDataFile:
                         continue
-                    if __k == 'Parameters':
+                    if __k == "Parameters":
                         __k = "Dict"
                     if isinstance(__v, Persistence.Persistence):
                         __v = __v.values()
                     if callable(__v):
-                        __text = self._missing%__v.__name__ + __text
+                        __text = self._missing % __v.__name__ + __text
                     if isinstance(__v, dict):
                         for val in __v.values():
                             if callable(val):
-                                __text = self._missing%val.__name__ + __text
-                    __text += "%s_config['Type'] = '%s'\n"%(__command, __k)
-                    __text += "%s_config['From'] = '%s'\n"%(__command, 'String')
-                    __text += "%s_config['Data'] = \"\"\"%s\"\"\"\n"%(__command, repr(__v))
-            __text += "study_config['%s'] = %s_config"%(__command, __command)
+                                __text = self._missing % val.__name__ + __text
+                    __text += "%s_config['Type'] = '%s'\n" % (__command, __k)
+                    __text += "%s_config['From'] = '%s'\n" % (__command, "String")
+                    __text += '%s_config[\'Data\'] = """%s"""\n' % (
+                        __command,
+                        repr(__v),
+                    )
+            __text += "study_config['%s'] = %s_config" % (__command, __command)
             numpy.set_printoptions(precision=8, threshold=1000, linewidth=75)
             if __switchoff:
                 self._switchoff = True
@@ -600,67 +796,80 @@ class _SCDViewer(GenericCaseViewer):
             self._addLine("#")
             self._addLine("Analysis_config = {}")
             self._addLine("Analysis_config['From'] = 'String'")
-            self._addLine("Analysis_config['Data'] = \"\"\"import numpy")
+            self._addLine('Analysis_config[\'Data\'] = """import numpy')
             self._addLine("xa=ADD.get('Analysis')[-1]")
-            self._addLine("print('Analysis:',xa)\"\"\"")
+            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)
-        study_config = __ExecVariables['study_config']
+        study_config = __ExecVariables["study_config"]
         # Pour Python 3 : self.__hasAlgorithm = bool(study_config['Algorithm'])
-        if 'Algorithm' in study_config:
+        if "Algorithm" in study_config:
             self.__hasAlgorithm = True
         else:
             self.__hasAlgorithm = False
-        if not self.__hasAlgorithm and \
-                "AlgorithmParameters" in study_config and \
-                isinstance(study_config['AlgorithmParameters'], dict) and \
-                "From" in study_config['AlgorithmParameters'] and \
-                "Data" in study_config['AlgorithmParameters'] and \
-                study_config['AlgorithmParameters']['From'] == 'Script':
-            __asScript = study_config['AlgorithmParameters']['Data']
-            __var = ImportFromScript(__asScript).getvalue( "Algorithm" )
-            __text = "#\nstudy_config['Algorithm'] = '%s'"%(__var,)
+        if (
+            not self.__hasAlgorithm
+            and "AlgorithmParameters" in study_config
+            and isinstance(study_config["AlgorithmParameters"], dict)
+            and "From" in study_config["AlgorithmParameters"]
+            and "Data" in study_config["AlgorithmParameters"]
+            and study_config["AlgorithmParameters"]["From"] == "Script"
+        ):
+            __asScript = study_config["AlgorithmParameters"]["Data"]
+            __var = ImportFromScript(__asScript).getvalue("Algorithm")
+            __text = "#\nstudy_config['Algorithm'] = '%s'" % (__var,)
             self._addLine(__text)
-        if self.__hasAlgorithm and \
-                "AlgorithmParameters" in study_config and \
-                isinstance(study_config['AlgorithmParameters'], dict) and \
-                "From" not in study_config['AlgorithmParameters'] and \
-                "Data" not in study_config['AlgorithmParameters']:
-            __text  = "#\n"
+        if (
+            self.__hasAlgorithm
+            and "AlgorithmParameters" in study_config
+            and isinstance(study_config["AlgorithmParameters"], dict)
+            and "From" not in study_config["AlgorithmParameters"]
+            and "Data" not in study_config["AlgorithmParameters"]
+        ):
+            __text = "#\n"
             __text += "AlgorithmParameters_config['Type'] = 'Dict'\n"
             __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'])
+        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":
+            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):
     """
     Etablissement des commandes d'un cas YACS (Cas->SCD->YACS)
     """
+
     __slots__ = ("__internalSCD", "_append")
 
     def __init__(self, __name="", __objname="case", __content=None, __object=None):
         "Initialisation et enregistrement de l'entete"
         GenericCaseViewer.__init__(self, __name, __objname, __content, __object)
         self.__internalSCD = _SCDViewer(__name, __objname, __content, __object)
-        self._append       = self.__internalSCD._append
+        self._append = self.__internalSCD._append
 
     def dump(self, __filename=None, __upa=None):
         "Restitution normalisée des commandes"
@@ -668,14 +877,16 @@ class _YACSViewer(GenericCaseViewer):
         if __filename is None:
             raise ValueError("A file name has to be given for YACS XML output.")
         else:
-            __file    = os.path.abspath(__filename)
+            __file = os.path.abspath(__filename)
             if os.path.isfile(__file) or os.path.islink(__file):
                 os.remove(__file)
         # -----
         if not lpi.has_salome or not lpi.has_adao:
             raise ImportError(
-                "Unable to get SALOME (%s) or ADAO (%s) environnement for YACS conversion.\n"%(lpi.has_salome, lpi.has_adao) + \
-                "Please load the right SALOME environnement before trying to use it.")
+                "Unable to get SALOME (%s) or ADAO (%s) environnement for YACS conversion.\n"
+                % (lpi.has_salome, lpi.has_adao)
+                + "Please load the right SALOME environnement before trying to use it."
+            )
         else:
             from daYacsSchemaCreator.run import create_schema_from_content
         # -----
@@ -684,9 +895,9 @@ class _YACSViewer(GenericCaseViewer):
         create_schema_from_content(__SCDdump, __file)
         # -----
         if not os.path.exists(__file):
-            __msg  = "An error occured during the ADAO YACS Schema build for\n"
+            __msg = "An error occured during the ADAO YACS Schema build for\n"
             __msg += "the target output file:\n"
-            __msg += "  %s\n"%__file
+            __msg += "  %s\n" % __file
             __msg += "See errors details in your launching terminal log.\n"
             raise ValueError(__msg)
         # -----
@@ -695,12 +906,14 @@ class _YACSViewer(GenericCaseViewer):
         __fid.close()
         return __text
 
+
 # ==============================================================================
 class _ReportViewer(GenericCaseViewer):
     """
     Partie commune de restitution simple
     """
-    __slots__ = ("_r")
+
+    __slots__ = ("_r",)
 
     def __init__(self, __name="", __objname="case", __content=None, __object=None):
         "Initialisation et enregistrement de l'entete"
@@ -711,37 +924,58 @@ class _ReportViewer(GenericCaseViewer):
             self._r.append("ADAO Study report", "title")
         else:
             self._r.append(str(self._name), "title")
-        self._r.append("Summary build with %s version %s"%(version.name, version.version))
+        self._r.append(
+            "Summary build with %s version %s" % (version.name, version.version)
+        )
         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):
+    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  = "<i>%s</i> command has been set"%str(__command.replace("set", ""))
+            __text = "<i>%s</i> command has been set" % str(
+                __command.replace("set", "")
+            )
             __ktext = ""
             for k in __keys:
-                if k not in __local: continue                           # noqa: E701
+                if k not in __local:
+                    continue
                 __v = __local[k]
-                if __v is None: continue                                # noqa: E701
-                if   k == "Checked"              and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "ColMajor"             and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "CrossObs"             and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "SyncObs"              and     __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "InputFunctionAsMulti" and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "PerformanceProfile"   and     __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "Stored"               and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "nextStep"             and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "noDetails":                        continue  # noqa: E241,E271,E272,E701
-                if   k == "Concept":                          continue  # noqa: E241,E271,E272,E701
-                if   k == "self":                             continue  # noqa: E241,E271,E272,E701
+                if __v is None:
+                    continue
+                if k == "Checked" and not __v:
+                    continue
+                if k == "ColMajor" and not __v:
+                    continue
+                if k == "CrossObs" and not __v:
+                    continue
+                if k == "SyncObs" and __v:
+                    continue
+                if k == "InputFunctionAsMulti" and not __v:
+                    continue
+                if k == "PerformanceProfile" and __v:
+                    continue
+                if k == "Stored" and not __v:
+                    continue
+                if k == "nextStep" and not __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=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
@@ -752,44 +986,54 @@ class _ReportViewer(GenericCaseViewer):
         "Enregistrement du final"
         raise NotImplementedError()
 
+
 class _SimpleReportInRstViewer(_ReportViewer):
     """
     Restitution simple en RST
     """
+
     __slots__ = ()
 
     def _finalize(self, __upa=None):
         self._lineSerie.append(Reporting.ReportViewInRst(self._r).__str__())
 
+
 class _SimpleReportInHtmlViewer(_ReportViewer):
     """
     Restitution simple en HTML
     """
+
     __slots__ = ()
 
     def _finalize(self, __upa=None):
         self._lineSerie.append(Reporting.ReportViewInHtml(self._r).__str__())
 
+
 class _SimpleReportInPlainTxtViewer(_ReportViewer):
     """
     Restitution simple en TXT
     """
+
     __slots__ = ()
 
     def _finalize(self, __upa=None):
         self._lineSerie.append(Reporting.ReportViewInPlainTxt(self._r).__str__())
 
+
 # ==============================================================================
 class ImportFromScript(object):
     """
     Obtention d'une variable nommee depuis un fichier script importé
     """
+
     __slots__ = ("__basename", "__filenspace", "__filestring")
 
     def __init__(self, __filename=None):
         "Verifie l'existence et importe le script"
         if __filename is None:
-            raise ValueError("The name of the file, containing the variable to be read, has to be specified.")
+            raise ValueError(
+                "The name of the file, containing the variable to be read, has to be specified."
+            )
         __fullname, __i = __filename, 0
         while not os.path.exists(__fullname) and __i < len(sys.path):
             # Correction avec le sys.path si nécessaire
@@ -800,37 +1044,44 @@ class ImportFromScript(object):
                 __filename = __fullname
             else:
                 raise ValueError(
-                    "The file containing the variable to be imported doesn't seem to" + \
-                    " exist. Please check the file. The given file name is:\n  \"%s\""%str(__filename))
-        if os.path.dirname(__filename) != '':
+                    "The file containing the variable to be imported doesn't seem to"
+                    + ' exist. Please check the file. The given file name is:\n  "%s"'
+                    % str(__filename)
+                )
+        if os.path.dirname(__filename) != "":
             sys.path.insert(0, os.path.dirname(__filename))
             __basename = os.path.basename(__filename).rstrip(".py")
         else:
             __basename = __filename.rstrip(".py")
-        PlatformInfo.checkFileNameImportability( __basename + ".py" )
+        PlatformInfo.checkFileNameImportability(__basename + ".py")
         self.__basename = __basename
         try:
             self.__filenspace = __import__(__basename, globals(), locals(), [])
         except NameError:
             self.__filenspace = ""
-        with open(__filename, 'r') as fid:
+        with open(__filename, "r") as fid:
             self.__filestring = fid.read()
 
-    def getvalue(self, __varname=None, __synonym=None ):
+    def getvalue(self, __varname=None, __synonym=None):
         "Renvoie la variable demandee par son nom ou son synonyme"
         if __varname is None:
-            raise ValueError("The name of the variable to be read has to be specified. Please check the content of the file and the syntax.")
+            raise ValueError(
+                "The name of the variable to be read has to be specified."
+                + " Please check the content of the file and the syntax."
+            )
         if not hasattr(self.__filenspace, __varname):
             if __synonym is None:
                 raise ValueError(
-                    "The imported script file \"%s\""%(str(self.__basename) + ".py",) + \
-                    " doesn't contain the mandatory variable \"%s\""%(__varname,) + \
-                    " to be read. Please check the content of the file and the syntax.")
+                    'The imported script file "%s"' % (str(self.__basename) + ".py",)
+                    + ' doesn\'t contain the mandatory variable "%s"' % (__varname,)
+                    + " to be read. Please check the content of the file and the syntax."
+                )
             elif not hasattr(self.__filenspace, __synonym):
                 raise ValueError(
-                    "The imported script file \"%s\""%(str(self.__basename) + ".py",) + \
-                    " doesn't contain the mandatory variable \"%s\""%(__synonym,) + \
-                    " to be read. Please check the content of the file and the syntax.")
+                    'The imported script file "%s"' % (str(self.__basename) + ".py",)
+                    + ' doesn\'t contain the mandatory variable "%s"' % (__synonym,)
+                    + " to be read. Please check the content of the file and the syntax."
+                )
             else:
                 return getattr(self.__filenspace, __synonym)
         else:
@@ -840,11 +1091,13 @@ class ImportFromScript(object):
         "Renvoie le script complet"
         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):
@@ -866,13 +1119,13 @@ class ImportDetector(object):
             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')
+        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')
+            mimetypes.add_type("text/plain", ".txt")
+            mimetypes.add_type("text/csv", ".csv")
+            mimetypes.add_type("text/tab-separated-values", ".tsv")
 
     # File related tests
     # ------------------
@@ -887,7 +1140,10 @@ class ImportDetector(object):
 
     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))
+            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
 
@@ -904,7 +1160,10 @@ class ImportDetector(object):
 
     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))
+            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
 
@@ -938,6 +1197,7 @@ class ImportDetector(object):
     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
@@ -951,10 +1211,22 @@ class ImportFromFile(object):
     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", "_colnames", "_colindex", "_varsline", "_format",
-        "_delimiter", "_skiprows", "__url", "__filestring", "__header",
-        "__allowvoid", "__binaryformats", "__supportedformats")
+        "_filename",
+        "_colnames",
+        "_colindex",
+        "_varsline",
+        "_format",
+        "_delimiter",
+        "_skiprows",
+        "__url",
+        "__filestring",
+        "__header",
+        "__allowvoid",
+        "__binaryformats",
+        "__supportedformats",
+    )
 
     def __enter__(self):
         return self
@@ -962,7 +1234,14 @@ class ImportFromFile(object):
     def __exit__(self, exc_type, exc_val, exc_tb):
         return False
 
-    def __init__(self, Filename=None, ColNames=None, ColIndex=None, Format="Guess", AllowVoidNameList=True):
+    def __init__(
+        self,
+        Filename=None,
+        ColNames=None,
+        ColIndex=None,
+        Format="Guess",
+        AllowVoidNameList=True,
+    ):
         """
         Verifie l'existence et les informations de définition du fichier. Les
         noms de colonnes ou de variables sont ignorées si le format ne permet
@@ -980,10 +1259,10 @@ class ImportFromFile(object):
             "application/numpy.npz",
             "application/dymola.sdf",
         )
-        self.__url = ImportDetector( Filename, Format)
+        self.__url = ImportDetector(Filename, Format)
         self.__url.raise_error_if_not_local_file()
         self._filename = self.__url.get_absolute_name()
-        PlatformInfo.checkFileNameConformity( self._filename )
+        PlatformInfo.checkFileNameConformity(self._filename)
         #
         self._format = self.__url.get_comprehensive_mime()
         #
@@ -1016,7 +1295,7 @@ class ImportFromFile(object):
         #
         self.__allowvoid = bool(AllowVoidNameList)
 
-    def __getentete(self, __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
@@ -1024,7 +1303,7 @@ class ImportFromFile(object):
         if self._format in self.__binaryformats:
             pass
         else:
-            with open(self._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)
@@ -1035,12 +1314,12 @@ class ImportFromFile(object):
                     __header.append(fid.readline())
         return (__header, __varsline, __skiprows)
 
-    def __getindices(self, __colnames, __colindex, __delimiter=None ):
+    def __getindices(self, __colnames, __colindex, __delimiter=None):
         "Indices de colonnes correspondants à l'index et aux variables"
         if __delimiter is None:
-            __varserie = self._varsline.strip('#').strip().split()
+            __varserie = self._varsline.strip("#").strip().split()
         else:
-            __varserie = self._varsline.strip('#').strip().split(str(__delimiter))
+            __varserie = self._varsline.strip("#").strip().split(str(__delimiter))
         #
         if __colnames is not None:
             __usecols = []
@@ -1054,7 +1333,10 @@ class ImportFromFile(object):
                 if self.__allowvoid:
                     __usecols = None
                 else:
-                    raise ValueError("Can not found any column corresponding to the required names %s"%(__colnames,))
+                    raise ValueError(
+                        "Can not found any column corresponding to the required names %s"
+                        % (__colnames,)
+                    )
         else:
             __usecols = None
         #
@@ -1071,15 +1353,15 @@ class ImportFromFile(object):
 
     def getsupported(self):
         self.__supportedformats = {}
-        self.__supportedformats["text/plain"]                = True
-        self.__supportedformats["text/csv"]                  = True
+        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"]    = lpi.has_sdf
+        self.__supportedformats["application/numpy.npy"] = True
+        self.__supportedformats["application/numpy.npz"] = True
+        self.__supportedformats["application/dymola.sdf"] = lpi.has_sdf
         return self.__supportedformats
 
-    def getvalue(self, ColNames=None, ColIndex=None ):
+    def getvalue(self, ColNames=None, ColIndex=None):
         "Renvoie la ou les variables demandées par la liste de leurs noms"
         # Uniquement si mise à jour
         if ColNames is not None:
@@ -1098,36 +1380,53 @@ class ImportFromFile(object):
                     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 )
+                        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
-                            __columns = numpy.vstack((__columns, numpy.reshape(__allcolumns[nom], (1, -1))))
+                            __columns = numpy.vstack(
+                                (__columns, numpy.reshape(__allcolumns[nom], (1, -1)))
+                            )
                         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)
+                    __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)
+            __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)
+                __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 lpi.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))]
+                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))))
+                        __columns = numpy.vstack(
+                            (__columns, numpy.reshape(__content[nom].data, (1, -1)))
+                        )
                     else:
                         # Première colonne
                         __columns = numpy.reshape(__content[nom].data, (1, -1))
@@ -1135,22 +1434,50 @@ class ImportFromFile(object):
                 __index = __content[self._colindex].data
         #
         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)
+            __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)
+                __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 == "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)
+            __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)
+                __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\" or no reader available"%self._format)
+            raise ValueError(
+                'Unkown file format "%s" or no reader available' % self._format
+            )
         if __columns is None:
             __columns = ()
 
@@ -1159,6 +1486,7 @@ class ImportFromFile(object):
                 return value.decode()
             except ValueError:
                 return value
+
         if __index is not None:
             __index = tuple([toString(v) for v in __index])
         #
@@ -1169,12 +1497,13 @@ class ImportFromFile(object):
         if self._format in self.__binaryformats:
             return ""
         else:
-            with open(self._filename, 'r') as fid:
+            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
@@ -1185,6 +1514,7 @@ class ImportScalarLinesFromFile(ImportFromFile):
 
     Seule la méthode "getvalue" est changée.
     """
+
     __slots__ = ()
 
     def __enter__(self):
@@ -1196,77 +1526,104 @@ 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 ["text/plain", "text/csv", "text/tab-separated-values"]:
-            raise ValueError("Unkown file format \"%s\""%self._format)
+            raise ValueError('Unkown file format "%s"' % self._format)
 
-    def getvalue(self, VarNames = None, HeaderNames=()):
+    def getvalue(self, VarNames=None, HeaderNames=()):
         "Renvoie la ou les variables demandées par la liste de leurs noms"
         if VarNames is not None:
             __varnames = tuple(VarNames)
         else:
             __varnames = None
         #
-        if "Name" in self._varsline and "Value" in self._varsline and "Minimum" in self._varsline and "Maximum" in self._varsline:
+        if (
+            "Name" in self._varsline
+            and "Value" in self._varsline
+            and "Minimum" in self._varsline
+            and "Maximum" in self._varsline
+        ):
             __ftype = "NamValMinMax"
-            __dtypes   = {'names'  : ('Name', 'Value', 'Minimum', 'Maximum'),  # noqa: E203
-                          'formats': ('S128', 'g', 'g', 'g')}
-            __usecols  = (0, 1, 2, 3)
-
-            def __replaceNoneN( s ):
-                if s.strip() in (b'None', 'None'):
+            __dtypes = {
+                "names": ("Name", "Value", "Minimum", "Maximum"),
+                "formats": ("S128", "g", "g", "g"),
+            }
+            __usecols = (0, 1, 2, 3)
+
+            def __replaceNoneN(s):
+                if s.strip() in (b"None", "None"):
                     return -numpy.inf
                 else:
                     return s
 
-            def __replaceNoneP( s ):
-                if s.strip() in (b'None', 'None'):
+            def __replaceNoneP(s):
+                if s.strip() in (b"None", "None"):
                     return numpy.inf
                 else:
                     return s
+
             __converters = {2: __replaceNoneN, 3: __replaceNoneP}
-        elif "Name" in self._varsline and "Value" in self._varsline and ("Minimum" not in self._varsline or "Maximum" not in self._varsline):
+        elif (
+            "Name" in self._varsline
+            and "Value" in self._varsline
+            and ("Minimum" not in self._varsline or "Maximum" not in self._varsline)
+        ):
             __ftype = "NamVal"
-            __dtypes   = {'names'  : ('Name', 'Value'),  # noqa: E203
-                          'formats': ('S128', 'g')}
+            __dtypes = {
+                "names": ("Name", "Value"),
+                "formats": ("S128", "g"),
+            }
             __converters = None
-            __usecols  = (0, 1)
-        elif len(HeaderNames) > 0 and numpy.all([kw in self._varsline for kw in HeaderNames]):
+            __usecols = (0, 1)
+        elif len(HeaderNames) > 0 and numpy.all(
+            [kw in self._varsline for kw in HeaderNames]
+        ):
             __ftype = "NamLotOfVals"
-            __dtypes   = {'names'  : HeaderNames,  # noqa: E203
-                          'formats': tuple(['S128',] + ['g'] * (len(HeaderNames) - 1))}
-            __usecols  = tuple(range(len(HeaderNames)))
-
-            def __replaceNone( s ):
-                if s.strip() in (b'None', 'None'):
+            __dtypes = {
+                "names": HeaderNames,
+                "formats": tuple(
+                    [
+                        "S128",
+                    ]
+                    + ["g"] * (len(HeaderNames) - 1)
+                ),
+            }
+            __usecols = tuple(range(len(HeaderNames)))
+
+            def __replaceNone(s):
+                if s.strip() in (b"None", "None"):
                     return numpy.nan
                 else:
                     return s
+
             __converters = dict()
             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\""%self._varsline)
+            raise ValueError(
+                "Can not find names of columns for initial values."
+                + ' Wrong first line is:\n            "%s"' % self._varsline
+            )
         #
         if self._format == "text/plain":
             __content = numpy.loadtxt(
                 self._filename,
-                dtype      = __dtypes,
-                usecols    = __usecols,
-                skiprows   = self._skiprows,
-                converters = __converters,
-                ndmin      = 1,
+                dtype=__dtypes,
+                usecols=__usecols,
+                skiprows=self._skiprows,
+                converters=__converters,
+                ndmin=1,
             )
         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,
-                ndmin      = 1,
+                dtype=__dtypes,
+                usecols=__usecols,
+                skiprows=self._skiprows,
+                converters=__converters,
+                delimiter=self._delimiter,
+                ndmin=1,
             )
         else:
-            raise ValueError("Unkown file format \"%s\""%self._format)
+            raise ValueError('Unkown file format "%s"' % self._format)
         #
         __names, __thevalue, __bounds = [], [], []
         for sub in __content:
@@ -1298,20 +1655,22 @@ class ImportScalarLinesFromFile(ImportFromFile):
                 __thevalue.append(va)
                 __bounds.append((mi, ma))
         #
-        __names      = tuple(__names)
+        __names = tuple(__names)
         __thevalue = numpy.array(__thevalue)
-        __bounds     = tuple(__bounds)
+        __bounds = tuple(__bounds)
         #
         return (__names, __thevalue, __bounds)
 
+
 # ==============================================================================
 class EficasGUI(object):
     """
     Lancement autonome de l'interface EFICAS/ADAO
     """
+
     __slots__ = ("__msg", "__path_settings_ok")
 
-    def __init__(self, __addpath = None):
+    def __init__(self, __addpath=None):
         # Chemin pour l'installation (ordre important)
         self.__msg = ""
         self.__path_settings_ok = False
@@ -1323,44 +1682,54 @@ class EficasGUI(object):
             __EFICAS_TOOLS_ROOT = os.environ["EFICAS_NOUVEAU_ROOT"]
             __path_ok = True
         else:
-            self.__msg += "\nKeyError:\n" + \
-                "  the required environment variable EFICAS_TOOLS_ROOT is unknown.\n" + \
-                "  You have either to be in SALOME environment, or to set this\n" + \
-                "  variable in your environment to the right path \"<...>\" to\n" + \
-                "  find an installed EFICAS application. For example:\n" + \
-                "      EFICAS_TOOLS_ROOT=\"<...>\" command\n"
+            self.__msg += (
+                "\nKeyError:\n"
+                + "  the required environment variable EFICAS_TOOLS_ROOT is unknown.\n"
+                + "  You have either to be in SALOME environment, or to set this\n"
+                + '  variable in your environment to the right path "<...>" to\n'
+                + "  find an installed EFICAS application. For example:\n"
+                + '      EFICAS_TOOLS_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"
+            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  # noqa: F401
+
             __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"
+            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"
+            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:
@@ -1382,9 +1751,13 @@ class EficasGUI(object):
             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.")
+            logging.debug(
+                "Can not launch standalone EFICAS/ADAO interface for path errors."
+            )
+
 
 # ==============================================================================
 if __name__ == "__main__":
index 5903cddbced50da59c738fa77ad20e791ad116ec..ec1f7b71a17fd72e926c20457d76573c773f532c 100644 (file)
@@ -25,19 +25,30 @@ __doc__ = """
 """
 __author__ = "Jean-Philippe ARGAUD"
 
-import os, copy, types, sys, logging, math, numpy, scipy, itertools, warnings
+import os
+import copy
+import types
+import sys
+import logging
+import math
+import numpy
+import scipy
+import itertools
+import warnings
 import scipy.linalg  # Py3.6
 from daCore.BasicObjects import Operator, Covariance, PartialAlgorithm
 from daCore.PlatformInfo import PlatformInfo, vt, vfloat
+
 mpr = PlatformInfo().MachinePrecision()
 mfp = PlatformInfo().MaximumPrecision()
 # logging.getLogger().setLevel(logging.DEBUG)
 
+
 # ==============================================================================
-def ExecuteFunction( triplet ):
+def ExecuteFunction(triplet):
     assert len(triplet) == 3, "Incorrect number of arguments"
     X, xArgs, funcrepr = triplet
-    __X = numpy.ravel( X ).reshape((-1, 1))
+    __X = numpy.ravel(X).reshape((-1, 1))
     __sys_path_tmp = sys.path
     sys.path.insert(0, funcrepr["__userFunction__path"])
     __module = __import__(funcrepr["__userFunction__modl"], globals(), locals(), [])
@@ -45,10 +56,11 @@ def ExecuteFunction( triplet ):
     sys.path = __sys_path_tmp
     del __sys_path_tmp
     if isinstance(xArgs, dict):
-        __HX  = __fonction( __X, **xArgs )
+        __HX = __fonction(__X, **xArgs)
     else:
-        __HX  = __fonction( __X )
-    return numpy.ravel( __HX )
+        __HX = __fonction(__X)
+    return numpy.ravel(__HX)
+
 
 # ==============================================================================
 class FDApproximation(object):
@@ -61,28 +73,49 @@ class FDApproximation(object):
     "dX" qui sera multiplié par "increment" (donc en %), et on effectue de DF
     centrées si le booléen "centeredDF" est vrai.
     """
+
     __slots__ = (
-        "__name", "__extraArgs", "__mpEnabled", "__mpWorkers", "__mfEnabled",
-        "__rmEnabled", "__avoidRC", "__tolerBP", "__centeredDF", "__lengthRJ",
-        "__listJPCP", "__listJPCI", "__listJPCR", "__listJPPN", "__listJPIN",
-        "__userOperator", "__userFunction", "__increment", "__pool", "__dX",
-        "__userFunction__name", "__userFunction__modl", "__userFunction__path",
+        "__name",
+        "__extraArgs",
+        "__mpEnabled",
+        "__mpWorkers",
+        "__mfEnabled",
+        "__rmEnabled",
+        "__avoidRC",
+        "__tolerBP",
+        "__centeredDF",
+        "__lengthRJ",
+        "__listJPCP",
+        "__listJPCI",
+        "__listJPCR",
+        "__listJPPN",
+        "__listJPIN",
+        "__userOperator",
+        "__userFunction",
+        "__increment",
+        "__pool",
+        "__dX",
+        "__userFunction__name",
+        "__userFunction__modl",
+        "__userFunction__path",
     )
 
-    def __init__(self,
-                 name                  = "FDApproximation",
-                 Function              = None,
-                 centeredDF            = False,
-                 increment             = 0.01,
-                 dX                    = None,
-                 extraArguments        = None,
-                 reducingMemoryUse     = False,
-                 avoidingRedundancy    = True,
-                 toleranceInRedundancy = 1.e-18,
-                 lengthOfRedundancy    = -1,
-                 mpEnabled             = False,
-                 mpWorkers             = None,
-                 mfEnabled             = False ):
+    def __init__(
+        self,
+        name="FDApproximation",
+        Function=None,
+        centeredDF=False,
+        increment=0.01,
+        dX=None,
+        extraArguments=None,
+        reducingMemoryUse=False,
+        avoidingRedundancy=True,
+        toleranceInRedundancy=1.0e-18,
+        lengthOfRedundancy=-1,
+        mpEnabled=False,
+        mpWorkers=None,
+        mfEnabled=False,
+    ):
         #
         self.__name = str(name)
         self.__extraArgs = extraArguments
@@ -90,6 +123,7 @@ class FDApproximation(object):
         if mpEnabled:
             try:
                 import multiprocessing  # noqa: F401
+
                 self.__mpEnabled = True
             except ImportError:
                 self.__mpEnabled = False
@@ -98,13 +132,16 @@ class FDApproximation(object):
         self.__mpWorkers = mpWorkers
         if self.__mpWorkers is not None and self.__mpWorkers < 1:
             self.__mpWorkers = None
-        logging.debug("FDA Calculs en multiprocessing : %s (nombre de processus : %s)"%(self.__mpEnabled, self.__mpWorkers))
+        logging.debug(
+            "FDA Calculs en multiprocessing : %s (nombre de processus : %s)"
+            % (self.__mpEnabled, self.__mpWorkers)
+        )
         #
         self.__mfEnabled = bool(mfEnabled)
-        logging.debug("FDA Calculs en multifonctions : %s"%(self.__mfEnabled,))
+        logging.debug("FDA Calculs en multifonctions : %s" % (self.__mfEnabled,))
         #
         self.__rmEnabled = bool(reducingMemoryUse)
-        logging.debug("FDA Calculs avec réduction mémoire : %s"%(self.__rmEnabled,))
+        logging.debug("FDA Calculs avec réduction mémoire : %s" % (self.__rmEnabled,))
         #
         if avoidingRedundancy:
             self.__avoidRC = True
@@ -117,69 +154,102 @@ class FDApproximation(object):
             self.__listJPIN = []  # Jacobian Previous Calculated Increment Norms
         else:
             self.__avoidRC = False
-        logging.debug("FDA Calculs avec réduction des doublons : %s"%self.__avoidRC)
+        logging.debug("FDA Calculs avec réduction des doublons : %s" % self.__avoidRC)
         if self.__avoidRC:
-            logging.debug("FDA Tolérance de détermination des doublons : %.2e"%self.__tolerBP)
+            logging.debug(
+                "FDA Tolérance de détermination des doublons : %.2e" % self.__tolerBP
+            )
         #
         if self.__mpEnabled:
             if isinstance(Function, types.FunctionType):
                 logging.debug("FDA Calculs en multiprocessing : FunctionType")
                 self.__userFunction__name = Function.__name__
                 try:
-                    mod = os.path.join(Function.__globals__['filepath'], Function.__globals__['filename'])
+                    mod = os.path.join(
+                        Function.__globals__["filepath"],
+                        Function.__globals__["filename"],
+                    )
                 except Exception:
-                    mod = os.path.abspath(Function.__globals__['__file__'])
+                    mod = os.path.abspath(Function.__globals__["__file__"])
                 if not os.path.isfile(mod):
-                    raise ImportError("No user defined function or method found with the name %s"%(mod,))
-                self.__userFunction__modl = os.path.basename(mod).replace('.pyc', '').replace('.pyo', '').replace('.py', '')
+                    raise ImportError(
+                        "No user defined function or method found with the name %s"
+                        % (mod,)
+                    )
+                self.__userFunction__modl = (
+                    os.path.basename(mod)
+                    .replace(".pyc", "")
+                    .replace(".pyo", "")
+                    .replace(".py", "")
+                )
                 self.__userFunction__path = os.path.dirname(mod)
                 del mod
                 self.__userOperator = Operator(
-                    name                 = self.__name,
-                    fromMethod           = Function,
-                    avoidingRedundancy   = self.__avoidRC,
-                    inputAsMultiFunction = self.__mfEnabled,
-                    extraArguments       = self.__extraArgs )
-                self.__userFunction = self.__userOperator.appliedTo  # Pour le calcul Direct
+                    name=self.__name,
+                    fromMethod=Function,
+                    avoidingRedundancy=self.__avoidRC,
+                    inputAsMultiFunction=self.__mfEnabled,
+                    extraArguments=self.__extraArgs,
+                )
+                self.__userFunction = (
+                    self.__userOperator.appliedTo
+                )  # Pour le calcul Direct
             elif isinstance(Function, types.MethodType):
                 logging.debug("FDA Calculs en multiprocessing : MethodType")
                 self.__userFunction__name = Function.__name__
                 try:
-                    mod = os.path.join(Function.__globals__['filepath'], Function.__globals__['filename'])
+                    mod = os.path.join(
+                        Function.__globals__["filepath"],
+                        Function.__globals__["filename"],
+                    )
                 except Exception:
-                    mod = os.path.abspath(Function.__func__.__globals__['__file__'])
+                    mod = os.path.abspath(Function.__func__.__globals__["__file__"])
                 if not os.path.isfile(mod):
-                    raise ImportError("No user defined function or method found with the name %s"%(mod,))
-                self.__userFunction__modl = os.path.basename(mod).replace('.pyc', '').replace('.pyo', '').replace('.py', '')
+                    raise ImportError(
+                        "No user defined function or method found with the name %s"
+                        % (mod,)
+                    )
+                self.__userFunction__modl = (
+                    os.path.basename(mod)
+                    .replace(".pyc", "")
+                    .replace(".pyo", "")
+                    .replace(".py", "")
+                )
                 self.__userFunction__path = os.path.dirname(mod)
                 del mod
                 self.__userOperator = Operator(
-                    name                 = self.__name,
-                    fromMethod           = Function,
-                    avoidingRedundancy   = self.__avoidRC,
-                    inputAsMultiFunction = self.__mfEnabled,
-                    extraArguments       = self.__extraArgs )
-                self.__userFunction = self.__userOperator.appliedTo  # Pour le calcul Direct
+                    name=self.__name,
+                    fromMethod=Function,
+                    avoidingRedundancy=self.__avoidRC,
+                    inputAsMultiFunction=self.__mfEnabled,
+                    extraArguments=self.__extraArgs,
+                )
+                self.__userFunction = (
+                    self.__userOperator.appliedTo
+                )  # Pour le calcul Direct
             else:
-                raise TypeError("User defined function or method has to be provided for finite differences approximation.")
+                raise TypeError(
+                    "User defined function or method has to be provided for finite differences approximation."
+                )
         else:
             self.__userOperator = Operator(
-                name                 = self.__name,
-                fromMethod           = Function,
-                avoidingRedundancy   = self.__avoidRC,
-                inputAsMultiFunction = self.__mfEnabled,
-                extraArguments       = self.__extraArgs )
+                name=self.__name,
+                fromMethod=Function,
+                avoidingRedundancy=self.__avoidRC,
+                inputAsMultiFunction=self.__mfEnabled,
+                extraArguments=self.__extraArgs,
+            )
             self.__userFunction = self.__userOperator.appliedTo
         #
         self.__centeredDF = bool(centeredDF)
-        if abs(float(increment)) > 1.e-15:
-            self.__increment  = float(increment)
+        if abs(float(increment)) > 1.0e-15:
+            self.__increment = float(increment)
         else:
-            self.__increment  = 0.01
+            self.__increment = 0.01
         if dX is None:
-            self.__dX     = None
+            self.__dX = None
         else:
-            self.__dX     = numpy.ravel( dX )
+            self.__dX = numpy.ravel(dX)
 
     # ---------------------------------------------------------
     def __doublon__(self, __e, __l, __n, __v=None):
@@ -188,35 +258,40 @@ class FDApproximation(object):
             if numpy.linalg.norm(__e - __l[i]) < self.__tolerBP * __n[i]:
                 __ac, __iac = True, i
                 if __v is not None:
-                    logging.debug("FDA Cas%s déjà calculé, récupération du doublon %i"%(__v, __iac))
+                    logging.debug(
+                        "FDA Cas%s déjà calculé, récupération du doublon %i"
+                        % (__v, __iac)
+                    )
                 break
         return __ac, __iac
 
     # ---------------------------------------------------------
-    def __listdotwith__(self, __LMatrix, __dotWith = None, __dotTWith = None):
+    def __listdotwith__(self, __LMatrix, __dotWith=None, __dotTWith=None):
         "Produit incrémental d'une matrice liste de colonnes avec un vecteur"
         if not isinstance(__LMatrix, (list, tuple)):
-            raise TypeError("Columnwise list matrix has not the proper type: %s"%type(__LMatrix))
+            raise TypeError(
+                "Columnwise list matrix has not the proper type: %s" % type(__LMatrix)
+            )
         if __dotWith is not None:
-            __Idwx = numpy.ravel( __dotWith )
+            __Idwx = numpy.ravel(__dotWith)
             assert len(__LMatrix) == __Idwx.size, "Incorrect size of elements"
             __Produit = numpy.zeros(__LMatrix[0].size)
             for i, col in enumerate(__LMatrix):
                 __Produit += float(__Idwx[i]) * col
             return __Produit
         elif __dotTWith is not None:
-            _Idwy = numpy.ravel( __dotTWith ).T
+            _Idwy = numpy.ravel(__dotTWith).T
             assert __LMatrix[0].size == _Idwy.size, "Incorrect size of elements"
             __Produit = numpy.zeros(len(__LMatrix))
             for i, col in enumerate(__LMatrix):
-                __Produit[i] = vfloat( _Idwy @ col)
+                __Produit[i] = vfloat(_Idwy @ col)
             return __Produit
         else:
             __Produit = None
         return __Produit
 
     # ---------------------------------------------------------
-    def DirectOperator(self, X, **extraArgs ):
+    def DirectOperator(self, X, **extraArgs):
         """
         Calcul du direct à l'aide de la fonction fournie.
 
@@ -225,14 +300,14 @@ class FDApproximation(object):
         """
         logging.debug("FDA Calcul DirectOperator (explicite)")
         if self.__mfEnabled:
-            _HX = self.__userFunction( X, argsAsSerie = True )
+            _HX = self.__userFunction(X, argsAsSerie=True)
         else:
-            _HX = numpy.ravel(self.__userFunction( numpy.ravel(X) ))
+            _HX = numpy.ravel(self.__userFunction(numpy.ravel(X)))
         #
         return _HX
 
     # ---------------------------------------------------------
-    def TangentMatrix(self, X, dotWith = None, dotTWith = None ):
+    def TangentMatrix(self, X, dotWith=None, dotTWith=None):
         """
         Calcul de l'opérateur tangent comme la Jacobienne par différences finies,
         c'est-à-dire le gradient de H en X. On utilise des différences finies
@@ -258,44 +333,59 @@ class FDApproximation(object):
 
         """
         logging.debug("FDA Début du calcul de la Jacobienne")
-        logging.debug("FDA   Incrément de............: %s*X"%float(self.__increment))
-        logging.debug("FDA   Approximation centrée...: %s"%(self.__centeredDF))
+        logging.debug("FDA   Incrément de............: %s*X" % float(self.__increment))
+        logging.debug("FDA   Approximation centrée...: %s" % (self.__centeredDF))
         #
         if X is None or len(X) == 0:
-            raise ValueError("Nominal point X for approximate derivatives can not be None or void (given X: %s)."%(str(X),))
+            raise ValueError(
+                "Nominal point X for approximate derivatives can not be None or void (given X: %s)."
+                % (str(X),)
+            )
         #
-        _X = numpy.ravel( X )
+        _X = numpy.ravel(X)
         #
         if self.__dX is None:
-            _dX  = self.__increment * _X
+            _dX = self.__increment * _X
         else:
-            _dX = numpy.ravel( self.__dX )
-        assert len(_X) == len(_dX), "Inconsistent dX increment length with respect to the X one"
-        assert _X.size == _dX.size, "Inconsistent dX increment size with respect to the X one"
+            _dX = numpy.ravel(self.__dX)
+        assert len(_X) == len(
+            _dX
+        ), "Inconsistent dX increment length with respect to the X one"
+        assert (
+            _X.size == _dX.size
+        ), "Inconsistent dX increment size with respect to the X one"
         #
-        if (_dX == 0.).any():
+        if (_dX == 0.0).any():
             moyenne = _dX.mean()
-            if moyenne == 0.:
-                _dX = numpy.where( _dX == 0., float(self.__increment), _dX )
+            if moyenne == 0.0:
+                _dX = numpy.where(_dX == 0.0, float(self.__increment), _dX)
             else:
-                _dX = numpy.where( _dX == 0., moyenne, _dX )
+                _dX = numpy.where(_dX == 0.0, moyenne, _dX)
         #
-        __alreadyCalculated  = False
+        __alreadyCalculated = False
         if self.__avoidRC:
-            __bidon, __alreadyCalculatedP = self.__doublon__( _X, self.__listJPCP, self.__listJPPN, None)
-            __bidon, __alreadyCalculatedI = self.__doublon__(_dX, self.__listJPCI, self.__listJPIN, None)
+            __bidon, __alreadyCalculatedP = self.__doublon__(
+                _X, self.__listJPCP, self.__listJPPN, None
+            )
+            __bidon, __alreadyCalculatedI = self.__doublon__(
+                _dX, self.__listJPCI, self.__listJPIN, None
+            )
             if __alreadyCalculatedP == __alreadyCalculatedI > -1:
                 __alreadyCalculated, __i = True, __alreadyCalculatedP
-                logging.debug("FDA Cas J déjà calculé, récupération du doublon %i"%__i)
+                logging.debug(
+                    "FDA Cas J déjà calculé, récupération du doublon %i" % __i
+                )
         #
         if __alreadyCalculated:
-            logging.debug("FDA   Calcul Jacobienne (par récupération du doublon %i)"%__i)
+            logging.debug(
+                "FDA   Calcul Jacobienne (par récupération du doublon %i)" % __i
+            )
             _Jacobienne = self.__listJPCR[__i]
             logging.debug("FDA Fin du calcul de la Jacobienne")
             if dotWith is not None:
-                return numpy.dot(  _Jacobienne, numpy.ravel( dotWith ))
+                return numpy.dot(_Jacobienne, numpy.ravel(dotWith))
             elif dotTWith is not None:
-                return numpy.dot(_Jacobienne.T, numpy.ravel( dotTWith ))
+                return numpy.dot(_Jacobienne.T, numpy.ravel(dotTWith))
         else:
             logging.debug("FDA   Calcul Jacobienne (explicite)")
             if self.__centeredDF:
@@ -307,57 +397,70 @@ class FDApproximation(object):
                         "__userFunction__name": self.__userFunction__name,
                     }
                     _jobs = []
-                    for i in range( len(_dX) ):
-                        _dXi            = _dX[i]
-                        _X_plus_dXi     = numpy.array( _X, dtype=float )
-                        _X_plus_dXi[i]  = _X[i] + _dXi
-                        _X_moins_dXi    = numpy.array( _X, dtype=float )
+                    for i in range(len(_dX)):
+                        _dXi = _dX[i]
+                        _X_plus_dXi = numpy.array(_X, dtype=float)
+                        _X_plus_dXi[i] = _X[i] + _dXi
+                        _X_moins_dXi = numpy.array(_X, dtype=float)
                         _X_moins_dXi[i] = _X[i] - _dXi
                         #
-                        _jobs.append( ( _X_plus_dXi, self.__extraArgs, funcrepr) )
-                        _jobs.append( (_X_moins_dXi, self.__extraArgs, funcrepr) )
+                        _jobs.append((_X_plus_dXi, self.__extraArgs, funcrepr))
+                        _jobs.append((_X_moins_dXi, self.__extraArgs, funcrepr))
                     #
                     import multiprocessing
+
                     self.__pool = multiprocessing.Pool(self.__mpWorkers)
-                    _HX_plusmoins_dX = self.__pool.map( ExecuteFunction, _jobs )
+                    _HX_plusmoins_dX = self.__pool.map(ExecuteFunction, _jobs)
                     self.__pool.close()
                     self.__pool.join()
                     #
-                    _Jacobienne  = []
-                    for i in range( len(_dX) ):
-                        _Jacobienne.append( numpy.ravel( _HX_plusmoins_dX[2 * i] - _HX_plusmoins_dX[2 * i + 1] ) / (2. * _dX[i]) )
+                    _Jacobienne = []
+                    for i in range(len(_dX)):
+                        _Jacobienne.append(
+                            numpy.ravel(
+                                _HX_plusmoins_dX[2 * i] - _HX_plusmoins_dX[2 * i + 1]
+                            )
+                            / (2.0 * _dX[i])
+                        )
                     #
                 elif self.__mfEnabled:
                     _xserie = []
-                    for i in range( len(_dX) ):
-                        _dXi            = _dX[i]
-                        _X_plus_dXi     = numpy.array( _X, dtype=float )
-                        _X_plus_dXi[i]  = _X[i] + _dXi
-                        _X_moins_dXi    = numpy.array( _X, dtype=float )
+                    for i in range(len(_dX)):
+                        _dXi = _dX[i]
+                        _X_plus_dXi = numpy.array(_X, dtype=float)
+                        _X_plus_dXi[i] = _X[i] + _dXi
+                        _X_moins_dXi = numpy.array(_X, dtype=float)
                         _X_moins_dXi[i] = _X[i] - _dXi
                         #
-                        _xserie.append( _X_plus_dXi )
-                        _xserie.append( _X_moins_dXi )
+                        _xserie.append(_X_plus_dXi)
+                        _xserie.append(_X_moins_dXi)
                     #
-                    _HX_plusmoins_dX = self.DirectOperator( _xserie )
+                    _HX_plusmoins_dX = self.DirectOperator(_xserie)
                     #
-                    _Jacobienne  = []
-                    for i in range( len(_dX) ):
-                        _Jacobienne.append( numpy.ravel( _HX_plusmoins_dX[2 * i] - _HX_plusmoins_dX[2 * i + 1] ) / (2. * _dX[i]) )
+                    _Jacobienne = []
+                    for i in range(len(_dX)):
+                        _Jacobienne.append(
+                            numpy.ravel(
+                                _HX_plusmoins_dX[2 * i] - _HX_plusmoins_dX[2 * i + 1]
+                            )
+                            / (2.0 * _dX[i])
+                        )
                     #
                 else:
-                    _Jacobienne  = []
-                    for i in range( _dX.size ):
-                        _dXi            = _dX[i]
-                        _X_plus_dXi     = numpy.array( _X, dtype=float )
-                        _X_plus_dXi[i]  = _X[i] + _dXi
-                        _X_moins_dXi    = numpy.array( _X, dtype=float )
+                    _Jacobienne = []
+                    for i in range(_dX.size):
+                        _dXi = _dX[i]
+                        _X_plus_dXi = numpy.array(_X, dtype=float)
+                        _X_plus_dXi[i] = _X[i] + _dXi
+                        _X_moins_dXi = numpy.array(_X, dtype=float)
                         _X_moins_dXi[i] = _X[i] - _dXi
                         #
-                        _HX_plus_dXi    = self.DirectOperator( _X_plus_dXi )
-                        _HX_moins_dXi   = self.DirectOperator( _X_moins_dXi )
+                        _HX_plus_dXi = self.DirectOperator(_X_plus_dXi)
+                        _HX_moins_dXi = self.DirectOperator(_X_moins_dXi)
                         #
-                        _Jacobienne.append( numpy.ravel( _HX_plus_dXi - _HX_moins_dXi ) / (2. * _dXi) )
+                        _Jacobienne.append(
+                            numpy.ravel(_HX_plus_dXi - _HX_moins_dXi) / (2.0 * _dXi)
+                        )
                 #
             else:
                 #
@@ -368,60 +471,61 @@ class FDApproximation(object):
                         "__userFunction__name": self.__userFunction__name,
                     }
                     _jobs = []
-                    _jobs.append( (_X, self.__extraArgs, funcrepr) )
-                    for i in range( len(_dX) ):
-                        _X_plus_dXi    = numpy.array( _X, dtype=float )
+                    _jobs.append((_X, self.__extraArgs, funcrepr))
+                    for i in range(len(_dX)):
+                        _X_plus_dXi = numpy.array(_X, dtype=float)
                         _X_plus_dXi[i] = _X[i] + _dX[i]
                         #
-                        _jobs.append( (_X_plus_dXi, self.__extraArgs, funcrepr) )
+                        _jobs.append((_X_plus_dXi, self.__extraArgs, funcrepr))
                     #
                     import multiprocessing
+
                     self.__pool = multiprocessing.Pool(self.__mpWorkers)
-                    _HX_plus_dX = self.__pool.map( ExecuteFunction, _jobs )
+                    _HX_plus_dX = self.__pool.map(ExecuteFunction, _jobs)
                     self.__pool.close()
                     self.__pool.join()
                     #
                     _HX = _HX_plus_dX.pop(0)
                     #
                     _Jacobienne = []
-                    for i in range( len(_dX) ):
-                        _Jacobienne.append( numpy.ravel(( _HX_plus_dX[i] - _HX ) / _dX[i]) )
+                    for i in range(len(_dX)):
+                        _Jacobienne.append(numpy.ravel((_HX_plus_dX[i] - _HX) / _dX[i]))
                     #
                 elif self.__mfEnabled:
                     _xserie = []
-                    _xserie.append( _X )
-                    for i in range( len(_dX) ):
-                        _X_plus_dXi    = numpy.array( _X, dtype=float )
+                    _xserie.append(_X)
+                    for i in range(len(_dX)):
+                        _X_plus_dXi = numpy.array(_X, dtype=float)
                         _X_plus_dXi[i] = _X[i] + _dX[i]
                         #
-                        _xserie.append( _X_plus_dXi )
+                        _xserie.append(_X_plus_dXi)
                     #
-                    _HX_plus_dX = self.DirectOperator( _xserie )
+                    _HX_plus_dX = self.DirectOperator(_xserie)
                     #
                     _HX = _HX_plus_dX.pop(0)
                     #
                     _Jacobienne = []
-                    for i in range( len(_dX) ):
-                        _Jacobienne.append( numpy.ravel(( _HX_plus_dX[i] - _HX ) / _dX[i]) )
+                    for i in range(len(_dX)):
+                        _Jacobienne.append(numpy.ravel((_HX_plus_dX[i] - _HX) / _dX[i]))
                     #
                 else:
-                    _Jacobienne  = []
-                    _HX = self.DirectOperator( _X )
-                    for i in range( _dX.size ):
-                        _dXi            = _dX[i]
-                        _X_plus_dXi     = numpy.array( _X, dtype=float )
-                        _X_plus_dXi[i]  = _X[i] + _dXi
+                    _Jacobienne = []
+                    _HX = self.DirectOperator(_X)
+                    for i in range(_dX.size):
+                        _dXi = _dX[i]
+                        _X_plus_dXi = numpy.array(_X, dtype=float)
+                        _X_plus_dXi[i] = _X[i] + _dXi
                         #
-                        _HX_plus_dXi = self.DirectOperator( _X_plus_dXi )
+                        _HX_plus_dXi = self.DirectOperator(_X_plus_dXi)
                         #
-                        _Jacobienne.append( numpy.ravel(( _HX_plus_dXi - _HX ) / _dXi) )
+                        _Jacobienne.append(numpy.ravel((_HX_plus_dXi - _HX) / _dXi))
             #
             if (dotWith is not None) or (dotTWith is not None):
                 __Produit = self.__listdotwith__(_Jacobienne, dotWith, dotTWith)
             else:
                 __Produit = None
             if __Produit is None or self.__avoidRC:
-                _Jacobienne = numpy.transpose( numpy.vstack( _Jacobienne ) )
+                _Jacobienne = numpy.transpose(numpy.vstack(_Jacobienne))
                 if self.__avoidRC:
                     if self.__lengthRJ < 0:
                         self.__lengthRJ = 2 * _X.size
@@ -431,11 +535,11 @@ class FDApproximation(object):
                         self.__listJPCR.pop(0)
                         self.__listJPPN.pop(0)
                         self.__listJPIN.pop(0)
-                    self.__listJPCP.append( copy.copy(_X) )
-                    self.__listJPCI.append( copy.copy(_dX) )
-                    self.__listJPCR.append( copy.copy(_Jacobienne) )
-                    self.__listJPPN.append( numpy.linalg.norm(_X) )
-                    self.__listJPIN.append( numpy.linalg.norm(_Jacobienne) )
+                    self.__listJPCP.append(copy.copy(_X))
+                    self.__listJPCI.append(copy.copy(_dX))
+                    self.__listJPCR.append(copy.copy(_Jacobienne))
+                    self.__listJPPN.append(numpy.linalg.norm(_X))
+                    self.__listJPIN.append(numpy.linalg.norm(_Jacobienne))
             logging.debug("FDA Fin du calcul de la Jacobienne")
             if __Produit is not None:
                 return __Produit
@@ -443,7 +547,7 @@ class FDApproximation(object):
         return _Jacobienne
 
     # ---------------------------------------------------------
-    def TangentOperator(self, paire, **extraArgs ):
+    def TangentOperator(self, paire, **extraArgs):
         """
         Calcul du tangent à l'aide de la Jacobienne.
 
@@ -462,23 +566,27 @@ class FDApproximation(object):
             #
             # Calcul de la forme matricielle si le second argument est None
             # -------------------------------------------------------------
-            _Jacobienne = self.TangentMatrix( X )
+            _Jacobienne = self.TangentMatrix(X)
             if self.__mfEnabled:
-                return [_Jacobienne,]
+                return [
+                    _Jacobienne,
+                ]
             else:
                 return _Jacobienne
         else:
             #
             # Calcul de la valeur linéarisée de H en X appliqué à dX
             # ------------------------------------------------------
-            _HtX = self.TangentMatrix( X, dotWith = dX )
+            _HtX = self.TangentMatrix(X, dotWith=dX)
             if self.__mfEnabled:
-                return [_HtX,]
+                return [
+                    _HtX,
+                ]
             else:
                 return _HtX
 
     # ---------------------------------------------------------
-    def AdjointOperator(self, paire, **extraArgs ):
+    def AdjointOperator(self, paire, **extraArgs):
         """
         Calcul de l'adjoint à l'aide de la Jacobienne.
 
@@ -497,27 +605,34 @@ class FDApproximation(object):
             #
             # Calcul de la forme matricielle si le second argument est None
             # -------------------------------------------------------------
-            _JacobienneT = self.TangentMatrix( X ).T
+            _JacobienneT = self.TangentMatrix(X).T
             if self.__mfEnabled:
-                return [_JacobienneT,]
+                return [
+                    _JacobienneT,
+                ]
             else:
                 return _JacobienneT
         else:
             #
             # Calcul de la valeur de l'adjoint en X appliqué à Y
             # --------------------------------------------------
-            _HaY = self.TangentMatrix( X, dotTWith = Y )
+            _HaY = self.TangentMatrix(X, dotTWith=Y)
             if self.__mfEnabled:
-                return [_HaY,]
+                return [
+                    _HaY,
+                ]
             else:
                 return _HaY
 
+
 # ==============================================================================
-def SetInitialDirection( __Direction = [], __Amplitude = 1., __Position = None ):
+def SetInitialDirection(__Direction=[], __Amplitude=1.0, __Position=None):
     "Établit ou élabore une direction avec une amplitude"
     #
     if len(__Direction) == 0 and __Position is None:
-        raise ValueError("If initial direction is void, current position has to be given")
+        raise ValueError(
+            "If initial direction is void, current position has to be given"
+        )
     if abs(float(__Amplitude)) < mpr:
         raise ValueError("Amplitude of perturbation can not be zero")
     #
@@ -526,190 +641,231 @@ def SetInitialDirection( __Direction = [], __Amplitude = 1., __Position = None )
     else:
         __dX0 = []
         __X0 = numpy.ravel(numpy.asarray(__Position))
-        __mX0 = numpy.mean( __X0, dtype=mfp )
+        __mX0 = numpy.mean(__X0, dtype=mfp)
         if abs(__mX0) < 2 * mpr:
-            __mX0 = 1.  # Évite le problème de position nulle
+            __mX0 = 1.0  # Évite le problème de position nulle
         for v in __X0:
-            if abs(v) > 1.e-8:
-                __dX0.append( numpy.random.normal(0., abs(v)) )
+            if abs(v) > 1.0e-8:
+                __dX0.append(numpy.random.normal(0.0, abs(v)))
             else:
-                __dX0.append( numpy.random.normal(0., __mX0) )
+                __dX0.append(numpy.random.normal(0.0, __mX0))
     #
     __dX0 = numpy.asarray(__dX0, float)  # Évite le problème d'array de taille 1
-    __dX0 = numpy.ravel( __dX0 )         # Redresse les vecteurs
+    __dX0 = numpy.ravel(__dX0)  # Redresse les vecteurs
     __dX0 = float(__Amplitude) * __dX0
     #
     return __dX0
 
+
 # ==============================================================================
-def EnsembleOfCenteredPerturbations( __bgCenter, __bgCovariance, __nbMembers ):
+def EnsembleOfCenteredPerturbations(__bgCenter, __bgCovariance, __nbMembers):
     "Génération d'un ensemble de taille __nbMembers-1 d'états aléatoires centrés"
     #
     __bgCenter = numpy.ravel(__bgCenter)[:, None]
     if __nbMembers < 1:
-        raise ValueError("Number of members has to be strictly more than 1 (given number: %s)."%(str(__nbMembers),))
+        raise ValueError(
+            "Number of members has to be strictly more than 1 (given number: %s)."
+            % (str(__nbMembers),)
+        )
     #
     if __bgCovariance is None:
-        _Perturbations = numpy.tile( __bgCenter, __nbMembers)
+        _Perturbations = numpy.tile(__bgCenter, __nbMembers)
     else:
-        _Z = numpy.random.multivariate_normal(numpy.zeros(__bgCenter.size), __bgCovariance, size=__nbMembers).T
-        _Perturbations = numpy.tile( __bgCenter, __nbMembers) + _Z
+        _Z = numpy.random.multivariate_normal(
+            numpy.zeros(__bgCenter.size), __bgCovariance, size=__nbMembers
+        ).T
+        _Perturbations = numpy.tile(__bgCenter, __nbMembers) + _Z
     #
     return _Perturbations
 
+
 # ==============================================================================
 def EnsembleOfBackgroundPerturbations(
-        __bgCenter,
-        __bgCovariance,
-        __nbMembers,
-        __withSVD = True ):
+    __bgCenter, __bgCovariance, __nbMembers, __withSVD=True
+):
     "Génération d'un ensemble de taille __nbMembers-1 d'états aléatoires centrés"
+
     def __CenteredRandomAnomalies(Zr, N):
         """
         Génère une matrice de N anomalies aléatoires centrées sur Zr selon les
         notes manuscrites de MB et conforme au code de PS avec eps = -1
         """
         eps = -1
-        Q = numpy.identity(N - 1) - numpy.ones((N - 1, N - 1)) / numpy.sqrt(N) / (numpy.sqrt(N) - eps)
+        Q = numpy.identity(N - 1) - numpy.ones((N - 1, N - 1)) / numpy.sqrt(N) / (
+            numpy.sqrt(N) - eps
+        )
         Q = numpy.concatenate((Q, [eps * numpy.ones(N - 1) / numpy.sqrt(N)]), axis=0)
-        R, _ = numpy.linalg.qr(numpy.random.normal(size = (N - 1, N - 1)))
+        R, _ = numpy.linalg.qr(numpy.random.normal(size=(N - 1, N - 1)))
         Q = numpy.dot(Q, R)
         Zr = numpy.dot(Q, Zr)
         return Zr.T
+
     #
     __bgCenter = numpy.ravel(__bgCenter).reshape((-1, 1))
     if __nbMembers < 1:
-        raise ValueError("Number of members has to be strictly more than 1 (given number: %s)."%(str(__nbMembers),))
+        raise ValueError(
+            "Number of members has to be strictly more than 1 (given number: %s)."
+            % (str(__nbMembers),)
+        )
     if __bgCovariance is None:
-        _Perturbations = numpy.tile( __bgCenter, __nbMembers)
+        _Perturbations = numpy.tile(__bgCenter, __nbMembers)
     else:
         if __withSVD:
             _U, _s, _V = numpy.linalg.svd(__bgCovariance, full_matrices=False)
             _nbctl = __bgCenter.size
             if __nbMembers > _nbctl:
-                _Z = numpy.concatenate((numpy.dot(
-                    numpy.diag(numpy.sqrt(_s[:_nbctl])), _V[:_nbctl]),
-                    numpy.random.multivariate_normal(numpy.zeros(_nbctl), __bgCovariance, __nbMembers - 1 - _nbctl)), axis = 0)
+                _Z = numpy.concatenate(
+                    (
+                        numpy.dot(numpy.diag(numpy.sqrt(_s[:_nbctl])), _V[:_nbctl]),
+                        numpy.random.multivariate_normal(
+                            numpy.zeros(_nbctl),
+                            __bgCovariance,
+                            __nbMembers - 1 - _nbctl,
+                        ),
+                    ),
+                    axis=0,
+                )
             else:
-                _Z = numpy.dot(numpy.diag(numpy.sqrt(_s[:__nbMembers - 1])), _V[:__nbMembers - 1])
+                _Z = numpy.dot(
+                    numpy.diag(numpy.sqrt(_s[: __nbMembers - 1])), _V[: __nbMembers - 1]
+                )
             _Zca = __CenteredRandomAnomalies(_Z, __nbMembers)
             _Perturbations = __bgCenter + _Zca
         else:
             if max(abs(__bgCovariance.flatten())) > 0:
                 _nbctl = __bgCenter.size
-                _Z = numpy.random.multivariate_normal(numpy.zeros(_nbctl), __bgCovariance, __nbMembers - 1)
+                _Z = numpy.random.multivariate_normal(
+                    numpy.zeros(_nbctl), __bgCovariance, __nbMembers - 1
+                )
                 _Zca = __CenteredRandomAnomalies(_Z, __nbMembers)
                 _Perturbations = __bgCenter + _Zca
             else:
-                _Perturbations = numpy.tile( __bgCenter, __nbMembers)
+                _Perturbations = numpy.tile(__bgCenter, __nbMembers)
     #
     return _Perturbations
 
+
 # ==============================================================================
-def EnsembleMean( __Ensemble ):
+def EnsembleMean(__Ensemble):
     "Renvoie la moyenne empirique d'un ensemble"
-    return numpy.asarray(__Ensemble).mean(axis=1, dtype=mfp).astype('float').reshape((-1, 1))
+    return (
+        numpy.asarray(__Ensemble)
+        .mean(axis=1, dtype=mfp)
+        .astype("float")
+        .reshape((-1, 1))
+    )
+
 
 # ==============================================================================
-def EnsembleOfAnomalies( __Ensemble, __OptMean = None, __Normalisation = 1. ):
+def EnsembleOfAnomalies(__Ensemble, __OptMean=None, __Normalisation=1.0):
     "Renvoie les anomalies centrées à partir d'un ensemble"
     if __OptMean is None:
-        __Em = EnsembleMean( __Ensemble )
+        __Em = EnsembleMean(__Ensemble)
     else:
-        __Em = numpy.ravel( __OptMean ).reshape((-1, 1))
+        __Em = numpy.ravel(__OptMean).reshape((-1, 1))
     #
-    return __Normalisation * (numpy.asarray( __Ensemble ) - __Em)
+    return __Normalisation * (numpy.asarray(__Ensemble) - __Em)
+
 
 # ==============================================================================
-def EnsembleErrorCovariance( __Ensemble, __Quick = False ):
+def EnsembleErrorCovariance(__Ensemble, __Quick=False):
     "Renvoie l'estimation empirique de la covariance d'ensemble"
     if __Quick:
         # Covariance rapide mais rarement définie positive
-        __Covariance = numpy.cov( __Ensemble )
+        __Covariance = numpy.cov(__Ensemble)
     else:
         # Résultat souvent identique à numpy.cov, mais plus robuste
-        __n, __m = numpy.asarray( __Ensemble ).shape
-        __Anomalies = EnsembleOfAnomalies( __Ensemble )
+        __n, __m = numpy.asarray(__Ensemble).shape
+        __Anomalies = EnsembleOfAnomalies(__Ensemble)
         # Estimation empirique
-        __Covariance = ( __Anomalies @ __Anomalies.T ) / (__m - 1)
+        __Covariance = (__Anomalies @ __Anomalies.T) / (__m - 1)
         # Assure la symétrie
-        __Covariance = ( __Covariance + __Covariance.T ) * 0.5
+        __Covariance = (__Covariance + __Covariance.T) * 0.5
         # Assure la positivité
-        __epsilon    = mpr * numpy.trace( __Covariance )
+        __epsilon = mpr * numpy.trace(__Covariance)
         __Covariance = __Covariance + __epsilon * numpy.identity(__n)
     #
     return __Covariance
 
+
 # ==============================================================================
-def SingularValuesEstimation( __Ensemble, __Using = "SVDVALS"):
+def SingularValuesEstimation(__Ensemble, __Using="SVDVALS"):
     "Renvoie les valeurs singulières de l'ensemble et leur carré"
     if __Using == "SVDVALS":  # Recommandé
-        __sv   = scipy.linalg.svdvals( __Ensemble )
+        __sv = scipy.linalg.svdvals(__Ensemble)
         __svsq = __sv**2
     elif __Using == "SVD":
-        _, __sv, _ = numpy.linalg.svd( __Ensemble )
+        _, __sv, _ = numpy.linalg.svd(__Ensemble)
         __svsq = __sv**2
     elif __Using == "EIG":  # Lent
-        __eva, __eve = numpy.linalg.eig( __Ensemble @ __Ensemble.T )
-        __svsq = numpy.sort(numpy.abs(numpy.real( __eva )))[::-1]
-        __sv   = numpy.sqrt( __svsq )
+        __eva, __eve = numpy.linalg.eig(__Ensemble @ __Ensemble.T)
+        __svsq = numpy.sort(numpy.abs(numpy.real(__eva)))[::-1]
+        __sv = numpy.sqrt(__svsq)
     elif __Using == "EIGH":
-        __eva, __eve = numpy.linalg.eigh( __Ensemble @ __Ensemble.T )
-        __svsq = numpy.sort(numpy.abs(numpy.real( __eva )))[::-1]
-        __sv   = numpy.sqrt( __svsq )
+        __eva, __eve = numpy.linalg.eigh(__Ensemble @ __Ensemble.T)
+        __svsq = numpy.sort(numpy.abs(numpy.real(__eva)))[::-1]
+        __sv = numpy.sqrt(__svsq)
     elif __Using == "EIGVALS":
-        __eva  = numpy.linalg.eigvals( __Ensemble @ __Ensemble.T )
-        __svsq = numpy.sort(numpy.abs(numpy.real( __eva )))[::-1]
-        __sv   = numpy.sqrt( __svsq )
+        __eva = numpy.linalg.eigvals(__Ensemble @ __Ensemble.T)
+        __svsq = numpy.sort(numpy.abs(numpy.real(__eva)))[::-1]
+        __sv = numpy.sqrt(__svsq)
     elif __Using == "EIGVALSH":
-        __eva = numpy.linalg.eigvalsh( __Ensemble @ __Ensemble.T )
-        __svsq = numpy.sort(numpy.abs(numpy.real( __eva )))[::-1]
-        __sv   = numpy.sqrt( __svsq )
+        __eva = numpy.linalg.eigvalsh(__Ensemble @ __Ensemble.T)
+        __svsq = numpy.sort(numpy.abs(numpy.real(__eva)))[::-1]
+        __sv = numpy.sqrt(__svsq)
     else:
-        raise ValueError("Error in requested variant name: %s"%__Using)
+        raise ValueError("Error in requested variant name: %s" % __Using)
     #
     __tisv = __svsq / __svsq.sum()
-    __qisv = 1. - __svsq.cumsum() / __svsq.sum()
+    __qisv = 1.0 - __svsq.cumsum() / __svsq.sum()
     # Différence à 1.e-16 : __qisv = 1. - __tisv.cumsum()
     #
     return __sv, __svsq, __tisv, __qisv
 
+
 # ==============================================================================
-def MaxL2NormByColumn(__Ensemble, __LcCsts = False, __IncludedPoints = []):
+def MaxL2NormByColumn(__Ensemble, __LcCsts=False, __IncludedPoints=[]):
     "Maximum des normes L2 calculées par colonne"
     if __LcCsts and len(__IncludedPoints) > 0:
         normes = numpy.linalg.norm(
-            numpy.take(__Ensemble, __IncludedPoints, axis=0, mode='clip'),
-            axis = 0,
+            numpy.take(__Ensemble, __IncludedPoints, axis=0, mode="clip"),
+            axis=0,
         )
     else:
-        normes = numpy.linalg.norm( __Ensemble, axis = 0)
+        normes = numpy.linalg.norm(__Ensemble, axis=0)
     nmax = numpy.max(normes)
     imax = numpy.argmax(normes)
     return nmax, imax, normes
 
-def MaxLinfNormByColumn(__Ensemble, __LcCsts = False, __IncludedPoints = []):
+
+def MaxLinfNormByColumn(__Ensemble, __LcCsts=False, __IncludedPoints=[]):
     "Maximum des normes Linf calculées par colonne"
     if __LcCsts and len(__IncludedPoints) > 0:
         normes = numpy.linalg.norm(
-            numpy.take(__Ensemble, __IncludedPoints, axis=0, mode='clip'),
-            axis = 0, ord=numpy.inf,
+            numpy.take(__Ensemble, __IncludedPoints, axis=0, mode="clip"),
+            axis=0,
+            ord=numpy.inf,
         )
     else:
-        normes = numpy.linalg.norm( __Ensemble, axis = 0, ord=numpy.inf)
+        normes = numpy.linalg.norm(__Ensemble, axis=0, ord=numpy.inf)
     nmax = numpy.max(normes)
     imax = numpy.argmax(normes)
     return nmax, imax, normes
 
+
 def InterpolationErrorByColumn(
-        __Ensemble = None, __Basis = None, __Points = None, __M = 2,  # Usage 1
-        __Differences = None,                                         # Usage 2
-        __ErrorNorm = None,                                           # Commun
-        __LcCsts = False, __IncludedPoints = [],                      # Commun
-        __CDM = False,  # ComputeMaxDifference                        # Commun
-        __RMU = False,  # ReduceMemoryUse                             # Commun
-        __FTL = False,  # ForceTril                                   # Commun
-        ):   # noqa: E123
+    __Ensemble=None,
+    __Basis=None,
+    __Points=None,
+    __M=2,  # Usage 1
+    __Differences=None,  # Usage 2
+    __ErrorNorm=None,  # Commun
+    __LcCsts=False,
+    __IncludedPoints=[],  # Commun
+    __CDM=False,  # ComputeMaxDifference                        # Commun
+    __RMU=False,  # ReduceMemoryUse                             # Commun
+    __FTL=False,  # ForceTril                                   # Commun
+):
     "Analyse des normes d'erreurs d'interpolation calculées par colonne"
     if __ErrorNorm == "L2":
         NormByColumn = MaxL2NormByColumn
@@ -718,7 +874,7 @@ def InterpolationErrorByColumn(
     #
     if __Differences is None and not __RMU:  # Usage 1
         if __FTL:
-            rBasis = numpy.tril( __Basis[__Points, :] )
+            rBasis = numpy.tril(__Basis[__Points, :])
         else:
             rBasis = __Basis[__Points, :]
         rEnsemble = __Ensemble[__Points, :]
@@ -727,7 +883,7 @@ def InterpolationErrorByColumn(
             rBasis_inv = numpy.linalg.inv(rBasis)
             Interpolator = numpy.dot(__Basis, numpy.dot(rBasis_inv, rEnsemble))
         else:
-            rBasis_inv = 1. / rBasis
+            rBasis_inv = 1.0 / rBasis
             Interpolator = numpy.outer(__Basis, numpy.outer(rBasis_inv, rEnsemble))
         #
         differences = __Ensemble - Interpolator
@@ -739,7 +895,7 @@ def InterpolationErrorByColumn(
         #
     elif __Differences is None and __RMU:  # Usage 1
         if __FTL:
-            rBasis = numpy.tril( __Basis[__Points, :] )
+            rBasis = numpy.tril(__Basis[__Points, :])
         else:
             rBasis = __Basis[__Points, :]
         rEnsemble = __Ensemble[__Points, :]
@@ -748,25 +904,31 @@ def InterpolationErrorByColumn(
             rBasis_inv = numpy.linalg.inv(rBasis)
             rCoordinates = numpy.dot(rBasis_inv, rEnsemble)
         else:
-            rBasis_inv = 1. / rBasis
+            rBasis_inv = 1.0 / rBasis
             rCoordinates = numpy.outer(rBasis_inv, rEnsemble)
         #
-        error = 0.
+        error = 0.0
         nbr = -1
         for iCol in range(__Ensemble.shape[1]):
             if __M > 1:
-                iDifference = __Ensemble[:, iCol] - numpy.dot(__Basis, rCoordinates[:, iCol])
+                iDifference = __Ensemble[:, iCol] - numpy.dot(
+                    __Basis, rCoordinates[:, iCol]
+                )
             else:
-                iDifference = __Ensemble[:, iCol] - numpy.ravel(numpy.outer(__Basis, rCoordinates[:, iCol]))
+                iDifference = __Ensemble[:, iCol] - numpy.ravel(
+                    numpy.outer(__Basis, rCoordinates[:, iCol])
+                )
             #
             normDifference, _, _ = NormByColumn(iDifference, __LcCsts, __IncludedPoints)
             #
             if normDifference > error:
-                error         = normDifference
-                nbr           = iCol
+                error = normDifference
+                nbr = iCol
         #
         if __CDM:
-            maxDifference = __Ensemble[:, nbr] - numpy.dot(__Basis, rCoordinates[:, nbr])
+            maxDifference = __Ensemble[:, nbr] - numpy.dot(
+                __Basis, rCoordinates[:, nbr]
+            )
         #
     else:  # Usage 2
         differences = __Differences
@@ -782,21 +944,25 @@ def InterpolationErrorByColumn(
     else:
         return error, nbr
 
+
 # ==============================================================================
-def EnsemblePerturbationWithGivenCovariance(
-        __Ensemble,
-        __Covariance,
-        __Seed = None ):
+def EnsemblePerturbationWithGivenCovariance(__Ensemble, __Covariance, __Seed=None):
     "Ajout d'une perturbation à chaque membre d'un ensemble selon une covariance prescrite"
     if hasattr(__Covariance, "assparsematrix"):
-        if (abs(__Ensemble).mean() > mpr) and (abs(__Covariance.assparsematrix()) / abs(__Ensemble).mean() < mpr).all():
+        if (abs(__Ensemble).mean() > mpr) and (
+            abs(__Covariance.assparsematrix()) / abs(__Ensemble).mean() < mpr
+        ).all():
             # Traitement d'une covariance nulle ou presque
             return __Ensemble
-        if (abs(__Ensemble).mean() <= mpr) and (abs(__Covariance.assparsematrix()) < mpr).all():
+        if (abs(__Ensemble).mean() <= mpr) and (
+            abs(__Covariance.assparsematrix()) < mpr
+        ).all():
             # Traitement d'une covariance nulle ou presque
             return __Ensemble
     else:
-        if (abs(__Ensemble).mean() > mpr) and (abs(__Covariance) / abs(__Ensemble).mean() < mpr).all():
+        if (abs(__Ensemble).mean() > mpr) and (
+            abs(__Covariance) / abs(__Ensemble).mean() < mpr
+        ).all():
             # Traitement d'une covariance nulle ou presque
             return __Ensemble
         if (abs(__Ensemble).mean() <= mpr) and (abs(__Covariance) < mpr).all():
@@ -809,35 +975,42 @@ def EnsemblePerturbationWithGivenCovariance(
     #
     if hasattr(__Covariance, "isscalar") and __Covariance.isscalar():
         # Traitement d'une covariance multiple de l'identité
-        __zero = 0.
-        __std  = numpy.sqrt(__Covariance.assparsematrix())
+        __zero = 0.0
+        __std = numpy.sqrt(__Covariance.assparsematrix())
         __Ensemble += numpy.random.normal(__zero, __std, size=(__m, __n)).T
     #
     elif hasattr(__Covariance, "isvector") and __Covariance.isvector():
         # Traitement d'une covariance diagonale avec variances non identiques
         __zero = numpy.zeros(__n)
-        __std  = numpy.sqrt(__Covariance.assparsematrix())
-        __Ensemble += numpy.asarray([numpy.random.normal(__zero, __std) for i in range(__m)]).T
+        __std = numpy.sqrt(__Covariance.assparsematrix())
+        __Ensemble += numpy.asarray(
+            [numpy.random.normal(__zero, __std) for i in range(__m)]
+        ).T
     #
     elif hasattr(__Covariance, "ismatrix") and __Covariance.ismatrix():
         # Traitement d'une covariance pleine
-        __Ensemble += numpy.random.multivariate_normal(numpy.zeros(__n), __Covariance.asfullmatrix(__n), size=__m).T
+        __Ensemble += numpy.random.multivariate_normal(
+            numpy.zeros(__n), __Covariance.asfullmatrix(__n), size=__m
+        ).T
     #
     elif isinstance(__Covariance, numpy.ndarray):
         # Traitement d'une covariance numpy pleine, sachant qu'on arrive ici en dernier
-        __Ensemble += numpy.random.multivariate_normal(numpy.zeros(__n), __Covariance, size=__m).T
+        __Ensemble += numpy.random.multivariate_normal(
+            numpy.zeros(__n), __Covariance, size=__m
+        ).T
     #
     else:
-        raise ValueError("Error in ensemble perturbation with inadequate covariance specification")
+        raise ValueError(
+            "Error in ensemble perturbation with inadequate covariance specification"
+        )
     #
     return __Ensemble
 
+
 # ==============================================================================
 def CovarianceInflation(
-        __InputCovOrEns,
-        __InflationType   = None,
-        __InflationFactor = None,
-        __BackgroundCov   = None ):
+    __InputCovOrEns, __InflationType=None, __InflationFactor=None, __BackgroundCov=None
+):
     """
     Inflation applicable soit sur Pb ou Pa, soit sur les ensembles EXb ou EXa
 
@@ -852,97 +1025,142 @@ def CovarianceInflation(
     if __InputCovOrEns.size == 0:
         return __InputCovOrEns
     #
-    if __InflationType in ["MultiplicativeOnAnalysisCovariance", "MultiplicativeOnBackgroundCovariance"]:
-        if __InflationFactor < 1.:
-            raise ValueError("Inflation factor for multiplicative inflation has to be greater or equal than 1.")
-        if __InflationFactor < 1. + mpr:  # No inflation = 1
+    if __InflationType in [
+        "MultiplicativeOnAnalysisCovariance",
+        "MultiplicativeOnBackgroundCovariance",
+    ]:
+        if __InflationFactor < 1.0:
+            raise ValueError(
+                "Inflation factor for multiplicative inflation has to be greater or equal than 1."
+            )
+        if __InflationFactor < 1.0 + mpr:  # No inflation = 1
             return __InputCovOrEns
         __OutputCovOrEns = __InflationFactor**2 * __InputCovOrEns
     #
-    elif __InflationType in ["MultiplicativeOnAnalysisAnomalies", "MultiplicativeOnBackgroundAnomalies"]:
-        if __InflationFactor < 1.:
-            raise ValueError("Inflation factor for multiplicative inflation has to be greater or equal than 1.")
-        if __InflationFactor < 1. + mpr:  # No inflation = 1
+    elif __InflationType in [
+        "MultiplicativeOnAnalysisAnomalies",
+        "MultiplicativeOnBackgroundAnomalies",
+    ]:
+        if __InflationFactor < 1.0:
+            raise ValueError(
+                "Inflation factor for multiplicative inflation has to be greater or equal than 1."
+            )
+        if __InflationFactor < 1.0 + mpr:  # No inflation = 1
             return __InputCovOrEns
-        __InputCovOrEnsMean = __InputCovOrEns.mean(axis=1, dtype=mfp).astype('float')
-        __OutputCovOrEns = __InputCovOrEnsMean[:, numpy.newaxis] \
-            + __InflationFactor * (__InputCovOrEns - __InputCovOrEnsMean[:, numpy.newaxis])
+        __InputCovOrEnsMean = __InputCovOrEns.mean(axis=1, dtype=mfp).astype("float")
+        __OutputCovOrEns = __InputCovOrEnsMean[:, numpy.newaxis] + __InflationFactor * (
+            __InputCovOrEns - __InputCovOrEnsMean[:, numpy.newaxis]
+        )
     #
-    elif __InflationType in ["AdditiveOnAnalysisCovariance", "AdditiveOnBackgroundCovariance"]:
-        if __InflationFactor < 0.:
-            raise ValueError("Inflation factor for additive inflation has to be greater or equal than 0.")
+    elif __InflationType in [
+        "AdditiveOnAnalysisCovariance",
+        "AdditiveOnBackgroundCovariance",
+    ]:
+        if __InflationFactor < 0.0:
+            raise ValueError(
+                "Inflation factor for additive inflation has to be greater or equal than 0."
+            )
         if __InflationFactor < mpr:  # No inflation = 0
             return __InputCovOrEns
         __n, __m = __InputCovOrEns.shape
         if __n != __m:
-            raise ValueError("Additive inflation can only be applied to squared (covariance) matrix.")
+            raise ValueError(
+                "Additive inflation can only be applied to squared (covariance) matrix."
+            )
         __tr = __InputCovOrEns.trace() / __n
         if __InflationFactor > __tr:
-            raise ValueError("Inflation factor for additive inflation has to be small over %.0e."%__tr)
-        __OutputCovOrEns = (1. - __InflationFactor) * __InputCovOrEns + __InflationFactor * numpy.identity(__n)
+            raise ValueError(
+                "Inflation factor for additive inflation has to be small over %.0e."
+                % __tr
+            )
+        __OutputCovOrEns = (
+            1.0 - __InflationFactor
+        ) * __InputCovOrEns + __InflationFactor * numpy.identity(__n)
     #
     elif __InflationType == "HybridOnBackgroundCovariance":
-        if __InflationFactor < 0.:
-            raise ValueError("Inflation factor for hybrid inflation has to be greater or equal than 0.")
+        if __InflationFactor < 0.0:
+            raise ValueError(
+                "Inflation factor for hybrid inflation has to be greater or equal than 0."
+            )
         if __InflationFactor < mpr:  # No inflation = 0
             return __InputCovOrEns
         __n, __m = __InputCovOrEns.shape
         if __n != __m:
-            raise ValueError("Additive inflation can only be applied to squared (covariance) matrix.")
+            raise ValueError(
+                "Additive inflation can only be applied to squared (covariance) matrix."
+            )
         if __BackgroundCov is None:
-            raise ValueError("Background covariance matrix B has to be given for hybrid inflation.")
+            raise ValueError(
+                "Background covariance matrix B has to be given for hybrid inflation."
+            )
         if __InputCovOrEns.shape != __BackgroundCov.shape:
-            raise ValueError("Ensemble covariance matrix has to be of same size than background covariance matrix B.")
-        __OutputCovOrEns = (1. - __InflationFactor) * __InputCovOrEns + __InflationFactor * __BackgroundCov
+            raise ValueError(
+                "Ensemble covariance matrix has to be of same size than background covariance matrix B."
+            )
+        __OutputCovOrEns = (
+            1.0 - __InflationFactor
+        ) * __InputCovOrEns + __InflationFactor * __BackgroundCov
     #
     elif __InflationType == "Relaxation":
         raise NotImplementedError("Relaxation inflation type not implemented")
     #
     else:
-        raise ValueError("Error in inflation type, '%s' is not a valid keyword."%__InflationType)
+        raise ValueError(
+            "Error in inflation type, '%s' is not a valid keyword." % __InflationType
+        )
     #
     return __OutputCovOrEns
 
+
 # ==============================================================================
-def HessienneEstimation( __selfA, __nb, __HaM, __HtM, __BI, __RI ):
+def HessienneEstimation(__selfA, __nb, __HaM, __HtM, __BI, __RI):
     "Estimation de la Hessienne"
     #
     __HessienneI = []
     for i in range(int(__nb)):
-        __ee    = numpy.zeros((__nb, 1))
-        __ee[i] = 1.
-        __HtEE  = numpy.dot(__HtM, __ee).reshape((-1, 1))
-        __HessienneI.append( numpy.ravel( __BI * __ee + __HaM * (__RI * __HtEE) ) )
+        __ee = numpy.zeros((__nb, 1))
+        __ee[i] = 1.0
+        __HtEE = numpy.dot(__HtM, __ee).reshape((-1, 1))
+        __HessienneI.append(numpy.ravel(__BI * __ee + __HaM * (__RI * __HtEE)))
     #
-    __A = numpy.linalg.inv(numpy.array( __HessienneI ))
+    __A = numpy.linalg.inv(numpy.array(__HessienneI))
     __A = (__A + __A.T) * 0.5  # Symétrie
-    __A = __A + mpr * numpy.trace( __A ) * numpy.identity(__nb)  # Positivité
+    __A = __A + mpr * numpy.trace(__A) * numpy.identity(__nb)  # Positivité
     #
     if min(__A.shape) != max(__A.shape):
         raise ValueError(
-            "The %s a posteriori covariance matrix A"%(__selfA._name,) + \
-            " is of shape %s, despites it has to be a"%(str(__A.shape),) + \
-            " squared matrix. There is an error in the observation operator," + \
-            " please check it.")
+            "The %s a posteriori covariance matrix A" % (__selfA._name,)
+            + " is of shape %s, despites it has to be a" % (str(__A.shape),)
+            + " squared matrix. There is an error in the observation operator,"
+            + " please check it."
+        )
     if (numpy.diag(__A) < 0).any():
         raise ValueError(
-            "The %s a posteriori covariance matrix A"%(__selfA._name,) + \
-            " has at least one negative value on its diagonal. There is an" + \
-            " error in the observation operator, please check it.")
-    if logging.getLogger().level < logging.WARNING:  # La vérification n'a lieu qu'en debug
+            "The %s a posteriori covariance matrix A" % (__selfA._name,)
+            + " has at least one negative value on its diagonal. There is an"
+            + " error in the observation operator, please check it."
+        )
+    if (
+        logging.getLogger().level < logging.WARNING
+    ):  # La vérification n'a lieu qu'en debug
         try:
-            numpy.linalg.cholesky( __A )
-            logging.debug("%s La matrice de covariance a posteriori A est bien symétrique définie positive."%(__selfA._name,))
+            numpy.linalg.cholesky(__A)
+            logging.debug(
+                "%s La matrice de covariance a posteriori A est bien symétrique définie positive."
+                % (__selfA._name,)
+            )
         except Exception:
             raise ValueError(
-                "The %s a posteriori covariance matrix A"%(__selfA._name,) + \
-                " is not symmetric positive-definite. Please check your a" + \
-                " priori covariances and your observation operator.")
+                "The %s a posteriori covariance matrix A" % (__selfA._name,)
+                + " is not symmetric positive-definite. Please check your a"
+                + " priori covariances and your observation operator."
+            )
     #
     return __A
 
+
 # ==============================================================================
-def QuantilesEstimations( selfA, A, Xa, HXa = None, Hm = None, HtM = None ):
+def QuantilesEstimations(selfA, A, Xa, HXa=None, Hm=None, HtM=None):
     "Estimation des quantiles a posteriori à partir de A>0 (selfA est modifié)"
     nbsamples = selfA._parameters["NumberOfSamplesForQuantiles"]
     #
@@ -954,28 +1172,51 @@ def QuantilesEstimations( selfA, A, Xa, HXa = None, Hm = None, HtM = None ):
     else:
         LBounds = None
     if LBounds is not None:
-        LBounds = ForceNumericBounds( LBounds )
+        LBounds = ForceNumericBounds(LBounds)
     __Xa = numpy.ravel(Xa)
     #
     # Échantillonnage des états
-    YfQ  = None
-    EXr  = None
+    YfQ = None
+    EXr = None
     for i in range(nbsamples):
-        if selfA._parameters["SimulationForQuantiles"] == "Linear" and HtM is not None and HXa is not None:
+        if (
+            selfA._parameters["SimulationForQuantiles"] == "Linear"
+            and HtM is not None
+            and HXa is not None
+        ):
             dXr = (numpy.random.multivariate_normal(__Xa, A) - __Xa).reshape((-1, 1))
             if LBounds is not None:  # "EstimateProjection" par défaut
-                dXr = numpy.max(numpy.hstack((dXr, LBounds[:, 0].reshape((-1, 1))) - __Xa.reshape((-1, 1))), axis=1)
-                dXr = numpy.min(numpy.hstack((dXr, LBounds[:, 1].reshape((-1, 1))) - __Xa.reshape((-1, 1))), axis=1)
+                dXr = numpy.max(
+                    numpy.hstack(
+                        (dXr, LBounds[:, 0].reshape((-1, 1))) - __Xa.reshape((-1, 1))
+                    ),
+                    axis=1,
+                )
+                dXr = numpy.min(
+                    numpy.hstack(
+                        (dXr, LBounds[:, 1].reshape((-1, 1))) - __Xa.reshape((-1, 1))
+                    ),
+                    axis=1,
+                )
             dYr = HtM @ dXr
             Yr = HXa.reshape((-1, 1)) + dYr
             if selfA._toStore("SampledStateForQuantiles"):
                 Xr = __Xa + numpy.ravel(dXr)
-        elif selfA._parameters["SimulationForQuantiles"] == "NonLinear" and Hm is not None:
+        elif (
+            selfA._parameters["SimulationForQuantiles"] == "NonLinear"
+            and Hm is not None
+        ):
             Xr = numpy.random.multivariate_normal(__Xa, A)
             if LBounds is not None:  # "EstimateProjection" par défaut
-                Xr = numpy.max(numpy.hstack((Xr.reshape((-1, 1)), LBounds[:, 0].reshape((-1, 1)))), axis=1)
-                Xr = numpy.min(numpy.hstack((Xr.reshape((-1, 1)), LBounds[:, 1].reshape((-1, 1)))), axis=1)
-            Yr = numpy.asarray(Hm( Xr ))
+                Xr = numpy.max(
+                    numpy.hstack((Xr.reshape((-1, 1)), LBounds[:, 0].reshape((-1, 1)))),
+                    axis=1,
+                )
+                Xr = numpy.min(
+                    numpy.hstack((Xr.reshape((-1, 1)), LBounds[:, 1].reshape((-1, 1)))),
+                    axis=1,
+                )
+            Yr = numpy.asarray(Hm(Xr))
         else:
             raise ValueError("Quantile simulations has only to be Linear or NonLinear.")
         #
@@ -992,41 +1233,45 @@ def QuantilesEstimations( selfA, A, Xa, HXa = None, Hm = None, HtM = None ):
     YfQ.sort(axis=-1)
     YQ = None
     for quantile in selfA._parameters["Quantiles"]:
-        if not (0. <= float(quantile) <= 1.):
+        if not (0.0 <= float(quantile) <= 1.0):
             continue
-        indice = int(nbsamples * float(quantile) - 1. / nbsamples)
+        indice = int(nbsamples * float(quantile) - 1.0 / nbsamples)
         if YQ is None:
             YQ = YfQ[:, indice].reshape((-1, 1))
         else:
             YQ = numpy.hstack((YQ, YfQ[:, indice].reshape((-1, 1))))
     if YQ is not None:  # Liste non vide de quantiles
-        selfA.StoredVariables["SimulationQuantiles"].store( YQ )
+        selfA.StoredVariables["SimulationQuantiles"].store(YQ)
     if selfA._toStore("SampledStateForQuantiles"):
-        selfA.StoredVariables["SampledStateForQuantiles"].store( EXr )
+        selfA.StoredVariables["SampledStateForQuantiles"].store(EXr)
     #
     return 0
 
+
 # ==============================================================================
-def ForceNumericBounds( __Bounds, __infNumbers = True ):
+def ForceNumericBounds(__Bounds, __infNumbers=True):
     "Force les bornes à être des valeurs numériques, sauf si globalement None"
     # Conserve une valeur par défaut à None s'il n'y a pas de bornes
     if __Bounds is None:
         return None
     #
     # Converti toutes les bornes individuelles None à +/- l'infini chiffré
-    __Bounds = numpy.asarray( __Bounds, dtype=float ).reshape((-1, 2))
+    __Bounds = numpy.asarray(__Bounds, dtype=float).reshape((-1, 2))
     if len(__Bounds.shape) != 2 or __Bounds.shape[0] == 0 or __Bounds.shape[1] != 2:
-        raise ValueError("Incorrectly shaped bounds data (effective shape is %s)"%(__Bounds.shape,))
+        raise ValueError(
+            "Incorrectly shaped bounds data (effective shape is %s)" % (__Bounds.shape,)
+        )
     if __infNumbers:
-        __Bounds[numpy.isnan(__Bounds[:, 0]), 0] = -float('inf')
-        __Bounds[numpy.isnan(__Bounds[:, 1]), 1] = float('inf')
+        __Bounds[numpy.isnan(__Bounds[:, 0]), 0] = -float("inf")
+        __Bounds[numpy.isnan(__Bounds[:, 1]), 1] = float("inf")
     else:
         __Bounds[numpy.isnan(__Bounds[:, 0]), 0] = -sys.float_info.max
         __Bounds[numpy.isnan(__Bounds[:, 1]), 1] = sys.float_info.max
     return __Bounds
 
+
 # ==============================================================================
-def RecentredBounds( __Bounds, __Center, __Scale = None ):
+def RecentredBounds(__Bounds, __Center, __Scale=None):
     "Recentre les bornes autour de 0, sauf si globalement None"
     # Conserve une valeur par défaut à None s'il n'y a pas de bornes
     if __Bounds is None:
@@ -1034,13 +1279,16 @@ def RecentredBounds( __Bounds, __Center, __Scale = None ):
     #
     if __Scale is None:
         # Recentre les valeurs numériques de bornes
-        return ForceNumericBounds( __Bounds ) - numpy.ravel( __Center ).reshape((-1, 1))
+        return ForceNumericBounds(__Bounds) - numpy.ravel(__Center).reshape((-1, 1))
     else:
         # Recentre les valeurs numériques de bornes et change l'échelle par une matrice
-        return __Scale @ (ForceNumericBounds( __Bounds, False ) - numpy.ravel( __Center ).reshape((-1, 1)))
+        return __Scale @ (
+            ForceNumericBounds(__Bounds, False) - numpy.ravel(__Center).reshape((-1, 1))
+        )
+
 
 # ==============================================================================
-def ApplyBounds( __Vector, __Bounds, __newClip = True ):
+def ApplyBounds(__Vector, __Bounds, __newClip=True):
     "Applique des bornes numériques à un point"
     # Conserve une valeur par défaut s'il n'y a pas de bornes
     if __Bounds is None:
@@ -1051,7 +1299,10 @@ def ApplyBounds( __Vector, __Bounds, __newClip = True ):
     if not isinstance(__Bounds, numpy.ndarray):  # Is an array
         raise ValueError("Incorrect array definition of bounds data")
     if 2 * __Vector.size != __Bounds.size:  # Is a 2 column array of vector length
-        raise ValueError("Incorrect bounds number (%i) to be applied for this vector (of size %i)"%(__Bounds.size, __Vector.size))
+        raise ValueError(
+            "Incorrect bounds number (%i) to be applied for this vector (of size %i)"
+            % (__Bounds.size, __Vector.size)
+        )
     if len(__Bounds.shape) != 2 or min(__Bounds.shape) <= 0 or __Bounds.shape[1] != 2:
         raise ValueError("Incorrectly shaped bounds data")
     #
@@ -1061,74 +1312,103 @@ def ApplyBounds( __Vector, __Bounds, __newClip = True ):
             __Bounds[:, 1].reshape(__Vector.shape),
         )
     else:
-        __Vector = numpy.max(numpy.hstack((__Vector.reshape((-1, 1)), numpy.asmatrix(__Bounds)[:, 0])), axis=1)
-        __Vector = numpy.min(numpy.hstack((__Vector.reshape((-1, 1)), numpy.asmatrix(__Bounds)[:, 1])), axis=1)
+        __Vector = numpy.max(
+            numpy.hstack((__Vector.reshape((-1, 1)), numpy.asmatrix(__Bounds)[:, 0])),
+            axis=1,
+        )
+        __Vector = numpy.min(
+            numpy.hstack((__Vector.reshape((-1, 1)), numpy.asmatrix(__Bounds)[:, 1])),
+            axis=1,
+        )
         __Vector = numpy.asarray(__Vector)
     #
     return __Vector
 
+
 # ==============================================================================
-def VariablesAndIncrementsBounds( __Bounds, __BoxBounds, __Xini, __Name, __Multiplier = 1. ):
-    __Bounds    = ForceNumericBounds( __Bounds )
-    __BoxBounds = ForceNumericBounds( __BoxBounds )
+def VariablesAndIncrementsBounds(
+    __Bounds, __BoxBounds, __Xini, __Name, __Multiplier=1.0
+):
+    __Bounds = ForceNumericBounds(__Bounds)
+    __BoxBounds = ForceNumericBounds(__BoxBounds)
     if __Bounds is None and __BoxBounds is None:
-        raise ValueError("Algorithm %s requires bounds on all variables (by Bounds), or on all variable increments (by BoxBounds), or both, to be explicitly given."%(__Name,))
+        raise ValueError(
+            "Algorithm %s requires bounds on all variables (by Bounds), or on all"
+            % (__Name,)
+            + " variable increments (by BoxBounds), or both, to be explicitly given."
+        )
     elif __Bounds is None and __BoxBounds is not None:
-        __Bounds    = __BoxBounds
-        logging.debug("%s Definition of parameter bounds from current parameter increment bounds"%(__Name,))
+        __Bounds = __BoxBounds
+        logging.debug(
+            "%s Definition of parameter bounds from current parameter increment bounds"
+            % (__Name,)
+        )
     elif __Bounds is not None and __BoxBounds is None:
-        __BoxBounds = __Multiplier * (__Bounds - __Xini.reshape((-1, 1)))  # "M * [Xmin,Xmax]-Xini"
-        logging.debug("%s Definition of parameter increment bounds from current parameter bounds"%(__Name,))
+        __BoxBounds = __Multiplier * (
+            __Bounds - __Xini.reshape((-1, 1))
+        )  # "M * [Xmin,Xmax]-Xini"
+        logging.debug(
+            "%s Definition of parameter increment bounds from current parameter bounds"
+            % (__Name,)
+        )
     return __Bounds, __BoxBounds
 
+
 # ==============================================================================
-def Apply3DVarRecentringOnEnsemble( __EnXn, __EnXf, __Ynpu, __HO, __R, __B, __SuppPars ):
+def Apply3DVarRecentringOnEnsemble(__EnXn, __EnXf, __Ynpu, __HO, __R, __B, __SuppPars):
     "Recentre l'ensemble Xn autour de l'analyse 3DVAR"
     __Betaf = __SuppPars["HybridCovarianceEquilibrium"]
     #
-    Xf = EnsembleMean( __EnXf )
-    Pf = Covariance( asCovariance=EnsembleErrorCovariance(__EnXf) )
+    Xf = EnsembleMean(__EnXf)
+    Pf = Covariance(asCovariance=EnsembleErrorCovariance(__EnXf))
     Pf = (1 - __Betaf) * __B.asfullmatrix(Xf.size) + __Betaf * Pf
     #
     selfB = PartialAlgorithm("3DVAR")
     selfB._parameters["Minimizer"] = "LBFGSB"
-    selfB._parameters["MaximumNumberOfIterations"] = __SuppPars["HybridMaximumNumberOfIterations"]
-    selfB._parameters["CostDecrementTolerance"] = __SuppPars["HybridCostDecrementTolerance"]
+    selfB._parameters["MaximumNumberOfIterations"] = __SuppPars[
+        "HybridMaximumNumberOfIterations"
+    ]
+    selfB._parameters["CostDecrementTolerance"] = __SuppPars[
+        "HybridCostDecrementTolerance"
+    ]
     selfB._parameters["ProjectedGradientTolerance"] = -1
-    selfB._parameters["GradientNormTolerance"] = 1.e-05
+    selfB._parameters["GradientNormTolerance"] = 1.0e-05
     selfB._parameters["StoreInternalVariables"] = False
     selfB._parameters["optiprint"] = -1
     selfB._parameters["optdisp"] = 0
     selfB._parameters["Bounds"] = None
     selfB._parameters["InitializationPoint"] = Xf
     from daAlgorithms.Atoms import std3dvar
+
     std3dvar.std3dvar(selfB, Xf, __Ynpu, None, __HO, None, __R, Pf)
     Xa = selfB.get("Analysis")[-1].reshape((-1, 1))
     del selfB
     #
-    return Xa + EnsembleOfAnomalies( __EnXn )
+    return Xa + EnsembleOfAnomalies(__EnXn)
+
 
 # ==============================================================================
-def GenerateRandomPointInHyperSphere( __Center, __Radius ):
+def GenerateRandomPointInHyperSphere(__Center, __Radius):
     "Génère un point aléatoire uniformément à l'intérieur d'une hyper-sphère"
-    __Dimension  = numpy.asarray( __Center ).size
-    __GaussDelta = numpy.random.normal( 0, 1, size=__Center.shape )
-    __VectorNorm = numpy.linalg.norm( __GaussDelta )
-    __PointOnHS  = __Radius * (__GaussDelta / __VectorNorm)
-    __MoveInHS   = math.exp( math.log(numpy.random.uniform()) / __Dimension)  # rand()**1/n
-    __PointInHS  = __MoveInHS * __PointOnHS
+    __Dimension = numpy.asarray(__Center).size
+    __GaussDelta = numpy.random.normal(0, 1, size=__Center.shape)
+    __VectorNorm = numpy.linalg.norm(__GaussDelta)
+    __PointOnHS = __Radius * (__GaussDelta / __VectorNorm)
+    __MoveInHS = math.exp(math.log(numpy.random.uniform()) / __Dimension)  # rand()**1/n
+    __PointInHS = __MoveInHS * __PointOnHS
     return __Center + __PointInHS
 
+
 # ==============================================================================
 class GenerateWeightsAndSigmaPoints(object):
     "Génère les points sigma et les poids associés"
 
-    def __init__(self,
-                 Nn=0, EO="State", VariantM="UKF",
-                 Alpha=None, Beta=2., Kappa=0.):
+    def __init__(
+        self, Nn=0, EO="State", VariantM="UKF", Alpha=None, Beta=2.0, Kappa=0.0
+    ):
         self.Nn = int(Nn)
-        self.Alpha = numpy.longdouble( Alpha )
-        self.Beta  = numpy.longdouble( Beta )
+        self.Alpha = numpy.longdouble(Alpha)
+        self.Beta = numpy.longdouble(Beta)
         if abs(Kappa) < 2 * mpr:
             if EO == "Parameters" and VariantM == "UKF":
                 self.Kappa = 3 - self.Nn
@@ -1136,11 +1416,13 @@ class GenerateWeightsAndSigmaPoints(object):
                 self.Kappa = 0
         else:
             self.Kappa = Kappa
-        self.Kappa  = numpy.longdouble( self.Kappa )
-        self.Lambda = self.Alpha**2 * ( self.Nn + self.Kappa ) - self.Nn
-        self.Gamma  = self.Alpha * numpy.sqrt( self.Nn + self.Kappa )
+        self.Kappa = numpy.longdouble(self.Kappa)
+        self.Lambda = self.Alpha**2 * (self.Nn + self.Kappa) - self.Nn
+        self.Gamma = self.Alpha * numpy.sqrt(self.Nn + self.Kappa)
         # Rq.: Gamma = sqrt(n+Lambda) = Alpha*sqrt(n+Kappa)
-        assert 0. < self.Alpha <= 1., "Alpha has to be between 0 strictly and 1 included"
+        assert (
+            0.0 < self.Alpha <= 1.0
+        ), "Alpha has to be between 0 strictly and 1 included"
         #
         if VariantM == "UKF":
             self.Wm, self.Wc, self.SC = self.__UKF2000()
@@ -1151,28 +1433,28 @@ class GenerateWeightsAndSigmaPoints(object):
         elif VariantM == "5OS":
             self.Wm, self.Wc, self.SC = self.__5OS2002()
         else:
-            raise ValueError("Variant \"%s\" is not a valid one."%VariantM)
+            raise ValueError('Variant "%s" is not a valid one.' % VariantM)
 
     def __UKF2000(self):
         "Standard Set, Julier et al. 2000 (aka Canonical UKF)"
         # Rq.: W^{(m)}_{i=/=0} = 1. / (2.*(n + Lambda))
-        Winn = 1. / (2. * ( self.Nn + self.Kappa ) * self.Alpha**2)
+        Winn = 1.0 / (2.0 * (self.Nn + self.Kappa) * self.Alpha**2)
         Ww = []
-        Ww.append( 0. )
+        Ww.append(0.0)
         for point in range(2 * self.Nn):
-            Ww.append( Winn )
+            Ww.append(Winn)
         # Rq.: LsLpL = Lambda / (n + Lambda)
-        LsLpL = 1. - self.Nn / (self.Alpha**2 * ( self.Nn + self.Kappa ))
-        Wm = numpy.array( Ww )
+        LsLpL = 1.0 - self.Nn / (self.Alpha**2 * (self.Nn + self.Kappa))
+        Wm = numpy.array(Ww)
         Wm[0] = LsLpL
-        Wc = numpy.array( Ww )
-        Wc[0] = LsLpL + (1. - self.Alpha**2 + self.Beta)
+        Wc = numpy.array(Ww)
+        Wc[0] = LsLpL + (1.0 - self.Alpha**2 + self.Beta)
         # OK: assert abs(Wm.sum()-1.) < self.Nn*mpr, "UKF ill-conditioned %s >= %s"%(abs(Wm.sum()-1.), self.Nn*mpr)
         #
         SC = numpy.zeros((self.Nn, len(Ww)))
         for ligne in range(self.Nn):
             it = ligne + 1
-            SC[ligne, it          ] = self.Gamma
+            SC[ligne, it] = self.Gamma
             SC[ligne, self.Nn + it] = -self.Gamma
         #
         return Wm, Wc, SC
@@ -1180,39 +1462,48 @@ class GenerateWeightsAndSigmaPoints(object):
     def __S3F2022(self):
         "Scaled Spherical Simplex Set, Papakonstantinou et al. 2022"
         # Rq.: W^{(m)}_{i=/=0} = (n + Kappa) / ((n + Lambda) * (n + 1 + Kappa))
-        Winn = 1. / ((self.Nn + 1. + self.Kappa) * self.Alpha**2)
+        Winn = 1.0 / ((self.Nn + 1.0 + self.Kappa) * self.Alpha**2)
         Ww = []
-        Ww.append( 0. )
+        Ww.append(0.0)
         for point in range(self.Nn + 1):
-            Ww.append( Winn )
+            Ww.append(Winn)
         # Rq.: LsLpL = Lambda / (n + Lambda)
-        LsLpL = 1. - self.Nn / (self.Alpha**2 * ( self.Nn + self.Kappa ))
-        Wm = numpy.array( Ww )
+        LsLpL = 1.0 - self.Nn / (self.Alpha**2 * (self.Nn + self.Kappa))
+        Wm = numpy.array(Ww)
         Wm[0] = LsLpL
-        Wc = numpy.array( Ww )
-        Wc[0] = LsLpL + (1. - self.Alpha**2 + self.Beta)
+        Wc = numpy.array(Ww)
+        Wc[0] = LsLpL + (1.0 - self.Alpha**2 + self.Beta)
         # OK: assert abs(Wm.sum()-1.) < self.Nn*mpr, "S3F ill-conditioned %s >= %s"%(abs(Wm.sum()-1.), self.Nn*mpr)
         #
         SC = numpy.zeros((self.Nn, len(Ww)))
         for ligne in range(self.Nn):
             it = ligne + 1
-            q_t = it / math.sqrt( it * (it + 1) * Winn )
-            SC[ligne, 1:it + 1] = -q_t / it
-            SC[ligne, it + 1  ] = q_t
+            q_t = it / math.sqrt(it * (it + 1) * Winn)
+            SC[ligne, 1 : it + 1] = -q_t / it  # noqa: E203
+            SC[ligne, it + 1] = q_t
         #
         return Wm, Wc, SC
 
     def __MSS2011(self):
         "Minimum Set, Menegaz et al. 2011"
         rho2 = (1 - self.Alpha) / self.Nn
-        Cc = numpy.real(scipy.linalg.sqrtm( numpy.identity(self.Nn) - rho2 ))
-        Ww = self.Alpha * rho2 * scipy.linalg.inv(Cc) @ numpy.ones(self.Nn) @ scipy.linalg.inv(Cc.T)
+        Cc = numpy.real(scipy.linalg.sqrtm(numpy.identity(self.Nn) - rho2))
+        Ww = (
+            self.Alpha
+            * rho2
+            * scipy.linalg.inv(Cc)
+            @ numpy.ones(self.Nn)
+            @ scipy.linalg.inv(Cc.T)
+        )
         Wm = Wc = numpy.concatenate((Ww, [self.Alpha]))
         # OK: assert abs(Wm.sum()-1.) < self.Nn*mpr, "MSS ill-conditioned %s >= %s"%(abs(Wm.sum()-1.), self.Nn*mpr)
+        Wm = Wc = Wm / numpy.sum(Wm)  # Renormalisation explicite
         #
         # inv(sqrt(W)) = diag(inv(sqrt(W)))
-        SC1an = Cc @ numpy.diag(1. / numpy.sqrt( Ww ))
-        SCnpu = (- numpy.sqrt(rho2) / numpy.sqrt(self.Alpha)) * numpy.ones(self.Nn).reshape((-1, 1))
+        SC1an = Cc @ numpy.diag(1.0 / numpy.sqrt(Ww))
+        SCnpu = (-numpy.sqrt(rho2) / numpy.sqrt(self.Alpha)) * numpy.ones(
+            self.Nn
+        ).reshape((-1, 1))
         SC = numpy.concatenate((SC1an, SCnpu), axis=1)
         #
         return Wm, Wc, SC
@@ -1221,15 +1512,15 @@ class GenerateWeightsAndSigmaPoints(object):
         "Fifth Order Set, Lerner 2002"
         Ww = []
         for point in range(2 * self.Nn):
-            Ww.append( (4. - self.Nn) / 18. )
+            Ww.append((4.0 - self.Nn) / 18.0)
         for point in range(2 * self.Nn, 2 * self.Nn**2):
-            Ww.append( 1. / 36. )
-        Ww.append( (self.Nn**2 - 7 * self.Nn) / 18. + 1.)
-        Wm = Wc = numpy.array( Ww )
+            Ww.append(1.0 / 36.0)
+        Ww.append((self.Nn**2 - 7 * self.Nn) / 18.0 + 1.0)
+        Wm = Wc = numpy.array(Ww)
         # OK: assert abs(Wm.sum()-1.) < self.Nn*mpr, "5OS ill-conditioned %s >= %s"%(abs(Wm.sum()-1.), self.Nn*mpr)
         #
-        xi1n  = numpy.diag( math.sqrt(3) * numpy.ones( self.Nn ) )
-        xi2n  = numpy.diag( -math.sqrt(3) * numpy.ones( self.Nn ) )
+        xi1n = numpy.diag(math.sqrt(3) * numpy.ones(self.Nn))
+        xi2n = numpy.diag(-math.sqrt(3) * numpy.ones(self.Nn))
         #
         xi3n1 = numpy.zeros((int((self.Nn - 1) * self.Nn / 2), self.Nn), dtype=float)
         xi3n2 = numpy.zeros((int((self.Nn - 1) * self.Nn / 2), self.Nn), dtype=float)
@@ -1244,14 +1535,25 @@ class GenerateWeightsAndSigmaPoints(object):
                 xi4n1[ia, i1] = xi4n1[ia, i2] = math.sqrt(3)
                 xi4n2[ia, i1] = xi4n2[ia, i2] = -math.sqrt(3)
                 ia += 1
-        SC = numpy.concatenate((xi1n, xi2n, xi3n1, xi3n2, xi4n1, xi4n2, numpy.zeros((1, self.Nn)))).T
+        SC = numpy.concatenate(
+            (xi1n, xi2n, xi3n1, xi3n2, xi4n1, xi4n2, numpy.zeros((1, self.Nn)))
+        ).T
         #
         return Wm, Wc, SC
 
     def nbOfPoints(self):
-        assert self.Nn      == self.SC.shape[0], "Size mismatch %i =/= %i"%(self.Nn, self.SC.shape[0])
-        assert self.Wm.size == self.SC.shape[1], "Size mismatch %i =/= %i"%(self.Wm.size, self.SC.shape[1])
-        assert self.Wm.size == self.Wc.size, "Size mismatch %i =/= %i"%(self.Wm.size, self.Wc.size)
+        assert self.Nn == self.SC.shape[0], "Size mismatch %i =/= %i" % (
+            self.Nn,
+            self.SC.shape[0],
+        )
+        assert self.Wm.size == self.SC.shape[1], "Size mismatch %i =/= %i" % (
+            self.Wm.size,
+            self.SC.shape[1],
+        )
+        assert self.Wm.size == self.Wc.size, "Size mismatch %i =/= %i" % (
+            self.Wm.size,
+            self.Wc.size,
+        )
         return self.Wm.size
 
     def get(self):
@@ -1259,45 +1561,69 @@ class GenerateWeightsAndSigmaPoints(object):
 
     def __repr__(self):
         "x.__repr__() <==> repr(x)"
-        msg  = ""
-        msg += "    Alpha   = %s\n"%self.Alpha
-        msg += "    Beta    = %s\n"%self.Beta
-        msg += "    Kappa   = %s\n"%self.Kappa
-        msg += "    Lambda  = %s\n"%self.Lambda
-        msg += "    Gamma   = %s\n"%self.Gamma
-        msg += "    Wm      = %s\n"%self.Wm
-        msg += "    Wc      = %s\n"%self.Wc
-        msg += "    sum(Wm) = %s\n"%numpy.sum(self.Wm)
-        msg += "    SC      =\n%s\n"%self.SC
+        msg = ""
+        msg += "    Alpha   = %s\n" % self.Alpha
+        msg += "    Beta    = %s\n" % self.Beta
+        msg += "    Kappa   = %s\n" % self.Kappa
+        msg += "    Lambda  = %s\n" % self.Lambda
+        msg += "    Gamma   = %s\n" % self.Gamma
+        msg += "    Wm      = %s\n" % self.Wm
+        msg += "    Wc      = %s\n" % self.Wc
+        msg += "    sum(Wm) = %s\n" % numpy.sum(self.Wm)
+        msg += "    SC      =\n%s\n" % self.SC
         return msg
 
+
 # ==============================================================================
-def GetNeighborhoodTopology( __ntype, __ipop ):
+def GetNeighborhoodTopology(__ntype, __ipop):
     "Renvoi une topologie de connexion pour une population de points"
-    if __ntype in ["FullyConnectedNeighborhood", "FullyConnectedNeighbourhood", "gbest"]:
+    if __ntype in [
+        "FullyConnectedNeighborhood",
+        "FullyConnectedNeighbourhood",
+        "gbest",
+    ]:
         __topology = [__ipop for __i in __ipop]
-    elif __ntype in ["RingNeighborhoodWithRadius1", "RingNeighbourhoodWithRadius1", "lbest"]:
+    elif __ntype in [
+        "RingNeighborhoodWithRadius1",
+        "RingNeighbourhoodWithRadius1",
+        "lbest",
+    ]:
         __cpop = list(__ipop[-1:]) + list(__ipop) + list(__ipop[:1])
-        __topology = [__cpop[__n:__n + 3] for __n in range(len(__ipop))]
+        __topology = [__cpop[__n : __n + 3] for __n in range(len(__ipop))]  # noqa: E203
     elif __ntype in ["RingNeighborhoodWithRadius2", "RingNeighbourhoodWithRadius2"]:
         __cpop = list(__ipop[-2:]) + list(__ipop) + list(__ipop[:2])
-        __topology = [__cpop[__n:__n + 5] for __n in range(len(__ipop))]
-    elif __ntype in ["AdaptativeRandomWith3Neighbors", "AdaptativeRandomWith3Neighbours", "abest"]:
+        __topology = [__cpop[__n : __n + 5] for __n in range(len(__ipop))]  # noqa: E203
+    elif __ntype in [
+        "AdaptativeRandomWith3Neighbors",
+        "AdaptativeRandomWith3Neighbours",
+        "abest",
+    ]:
         __cpop = 3 * list(__ipop)
         __topology = [[__i] + list(numpy.random.choice(__cpop, 3)) for __i in __ipop]
-    elif __ntype in ["AdaptativeRandomWith5Neighbors", "AdaptativeRandomWith5Neighbours"]:
+    elif __ntype in [
+        "AdaptativeRandomWith5Neighbors",
+        "AdaptativeRandomWith5Neighbours",
+    ]:
         __cpop = 5 * list(__ipop)
         __topology = [[__i] + list(numpy.random.choice(__cpop, 5)) for __i in __ipop]
     else:
-        raise ValueError("Swarm topology type unavailable because name \"%s\" is unknown."%__ntype)
+        raise ValueError(
+            'Swarm topology type unavailable because name "%s" is unknown.' % __ntype
+        )
     return __topology
 
+
 # ==============================================================================
-def FindIndexesFromNames( __NameOfLocations = None, __ExcludeLocations = None, ForceArray = False ):
+def FindIndexesFromNames(
+    __NameOfLocations=None, __ExcludeLocations=None, ForceArray=False
+):
     "Exprime les indices des noms exclus, en ignorant les absents"
     if __ExcludeLocations is None:
         __ExcludeIndexes = ()
-    elif isinstance(__ExcludeLocations, (list, numpy.ndarray, tuple)) and len(__ExcludeLocations) == 0:
+    elif (
+        isinstance(__ExcludeLocations, (list, numpy.ndarray, tuple))
+        and len(__ExcludeLocations) == 0
+    ):
         __ExcludeIndexes = ()
     # ----------
     elif __NameOfLocations is None:
@@ -1305,15 +1631,24 @@ def FindIndexesFromNames( __NameOfLocations = None, __ExcludeLocations = None, F
             __ExcludeIndexes = numpy.asarray(__ExcludeLocations, dtype=int)
         except ValueError as e:
             if "invalid literal for int() with base 10:" in str(e):
-                raise ValueError("to exclude named locations, initial location name list can not be void and has to have the same length as one state")
+                raise ValueError(
+                    "to exclude named locations, initial location name list can"
+                    + " not be void and has to have the same length as one state"
+                )
             else:
                 raise ValueError(str(e))
-    elif isinstance(__NameOfLocations, (list, numpy.ndarray, tuple)) and len(__NameOfLocations) == 0:
+    elif (
+        isinstance(__NameOfLocations, (list, numpy.ndarray, tuple))
+        and len(__NameOfLocations) == 0
+    ):
         try:
             __ExcludeIndexes = numpy.asarray(__ExcludeLocations, dtype=int)
         except ValueError as e:
             if "invalid literal for int() with base 10:" in str(e):
-                raise ValueError("to exclude named locations, initial location name list can not be void and has to have the same length as one state")
+                raise ValueError(
+                    "to exclude named locations, initial location name list can"
+                    + " not be void and has to have the same length as one state"
+                )
             else:
                 raise ValueError(str(e))
     # ----------
@@ -1322,32 +1657,49 @@ def FindIndexesFromNames( __NameOfLocations = None, __ExcludeLocations = None, F
             __ExcludeIndexes = numpy.asarray(__ExcludeLocations, dtype=int)
         except ValueError as e:
             if "invalid literal for int() with base 10:" in str(e):
-                if len(__NameOfLocations) < 1.e6 + 1 and len(__ExcludeLocations) > 1500:
+                if (
+                    len(__NameOfLocations) < 1.0e6 + 1
+                    and len(__ExcludeLocations) > 1500
+                ):
                     __Heuristic = True
                 else:
                     __Heuristic = False
                 if ForceArray or __Heuristic:
                     # Recherche par array permettant des noms invalides, peu efficace
-                    __NameToIndex = dict(numpy.array((
-                        __NameOfLocations,
-                        range(len(__NameOfLocations))
-                    )).T)
-                    __ExcludeIndexes = numpy.asarray([__NameToIndex.get(k, -1) for k in __ExcludeLocations], dtype=int)
+                    __NameToIndex = dict(
+                        numpy.array(
+                            (__NameOfLocations, range(len(__NameOfLocations)))
+                        ).T
+                    )
+                    __ExcludeIndexes = numpy.asarray(
+                        [__NameToIndex.get(k, -1) for k in __ExcludeLocations],
+                        dtype=int,
+                    )
                     #
                 else:
                     # Recherche par liste permettant des noms invalides, très efficace
-                    def __NameToIndex_get( cle, default = -1 ):
+                    def __NameToIndex_get(cle, default=-1):
                         if cle in __NameOfLocations:
                             return __NameOfLocations.index(cle)
                         else:
                             return default
-                    __ExcludeIndexes = numpy.asarray([__NameToIndex_get(k, -1) for k in __ExcludeLocations], dtype=int)
+
+                    __ExcludeIndexes = numpy.asarray(
+                        [__NameToIndex_get(k, -1) for k in __ExcludeLocations],
+                        dtype=int,
+                    )
                     #
-                    # Recherche par liste interdisant des noms invalides, mais encore un peu plus efficace
-                    # __ExcludeIndexes = numpy.asarray([__NameOfLocations.index(k) for k in __ExcludeLocations], dtype=int)
+                    # Exemple de recherche par liste encore un peu plus efficace,
+                    # mais interdisant des noms invalides :
+                    # __ExcludeIndexes = numpy.asarray(
+                    #     [__NameOfLocations.index(k) for k in __ExcludeLocations],
+                    #     dtype=int,
+                    # )
                     #
                 # Ignore les noms absents
-                __ExcludeIndexes = numpy.compress(__ExcludeIndexes > -1, __ExcludeIndexes)
+                __ExcludeIndexes = numpy.compress(
+                    __ExcludeIndexes > -1, __ExcludeIndexes
+                )
                 if len(__ExcludeIndexes) == 0:
                     __ExcludeIndexes = ()
             else:
@@ -1355,22 +1707,28 @@ def FindIndexesFromNames( __NameOfLocations = None, __ExcludeLocations = None, F
     # ----------
     return __ExcludeIndexes
 
+
 # ==============================================================================
 def BuildComplexSampleList(
-        __SampleAsnUplet,
-        __SampleAsExplicitHyperCube,
-        __SampleAsMinMaxStepHyperCube,
-        __SampleAsMinMaxLatinHyperCube,
-        __SampleAsMinMaxSobolSequence,
-        __SampleAsIndependantRandomVariables,
-        __X0,
-        __Seed = None ):
+    __SampleAsnUplet,
+    __SampleAsExplicitHyperCube,
+    __SampleAsMinMaxStepHyperCube,
+    __SampleAsMinMaxLatinHyperCube,
+    __SampleAsMinMaxSobolSequence,
+    __SampleAsIndependantRandomVariables,
+    __X0,
+    __Seed=None,
+):
     # ---------------------------
     if len(__SampleAsnUplet) > 0:
         sampleList = __SampleAsnUplet
         for i, Xx in enumerate(sampleList):
             if numpy.ravel(Xx).size != __X0.size:
-                raise ValueError("The size %i of the %ith state X in the sample and %i of the checking point Xb are different, they have to be identical."%(numpy.ravel(Xx).size, i + 1, __X0.size))
+                raise ValueError(
+                    "The size %i of the %ith state X in the sample and %i of the"
+                    % (numpy.ravel(Xx).size, i + 1, __X0.size)
+                    + " checking point Xb are different, they have to be identical."
+                )
     # ---------------------------
     elif len(__SampleAsExplicitHyperCube) > 0:
         sampleList = itertools.product(*list(__SampleAsExplicitHyperCube))
@@ -1379,24 +1737,38 @@ def BuildComplexSampleList(
         coordinatesList = []
         for i, dim in enumerate(__SampleAsMinMaxStepHyperCube):
             if len(dim) != 3:
-                raise ValueError("For dimension %i, the variable definition \"%s\" is incorrect, it should be [min,max,step]."%(i, dim))
+                raise ValueError(
+                    'For dimension %i, the variable definition "%s" is incorrect,'
+                    % (i, dim)
+                    + " it should be [min,max,step]."
+                )
             else:
-                coordinatesList.append(numpy.linspace(dim[0], dim[1], 1 + int((float(dim[1]) - float(dim[0])) / float(dim[2]))))
+                coordinatesList.append(
+                    numpy.linspace(
+                        dim[0],
+                        dim[1],
+                        1 + int((float(dim[1]) - float(dim[0])) / float(dim[2])),
+                    )
+                )
         sampleList = itertools.product(*coordinatesList)
     # ---------------------------
     elif len(__SampleAsMinMaxLatinHyperCube) > 0:
         if vt(scipy.version.version) <= vt("1.7.0"):
-            __msg = "In order to use Latin Hypercube sampling, you must at least use Scipy version 1.7.0 (and you are presently using Scipy %s). A void sample is then generated."%scipy.version.version
+            __msg = (
+                "In order to use Latin Hypercube sampling, you must at least use"
+                + " Scipy version 1.7.0 (and you are presently using"
+                + " Scipy %s). A void sample is then generated." % scipy.version.version
+            )
             warnings.warn(__msg, FutureWarning, stacklevel=50)
             sampleList = []
         else:
             __spDesc = list(__SampleAsMinMaxLatinHyperCube)
-            __nbDime, __nbSamp  = map(int, __spDesc.pop())  # Réduction du dernier
+            __nbDime, __nbSamp = map(int, __spDesc.pop())  # Réduction du dernier
             __sample = scipy.stats.qmc.LatinHypercube(
-                d = len(__spDesc),
-                seed = numpy.random.default_rng(__Seed),
+                d=len(__spDesc),
+                seed=numpy.random.default_rng(__Seed),
             )
-            __sample = __sample.random(n = __nbSamp)
+            __sample = __sample.random(n=__nbSamp)
             __bounds = numpy.array(__spDesc)[:, 0:2]
             __l_bounds = __bounds[:, 0]
             __u_bounds = __bounds[:, 1]
@@ -1404,19 +1776,33 @@ def BuildComplexSampleList(
     # ---------------------------
     elif len(__SampleAsMinMaxSobolSequence) > 0:
         if vt(scipy.version.version) <= vt("1.7.0"):
-            __msg = "In order to use Latin Hypercube sampling, you must at least use Scipy version 1.7.0 (and you are presently using Scipy %s). A void sample is then generated."%scipy.version.version
+            __msg = (
+                "In order to use Latin Hypercube sampling, you must at least use"
+                + " Scipy version 1.7.0 (and you are presently using"
+                + " Scipy %s). A void sample is then generated." % scipy.version.version
+            )
             warnings.warn(__msg, FutureWarning, stacklevel=50)
             sampleList = []
         else:
             __spDesc = list(__SampleAsMinMaxSobolSequence)
-            __nbDime, __nbSamp  = map(int, __spDesc.pop())  # Réduction du dernier
+            __nbDime, __nbSamp = map(int, __spDesc.pop())  # Réduction du dernier
             if __nbDime != len(__spDesc):
-                warnings.warn("Declared space dimension (%i) is not equal to number of bounds (%i), the last one will be used."%(__nbDime, len(__spDesc)), FutureWarning, stacklevel=50)
+                __msg = (
+                    "Declared space dimension"
+                    + " (%i) is not equal to number of bounds (%i),"
+                    % (__nbDime, len(__spDesc))
+                    + " the last one will be used."
+                )
+                warnings.warn(
+                    __msg,
+                    FutureWarning,
+                    stacklevel=50,
+                )
             __sample = scipy.stats.qmc.Sobol(
-                d = len(__spDesc),
-                seed = numpy.random.default_rng(__Seed),
+                d=len(__spDesc),
+                seed=numpy.random.default_rng(__Seed),
             )
-            __sample = __sample.random_base2(m = int(math.log2(__nbSamp)) + 1)
+            __sample = __sample.random_base2(m=int(math.log2(__nbSamp)) + 1)
             __bounds = numpy.array(__spDesc)[:, 0:2]
             __l_bounds = __bounds[:, 0]
             __u_bounds = __bounds[:, 1]
@@ -1426,23 +1812,39 @@ def BuildComplexSampleList(
         coordinatesList = []
         for i, dim in enumerate(__SampleAsIndependantRandomVariables):
             if len(dim) != 3:
-                raise ValueError("For dimension %i, the variable definition \"%s\" is incorrect, it should be ('distribution',(parameters),length) with distribution in ['normal'(mean,std),'lognormal'(mean,sigma),'uniform'(low,high),'weibull'(shape)]."%(i, dim))
-            elif not ( str(dim[0]) in ['normal', 'lognormal', 'uniform', 'weibull'] \
-                       and hasattr(numpy.random, str(dim[0])) ):
-                raise ValueError("For dimension %i, the distribution name \"%s\" is not allowed, please choose in ['normal'(mean,std),'lognormal'(mean,sigma),'uniform'(low,high),'weibull'(shape)]"%(i, str(dim[0])))
+                raise ValueError(
+                    'For dimension %i, the variable definition "%s" is incorrect,'
+                    % (i, dim)
+                    + " it should be ('distribution',(parameters),length) with"
+                    + " distribution in ['normal'(mean,std), 'lognormal'(mean,sigma),"
+                    + " 'uniform'(low,high), 'weibull'(shape)]."
+                )
+            elif not (
+                str(dim[0]) in ["normal", "lognormal", "uniform", "weibull"]
+                and hasattr(numpy.random, str(dim[0]))
+            ):
+                raise ValueError(
+                    'For dimension %i, the distribution name "%s" is not allowed,'
+                    % (i, str(dim[0]))
+                    + " please choose in ['normal'(mean,std), 'lognormal'(mean,sigma),"
+                    + " 'uniform'(low,high), 'weibull'(shape)]"
+                )
             else:
-                distribution = getattr(numpy.random, str(dim[0]), 'normal')
+                distribution = getattr(numpy.random, str(dim[0]), "normal")
                 coordinatesList.append(distribution(*dim[1], size=max(1, int(dim[2]))))
         sampleList = itertools.product(*coordinatesList)
     else:
-        sampleList = iter([__X0,])
+        sampleList = iter(
+            [
+                __X0,
+            ]
+        )
     # ----------
     return sampleList
 
+
 # ==============================================================================
-def multiXOsteps(
-        selfA, Xb, Y, U, HO, EM, CM, R, B, Q, oneCycle,
-        __CovForecast = False ):
+def multiXOsteps(selfA, Xb, Y, U, HO, EM, CM, R, B, Q, oneCycle, __CovForecast=False):
     """
     Prévision multi-pas avec une correction par pas (multi-méthodes)
     """
@@ -1450,16 +1852,21 @@ def multiXOsteps(
     # Initialisation
     # --------------
     if selfA._parameters["EstimationOf"] == "State":
-        if len(selfA.StoredVariables["Analysis"]) == 0 or not selfA._parameters["nextStep"]:
+        if (
+            len(selfA.StoredVariables["Analysis"]) == 0
+            or not selfA._parameters["nextStep"]
+        ):
             Xn = numpy.asarray(Xb)
             if __CovForecast:
                 Pn = B
-            selfA.StoredVariables["Analysis"].store( Xn )
+            selfA.StoredVariables["Analysis"].store(Xn)
             if selfA._toStore("APosterioriCovariance"):
                 if hasattr(B, "asfullmatrix"):
-                    selfA.StoredVariables["APosterioriCovariance"].store( B.asfullmatrix(Xn.size) )
+                    selfA.StoredVariables["APosterioriCovariance"].store(
+                        B.asfullmatrix(Xn.size)
+                    )
                 else:
-                    selfA.StoredVariables["APosterioriCovariance"].store( B )
+                    selfA.StoredVariables["APosterioriCovariance"].store(B)
             selfA._setInternalState("seed", numpy.random.get_state())
         elif selfA._parameters["nextStep"]:
             Xn = selfA._getInternalState("Xn")
@@ -1478,20 +1885,22 @@ def multiXOsteps(
     # Multi-steps
     # -----------
     for step in range(duration - 1):
-        selfA.StoredVariables["CurrentStepNumber"].store( len(selfA.StoredVariables["Analysis"]) )
+        selfA.StoredVariables["CurrentStepNumber"].store(
+            len(selfA.StoredVariables["Analysis"])
+        )
         #
         if hasattr(Y, "store"):
-            Ynpu = numpy.asarray( Y[step + 1] ).reshape((-1, 1))
+            Ynpu = numpy.asarray(Y[step + 1]).reshape((-1, 1))
         else:
-            Ynpu = numpy.asarray( Y ).reshape((-1, 1))
+            Ynpu = numpy.asarray(Y).reshape((-1, 1))
         #
         if U is not None:
             if hasattr(U, "store") and len(U) > 1:
-                Un = numpy.asarray( U[step] ).reshape((-1, 1))
+                Un = numpy.asarray(U[step]).reshape((-1, 1))
             elif hasattr(U, "store") and len(U) == 1:
-                Un = numpy.asarray( U[0] ).reshape((-1, 1))
+                Un = numpy.asarray(U[0]).reshape((-1, 1))
             else:
-                Un = numpy.asarray( U ).reshape((-1, 1))
+                Un = numpy.asarray(U).reshape((-1, 1))
         else:
             Un = None
         #
@@ -1505,8 +1914,10 @@ def multiXOsteps(
                 Ma = Ma.reshape(Xn.size, Xn.size)  # ADAO & check shape
                 Pn_predicted = Q + Mt @ (Pn @ Ma)
             Mm = EM["Direct"].appliedControledFormTo
-            Xn_predicted = Mm( (Xn, Un) ).reshape((-1, 1))
-            if CM is not None and "Tangent" in CM and Un is not None:  # Attention : si Cm est aussi dans M, doublon !
+            Xn_predicted = Mm((Xn, Un)).reshape((-1, 1))
+            if (
+                CM is not None and "Tangent" in CM and Un is not None
+            ):  # Attention : si Cm est aussi dans M, doublon !
                 Cm = CM["Tangent"].asMatrix(Xn_predicted)
                 Cm = Cm.reshape(Xn.size, Un.size)  # ADAO & check shape
                 Xn_predicted = Xn_predicted + (Cm @ Un).reshape((-1, 1))
@@ -1517,14 +1928,14 @@ def multiXOsteps(
                 Pn_predicted = Pn
         Xn_predicted = numpy.asarray(Xn_predicted).reshape((-1, 1))
         if selfA._toStore("ForecastState"):
-            selfA.StoredVariables["ForecastState"].store( Xn_predicted )
+            selfA.StoredVariables["ForecastState"].store(Xn_predicted)
         if __CovForecast:
             if hasattr(Pn_predicted, "asfullmatrix"):
                 Pn_predicted = Pn_predicted.asfullmatrix(Xn.size)
             else:
                 Pn_predicted = numpy.asarray(Pn_predicted).reshape((Xn.size, Xn.size))
             if selfA._toStore("ForecastCovariance"):
-                selfA.StoredVariables["ForecastCovariance"].store( Pn_predicted )
+                selfA.StoredVariables["ForecastCovariance"].store(Pn_predicted)
         #
         # Correct (Measurement Update)
         # ----------------------------
@@ -1540,6 +1951,7 @@ def multiXOsteps(
     #
     return 0
 
+
 # ==============================================================================
 if __name__ == "__main__":
     print("\n AUTODIAGNOSTIC\n")
index 29d7f71f5e961810f2468e8f9cd0cbc585ee3e9d..dfb2f49364c551f445311385e5d092b1f91ca98b 100644 (file)
 __author__ = "Jean-Philippe ARGAUD"
 __all__ = []
 
-import os, numpy, copy, math
-import gzip, bz2, pickle
+import os
+import copy
+import math
+import gzip
+import bz2
+import pickle
+import numpy
 
-from daCore.PlatformInfo import PathManagement ; PathManagement()  # noqa: E702,E203
-from daCore.PlatformInfo import PlatformInfo
+from daCore.PlatformInfo import PathManagement, PlatformInfo
+
+PathManagement()
 lpi = PlatformInfo()
 mfp = lpi.MaximumPrecision()
 
 if lpi.has_gnuplot:
     import Gnuplot
 
+
 # ==============================================================================
 class Persistence(object):
     """
     Classe générale de persistance définissant les accesseurs nécessaires
     (Template)
     """
+
     __slots__ = (
-        "__name", "__unit", "__basetype", "__values", "__tags", "__dynamic",
-        "__g", "__title", "__ltitle", "__pause", "__dataobservers",
+        "__name",
+        "__unit",
+        "__basetype",
+        "__values",
+        "__tags",
+        "__dynamic",
+        "__g",
+        "__title",
+        "__ltitle",
+        "__pause",
+        "__dataobservers",
     )
 
     def __init__(self, name="", unit="", basetype=str):
@@ -67,14 +84,14 @@ class Persistence(object):
         #
         self.__basetype = basetype
         #
-        self.__values   = []
-        self.__tags     = []
+        self.__values = []
+        self.__tags = []
         #
-        self.__dynamic  = False
-        self.__g        = None
-        self.__title    = None
-        self.__ltitle   = None
-        self.__pause    = None
+        self.__dynamic = False
+        self.__g = None
+        self.__title = None
+        self.__ltitle = None
+        self.__pause = None
         #
         self.__dataobservers = []
 
@@ -103,20 +120,20 @@ class Persistence(object):
         for hook, parameters, scheduler, order, osync, dovar in self.__dataobservers:
             if __step in scheduler:
                 if order is None or dovar is None:
-                    hook( self, parameters )
+                    hook(self, parameters)
                 else:
                     if not isinstance(order, (list, tuple)):
                         continue
                     if not isinstance(dovar, dict):
                         continue
                     if not bool(osync):  # Async observation
-                        hook( self, parameters, order, dovar )
+                        hook(self, parameters, order, dovar)
                     else:  # Sync observations
                         for v in order:
                             if len(dovar[v]) != len(self):
                                 break
                         else:
-                            hook( self, parameters, order, dovar )
+                            hook(self, parameters, order, dovar)
 
     def pop(self, item=None):
         """
@@ -139,7 +156,12 @@ class Persistence(object):
         longueur. Par défaut, renvoie 1.
         """
         if len(self.__values) > 0:
-            if self.__basetype in [numpy.matrix, numpy.ndarray, numpy.array, numpy.ravel]:
+            if self.__basetype in [
+                numpy.matrix,
+                numpy.ndarray,
+                numpy.array,
+                numpy.ravel,
+            ]:
                 return self.__values[-1].shape
             elif self.__basetype in [int, float]:
                 return (1,)
@@ -153,9 +175,9 @@ class Persistence(object):
     # ---------------------------------------------------------
     def __str__(self):
         "x.__str__() <==> str(x)"
-        msg  = "   Index        Value   Tags\n"
+        msg = "   Index        Value   Tags\n"
         for iv, vv in enumerate(self.__values):
-            msg += "  i=%05i  %10s   %s\n"%(iv, vv, self.__tags[iv])
+            msg += "  i=%05i  %10s   %s\n" % (iv, vv, self.__tags[iv])
         return msg
 
     def __len__(self):
@@ -165,7 +187,7 @@ class Persistence(object):
     def name(self):
         return self.__name
 
-    def __getitem__(self, index=None ):
+    def __getitem__(self, index=None):
         "x.__getitem__(y) <==> x[y]"
         return copy.copy(self.__values[index])
 
@@ -190,9 +212,12 @@ class Persistence(object):
                 for i in __indexOfFilteredItems:
                     if tagKey in self.__tags[i]:
                         if self.__tags[i][tagKey] == kwargs[tagKey]:
-                            __tmp.append( i )
-                        elif isinstance(kwargs[tagKey], (list, tuple)) and self.__tags[i][tagKey] in kwargs[tagKey]:
-                            __tmp.append( i )
+                            __tmp.append(i)
+                        elif (
+                            isinstance(kwargs[tagKey], (list, tuple))
+                            and self.__tags[i][tagKey] in kwargs[tagKey]
+                        ):
+                            __tmp.append(i)
                 __indexOfFilteredItems = __tmp
                 if len(__indexOfFilteredItems) == 0:
                     break
@@ -210,9 +235,9 @@ class Persistence(object):
         __keys = []
         for i in __indexOfFilteredItems:
             if keyword in self.__tags[i]:
-                __keys.append( self.__tags[i][keyword] )
+                __keys.append(self.__tags[i][keyword])
             else:
-                __keys.append( None )
+                __keys.append(None)
         return __keys
 
     def items(self, keyword=None, **kwargs):
@@ -221,16 +246,16 @@ class Persistence(object):
         __pairs = []
         for i in __indexOfFilteredItems:
             if keyword in self.__tags[i]:
-                __pairs.append( (self.__tags[i][keyword], self.__values[i]) )
+                __pairs.append((self.__tags[i][keyword], self.__values[i]))
             else:
-                __pairs.append( (None, self.__values[i]) )
+                __pairs.append((None, self.__values[i]))
         return __pairs
 
     def tagkeys(self):
         "D.tagkeys() -> list of D's tag keys"
         __allKeys = []
         for dicotags in self.__tags:
-            __allKeys.extend( list(dicotags.keys()) )
+            __allKeys.extend(list(dicotags.keys()))
         __allKeys = sorted(set(__allKeys))
         return __allKeys
 
@@ -249,14 +274,16 @@ class Persistence(object):
         if item is None:
             __indexOfFilteredItems = self.__filteredIndexes(**kwargs)
         else:
-            __indexOfFilteredItems = [item,]
+            __indexOfFilteredItems = [
+                item,
+            ]
         #
         # Dans le cas où la sortie donne les valeurs d'un "outputTag"
         if outputTag is not None and isinstance(outputTag, str):
             outputValues = []
             for index in __indexOfFilteredItems:
                 if outputTag in self.__tags[index].keys():
-                    outputValues.append( self.__tags[index][outputTag] )
+                    outputValues.append(self.__tags[index][outputTag])
             outputValues = sorted(set(outputValues))
             return outputValues
         #
@@ -267,7 +294,7 @@ class Persistence(object):
             else:
                 allTags = {}
                 for index in __indexOfFilteredItems:
-                    allTags.update( self.__tags[index] )
+                    allTags.update(self.__tags[index])
                 allKeys = sorted(allTags.keys())
                 return allKeys
 
@@ -297,7 +324,9 @@ class Persistence(object):
         élémentaires numpy.
         """
         try:
-            __sr = [numpy.mean(item, dtype=mfp).astype('float') for item in self.__values]
+            __sr = [
+                numpy.mean(item, dtype=mfp).astype("float") for item in self.__values
+            ]
         except Exception:
             raise TypeError("Base type is incompatible with numpy")
         return numpy.array(__sr).tolist()
@@ -312,10 +341,16 @@ class Persistence(object):
                l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
         """
         try:
-            if numpy.version.version >= '1.1.0':
-                __sr = [numpy.array(item).std(ddof=ddof, dtype=mfp).astype('float') for item in self.__values]
+            if numpy.version.version >= "1.1.0":
+                __sr = [
+                    numpy.array(item).std(ddof=ddof, dtype=mfp).astype("float")
+                    for item in self.__values
+                ]
             else:
-                return [numpy.array(item).std(dtype=mfp).astype('float') for item in self.__values]
+                return [
+                    numpy.array(item).std(dtype=mfp).astype("float")
+                    for item in self.__values
+                ]
         except Exception:
             raise TypeError("Base type is incompatible with numpy")
         return numpy.array(__sr).tolist()
@@ -384,19 +419,22 @@ class Persistence(object):
 
     def traces(self, offset=0):
         """
-        Trace
+        Trace (offset : voir numpy.trace)
 
         Renvoie la série contenant, à chaque pas, la trace (avec l'offset) des
         données au pas. Il faut que le type de base soit compatible avec les
         types élémentaires numpy.
         """
         try:
-            __sr = [numpy.trace(item, offset, dtype=mfp).astype('float') for item in self.__values]
+            __sr = [
+                numpy.trace(item, offset, dtype=mfp).astype("float")
+                for item in self.__values
+            ]
         except Exception:
             raise TypeError("Base type is incompatible with numpy")
         return numpy.array(__sr).tolist()
 
-    def maes(self, _predictor=None):
+    def maes(self, predictor=None):
         """
         Mean Absolute Error (MAE)
         mae(dX) = 1/n sum(dX_i)
@@ -407,27 +445,34 @@ class Persistence(object):
         prédicteur est None, sinon c'est appliqué à l'écart entre les données
         au pas et le prédicteur au même pas.
         """
-        if _predictor is None:
+        if predictor is None:
             try:
                 __sr = [numpy.mean(numpy.abs(item)) for item in self.__values]
             except Exception:
                 raise TypeError("Base type is incompatible with numpy")
         else:
-            if len(_predictor) != len(self.__values):
-                raise ValueError("Predictor number of steps is incompatible with the values")
+            if len(predictor) != len(self.__values):
+                raise ValueError(
+                    "Predictor number of steps is incompatible with the values"
+                )
             for i, item in enumerate(self.__values):
-                if numpy.asarray(_predictor[i]).size != numpy.asarray(item).size:
-                    raise ValueError("Predictor size at step %i is incompatible with the values"%i)
+                if numpy.asarray(predictor[i]).size != numpy.asarray(item).size:
+                    raise ValueError(
+                        "Predictor size at step %i is incompatible with the values" % i
+                    )
             try:
-                __sr = [numpy.mean(numpy.abs(numpy.ravel(item) - numpy.ravel(_predictor[i]))) for i, item in enumerate(self.__values)]
+                __sr = [
+                    numpy.mean(numpy.abs(numpy.ravel(item) - numpy.ravel(predictor[i])))
+                    for i, item in enumerate(self.__values)
+                ]
             except Exception:
                 raise TypeError("Base type is incompatible with numpy")
         return numpy.array(__sr).tolist()
 
-    def mses(self, _predictor=None):
+    def mses(self, predictor=None):
         """
         Mean-Square Error (MSE) ou Mean-Square Deviation (MSD)
-        mse(dX) = 1/n sum(dX_i**2)
+        mse(dX) = 1/n sum(dX_i**2) = 1/n ||X||^2
 
         Renvoie la série contenant, à chaque pas, la MSE des données au pas. Il
         faut que le type de base soit compatible avec les types élémentaires
@@ -435,28 +480,39 @@ class Persistence(object):
         prédicteur est None, sinon c'est appliqué à l'écart entre les données
         au pas et le prédicteur au même pas.
         """
-        if _predictor is None:
+        if predictor is None:
             try:
                 __n = self.shape()[0]
-                __sr = [(numpy.linalg.norm(item)**2 / __n) for item in self.__values]
+                __sr = [(numpy.linalg.norm(item) ** 2 / __n) for item in self.__values]
             except Exception:
                 raise TypeError("Base type is incompatible with numpy")
         else:
-            if len(_predictor) != len(self.__values):
-                raise ValueError("Predictor number of steps is incompatible with the values")
+            if len(predictor) != len(self.__values):
+                raise ValueError(
+                    "Predictor number of steps is incompatible with the values"
+                )
             for i, item in enumerate(self.__values):
-                if numpy.asarray(_predictor[i]).size != numpy.asarray(item).size:
-                    raise ValueError("Predictor size at step %i is incompatible with the values"%i)
+                if numpy.asarray(predictor[i]).size != numpy.asarray(item).size:
+                    raise ValueError(
+                        "Predictor size at step %i is incompatible with the values" % i
+                    )
             try:
                 __n = self.shape()[0]
-                __sr = [(numpy.linalg.norm(numpy.ravel(item) - numpy.ravel(_predictor[i]))**2 / __n) for i, item in enumerate(self.__values)]
+                __sr = [
+                    (
+                        numpy.linalg.norm(numpy.ravel(item) - numpy.ravel(predictor[i]))
+                        ** 2
+                        / __n
+                    )
+                    for i, item in enumerate(self.__values)
+                ]
             except Exception:
                 raise TypeError("Base type is incompatible with numpy")
         return numpy.array(__sr).tolist()
 
     msds = mses  # Mean-Square Deviation (MSD=MSE)
 
-    def rmses(self, _predictor=None):
+    def rmses(self, predictor=None):
         """
         Root-Mean-Square Error (RMSE) ou Root-Mean-Square Deviation (RMSD)
         rmse(dX) = sqrt( 1/n sum(dX_i**2) ) = sqrt( mse(dX) )
@@ -464,38 +520,52 @@ class Persistence(object):
         Renvoie la série contenant, à chaque pas, la RMSE des données au pas.
         Il faut que le type de base soit compatible avec les types élémentaires
         numpy. C'est réservé aux variables d'écarts ou d'incréments si le
-        prédicteur est None, sinon c'est appliqué à l'écart entre les données
-        au pas et le prédicteur au même pas.
+        prédicteur est None (c'est donc une RMS), sinon c'est appliqué à
+        l'écart entre les données au pas et le prédicteur au même pas.
         """
-        if _predictor is None:
+        if predictor is None:
             try:
                 __n = self.shape()[0]
-                __sr = [(numpy.linalg.norm(item) / math.sqrt(__n)) for item in self.__values]
+                __sr = [
+                    (numpy.linalg.norm(item) / math.sqrt(__n)) for item in self.__values
+                ]
             except Exception:
                 raise TypeError("Base type is incompatible with numpy")
         else:
-            if len(_predictor) != len(self.__values):
-                raise ValueError("Predictor number of steps is incompatible with the values")
+            if len(predictor) != len(self.__values):
+                raise ValueError(
+                    "Predictor number of steps is incompatible with the values"
+                )
             for i, item in enumerate(self.__values):
-                if numpy.asarray(_predictor[i]).size != numpy.asarray(item).size:
-                    raise ValueError("Predictor size at step %i is incompatible with the values"%i)
+                if numpy.asarray(predictor[i]).size != numpy.asarray(item).size:
+                    raise ValueError(
+                        "Predictor size at step %i is incompatible with the values" % i
+                    )
             try:
                 __n = self.shape()[0]
-                __sr = [(numpy.linalg.norm(numpy.ravel(item) - numpy.ravel(_predictor[i])) / math.sqrt(__n)) for i, item in enumerate(self.__values)]
+                __sr = [
+                    (
+                        numpy.linalg.norm(numpy.ravel(item) - numpy.ravel(predictor[i]))
+                        / math.sqrt(__n)
+                    )
+                    for i, item in enumerate(self.__values)
+                ]
             except Exception:
                 raise TypeError("Base type is incompatible with numpy")
         return numpy.array(__sr).tolist()
 
     rmsds = rmses  # Root-Mean-Square Deviation (RMSD=RMSE)
 
-    def __preplots(self,
-                   title    = "",
-                   xlabel   = "",
-                   ylabel   = "",
-                   ltitle   = None,
-                   geometry = "600x400",
-                   persist  = False,
-                   pause    = True ):
+    def __preplots(
+        self,
+        title="",
+        xlabel="",
+        ylabel="",
+        ltitle=None,
+        geometry="600x400",
+        persist=False,
+        pause=True,
+    ):
         "Préparation des plots"
         #
         # Vérification de la disponibilité du module Gnuplot
@@ -506,35 +576,39 @@ class Persistence(object):
         if ltitle is None:
             ltitle = ""
         __geometry = str(geometry)
-        __sizespec = (__geometry.split('+')[0]).replace('x', ',')
+        __sizespec = (__geometry.split("+")[0]).replace("x", ",")
         #
         if persist:
-            Gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist '
+            Gnuplot.GnuplotOpts.gnuplot_command = "gnuplot -persist "
         #
         self.__g = Gnuplot.Gnuplot()  # persist=1
-        self.__g('set terminal ' + Gnuplot.GnuplotOpts.default_term + ' size ' + __sizespec)
-        self.__g('set style data lines')
-        self.__g('set grid')
-        self.__g('set autoscale')
+        self.__g(
+            "set terminal " + Gnuplot.GnuplotOpts.default_term + " size " + __sizespec
+        )
+        self.__g("set style data lines")
+        self.__g("set grid")
+        self.__g("set autoscale")
         self.__g('set xlabel "' + str(xlabel) + '"')
         self.__g('set ylabel "' + str(ylabel) + '"')
-        self.__title  = title
+        self.__title = title
         self.__ltitle = ltitle
-        self.__pause  = pause
-
-    def plots(self,
-              item     = None,
-              step     = None,
-              steps    = None,
-              title    = "",
-              xlabel   = "",
-              ylabel   = "",
-              ltitle   = None,
-              geometry = "600x400",
-              filename = "",
-              dynamic  = False,
-              persist  = False,
-              pause    = True ):
+        self.__pause = pause
+
+    def plots(
+        self,
+        item=None,
+        step=None,
+        steps=None,
+        title="",
+        xlabel="",
+        ylabel="",
+        ltitle=None,
+        geometry="600x400",
+        filename="",
+        dynamic=False,
+        persist=False,
+        pause=True,
+    ):
         """
         Renvoie un affichage de la valeur à chaque pas, si elle est compatible
         avec un affichage Gnuplot (donc essentiellement un vecteur). Si
@@ -571,7 +645,7 @@ class Persistence(object):
                          Par défaut, pause = True
         """
         if not self.__dynamic:
-            self.__preplots(title, xlabel, ylabel, ltitle, geometry, persist, pause )
+            self.__preplots(title, xlabel, ylabel, ltitle, geometry, persist, pause)
             if dynamic:
                 self.__dynamic = True
                 if len(self.__values) == 0:
@@ -588,22 +662,25 @@ class Persistence(object):
         #
         i = -1
         for index in indexes:
-            self.__g('set title  "' + str(title) + ' (pas ' + str(index) + ')"')
+            self.__g('set title  "' + str(title) + " (pas " + str(index) + ')"')
             if isinstance(steps, (list, numpy.ndarray)):
                 Steps = list(steps)
             else:
                 Steps = list(range(len(self.__values[index])))
             #
-            self.__g.plot( Gnuplot.Data( Steps, self.__values[index], title=ltitle ) )
+            self.__g.plot(Gnuplot.Data(Steps, self.__values[index], title=ltitle))
             #
             if filename != "":
                 i += 1
-                stepfilename = "%s_%03i.ps"%(filename, i)
+                stepfilename = "%s_%03i.ps" % (filename, i)
                 if os.path.isfile(stepfilename):
-                    raise ValueError("Error: a file with this name \"%s\" already exists."%stepfilename)
+                    raise ValueError(
+                        'Error: a file with this name "%s" already exists.'
+                        % stepfilename
+                    )
                 self.__g.hardcopy(filename=stepfilename, color=1)
             if self.__pause:
-                eval(input('Please press return to continue...\n'))
+                eval(input("Please press return to continue...\n"))
 
     def __replots(self):
         """
@@ -614,10 +691,10 @@ class Persistence(object):
         #
         self.__g('set title  "' + str(self.__title))
         Steps = list(range(len(self.__values)))
-        self.__g.plot( Gnuplot.Data( Steps, self.__values, title=self.__ltitle ) )
+        self.__g.plot(Gnuplot.Data(Steps, self.__values, title=self.__ltitle))
         #
         if self.__pause:
-            eval(input('Please press return to continue...\n'))
+            eval(input("Please press return to continue...\n"))
 
     # ---------------------------------------------------------
     # On pourrait aussi utiliser d'autres attributs d'un "array" comme "tofile"
@@ -628,7 +705,7 @@ class Persistence(object):
         les types élémentaires numpy.
         """
         try:
-            return numpy.mean(self.__values, axis=0, dtype=mfp).astype('float')
+            return numpy.mean(self.__values, axis=0, dtype=mfp).astype("float")
         except Exception:
             raise TypeError("Base type is incompatible with numpy")
 
@@ -642,10 +719,12 @@ class Persistence(object):
                l'écart-type, qui est dans le diviseur. Inutile avant Numpy 1.1
         """
         try:
-            if numpy.version.version >= '1.1.0':
-                return numpy.asarray(self.__values).std(ddof=ddof, axis=0).astype('float')
+            if numpy.version.version >= "1.1.0":
+                return (
+                    numpy.asarray(self.__values).std(ddof=ddof, axis=0).astype("float")
+                )
             else:
-                return numpy.asarray(self.__values).std(axis=0).astype('float')
+                return numpy.asarray(self.__values).std(axis=0).astype("float")
         except Exception:
             raise TypeError("Base type is incompatible with numpy")
 
@@ -693,16 +772,18 @@ class Persistence(object):
         except Exception:
             raise TypeError("Base type is incompatible with numpy")
 
-    def plot(self,
-             steps    = None,
-             title    = "",
-             xlabel   = "",
-             ylabel   = "",
-             ltitle   = None,
-             geometry = "600x400",
-             filename = "",
-             persist  = False,
-             pause    = True ):
+    def plot(
+        self,
+        steps=None,
+        title="",
+        xlabel="",
+        ylabel="",
+        ltitle=None,
+        geometry="600x400",
+        filename="",
+        persist=False,
+        pause=True,
+    ):
         """
         Renvoie un affichage unique pour l'ensemble des valeurs à chaque pas, si
         elles sont compatibles avec un affichage Gnuplot (donc essentiellement
@@ -742,30 +823,40 @@ class Persistence(object):
         else:
             Steps = list(range(len(self.__values[0])))
         __geometry = str(geometry)
-        __sizespec = (__geometry.split('+')[0]).replace('x', ',')
+        __sizespec = (__geometry.split("+")[0]).replace("x", ",")
         #
         if persist:
-            Gnuplot.GnuplotOpts.gnuplot_command = 'gnuplot -persist '
+            Gnuplot.GnuplotOpts.gnuplot_command = "gnuplot -persist "
         #
         self.__g = Gnuplot.Gnuplot()  # persist=1
-        self.__g('set terminal ' + Gnuplot.GnuplotOpts.default_term + ' size ' + __sizespec)
-        self.__g('set style data lines')
-        self.__g('set grid')
-        self.__g('set autoscale')
-        self.__g('set title  "' + str(title)  + '"')
+        self.__g(
+            "set terminal " + Gnuplot.GnuplotOpts.default_term + " size " + __sizespec
+        )
+        self.__g("set style data lines")
+        self.__g("set grid")
+        self.__g("set autoscale")
+        self.__g('set title  "' + str(title) + '"')
         self.__g('set xlabel "' + str(xlabel) + '"')
         self.__g('set ylabel "' + str(ylabel) + '"')
         #
         # Tracé du ou des vecteurs demandés
         indexes = list(range(len(self.__values)))
-        self.__g.plot( Gnuplot.Data( Steps, self.__values[indexes.pop(0)], title=ltitle + " (pas 0)" ) )
+        self.__g.plot(
+            Gnuplot.Data(
+                Steps, self.__values[indexes.pop(0)], title=ltitle + " (pas 0)"
+            )
+        )
         for index in indexes:
-            self.__g.replot( Gnuplot.Data( Steps, self.__values[index], title=ltitle + " (pas %i)"%index ) )
+            self.__g.replot(
+                Gnuplot.Data(
+                    Steps, self.__values[index], title=ltitle + " (pas %i)" % index
+                )
+            )
         #
         if filename != "":
             self.__g.hardcopy(filename=filename, color=1)
         if pause:
-            eval(input('Please press return to continue...\n'))
+            eval(input("Please press return to continue...\n"))
 
     # ---------------------------------------------------------
     def s2mvr(self):
@@ -790,7 +881,15 @@ class Persistence(object):
             raise TypeError("Base type is incompatible with numpy")
 
     # ---------------------------------------------------------
-    def setDataObserver(self, HookFunction = None, HookParameters = None, Scheduler = None, Order = None, OSync = True, DOVar = None):
+    def setDataObserver(
+        self,
+        HookFunction=None,
+        HookParameters=None,
+        Scheduler=None,
+        Order=None,
+        OSync=True,
+        DOVar=None,
+    ):
         """
         Association à la variable d'un triplet définissant un observer.
 
@@ -801,21 +900,27 @@ class Persistence(object):
         #
         # Vérification du Scheduler
         # -------------------------
-        maxiter = int( 1e9 )
-        if isinstance(Scheduler, int):                # Considéré comme une fréquence à partir de 0
-            Schedulers = range( 0, maxiter, int(Scheduler) )
-        elif isinstance(Scheduler, range):            # Considéré comme un itérateur
+        maxiter = int(1e9)
+        if isinstance(Scheduler, int):  # Considéré comme une fréquence à partir de 0
+            Schedulers = range(0, maxiter, int(Scheduler))
+        elif isinstance(Scheduler, range):  # Considéré comme un itérateur
             Schedulers = Scheduler
-        elif isinstance(Scheduler, (list, tuple)):    # Considéré comme des index explicites
-            Schedulers = [int(i) for i in Scheduler]  # Similaire à map( int, Scheduler )  # noqa: E262
-        else:                                         # Dans tous les autres cas, activé par défaut
-            Schedulers = range( 0, maxiter )
+        elif isinstance(
+            Scheduler, (list, tuple)
+        ):  # Considéré comme des index explicites
+            Schedulers = [
+                int(i) for i in Scheduler
+            ]  # Similaire à map( int, Scheduler )
+        else:  # Dans tous les autres cas, activé par défaut
+            Schedulers = range(0, maxiter)
         #
         # Stockage interne de l'observer dans la variable
         # -----------------------------------------------
-        self.__dataobservers.append( [HookFunction, HookParameters, Schedulers, Order, OSync, DOVar] )
+        self.__dataobservers.append(
+            [HookFunction, HookParameters, Schedulers, Order, OSync, DOVar]
+        )
 
-    def removeDataObserver(self, HookFunction = None, AllObservers = False):
+    def removeDataObserver(self, HookFunction=None, AllObservers=False):
         """
         Suppression d'un observer nommé sur la variable.
 
@@ -824,11 +929,11 @@ class Persistence(object):
         AllObservers est vrai, supprime tous les observers enregistrés.
         """
         if hasattr(HookFunction, "func_name"):
-            name = str( HookFunction.func_name )
+            name = str(HookFunction.func_name)
         elif hasattr(HookFunction, "__name__"):
-            name = str( HookFunction.__name__ )
+            name = str(HookFunction.__name__)
         elif isinstance(HookFunction, str):
-            name = str( HookFunction )
+            name = str(HookFunction)
         else:
             name = None
         #
@@ -837,31 +942,36 @@ class Persistence(object):
         for [hf, _, _, _, _, _] in self.__dataobservers:
             ih = ih + 1
             if name is hf.__name__ or AllObservers:
-                index_to_remove.append( ih )
+                index_to_remove.append(ih)
         index_to_remove.reverse()
         for ih in index_to_remove:
-            self.__dataobservers.pop( ih )
+            self.__dataobservers.pop(ih)
         return len(index_to_remove)
 
     def hasDataObserver(self):
         return bool(len(self.__dataobservers) > 0)
 
+
 # ==============================================================================
 class SchedulerTrigger(object):
     """
     Classe générale d'interface de type Scheduler/Trigger
     """
+
     __slots__ = ()
 
-    def __init__(self,
-                 simplifiedCombo = None,
-                 startTime       = 0,
-                 endTime         = int( 1e9 ),
-                 timeDelay       = 1,
-                 timeUnit        = 1,
-                 frequency       = None ):
+    def __init__(
+        self,
+        simplifiedCombo=None,
+        startTime=0,
+        endTime=int(1e9),
+        timeDelay=1,
+        timeUnit=1,
+        frequency=None,
+    ):
         pass
 
+
 # ==============================================================================
 class OneScalar(Persistence):
     """
@@ -873,63 +983,76 @@ class OneScalar(Persistence):
     ou des matrices comme dans les classes suivantes, mais c'est déconseillé
     pour conserver une signification claire des noms.
     """
+
     __slots__ = ()
 
-    def __init__(self, name="", unit="", basetype = float):
+    def __init__(self, name="", unit="", basetype=float):
         Persistence.__init__(self, name, unit, basetype)
 
+
 class OneIndex(Persistence):
     """
     Classe définissant le stockage d'une valeur unique entière (int) par pas.
     """
+
     __slots__ = ()
 
-    def __init__(self, name="", unit="", basetype = int):
+    def __init__(self, name="", unit="", basetype=int):
         Persistence.__init__(self, name, unit, basetype)
 
+
 class OneVector(Persistence):
     """
     Classe de stockage d'une liste de valeurs numériques homogènes par pas. Ne
     pas utiliser cette classe pour des données hétérogènes, mais "OneList".
     """
+
     __slots__ = ()
 
-    def __init__(self, name="", unit="", basetype = numpy.ravel):
+    def __init__(self, name="", unit="", basetype=numpy.ravel):
         Persistence.__init__(self, name, unit, basetype)
 
+
 class OneMatrice(Persistence):
     """
     Classe de stockage d'une matrice de valeurs homogènes par pas.
     """
+
     __slots__ = ()
 
-    def __init__(self, name="", unit="", basetype = numpy.array):
+    def __init__(self, name="", unit="", basetype=numpy.array):
         Persistence.__init__(self, name, unit, basetype)
 
+
 class OneMatrix(Persistence):
     """
-    Classe de stockage d'une matrice de valeurs homogènes par pas.
+    Classe de stockage d'une matrice de valeurs homogènes par pas (obsolète).
     """
+
     __slots__ = ()
 
-    def __init__(self, name="", unit="", basetype = numpy.matrix):
+    def __init__(self, name="", unit="", basetype=numpy.matrix):
         Persistence.__init__(self, name, unit, basetype)
 
+
 class OneList(Persistence):
     """
     Classe de stockage d'une liste de valeurs hétérogènes (list) par pas. Ne
     pas utiliser cette classe pour des données numériques homogènes, mais
     "OneVector".
     """
+
     __slots__ = ()
 
-    def __init__(self, name="", unit="", basetype = list):
+    def __init__(self, name="", unit="", basetype=list):
         Persistence.__init__(self, name, unit, basetype)
 
-def NoType( value ):
+
+def NoType(value):
     "Fonction transparente, sans effet sur son argument"
     return value
 
+
 class OneNoType(Persistence):
     """
     Classe de stockage d'un objet sans modification (cast) de type. Attention,
@@ -938,11 +1061,13 @@ class OneNoType(Persistence):
     résultats inattendus. Cette classe n'est donc à utiliser qu'à bon escient
     volontairement, et pas du tout par défaut.
     """
+
     __slots__ = ()
 
-    def __init__(self, name="", unit="", basetype = NoType):
+    def __init__(self, name="", unit="", basetype=NoType):
         Persistence.__init__(self, name, unit, basetype)
 
+
 # ==============================================================================
 class CompositePersistence(object):
     """
@@ -952,6 +1077,7 @@ class CompositePersistence(object):
     Des objets par défaut sont prévus, et des objets supplémentaires peuvent
     être ajoutés.
     """
+
     __slots__ = ("__name", "__StoredObjects")
 
     def __init__(self, name="", defaults=True):
@@ -970,19 +1096,27 @@ class CompositePersistence(object):
         # Definition des objets par defaut
         # --------------------------------
         if defaults:
-            self.__StoredObjects["Informations"]     = OneNoType("Informations")
-            self.__StoredObjects["Background"]       = OneVector("Background", basetype=numpy.array)
-            self.__StoredObjects["BackgroundError"]  = OneMatrix("BackgroundError")
-            self.__StoredObjects["Observation"]      = OneVector("Observation", basetype=numpy.array)
+            self.__StoredObjects["Informations"] = OneNoType("Informations")
+            self.__StoredObjects["Background"] = OneVector(
+                "Background", basetype=numpy.array
+            )
+            self.__StoredObjects["BackgroundError"] = OneMatrix("BackgroundError")
+            self.__StoredObjects["Observation"] = OneVector(
+                "Observation", basetype=numpy.array
+            )
             self.__StoredObjects["ObservationError"] = OneMatrix("ObservationError")
-            self.__StoredObjects["Analysis"]         = OneVector("Analysis", basetype=numpy.array)
-            self.__StoredObjects["AnalysisError"]    = OneMatrix("AnalysisError")
-            self.__StoredObjects["Innovation"]       = OneVector("Innovation", basetype=numpy.array)
-            self.__StoredObjects["KalmanGainK"]      = OneMatrix("KalmanGainK")
-            self.__StoredObjects["OperatorH"]        = OneMatrix("OperatorH")
-            self.__StoredObjects["RmsOMA"]           = OneScalar("RmsOMA")
-            self.__StoredObjects["RmsOMB"]           = OneScalar("RmsOMB")
-            self.__StoredObjects["RmsBMA"]           = OneScalar("RmsBMA")
+            self.__StoredObjects["Analysis"] = OneVector(
+                "Analysis", basetype=numpy.array
+            )
+            self.__StoredObjects["AnalysisError"] = OneMatrix("AnalysisError")
+            self.__StoredObjects["Innovation"] = OneVector(
+                "Innovation", basetype=numpy.array
+            )
+            self.__StoredObjects["KalmanGainK"] = OneMatrix("KalmanGainK")
+            self.__StoredObjects["OperatorH"] = OneMatrix("OperatorH")
+            self.__StoredObjects["RmsOMA"] = OneScalar("RmsOMA")
+            self.__StoredObjects["RmsOMB"] = OneScalar("RmsOMB")
+            self.__StoredObjects["RmsBMA"] = OneScalar("RmsBMA")
         #
 
     def store(self, name=None, value=None, **kwargs):
@@ -992,10 +1126,10 @@ class CompositePersistence(object):
         if name is None:
             raise ValueError("Storable object name is required for storage.")
         if name not in self.__StoredObjects.keys():
-            raise ValueError("No such name '%s' exists in storable objects."%name)
-        self.__StoredObjects[name].store( value=value, **kwargs )
+            raise ValueError("No such name '%s' exists in storable objects." % name)
+        self.__StoredObjects[name].store(value=value, **kwargs)
 
-    def add_object(self, name=None, persistenceType=Persistence, basetype=None ):
+    def add_object(self, name=None, persistenceType=Persistence, basetype=None):
         """
         Ajoute dans les objets stockables un nouvel objet défini par son nom,
         son type de Persistence et son type de base à chaque pas.
@@ -1003,23 +1137,28 @@ class CompositePersistence(object):
         if name is None:
             raise ValueError("Object name is required for adding an object.")
         if name in self.__StoredObjects.keys():
-            raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
+            raise ValueError(
+                "An object with the same name '%s' already exists in storable objects. Choose another one."
+                % name
+            )
         if basetype is None:
-            self.__StoredObjects[name] = persistenceType( name=str(name) )
+            self.__StoredObjects[name] = persistenceType(name=str(name))
         else:
-            self.__StoredObjects[name] = persistenceType( name=str(name), basetype=basetype )
+            self.__StoredObjects[name] = persistenceType(
+                name=str(name), basetype=basetype
+            )
 
-    def get_object(self, name=None ):
+    def get_object(self, name=None):
         """
         Renvoie l'objet de type Persistence qui porte le nom demandé.
         """
         if name is None:
             raise ValueError("Object name is required for retrieving an object.")
         if name not in self.__StoredObjects.keys():
-            raise ValueError("No such name '%s' exists in stored objects."%name)
+            raise ValueError("No such name '%s' exists in stored objects." % name)
         return self.__StoredObjects[name]
 
-    def set_object(self, name=None, objet=None ):
+    def set_object(self, name=None, objet=None):
         """
         Affecte directement un 'objet' qui porte le nom 'name' demandé.
         Attention, il n'est pas effectué de vérification sur le type, qui doit
@@ -1029,32 +1168,35 @@ class CompositePersistence(object):
         if name is None:
             raise ValueError("Object name is required for setting an object.")
         if name in self.__StoredObjects.keys():
-            raise ValueError("An object with the same name '%s' already exists in storable objects. Choose another one."%name)
+            raise ValueError(
+                "An object with the same name '%s' already exists in storable objects. Choose another one."
+                % name
+            )
         self.__StoredObjects[name] = objet
 
-    def del_object(self, name=None ):
+    def del_object(self, name=None):
         """
         Supprime un objet de la liste des objets stockables.
         """
         if name is None:
             raise ValueError("Object name is required for retrieving an object.")
         if name not in self.__StoredObjects.keys():
-            raise ValueError("No such name '%s' exists in stored objects."%name)
+            raise ValueError("No such name '%s' exists in stored objects." % name)
         del self.__StoredObjects[name]
 
     # ---------------------------------------------------------
     # Méthodes d'accès de type dictionnaire
-    def __getitem__(self, name=None ):
+    def __getitem__(self, name=None):
         "x.__getitem__(y) <==> x[y]"
-        return self.get_object( name )
+        return self.get_object(name)
 
-    def __setitem__(self, name=None, objet=None ):
+    def __setitem__(self, name=None, objet=None):
         "x.__setitem__(i, y) <==> x[i]=y"
-        self.set_object( name, objet )
+        self.set_object(name, objet)
 
     def keys(self):
         "D.keys() -> list of D's keys"
-        return self.get_stored_objects(hideVoidObjects = False)
+        return self.get_stored_objects(hideVoidObjects=False)
 
     def values(self):
         "D.values() -> list of D's values"
@@ -1065,7 +1207,7 @@ class CompositePersistence(object):
         return self.__StoredObjects.items()
 
     # ---------------------------------------------------------
-    def get_stored_objects(self, hideVoidObjects = False):
+    def get_stored_objects(self, hideVoidObjects=False):
         "Renvoie la liste des objets présents"
         objs = self.__StoredObjects.keys()
         if hideVoidObjects:
@@ -1073,7 +1215,7 @@ class CompositePersistence(object):
             for k in objs:
                 try:
                     if len(self.__StoredObjects[k]) > 0:
-                        usedObjs.append( k )
+                        usedObjs.append(k)
                 finally:
                     pass
             objs = usedObjs
@@ -1088,25 +1230,25 @@ class CompositePersistence(object):
         """
         if filename is None:
             if compress == "gzip":
-                filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl.gz"
+                filename = os.tempnam(os.getcwd(), "dacp") + ".pkl.gz"
             elif compress == "bzip2":
-                filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl.bz2"
+                filename = os.tempnam(os.getcwd(), "dacp") + ".pkl.bz2"
             else:
-                filename = os.tempnam( os.getcwd(), 'dacp' ) + ".pkl"
+                filename = os.tempnam(os.getcwd(), "dacp") + ".pkl"
         else:
-            filename = os.path.abspath( filename )
+            filename = os.path.abspath(filename)
         #
         if mode == "pickle":
             if compress == "gzip":
-                output = gzip.open( filename, 'wb')
+                output = gzip.open(filename, "wb")
             elif compress == "bzip2":
-                output = bz2.BZ2File( filename, 'wb')
+                output = bz2.BZ2File(filename, "wb")
             else:
-                output = open( filename, 'wb')
+                output = open(filename, "wb")
             pickle.dump(self, output)
             output.close()
         else:
-            raise ValueError("Save mode '%s' unknown. Choose another one."%mode)
+            raise ValueError("Save mode '%s' unknown. Choose another one." % mode)
         #
         return filename
 
@@ -1117,23 +1259,24 @@ class CompositePersistence(object):
         if filename is None:
             raise ValueError("A file name if requested to load a composite.")
         else:
-            filename = os.path.abspath( filename )
+            filename = os.path.abspath(filename)
         #
         if mode == "pickle":
             if compress == "gzip":
-                pkl_file = gzip.open( filename, 'rb')
+                pkl_file = gzip.open(filename, "rb")
             elif compress == "bzip2":
-                pkl_file = bz2.BZ2File( filename, 'rb')
+                pkl_file = bz2.BZ2File(filename, "rb")
             else:
-                pkl_file = open(filename, 'rb')
+                pkl_file = open(filename, "rb")
             output = pickle.load(pkl_file)
             for k in output.keys():
                 self[k] = output[k]
         else:
-            raise ValueError("Load mode '%s' unknown. Choose another one."%mode)
+            raise ValueError("Load mode '%s' unknown. Choose another one." % mode)
         #
         return filename
 
+
 # ==============================================================================
 if __name__ == "__main__":
     print("\n AUTODIAGNOSTIC\n")
index 84d961ebe6aea1988048e8904ae423be73828e06..dc66e8de3cacb707378a0fbb57c5fb42d8b1c7f5 100644 (file)
@@ -53,19 +53,22 @@ import logging
 import re
 import numpy
 
+
 # ==============================================================================
-def uniq( __sequence ):
+def uniq(__sequence):
     """
     Fonction pour rendre unique chaque élément d'une liste, en préservant l'ordre
     """
     __seen = set()
     return [x for x in __sequence if x not in __seen and not __seen.add(x)]
 
+
 class PathManagement(object):
     """
     Mise à jour du path système pour les répertoires d'outils
     """
-    __slots__ = ("__paths")
+
+    __slots__ = ("__paths",)
 
     def __init__(self):
         "Déclaration des répertoires statiques"
@@ -76,10 +79,10 @@ class PathManagement(object):
         #
         for v in self.__paths.values():
             if os.path.isdir(v):
-                sys.path.insert(0, v )
+                sys.path.insert(0, v)
         #
         # Conserve en unique exemplaire chaque chemin
-        sys.path = uniq( sys.path )
+        sys.path = uniq(sys.path)
         del parent
 
     def getpaths(self):
@@ -88,127 +91,210 @@ class PathManagement(object):
         """
         return self.__paths
 
+
 # ==============================================================================
 class PlatformInfo(object):
     """
     Rassemblement des informations sur le code et la plateforme
     """
+
     __slots__ = ("has_salome", "has_yacs", "has_adao", "has_eficas")
 
     def __init__(self):
         "Sans effet"
-        self.has_salome = bool( "SALOME_ROOT_DIR" in os.environ )
-        self.has_yacs   = bool(   "YACS_ROOT_DIR" in os.environ )
-        self.has_adao   = bool(   "ADAO_ROOT_DIR" in os.environ )
-        self.has_eficas = bool( "EFICAS_ROOT_DIR" in os.environ )
+        self.has_salome = bool("SALOME_ROOT_DIR" in os.environ)
+        self.has_yacs = bool("YACS_ROOT_DIR" in os.environ)
+        self.has_adao = bool("ADAO_ROOT_DIR" in os.environ)
+        self.has_eficas = bool("EFICAS_ROOT_DIR" in os.environ)
         PathManagement()
 
     def getName(self):
         "Retourne le nom de l'application"
         import daCore.version as dav
+
         return dav.name
 
     def getVersion(self):
         "Retourne le numéro de la version"
         import daCore.version as dav
+
         return dav.version
 
     def getDate(self):
         "Retourne la date de création de la version"
         import daCore.version as dav
+
         return dav.date
 
     def getYear(self):
         "Retourne l'année de création de la version"
         import daCore.version as dav
+
         return dav.year
 
     def getSystemInformation(self, __prefix=""):
-        __msg  = ""
-        __msg += "\n%s%30s : %s"%(__prefix, "platform.system", platform.system())
-        __msg += "\n%s%30s : %s"%(__prefix, "sys.platform", sys.platform)
-        __msg += "\n%s%30s : %s"%(__prefix, "platform.version", platform.version())
-        __msg += "\n%s%30s : %s"%(__prefix, "platform.platform", platform.platform())
-        __msg += "\n%s%30s : %s"%(__prefix, "platform.machine", platform.machine())
+        __msg = ""
+        __msg += "\n%s%30s : %s" % (__prefix, "platform.system", platform.system())
+        __msg += "\n%s%30s : %s" % (__prefix, "sys.platform", sys.platform)
+        __msg += "\n%s%30s : %s" % (__prefix, "platform.version", platform.version())
+        __msg += "\n%s%30s : %s" % (__prefix, "platform.platform", platform.platform())
+        __msg += "\n%s%30s : %s" % (__prefix, "platform.machine", platform.machine())
         if len(platform.processor()) > 0:
-            __msg += "\n%s%30s : %s"%(__prefix, "platform.processor", platform.processor())
+            __msg += "\n%s%30s : %s" % (
+                __prefix,
+                "platform.processor",
+                platform.processor(),
+            )
         #
-        if sys.platform.startswith('linux'):
-            if hasattr(platform, 'linux_distribution'):
-                __msg += "\n%s%30s : %s"%(__prefix,
-                    "platform.linux_distribution", str(platform.linux_distribution()))  # noqa: E128
-            elif hasattr(platform, 'dist'):
-                __msg += "\n%s%30s : %s"%(__prefix,
-                    "platform.dist", str(platform.dist()))  # noqa: E128
-        elif sys.platform.startswith('darwin'):
-            if hasattr(platform, 'mac_ver'):
+        if sys.platform.startswith("linux"):
+            if hasattr(platform, "linux_distribution"):
+                __msg += "\n%s%30s : %s" % (
+                    __prefix,
+                    "platform.linux_distribution",
+                    str(platform.linux_distribution()),
+                )
+            elif hasattr(platform, "dist"):
+                __msg += "\n%s%30s : %s" % (
+                    __prefix,
+                    "platform.dist",
+                    str(platform.dist()),
+                )
+        elif sys.platform.startswith("darwin"):
+            if hasattr(platform, "mac_ver"):
                 # https://fr.wikipedia.org/wiki/MacOS
                 __macosxv10 = {
-                    '0' : 'Cheetah',      '1' : 'Puma',        '2' : 'Jaguar',         # noqa: E241,E203
-                    '3' : 'Panther',      '4' : 'Tiger',       '5' : 'Leopard',        # noqa: E241,E203
-                    '6' : 'Snow Leopard', '7' : 'Lion',        '8' : 'Mountain Lion',  # noqa: E241,E203
-                    '9' : 'Mavericks',    '10': 'Yosemite',    '11': 'El Capitan',     # noqa: E241,E203
-                    '12': 'Sierra',       '13': 'High Sierra', '14': 'Mojave',         # noqa: E241,E203
-                    '15': 'Catalina',
+                    "0": "Cheetah",
+                    "1": "Puma",
+                    "2": "Jaguar",
+                    "3": "Panther",
+                    "4": "Tiger",
+                    "5": "Leopard",
+                    "6": "Snow Leopard",
+                    "7": "Lion",
+                    "8": "Mountain Lion",
+                    "9": "Mavericks",
+                    "10": "Yosemite",
+                    "11": "El Capitan",
+                    "12": "Sierra",
+                    "13": "High Sierra",
+                    "14": "Mojave",
+                    "15": "Catalina",
                 }
                 for key in __macosxv10:
-                    __details = platform.mac_ver()[0].split('.')
+                    __details = platform.mac_ver()[0].split(".")
                     if (len(__details) > 0) and (__details[1] == key):
-                        __msg += "\n%s%30s : %s"%(__prefix,
-                            "platform.mac_ver", str(platform.mac_ver()[0] + "(" + __macosxv10[key] + ")"))  # noqa: E128
+                        __msg += "\n%s%30s : %s" % (
+                            __prefix,
+                            "platform.mac_ver",
+                            str(platform.mac_ver()[0] + "(" + __macosxv10[key] + ")"),
+                        )
                 __macosxv11 = {
-                    '11': 'Big Sur',      '12': 'Monterey',    '13': 'Ventura',  # noqa: E241
-                    '14': 'Sonoma',       '15': 'Sequoia',                       # noqa: E241
+                    "11": "Big Sur",
+                    "12": "Monterey",
+                    "13": "Ventura",
+                    "14": "Sonoma",
+                    "15": "Sequoia",
                 }
                 for key in __macosxv11:
-                    __details = platform.mac_ver()[0].split('.')
-                    if (__details[0] == key):
-                        __msg += "\n%s%30s : %s"%(__prefix,
-                            "platform.mac_ver", str(platform.mac_ver()[0] + "(" + __macosxv11[key] + ")"))  # noqa: E128
-            elif hasattr(platform, 'dist'):
-                __msg += "\n%s%30s : %s"%(__prefix, "platform.dist", str(platform.dist()))
-        elif os.name == 'nt':
-            __msg += "\n%s%30s : %s"%(__prefix, "platform.win32_ver", platform.win32_ver()[1])
+                    __details = platform.mac_ver()[0].split(".")
+                    if __details[0] == key:
+                        __msg += "\n%s%30s : %s" % (
+                            __prefix,
+                            "platform.mac_ver",
+                            str(platform.mac_ver()[0] + "(" + __macosxv11[key] + ")"),
+                        )
+            elif hasattr(platform, "dist"):
+                __msg += "\n%s%30s : %s" % (
+                    __prefix,
+                    "platform.dist",
+                    str(platform.dist()),
+                )
+        elif os.name == "nt":
+            __msg += "\n%s%30s : %s" % (
+                __prefix,
+                "platform.win32_ver",
+                platform.win32_ver()[1],
+            )
         #
         __msg += "\n"
-        __msg += "\n%s%30s : %s"%(__prefix, "platform.python_implementation", platform.python_implementation())
-        __msg += "\n%s%30s : %s"%(__prefix, "sys.executable", sys.executable)
-        __msg += "\n%s%30s : %s"%(__prefix, "sys.version", sys.version.replace('\n', ''))
-        __msg += "\n%s%30s : %s"%(__prefix, "sys.getfilesystemencoding", str(sys.getfilesystemencoding()))
+        __msg += "\n%s%30s : %s" % (
+            __prefix,
+            "platform.python_implementation",
+            platform.python_implementation(),
+        )
+        __msg += "\n%s%30s : %s" % (__prefix, "sys.executable", sys.executable)
+        __msg += "\n%s%30s : %s" % (
+            __prefix,
+            "sys.version",
+            sys.version.replace("\n", ""),
+        )
+        __msg += "\n%s%30s : %s" % (
+            __prefix,
+            "sys.getfilesystemencoding",
+            str(sys.getfilesystemencoding()),
+        )
         if sys.version_info.major == 3 and sys.version_info.minor < 11:  # Python 3.10
-            __msg += "\n%s%30s : %s"%(__prefix, "locale.getdefaultlocale", str(locale.getdefaultlocale()))
+            __msg += "\n%s%30s : %s" % (
+                __prefix,
+                "locale.getdefaultlocale",
+                str(locale.getdefaultlocale()),
+            )
         else:
-            __msg += "\n%s%30s : %s"%(__prefix, "locale.getlocale", str(locale.getlocale()))
+            __msg += "\n%s%30s : %s" % (
+                __prefix,
+                "locale.getlocale",
+                str(locale.getlocale()),
+            )
         __msg += "\n"
-        __msg += "\n%s%30s : %s"%(__prefix, "os.cpu_count", os.cpu_count())
-        if hasattr(os, 'sched_getaffinity'):
-            __msg += "\n%s%30s : %s"%(__prefix, "len(os.sched_getaffinity(0))", len(os.sched_getaffinity(0)))
+        __msg += "\n%s%30s : %s" % (__prefix, "os.cpu_count", os.cpu_count())
+        if hasattr(os, "sched_getaffinity"):
+            __msg += "\n%s%30s : %s" % (
+                __prefix,
+                "len(os.sched_getaffinity(0))",
+                len(os.sched_getaffinity(0)),
+            )
         else:
-            __msg += "\n%s%30s : %s"%(__prefix, "len(os.sched_getaffinity(0))", "Unsupported on this platform")
+            __msg += "\n%s%30s : %s" % (
+                __prefix,
+                "len(os.sched_getaffinity(0))",
+                "Unsupported on this platform",
+            )
         __msg += "\n"
-        __msg += "\n%s%30s : %s"%(__prefix, "platform.node", platform.node())
-        __msg += "\n%s%30s : %s"%(__prefix, "socket.getfqdn", socket.getfqdn())
-        __msg += "\n%s%30s : %s"%(__prefix, "os.path.expanduser", os.path.expanduser('~'))
+        __msg += "\n%s%30s : %s" % (__prefix, "platform.node", platform.node())
+        __msg += "\n%s%30s : %s" % (__prefix, "socket.getfqdn", socket.getfqdn())
+        __msg += "\n%s%30s : %s" % (
+            __prefix,
+            "os.path.expanduser",
+            os.path.expanduser("~"),
+        )
         return __msg
 
     def getApplicationInformation(self, __prefix=""):
-        __msg  = ""
-        __msg += "\n%s%30s : %s"%(__prefix, "ADAO version", self.getVersion())
+        __msg = ""
+        __msg += "\n%s%30s : %s" % (__prefix, "ADAO version", self.getVersion())
         __msg += "\n"
-        __msg += "\n%s%30s : %s"%(__prefix, "Python version", self.getPythonVersion())
-        __msg += "\n%s%30s : %s"%(__prefix, "Numpy version", self.getNumpyVersion())
-        __msg += "\n%s%30s : %s"%(__prefix, "Scipy version", self.getScipyVersion())
-        __msg += "\n%s%30s : %s"%(__prefix, "NLopt version", self.getNloptVersion())
-        __msg += "\n%s%30s : %s"%(__prefix, "MatplotLib version", self.getMatplotlibVersion())
-        __msg += "\n%s%30s : %s"%(__prefix, "GnuplotPy version", self.getGnuplotVersion())
+        __msg += "\n%s%30s : %s" % (__prefix, "Python version", self.getPythonVersion())
+        __msg += "\n%s%30s : %s" % (__prefix, "Numpy version", self.getNumpyVersion())
+        __msg += "\n%s%30s : %s" % (__prefix, "Scipy version", self.getScipyVersion())
+        __msg += "\n%s%30s : %s" % (__prefix, "NLopt version", self.getNloptVersion())
+        __msg += "\n%s%30s : %s" % (
+            __prefix,
+            "MatplotLib version",
+            self.getMatplotlibVersion(),
+        )
+        __msg += "\n%s%30s : %s" % (
+            __prefix,
+            "GnuplotPy version",
+            self.getGnuplotVersion(),
+        )
         __msg += "\n"
-        __msg += "\n%s%30s : %s"%(__prefix, "Pandas version", self.getPandasVersion())
-        __msg += "\n%s%30s : %s"%(__prefix, "Fmpy version", self.getFmpyVersion())
-        __msg += "\n%s%30s : %s"%(__prefix, "Sphinx version", self.getSphinxVersion())
+        __msg += "\n%s%30s : %s" % (__prefix, "Pandas version", self.getPandasVersion())
+        __msg += "\n%s%30s : %s" % (__prefix, "Fmpy version", self.getFmpyVersion())
+        __msg += "\n%s%30s : %s" % (__prefix, "Sphinx version", self.getSphinxVersion())
         return __msg
 
     def getAllInformation(self, __prefix="", __title="Whole system information"):
-        __msg  = ""
+        __msg = ""
         if len(__title) > 0:
             __msg += "\n" + "=" * 80 + "\n" + __title + "\n" + "=" * 80 + "\n"
         __msg += self.getSystemInformation(__prefix)
@@ -218,151 +304,185 @@ class PlatformInfo(object):
 
     def getPythonVersion(self):
         "Retourne la version de python disponible"
-        return ".".join([str(x) for x in sys.version_info[0:3]])  # map(str,sys.version_info[0:3]))
+        return ".".join(
+            [str(x) for x in sys.version_info[0:3]]
+        )  # map(str,sys.version_info[0:3]))
 
     # Tests des modules système
 
     def _has_numpy(self):
         try:
             import numpy  # noqa: F401
+
             has_numpy = True
         except ImportError:
-            raise ImportError("Numpy is not available, despites the fact it is mandatory.")
+            raise ImportError(
+                "Numpy is not available, despites the fact it is mandatory."
+            )
         return has_numpy
-    has_numpy = property(fget = _has_numpy)
+
+    has_numpy = property(fget=_has_numpy)
 
     def _has_scipy(self):
         try:
             import scipy
             import scipy.version
             import scipy.optimize  # noqa: F401
+
             has_scipy = True
         except ImportError:
             has_scipy = False
         return has_scipy
-    has_scipy = property(fget = _has_scipy)
+
+    has_scipy = property(fget=_has_scipy)
 
     def _has_matplotlib(self):
         try:
             import matplotlib  # noqa: F401
+
             has_matplotlib = True
         except ImportError:
             has_matplotlib = False
         return has_matplotlib
-    has_matplotlib = property(fget = _has_matplotlib)
+
+    has_matplotlib = property(fget=_has_matplotlib)
 
     def _has_sphinx(self):
         try:
             import sphinx  # noqa: F401
+
             has_sphinx = True
         except ImportError:
             has_sphinx = False
         return has_sphinx
-    has_sphinx = property(fget = _has_sphinx)
+
+    has_sphinx = property(fget=_has_sphinx)
 
     def _has_nlopt(self):
         try:
             import nlopt  # noqa: F401
+
             has_nlopt = True
         except ImportError:
             has_nlopt = False
         return has_nlopt
-    has_nlopt = property(fget = _has_nlopt)
+
+    has_nlopt = property(fget=_has_nlopt)
 
     def _has_pandas(self):
         try:
             import pandas  # noqa: F401
+
             has_pandas = True
         except ImportError:
             has_pandas = False
         return has_pandas
-    has_pandas = property(fget = _has_pandas)
+
+    has_pandas = property(fget=_has_pandas)
 
     def _has_sdf(self):
         try:
             import sdf  # noqa: F401
+
             has_sdf = True
         except ImportError:
             has_sdf = False
         return has_sdf
-    has_sdf = property(fget = _has_sdf)
+
+    has_sdf = property(fget=_has_sdf)
 
     def _has_fmpy(self):
         try:
             import fmpy  # noqa: F401
+
             has_fmpy = True
         except ImportError:
             has_fmpy = False
         return has_fmpy
-    has_fmpy = property(fget = _has_fmpy)
+
+    has_fmpy = property(fget=_has_fmpy)
 
     def _has_buildingspy(self):
         try:
             import buildingspy  # noqa: F401
+
             has_buildingspy = True
         except ImportError:
             has_buildingspy = False
         return has_buildingspy
-    has_buildingspy = property(fget = _has_buildingspy)
+
+    has_buildingspy = property(fget=_has_buildingspy)
 
     def _has_control(self):
         try:
             import control  # noqa: F401
+
             has_control = True
         except ImportError:
             has_control = False
         return has_control
-    has_control = property(fget = _has_control)
+
+    has_control = property(fget=_has_control)
 
     def _has_modelicares(self):
         try:
             import modelicares  # noqa: F401
+
             has_modelicares = True
         except ImportError:
             has_modelicares = False
         return has_modelicares
-    has_modelicares = property(fget = _has_modelicares)
+
+    has_modelicares = property(fget=_has_modelicares)
 
     # Tests des modules locaux
 
     def _has_gnuplot(self):
         try:
             import Gnuplot  # noqa: F401
+
             has_gnuplot = True
         except ImportError:
             has_gnuplot = False
         return has_gnuplot
-    has_gnuplot = property(fget = _has_gnuplot)
+
+    has_gnuplot = property(fget=_has_gnuplot)
 
     def _has_models(self):
         try:
             import Models  # noqa: F401
+
             has_models = True
         except ImportError:
             has_models = False
         return has_models
-    has_models = property(fget = _has_models)
+
+    has_models = property(fget=_has_models)
 
     def _has_pst4mod(self):
         try:
             import pst4mod  # noqa: F401
+
             has_pst4mod = True
         except ImportError:
             has_pst4mod = False
         return has_pst4mod
-    has_pst4mod = property(fget = _has_pst4mod)
+
+    has_pst4mod = property(fget=_has_pst4mod)
 
     # Versions
 
     def getNumpyVersion(self):
         "Retourne la version de numpy disponible"
         import numpy.version
+
         return numpy.version.version
 
     def getScipyVersion(self):
         "Retourne la version de scipy disponible"
         if self.has_scipy:
             import scipy
+
             __version = scipy.version.version
         else:
             __version = "0.0.0"
@@ -372,7 +492,8 @@ class PlatformInfo(object):
         "Retourne la version de nlopt disponible"
         if self.has_nlopt:
             import nlopt
-            __version = "%s.%s.%s"%(
+
+            __version = "%s.%s.%s" % (
                 nlopt.version_major(),
                 nlopt.version_minor(),
                 nlopt.version_bugfix(),
@@ -385,6 +506,7 @@ class PlatformInfo(object):
         "Retourne la version de matplotlib disponible"
         if self.has_matplotlib:
             import matplotlib
+
             __version = matplotlib.__version__
         else:
             __version = "0.0.0"
@@ -394,6 +516,7 @@ class PlatformInfo(object):
         "Retourne la version de pandas disponible"
         if self.has_pandas:
             import pandas
+
             __version = pandas.__version__
         else:
             __version = "0.0.0"
@@ -403,6 +526,7 @@ class PlatformInfo(object):
         "Retourne la version de gnuplotpy disponible"
         if self.has_gnuplot:
             import Gnuplot
+
             __version = Gnuplot.__version__
         else:
             __version = "0.0"
@@ -412,6 +536,7 @@ class PlatformInfo(object):
         "Retourne la version de fmpy disponible"
         if self.has_fmpy:
             import fmpy
+
             __version = fmpy.__version__
         else:
             __version = "0.0.0"
@@ -421,6 +546,7 @@ class PlatformInfo(object):
         "Retourne la version de sdf disponible"
         if self.has_sdf:
             import sdf
+
             __version = sdf.__version__
         else:
             __version = "0.0.0"
@@ -430,6 +556,7 @@ class PlatformInfo(object):
         "Retourne la version de sphinx disponible"
         if self.has_sphinx:
             import sphinx
+
             __version = sphinx.__version__
         else:
             __version = "0.0.0"
@@ -442,11 +569,17 @@ class PlatformInfo(object):
     def MaximumPrecision(self):
         "Retourne la précision maximale flottante pour Numpy"
         import numpy
+
         try:
-            numpy.array([1.,], dtype='float128')
-            mfp = 'float128'
+            numpy.array(
+                [
+                    1.0,
+                ],
+                dtype="float128",
+            )
+            mfp = "float128"
         except Exception:
-            mfp = 'float64'
+            mfp = "float64"
         return mfp
 
     def MachinePrecision(self):
@@ -459,26 +592,29 @@ class PlatformInfo(object):
 
     def __str__(self):
         import daCore.version as dav
-        return "%s %s (%s)"%(dav.name, dav.version, dav.date)
+
+        return "%s %s (%s)" % (dav.name, dav.version, dav.date)
+
 
 # ==============================================================================
-def vt( __version ):
+def vt(__version):
     "Version transformée pour comparaison robuste, obtenue comme un tuple"
     serie = []
     for sv in re.split("[_.+-]", __version):
         serie.append(sv.zfill(6))
     return tuple(serie)
 
-def isIterable( __sequence, __check = False, __header = "" ):
+
+def isIterable(__sequence, __check=False, __header=""):
     """
     Vérification que l'argument est un itérable interne.
     Remarque : pour permettre le test correct en MultiFonctions,
     - Ne pas accepter comme itérable un "numpy.ndarray"
     - Ne pas accepter comme itérable avec hasattr(__sequence, "__iter__")
     """
-    if isinstance( __sequence, (list, tuple, map, dict) ):
+    if isinstance(__sequence, (list, tuple, map, dict)):
         __isOk = True
-    elif type(__sequence).__name__ in ('generator', 'range'):
+    elif type(__sequence).__name__ in ("generator", "range"):
         __isOk = True
     elif "_iterator" in type(__sequence).__name__:
         __isOk = True
@@ -487,26 +623,40 @@ def isIterable( __sequence, __check = False, __header = "" ):
     else:
         __isOk = False
     if __check and not __isOk:
-        raise TypeError("Not iterable or unkown input type%s: %s"%(__header, type(__sequence),))
+        raise TypeError(
+            "Not iterable or unkown input type%s: %s"
+            % (
+                __header,
+                type(__sequence),
+            )
+        )
     return __isOk
 
-def date2int( __date: str, __lang="FR" ):
+
+def date2int(__date: str, __lang="FR"):
     """
     Fonction de secours, conversion pure : dd/mm/yy hh:mm ---> int(yyyymmddhhmm)
     """
     __date = __date.strip()
-    if __date.count('/') == 2 and __date.count(':') == 0 and __date.count(' ') == 0:
+    if __date.count("/") == 2 and __date.count(":") == 0 and __date.count(" ") == 0:
         d, m, y = __date.split("/")
         __number = (10**4) * int(y) + (10**2) * int(m) + int(d)
-    elif __date.count('/') == 2 and __date.count(':') == 1 and __date.count(' ') > 0:
+    elif __date.count("/") == 2 and __date.count(":") == 1 and __date.count(" ") > 0:
         part1, part2 = __date.split()
         d, m, y = part1.strip().split("/")
         h, n = part2.strip().split(":")
-        __number = (10**8) * int(y) + (10**6) * int(m) + (10**4) * int(d) + (10**2) * int(h) + int(n)
+        __number = (
+            (10**8) * int(y)
+            + (10**6) * int(m)
+            + (10**4) * int(d)
+            + (10**2) * int(h)
+            + int(n)
+        )
     else:
-        raise ValueError("Cannot convert \"%s\" as a D/M/Y H:M date"%__date)
+        raise ValueError('Cannot convert "%s" as a D/M/Y H:M date' % __date)
     return __number
 
+
 def vfloat(__value: numpy.ndarray):
     """
     Conversion en flottant d'un vecteur de taille 1 et de dimensions quelconques
@@ -516,9 +666,12 @@ def vfloat(__value: numpy.ndarray):
     elif isinstance(__value, (float, int)):
         return float(__value)
     else:
-        raise ValueError("Error in converting multiple float values from array when waiting for only one")
+        raise ValueError(
+            "Error in converting multiple float values from array when waiting for only one"
+        )
+
 
-def strvect2liststr( __strvect ):
+def strvect2liststr(__strvect):
     """
     Fonction de secours, conversion d'une chaîne de caractères de
     représentation de vecteur en une liste de chaînes de caractères de
@@ -530,7 +683,8 @@ def strvect2liststr( __strvect ):
         __strvect = __strvect.replace(st, " ")  # Blanc
     return __strvect.split()
 
-def strmatrix2liststr( __strvect ):
+
+def strmatrix2liststr(__strvect):
     """
     Fonction de secours, conversion d'une chaîne de caractères de
     représentation de matrice en une liste de chaînes de caractères de
@@ -541,19 +695,21 @@ def strmatrix2liststr( __strvect ):
     __strvect = __strvect.replace(",", " ")  # Blanc
     for st in ("]", ")"):
         __strvect = __strvect.replace(st, ";")  # "]" et ")" par ";"
-    __strvect = re.sub(r';\s*;', r';', __strvect)
+    __strvect = re.sub(r";\s*;", r";", __strvect)
     __strvect = __strvect.rstrip(";")  # Après ^ et avant v
     __strmat = [__l.split() for __l in __strvect.split(";")]
     return __strmat
 
-def checkFileNameConformity( __filename, __warnInsteadOfPrint=True ):
+
+def checkFileNameConformity(__filename, __warnInsteadOfPrint=True):
     if sys.platform.startswith("win") and len(__filename) > 256:
         __conform = False
         __msg = (
-            " For some shared or older file systems on Windows, a file " + \
-            "name longer than 256 characters can lead to access problems." + \
-            "\n  The name of the file in question is the following:" + \
-            "\n  %s")%(__filename,)
+            " For some shared or older file systems on Windows, a file "
+            + "name longer than 256 characters can lead to access problems."
+            + "\n  The name of the file in question is the following:"
+            + "\n  %s"
+        ) % (__filename,)
         if __warnInsteadOfPrint:
             logging.warning(__msg)
         else:
@@ -563,19 +719,21 @@ def checkFileNameConformity( __filename, __warnInsteadOfPrint=True ):
     #
     return __conform
 
-def checkFileNameImportability( __filename, __warnInsteadOfPrint=True ):
+
+def checkFileNameImportability(__filename, __warnInsteadOfPrint=True):
     if str(__filename).count(".") > 1:
         __conform = False
         __msg = (
-            " The file name contains %i point(s) before the extension " + \
-            "separator, which can potentially lead to problems when " + \
-            "importing this file into Python, as it can then be recognized " + \
-            "as a sub-module (generating a \"ModuleNotFoundError\"). If it " + \
-            "is intentional, make sure that there is no module with the " + \
-            "same name as the part before the first point, and that there is " + \
-            "no \"__init__.py\" file in the same directory." + \
-            "\n  The name of the file in question is the following:" + \
-            "\n  %s")%(int(str(__filename).count(".") - 1), __filename)
+            " The file name contains %i point(s) before the extension "
+            + "separator, which can potentially lead to problems when "
+            + "importing this file into Python, as it can then be recognized "
+            + 'as a sub-module (generating a "ModuleNotFoundError"). If it '
+            + "is intentional, make sure that there is no module with the "
+            + "same name as the part before the first point, and that there is "
+            + 'no "__init__.py" file in the same directory.'
+            + "\n  The name of the file in question is the following:"
+            + "\n  %s"
+        ) % (int(str(__filename).count(".") - 1), __filename)
         if __warnInsteadOfPrint is None:
             pass
         elif __warnInsteadOfPrint:
@@ -587,30 +745,32 @@ def checkFileNameImportability( __filename, __warnInsteadOfPrint=True ):
     #
     return __conform
 
+
 # ==============================================================================
 class SystemUsage(object):
     """
     Permet de récupérer les différentes tailles mémoires du process courant
     """
+
     __slots__ = ()
     #
     # Le module resource renvoie 0 pour les tailles mémoire. On utilise donc
     # plutôt : http://code.activestate.com/recipes/286222/ et Wikipedia
     #
-    _proc_status = '/proc/%d/status' % os.getpid()
-    _memo_status = '/proc/meminfo'
+    _proc_status = "/proc/%d/status" % os.getpid()
+    _memo_status = "/proc/meminfo"
     _scale = {
-        'o'  : 1.0,     # Multiples SI de l'octet          # noqa: E203
-        'ko' : 1.e3,                                       # noqa: E203
-        'Mo' : 1.e6,                                       # noqa: E203
-        'Go' : 1.e9,                                       # noqa: E203
-        'kio': 1024.0,  # Multiples binaires de l'octet    # noqa: E203
-        'Mio': 1024.0 * 1024.0,                            # noqa: E203
-        'Gio': 1024.0 * 1024.0 * 1024.0,                   # noqa: E203
-        'B'  : 1.0,     # Multiples binaires du byte=octet # noqa: E203
-        'kB' : 1024.0,                                     # noqa: E203
-        'MB' : 1024.0 * 1024.0,                            # noqa: E203
-        'GB' : 1024.0 * 1024.0 * 1024.0,                   # noqa: E203
+        "o": 1.0,  # Multiples SI de l'octet
+        "ko": 1.0e3,
+        "Mo": 1.0e6,
+        "Go": 1.0e9,
+        "kio": 1024.0,  # Multiples binaires de l'octet
+        "Mio": 1024.0 * 1024.0,
+        "Gio": 1024.0 * 1024.0 * 1024.0,
+        "B": 1.0,  # Multiples binaires du byte=octet
+        "kB": 1024.0,
+        "MB": 1024.0 * 1024.0,
+        "GB": 1024.0 * 1024.0 * 1024.0,
     }
 
     def __init__(self):
@@ -624,33 +784,37 @@ class SystemUsage(object):
             v = t.read()
             t.close()
         except IOError:
-            return 0.0            # non-Linux?
-        i = v.index(VmKey)        # get VmKey line e.g. 'VmRSS:  9999  kB\n ...'
+            return 0.0  # non-Linux?
+        i = v.index(VmKey)  # get VmKey line e.g. 'VmRSS:  9999  kB\n ...'
         v = v[i:].split(None, 3)  # whitespace
         if len(v) < 3:
-            return 0.0            # invalid format?
+            return 0.0  # invalid format?
         # convert Vm value to bytes
         mem = float(v[1]) * self._scale[v[2]]
         return mem / self._scale[unit]
 
     def getAvailablePhysicalMemory(self, unit="o"):
         "Renvoie la mémoire physique utilisable en octets"
-        return self._VmA('MemTotal:', unit)
+        return self._VmA("MemTotal:", unit)
 
     def getAvailableSwapMemory(self, unit="o"):
         "Renvoie la mémoire swap utilisable en octets"
-        return self._VmA('SwapTotal:', unit)
+        return self._VmA("SwapTotal:", unit)
 
     def getAvailableMemory(self, unit="o"):
         "Renvoie la mémoire totale (physique+swap) utilisable en octets"
-        return self._VmA('MemTotal:', unit) + self._VmA('SwapTotal:', unit)
+        return self._VmA("MemTotal:", unit) + self._VmA("SwapTotal:", unit)
 
     def getUsableMemory(self, unit="o"):
         """Renvoie la mémoire utilisable en octets
         Rq : il n'est pas sûr que ce décompte soit juste...
         """
-        return self._VmA('MemFree:', unit) + self._VmA('SwapFree:', unit) + \
-            self._VmA('Cached:', unit) + self._VmA('SwapCached:', unit)
+        return (
+            self._VmA("MemFree:", unit)
+            + self._VmA("SwapFree:", unit)
+            + self._VmA("Cached:", unit)
+            + self._VmA("SwapCached:", unit)
+        )
 
     def _VmB(self, VmKey, unit):
         "Lecture des paramètres mémoire du processus"
@@ -659,34 +823,35 @@ class SystemUsage(object):
             v = t.read()
             t.close()
         except IOError:
-            return 0.0            # non-Linux?
-        i = v.index(VmKey)        # get VmKey line e.g. 'VmRSS:  9999  kB\n ...'
+            return 0.0  # non-Linux?
+        i = v.index(VmKey)  # get VmKey line e.g. 'VmRSS:  9999  kB\n ...'
         v = v[i:].split(None, 3)  # whitespace
         if len(v) < 3:
-            return 0.0            # invalid format?
+            return 0.0  # invalid format?
         # convert Vm value to bytes
         mem = float(v[1]) * self._scale[v[2]]
         return mem / self._scale[unit]
 
     def getUsedMemory(self, unit="o"):
         "Renvoie la mémoire résidente utilisée en octets"
-        return self._VmB('VmRSS:', unit)
+        return self._VmB("VmRSS:", unit)
 
     def getVirtualMemory(self, unit="o"):
         "Renvoie la mémoire totale utilisée en octets"
-        return self._VmB('VmSize:', unit)
+        return self._VmB("VmSize:", unit)
 
     def getUsedStacksize(self, unit="o"):
         "Renvoie la taille du stack utilisé en octets"
-        return self._VmB('VmStk:', unit)
+        return self._VmB("VmStk:", unit)
 
     def getMaxUsedMemory(self, unit="o"):
         "Renvoie la mémoire résidente maximale mesurée"
-        return self._VmB('VmHWM:', unit)
+        return self._VmB("VmHWM:", unit)
 
     def getMaxVirtualMemory(self, unit="o"):
         "Renvoie la mémoire totale maximale mesurée"
-        return self._VmB('VmPeak:', unit)
+        return self._VmB("VmPeak:", unit)
+
 
 # ==============================================================================
 if __name__ == "__main__":
index 5d2af38d1e980809e4101e786bef37c5acfe8d8b..b5a934d5d7961c5d08787aa5a0843ce8b49f9b1d 100644 (file)
@@ -31,15 +31,17 @@ import os.path
 # ==============================================================================
 # Classes de services non utilisateur
 
+
 class _ReportPartM__(object):
     """
     Store and retrieve the data for C: internal class
     """
+
     __slots__ = ("__part", "__styles", "__content")
 
     def __init__(self, part="default"):
-        self.__part    = str(part)
-        self.__styles  = []
+        self.__part = str(part)
+        self.__styles = []
         self.__content = []
 
     def append(self, content, style="p", position=-1):
@@ -57,17 +59,19 @@ class _ReportPartM__(object):
     def get_content(self):
         return self.__content
 
+
 class _ReportM__(object):
     """
     Store and retrieve the data for C: internal class
     """
-    __slots__ = ("__document")
 
-    def __init__(self, part='default'):
+    __slots__ = ("__document",)
+
+    def __init__(self, part="default"):
         self.__document = {}
         self.__document[part] = _ReportPartM__(part)
 
-    def append(self, content, style="p", position=-1, part='default'):
+    def append(self, content, style="p", position=-1, part="default"):
         if part not in self.__document:
             self.__document[part] = _ReportPartM__(part)
         self.__document[part].append(content, style, position)
@@ -86,10 +90,12 @@ class _ReportM__(object):
     def clear(self):
         self.__init__()
 
+
 class __ReportC__(object):
     """
     Get user commands, update M and V: user intertace to create the report
     """
+
     __slots__ = ()
     #
     m = _ReportM__()
@@ -105,11 +111,13 @@ class __ReportC__(object):
     def clear(self):
         self.m.clear()
 
+
 class __ReportV__(object):
     """
     Interact with user and C: template for reports
     """
-    __slots__ = ("c")
+
+    __slots__ = ("c",)
     #
     default_filename = "report.txt"
 
@@ -122,7 +130,7 @@ class __ReportV__(object):
         _filename = os.path.abspath(filename)
         #
         _inside = self.get()
-        fid = open(_filename, 'w')
+        fid = open(_filename, "w")
         fid.write(_inside)
         fid.close()
         return filename, _filename
@@ -137,14 +145,17 @@ class __ReportV__(object):
         del self.c
         return 0
 
+
 # ==============================================================================
 # Classes d'interface utilisateur : ReportViewIn*, ReportStorage
 # Tags de structure : (title, h1, h2, h3, p, uli, oli, <b></b>, <i></i>)
 
+
 class ReportViewInHtml(__ReportV__):
     """
     Report in HTML
     """
+
     __slots__ = ()
     #
     default_filename = "report.html"
@@ -164,7 +175,11 @@ class ReportViewInHtml(__ReportV__):
             try:
                 ii = ps.index("title")
                 title = pc[ii]
-                pg += "%s\n%s\n%s"%('<hr noshade><h1 align="center">', title, '</h1><hr noshade>')
+                pg += "%s\n%s\n%s" % (
+                    '<hr noshade><h1 align="center">',
+                    title,
+                    "</h1><hr noshade>",
+                )
             except Exception:
                 pass
             for ip, sp in enumerate(ps):
@@ -186,14 +201,16 @@ class ReportViewInHtml(__ReportV__):
                 for tp in self.tags:
                     if sp == tp:
                         sp = self.tags[tp]
-                pg += "\n<%s>%s</%s>"%(sp, cp, sp)
+                pg += "\n<%s>%s</%s>" % (sp, cp, sp)
         pg += "\n</body>\n</html>"
         return pg
 
+
 class ReportViewInRst(__ReportV__):
     """
     Report in RST
     """
+
     __slots__ = ()
     #
     default_filename = "report.rst"
@@ -223,7 +240,7 @@ class ReportViewInRst(__ReportV__):
             try:
                 ii = ps.index("title")
                 title = pc[ii]
-                pg += "%s\n%s\n%s"%("=" * 80, title, "=" * 80)
+                pg += "%s\n%s\n%s" % ("=" * 80, title, "=" * 80)
             except Exception:
                 pass
             for ip, sp in enumerate(ps):
@@ -243,16 +260,22 @@ class ReportViewInRst(__ReportV__):
                 for tp in self.translation:
                     cp = cp.replace(tp, self.translation[tp])
                 if sp in self.titles.keys():
-                    pg += "\n%s\n%s\n%s"%(self.titles[sp][0] * len(cp), cp, self.titles[sp][1] * len(cp))
+                    pg += "\n%s\n%s\n%s" % (
+                        self.titles[sp][0] * len(cp),
+                        cp,
+                        self.titles[sp][1] * len(cp),
+                    )
                 elif sp in self.tags.keys():
-                    pg += "%s%s%s"%(self.tags[sp][0], cp, self.tags[sp][1])
+                    pg += "%s%s%s" % (self.tags[sp][0], cp, self.tags[sp][1])
             pg += "\n"
         return pg
 
+
 class ReportViewInPlainTxt(__ReportV__):
     """
     Report in plain TXT
     """
+
     #
     __slots__ = ()
     #
@@ -283,7 +306,7 @@ class ReportViewInPlainTxt(__ReportV__):
             try:
                 ii = ps.index("title")
                 title = pc[ii]
-                pg += "%s\n%s\n%s"%("=" * 80, title, "=" * 80)
+                pg += "%s\n%s\n%s" % ("=" * 80, title, "=" * 80)
             except Exception:
                 pass
             for ip, sp in enumerate(ps):
@@ -299,12 +322,17 @@ class ReportViewInPlainTxt(__ReportV__):
                 for tp in self.translation:
                     cp = cp.replace(tp, self.translation[tp])
                 if sp in self.titles.keys():
-                    pg += "\n%s\n%s\n%s"%(self.titles[sp][0] * len(cp), cp, -self.titles[sp][1] * len(cp))
+                    pg += "\n%s\n%s\n%s" % (
+                        self.titles[sp][0] * len(cp),
+                        cp,
+                        -self.titles[sp][1] * len(cp),
+                    )
                 elif sp in self.tags.keys():
-                    pg += "\n%s%s%s"%(self.tags[sp][0], cp, self.tags[sp][1])
+                    pg += "\n%s%s%s" % (self.tags[sp][0], cp, self.tags[sp][1])
             pg += "\n"
         return pg
 
+
 # Interface utilisateur de stockage des informations
 ReportStorage = __ReportC__
 
index b14072b2a7d07669d226afcfa0982dfaf4c440c9..54b42539e96c4812d4991fbabf44dbf247f3a755 100644 (file)
@@ -29,32 +29,36 @@ __all__ = ["ObserverTemplates"]
 
 import numpy
 
+
 # ==============================================================================
 class TemplateStorage(object):
     """
     Classe générale de stockage de type dictionnaire étendu
     (Template)
     """
+
     __slots__ = ("__preferedLanguage", "__values", "__order")
 
-    def __init__( self, language = "fr_FR" ):
+    def __init__(self, language="fr_FR"):
         self.__preferedLanguage = language
-        self.__values           = {}
-        self.__order            = -1
+        self.__values = {}
+        self.__order = -1
 
-    def store( self, name = None, content = None, fr_FR = "", en_EN = "", order = "next" ):
+    def store(self, name=None, content=None, fr_FR="", en_EN="", order="next"):
         "D.store(k, c,  fr_FR, en_EN, o) -> Store template k and its main characteristics"
         if name is None or content is None:
-            raise ValueError("To be consistent, the storage of a template must provide a name and a content.")
+            raise ValueError(
+                "To be consistent, the storage of a template must provide a name and a content."
+            )
         if order == "next":
             self.__order += 1
         else:
             self.__order = int(order)
         self.__values[str(name)] = {
-            'content': str(content),
-            'fr_FR'  : str(fr_FR),         # noqa: E203
-            'en_EN'  : str(en_EN),         # noqa: E203
-            'order'  : int(self.__order),  # noqa: E203
+            "content": str(content),
+            "fr_FR": str(fr_FR),
+            "en_EN": str(en_EN),
+            "order": int(self.__order),
         }
 
     def keys(self):
@@ -70,11 +74,11 @@ class TemplateStorage(object):
         "x.__len__() <==> len(x)"
         return len(self.__values)
 
-    def __getitem__(self, name=None ):
+    def __getitem__(self, name=None):
         "x.__getitem__(y) <==> x[y]"
-        return self.__values[name]['content']
+        return self.__values[name]["content"]
 
-    def getdoc(self, name = None, lang = "fr_FR"):
+    def getdoc(self, name=None, lang="fr_FR"):
         "D.getdoc(k, l) -> Return documentation of key k in language l"
         if lang not in self.__values[name]:
             lang = self.__preferedLanguage
@@ -84,247 +88,248 @@ class TemplateStorage(object):
         "D.keys_in_presentation_order() -> list of D's keys in presentation order"
         __orders = []
         for ik in self.keys():
-            __orders.append( self.__values[ik]['order'] )
+            __orders.append(self.__values[ik]["order"])
         __reorder = numpy.array(__orders).argsort()
         return (numpy.array(self.keys())[__reorder]).tolist()
 
+
 # ==============================================================================
 ObserverTemplates = TemplateStorage()
 
 ObserverTemplates.store(
-    name    = "ValuePrinter",
-    content = """print(str(info)+" "+str(var[-1]))""",
-    fr_FR   = "Imprime sur la sortie standard la valeur courante de la variable",
-    en_EN   = "Print on standard output the current value of the variable",
-    order   = "next",
+    name="ValuePrinter",
+    content="""print(str(info)+" "+str(var[-1]))""",
+    fr_FR="Imprime sur la sortie standard la valeur courante de la variable",
+    en_EN="Print on standard output the current value of the variable",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueAndIndexPrinter",
-    content = """print(str(info)+(" index %i:"%(len(var)-1))+" "+str(var[-1]))""",
-    fr_FR   = "Imprime sur la sortie standard la valeur courante de la variable, en ajoutant son index",
-    en_EN   = "Print on standard output the current value of the variable, adding its index",
-    order   = "next",
+    name="ValueAndIndexPrinter",
+    content="""print(str(info)+(" index %i:"%(len(var)-1))+" "+str(var[-1]))""",
+    fr_FR="Imprime sur la sortie standard la valeur courante de la variable, en ajoutant son index",
+    en_EN="Print on standard output the current value of the variable, adding its index",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueSeriePrinter",
-    content = """print(str(info)+" "+str(var[:]))""",
-    fr_FR   = "Imprime sur la sortie standard la série des valeurs de la variable",
-    en_EN   = "Print on standard output the value series of the variable",
-    order   = "next",
+    name="ValueSeriePrinter",
+    content="""print(str(info)+" "+str(var[:]))""",
+    fr_FR="Imprime sur la sortie standard la série des valeurs de la variable",
+    en_EN="Print on standard output the value series of the variable",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueSaver",
-    content = """import numpy, re\nv=numpy.array(var[-1], ndmin=1)\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
-    fr_FR   = "Enregistre la valeur courante de la variable dans un fichier du répertoire '/tmp' nommé 'value...txt' selon le nom de la variable et l'étape d'enregistrement",
-    en_EN   = "Save the current value of the variable in a file of the '/tmp' directory named 'value...txt' from the variable name and the saving step",
-    order   = "next",
+    name="ValueSaver",
+    content="""import numpy, re\nv=numpy.array(var[-1], ndmin=1)\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
+    fr_FR="Enregistre la valeur courante de la variable dans un fichier du répertoire '/tmp' nommé 'value...txt' selon le nom de la variable et l'étape d'enregistrement",
+    en_EN="Save the current value of the variable in a file of the '/tmp' directory named 'value...txt' from the variable name and the saving step",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueSerieSaver",
-    content = """import numpy, re\nv=numpy.array(var[:], ndmin=1)\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
-    fr_FR   = "Enregistre la série des valeurs de la variable dans un fichier du répertoire '/tmp' nommé 'value...txt' selon le nom de la variable et l'étape",
-    en_EN   = "Save the value series of the variable in a file of the '/tmp' directory named 'value...txt' from the variable name and the saving step",
-    order   = "next",
+    name="ValueSerieSaver",
+    content="""import numpy, re\nv=numpy.array(var[:], ndmin=1)\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
+    fr_FR="Enregistre la série des valeurs de la variable dans un fichier du répertoire '/tmp' nommé 'value...txt' selon le nom de la variable et l'étape",
+    en_EN="Save the value series of the variable in a file of the '/tmp' directory named 'value...txt' from the variable name and the saving step",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValuePrinterAndSaver",
-    content = """import numpy, re\nv=numpy.array(var[-1], ndmin=1)\nprint(str(info)+" "+str(v))\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
-    fr_FR   = "Imprime sur la sortie standard et, en même temps enregistre dans un fichier du répertoire '/tmp', la valeur courante de la variable",
-    en_EN   = "Print on standard output and, in the same time save in a file of the '/tmp' directory, the current value of the variable",
-    order   = "next",
+    name="ValuePrinterAndSaver",
+    content="""import numpy, re\nv=numpy.array(var[-1], ndmin=1)\nprint(str(info)+" "+str(v))\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
+    fr_FR="Imprime sur la sortie standard et, en même temps enregistre dans un fichier du répertoire '/tmp', la valeur courante de la variable",
+    en_EN="Print on standard output and, in the same time save in a file of the '/tmp' directory, the current value of the variable",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueIndexPrinterAndSaver",
-    content = """import numpy, re\nv=numpy.array(var[-1], ndmin=1)\nprint(str(info)+(" index %i:"%(len(var)-1))+" "+str(v))\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
-    fr_FR   = "Imprime sur la sortie standard et, en même temps enregistre dans un fichier du répertoire '/tmp', la valeur courante de la variable, en ajoutant son index",
-    en_EN   = "Print on standard output and, in the same time save in a file of the '/tmp' directory, the current value of the variable, adding its index",
-    order   = "next",
+    name="ValueIndexPrinterAndSaver",
+    content="""import numpy, re\nv=numpy.array(var[-1], ndmin=1)\nprint(str(info)+(" index %i:"%(len(var)-1))+" "+str(v))\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
+    fr_FR="Imprime sur la sortie standard et, en même temps enregistre dans un fichier du répertoire '/tmp', la valeur courante de la variable, en ajoutant son index",
+    en_EN="Print on standard output and, in the same time save in a file of the '/tmp' directory, the current value of the variable, adding its index",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueSeriePrinterAndSaver",
-    content = """import numpy, re\nv=numpy.array(var[:], ndmin=1)\nprint(str(info)+" "+str(v))\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
-    fr_FR   = "Imprime sur la sortie standard et, en même temps, enregistre dans un fichier du répertoire '/tmp', la série des valeurs de la variable",
-    en_EN   = "Print on standard output and, in the same time, save in a file of the '/tmp' directory, the value series of the variable",
-    order   = "next",
+    name="ValueSeriePrinterAndSaver",
+    content="""import numpy, re\nv=numpy.array(var[:], ndmin=1)\nprint(str(info)+" "+str(v))\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)""",
+    fr_FR="Imprime sur la sortie standard et, en même temps, enregistre dans un fichier du répertoire '/tmp', la série des valeurs de la variable",
+    en_EN="Print on standard output and, in the same time, save in a file of the '/tmp' directory, the value series of the variable",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueGnuPlotter",
-    content = """import numpy, Gnuplot\nv=numpy.array(var[-1], ndmin=1)\nglobal igfig, gp\ntry:\n    igfig+=1\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\nexcept:\n    igfig=0\n    gp=Gnuplot.Gnuplot(persist=1)\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\n    gp('set style data lines')\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
-    fr_FR   = "Affiche graphiquement avec Gnuplot la valeur courante de la variable (affichage persistant)",
-    en_EN   = "Graphically plot with Gnuplot the current value of the variable (persistent plot)",
-    order   = "next",
+    name="ValueGnuPlotter",
+    content="""import numpy, Gnuplot\nv=numpy.array(var[-1], ndmin=1)\nglobal igfig, gp\ntry:\n    igfig+=1\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\nexcept:\n    igfig=0\n    gp=Gnuplot.Gnuplot(persist=1)\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\n    gp('set style data lines')\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
+    fr_FR="Affiche graphiquement avec Gnuplot la valeur courante de la variable (affichage persistant)",
+    en_EN="Graphically plot with Gnuplot the current value of the variable (persistent plot)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueSerieGnuPlotter",
-    content = """import numpy, Gnuplot\nv=numpy.array(var[:], ndmin=1)\nglobal igfig, gp\ntry:\n    igfig+=1\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\nexcept:\n    igfig=0\n    gp=Gnuplot.Gnuplot(persist=1)\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\n    gp('set style data lines')\n    gp('set xlabel \"Step\"')\n    gp('set ylabel \"Variable\"')\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
-    fr_FR   = "Affiche graphiquement avec Gnuplot la série des valeurs de la variable (affichage persistant)",
-    en_EN   = "Graphically plot with Gnuplot the value series of the variable (persistent plot)",
-    order   = "next",
+    name="ValueSerieGnuPlotter",
+    content="""import numpy, Gnuplot\nv=numpy.array(var[:], ndmin=1)\nglobal igfig, gp\ntry:\n    igfig+=1\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\nexcept:\n    igfig=0\n    gp=Gnuplot.Gnuplot(persist=1)\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\n    gp('set style data lines')\n    gp('set xlabel \"Step\"')\n    gp('set ylabel \"Variable\"')\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
+    fr_FR="Affiche graphiquement avec Gnuplot la série des valeurs de la variable (affichage persistant)",
+    en_EN="Graphically plot with Gnuplot the value series of the variable (persistent plot)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValuePrinterAndGnuPlotter",
-    content = """print(str(info)+' '+str(var[-1]))\nimport numpy, Gnuplot\nv=numpy.array(var[-1], ndmin=1)\nglobal igfig, gp\ntry:\n    igfig+=1\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\nexcept:\n    igfig=0\n    gp=Gnuplot.Gnuplot(persist=1)\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\n    gp('set style data lines')\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
-    fr_FR   = "Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la valeur courante de la variable (affichage persistant)",
-    en_EN   = "Print on standard output and, in the same time, graphically plot with Gnuplot the current value of the variable (persistent plot)",
-    order   = "next",
+    name="ValuePrinterAndGnuPlotter",
+    content="""print(str(info)+' '+str(var[-1]))\nimport numpy, Gnuplot\nv=numpy.array(var[-1], ndmin=1)\nglobal igfig, gp\ntry:\n    igfig+=1\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\nexcept:\n    igfig=0\n    gp=Gnuplot.Gnuplot(persist=1)\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\n    gp('set style data lines')\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
+    fr_FR="Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la valeur courante de la variable (affichage persistant)",
+    en_EN="Print on standard output and, in the same time, graphically plot with Gnuplot the current value of the variable (persistent plot)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueSeriePrinterAndGnuPlotter",
-    content = """print(str(info)+' '+str(var[:]))\nimport numpy, Gnuplot\nv=numpy.array(var[:], ndmin=1)\nglobal igfig, gp\ntry:\n    igfig+=1\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\nexcept:\n    igfig=0\n    gp=Gnuplot.Gnuplot(persist=1)\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\n    gp('set style data lines')\n    gp('set xlabel \"Step\"')\n    gp('set ylabel \"Variable\"')\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
-    fr_FR   = "Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la série des valeurs de la variable (affichage persistant)",
-    en_EN   = "Print on standard output and, in the same time, graphically plot with Gnuplot the value series of the variable (persistent plot)",
-    order   = "next",
+    name="ValueSeriePrinterAndGnuPlotter",
+    content="""print(str(info)+' '+str(var[:]))\nimport numpy, Gnuplot\nv=numpy.array(var[:], ndmin=1)\nglobal igfig, gp\ntry:\n    igfig+=1\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\nexcept:\n    igfig=0\n    gp=Gnuplot.Gnuplot(persist=1)\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\n    gp('set style data lines')\n    gp('set xlabel \"Step\"')\n    gp('set ylabel \"Variable\"')\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
+    fr_FR="Imprime sur la sortie standard et, en même temps, affiche graphiquement avec Gnuplot la série des valeurs de la variable (affichage persistant)",
+    en_EN="Print on standard output and, in the same time, graphically plot with Gnuplot the value series of the variable (persistent plot)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValuePrinterSaverAndGnuPlotter",
-    content = """print(str(info)+' '+str(var[-1]))\nimport numpy, re\nv=numpy.array(var[-1], ndmin=1)\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)\nimport Gnuplot\nglobal igfig, gp\ntry:\n    igfig+=1\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\nexcept:\n    igfig=0\n    gp=Gnuplot.Gnuplot(persist=1)\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\n    gp('set style data lines')\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
-    fr_FR   = "Imprime sur la sortie standard et, en même temps, enregistre dans un fichier du répertoire '/tmp' et affiche graphiquement la valeur courante de la variable (affichage persistant)",
-    en_EN   = "Print on standard output and, in the same, time save in a file of the '/tmp' directory and graphically plot the current value of the variable (persistent plot)",
-    order   = "next",
+    name="ValuePrinterSaverAndGnuPlotter",
+    content="""print(str(info)+' '+str(var[-1]))\nimport numpy, re\nv=numpy.array(var[-1], ndmin=1)\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)\nimport Gnuplot\nglobal igfig, gp\ntry:\n    igfig+=1\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\nexcept:\n    igfig=0\n    gp=Gnuplot.Gnuplot(persist=1)\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\n    gp('set style data lines')\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
+    fr_FR="Imprime sur la sortie standard et, en même temps, enregistre dans un fichier du répertoire '/tmp' et affiche graphiquement la valeur courante de la variable (affichage persistant)",
+    en_EN="Print on standard output and, in the same, time save in a file of the '/tmp' directory and graphically plot the current value of the variable (persistent plot)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueSeriePrinterSaverAndGnuPlotter",
-    content = """print(str(info)+' '+str(var[:]))\nimport numpy, re\nv=numpy.array(var[:], ndmin=1)\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)\nimport Gnuplot\nglobal igfig, gp\ntry:\n    igfig+=1\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\nexcept:\n    igfig=0\n    gp=Gnuplot.Gnuplot(persist=1)\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\n    gp('set style data lines')\n    gp('set xlabel \"Step\"')\n    gp('set ylabel \"Variable\"')\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
-    fr_FR   = "Imprime sur la sortie standard et, en même temps, enregistre dans un fichier du répertoire '/tmp' et affiche graphiquement la série des valeurs de la variable (affichage persistant)",
-    en_EN   = "Print on standard output and, in the same, time save in a file of the '/tmp' directory and graphically plot the value series of the variable (persistent plot)",
-    order   = "next",
+    name="ValueSeriePrinterSaverAndGnuPlotter",
+    content="""print(str(info)+' '+str(var[:]))\nimport numpy, re\nv=numpy.array(var[:], ndmin=1)\nglobal istep\ntry:\n    istep+=1\nexcept:\n    istep=0\nf='/tmp/value_%s_%05i.txt'%(info,istep)\nf=re.sub(r'\\s','_',f)\nprint('Value saved in \"%s\"'%f)\nnumpy.savetxt(f,v)\nimport Gnuplot\nglobal igfig, gp\ntry:\n    igfig+=1\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\nexcept:\n    igfig=0\n    gp=Gnuplot.Gnuplot(persist=1)\n    gp('set title \"%s (Figure %i)\"'%(info,igfig))\n    gp('set style data lines')\n    gp('set xlabel \"Step\"')\n    gp('set ylabel \"Variable\"')\ngp.plot( Gnuplot.Data( v, with_='lines lw 2' ) )""",
+    fr_FR="Imprime sur la sortie standard et, en même temps, enregistre dans un fichier du répertoire '/tmp' et affiche graphiquement la série des valeurs de la variable (affichage persistant)",
+    en_EN="Print on standard output and, in the same, time save in a file of the '/tmp' directory and graphically plot the value series of the variable (persistent plot)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueMatPlotter",
-    content = """import numpy\nimport matplotlib.pyplot as plt\nv=numpy.array(var[-1], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nax.plot(v)\nplt.show()""",
-    fr_FR   = "Affiche graphiquement avec Matplolib la valeur courante de la variable (affichage non persistant)",
-    en_EN   = "Graphically plot with Matplolib the current value of the variable (non persistent plot)",
-    order   = "next",
+    name="ValueMatPlotter",
+    content="""import numpy\nimport matplotlib.pyplot as plt\nv=numpy.array(var[-1], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nax.plot(v)\nplt.show()""",
+    fr_FR="Affiche graphiquement avec Matplolib la valeur courante de la variable (affichage non persistant)",
+    en_EN="Graphically plot with Matplolib the current value of the variable (non persistent plot)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueMatPlotterSaver",
-    content = """import numpy, re\nimport matplotlib.pyplot as plt\nv=numpy.array(var[-1], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nax.plot(v)\nf='/tmp/figure_%s_%05i.pdf'%(info,imfig)\nf=re.sub(r'\\s','_',f)\nplt.savefig(f)\nplt.show()""",
-    fr_FR   = "Affiche graphiquement avec Matplolib la valeur courante de la variable, et enregistre la figure dans un fichier du répertoire '/tmp' (figure persistante)",
-    en_EN   = "Graphically plot with Matplolib the current value of the variable, and save the figure in a file of the '/tmp' directory (persistant figure)",
-    order   = "next",
+    name="ValueMatPlotterSaver",
+    content="""import numpy, re\nimport matplotlib.pyplot as plt\nv=numpy.array(var[-1], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nax.plot(v)\nf='/tmp/figure_%s_%05i.pdf'%(info,imfig)\nf=re.sub(r'\\s','_',f)\nplt.savefig(f)\nplt.show()""",
+    fr_FR="Affiche graphiquement avec Matplolib la valeur courante de la variable, et enregistre la figure dans un fichier du répertoire '/tmp' (figure persistante)",
+    en_EN="Graphically plot with Matplolib the current value of the variable, and save the figure in a file of the '/tmp' directory (persistant figure)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueSerieMatPlotter",
-    content = """import numpy\nimport matplotlib.pyplot as plt\nv=numpy.array(var[:], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\n    ax.set_xlabel('Step')\n    ax.set_ylabel('Variable')\nax.plot(v)\nplt.show()""",
-    fr_FR   = "Affiche graphiquement avec Matplolib la série des valeurs de la variable (affichage non persistant)",
-    en_EN   = "Graphically plot with Matplolib the value series of the variable (non persistent plot)",
-    order   = "next",
+    name="ValueSerieMatPlotter",
+    content="""import numpy\nimport matplotlib.pyplot as plt\nv=numpy.array(var[:], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\n    ax.set_xlabel('Step')\n    ax.set_ylabel('Variable')\nax.plot(v)\nplt.show()""",
+    fr_FR="Affiche graphiquement avec Matplolib la série des valeurs de la variable (affichage non persistant)",
+    en_EN="Graphically plot with Matplolib the value series of the variable (non persistent plot)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueSerieMatPlotterSaver",
-    content = """import numpy, re\nimport matplotlib.pyplot as plt\nv=numpy.array(var[:], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\n    ax.set_xlabel('Step')\n    ax.set_ylabel('Variable')\nax.plot(v)\nf='/tmp/figure_%s_%05i.pdf'%(info,imfig)\nf=re.sub(r'\\s','_',f)\nplt.savefig(f)\nplt.show()""",
-    fr_FR   = "Affiche graphiquement avec Matplolib la série des valeurs de la variable, et enregistre la figure dans un fichier du répertoire '/tmp' (figure persistante)",
-    en_EN   = "Graphically plot with Matplolib the value series of the variable, and save the figure in a file of the '/tmp' directory (persistant figure)",
-    order   = "next",
+    name="ValueSerieMatPlotterSaver",
+    content="""import numpy, re\nimport matplotlib.pyplot as plt\nv=numpy.array(var[:], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\n    ax.set_xlabel('Step')\n    ax.set_ylabel('Variable')\nax.plot(v)\nf='/tmp/figure_%s_%05i.pdf'%(info,imfig)\nf=re.sub(r'\\s','_',f)\nplt.savefig(f)\nplt.show()""",
+    fr_FR="Affiche graphiquement avec Matplolib la série des valeurs de la variable, et enregistre la figure dans un fichier du répertoire '/tmp' (figure persistante)",
+    en_EN="Graphically plot with Matplolib the value series of the variable, and save the figure in a file of the '/tmp' directory (persistant figure)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValuePrinterAndMatPlotter",
-    content = """print(str(info)+' '+str(var[-1]))\nimport numpy\nimport matplotlib.pyplot as plt\nv=numpy.array(var[-1], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nax.plot(v)\nplt.show()""",
-    fr_FR   = "Affiche graphiquement avec Matplolib la valeur courante de la variable (affichage non persistant)",
-    en_EN   = "Graphically plot with Matplolib the current value of the variable (non persistent plot)",
-    order   = "next",
+    name="ValuePrinterAndMatPlotter",
+    content="""print(str(info)+' '+str(var[-1]))\nimport numpy\nimport matplotlib.pyplot as plt\nv=numpy.array(var[-1], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nax.plot(v)\nplt.show()""",
+    fr_FR="Affiche graphiquement avec Matplolib la valeur courante de la variable (affichage non persistant)",
+    en_EN="Graphically plot with Matplolib the current value of the variable (non persistent plot)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValuePrinterAndMatPlotterSaver",
-    content = """print(str(info)+' '+str(var[-1]))\nimport numpy, re\nimport matplotlib.pyplot as plt\nv=numpy.array(var[-1], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nax.plot(v)\nf='/tmp/figure_%s_%05i.pdf'%(info,imfig)\nf=re.sub(r'\\s','_',f)\nplt.savefig(f)\nplt.show()""",
-    fr_FR   = "Affiche graphiquement avec Matplolib la valeur courante de la variable, et enregistre la figure dans un fichier du répertoire '/tmp' (figure persistante)",
-    en_EN   = "Graphically plot with Matplolib the current value of the variable, and save the figure in a file of the '/tmp' directory (persistant figure)",
-    order   = "next",
+    name="ValuePrinterAndMatPlotterSaver",
+    content="""print(str(info)+' '+str(var[-1]))\nimport numpy, re\nimport matplotlib.pyplot as plt\nv=numpy.array(var[-1], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nax.plot(v)\nf='/tmp/figure_%s_%05i.pdf'%(info,imfig)\nf=re.sub(r'\\s','_',f)\nplt.savefig(f)\nplt.show()""",
+    fr_FR="Affiche graphiquement avec Matplolib la valeur courante de la variable, et enregistre la figure dans un fichier du répertoire '/tmp' (figure persistante)",
+    en_EN="Graphically plot with Matplolib the current value of the variable, and save the figure in a file of the '/tmp' directory (persistant figure)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueSeriePrinterAndMatPlotter",
-    content = """print(str(info)+' '+str(var[:]))\nimport numpy\nimport matplotlib.pyplot as plt\nv=numpy.array(var[:], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\n    ax.set_xlabel('Step')\n    ax.set_ylabel('Variable')\nax.plot(v)\nplt.show()""",
-    fr_FR   = "Affiche graphiquement avec Matplolib la série des valeurs de la variable (affichage non persistant)",
-    en_EN   = "Graphically plot with Matplolib the value series of the variable (non persistent plot)",
-    order   = "next",
+    name="ValueSeriePrinterAndMatPlotter",
+    content="""print(str(info)+' '+str(var[:]))\nimport numpy\nimport matplotlib.pyplot as plt\nv=numpy.array(var[:], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\n    ax.set_xlabel('Step')\n    ax.set_ylabel('Variable')\nax.plot(v)\nplt.show()""",
+    fr_FR="Affiche graphiquement avec Matplolib la série des valeurs de la variable (affichage non persistant)",
+    en_EN="Graphically plot with Matplolib the value series of the variable (non persistent plot)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueSeriePrinterAndMatPlotterSaver",
-    content = """print(str(info)+' '+str(var[:]))\nimport numpy, re\nimport matplotlib.pyplot as plt\nv=numpy.array(var[:], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\n    ax.set_xlabel('Step')\n    ax.set_ylabel('Variable')\nax.plot(v)\nf='/tmp/figure_%s_%05i.pdf'%(info,imfig)\nf=re.sub(r'\\s','_',f)\nplt.savefig(f)\nplt.show()""",
-    fr_FR   = "Affiche graphiquement avec Matplolib la série des valeurs de la variable, et enregistre la figure dans un fichier du répertoire '/tmp' (figure persistante)",
-    en_EN   = "Graphically plot with Matplolib the value series of the variable, and save the figure in a file of the '/tmp' directory (persistant figure)",
-    order   = "next",
+    name="ValueSeriePrinterAndMatPlotterSaver",
+    content="""print(str(info)+' '+str(var[:]))\nimport numpy, re\nimport matplotlib.pyplot as plt\nv=numpy.array(var[:], ndmin=1)\nglobal imfig, mp, ax\nplt.ion()\ntry:\n    imfig+=1\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\nexcept:\n    imfig=0\n    mp = plt.figure()\n    ax = mp.add_subplot(1, 1, 1)\n    mp.suptitle('%s (Figure %i)'%(info,imfig))\n    ax.set_xlabel('Step')\n    ax.set_ylabel('Variable')\nax.plot(v)\nf='/tmp/figure_%s_%05i.pdf'%(info,imfig)\nf=re.sub(r'\\s','_',f)\nplt.savefig(f)\nplt.show()""",
+    fr_FR="Affiche graphiquement avec Matplolib la série des valeurs de la variable, et enregistre la figure dans un fichier du répertoire '/tmp' (figure persistante)",
+    en_EN="Graphically plot with Matplolib the value series of the variable, and save the figure in a file of the '/tmp' directory (persistant figure)",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueMean",
-    content = """import numpy\nprint(str(info)+' '+str(numpy.nanmean(var[-1])))""",
-    fr_FR   = "Imprime sur la sortie standard la moyenne de la valeur courante de la variable",
-    en_EN   = "Print on standard output the mean of the current value of the variable",
-    order   = "next",
+    name="ValueMean",
+    content="""import numpy\nprint(str(info)+' '+str(numpy.nanmean(var[-1])))""",
+    fr_FR="Imprime sur la sortie standard la moyenne de la valeur courante de la variable",
+    en_EN="Print on standard output the mean of the current value of the variable",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueStandardError",
-    content = """import numpy\nprint(str(info)+' '+str(numpy.nanstd(var[-1])))""",
-    fr_FR   = "Imprime sur la sortie standard l'écart-type de la valeur courante de la variable",
-    en_EN   = "Print on standard output the standard error of the current value of the variable",
-    order   = "next",
+    name="ValueStandardError",
+    content="""import numpy\nprint(str(info)+' '+str(numpy.nanstd(var[-1])))""",
+    fr_FR="Imprime sur la sortie standard l'écart-type de la valeur courante de la variable",
+    en_EN="Print on standard output the standard error of the current value of the variable",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueVariance",
-    content = """import numpy\nprint(str(info)+' '+str(numpy.nanvar(var[-1])))""",
-    fr_FR   = "Imprime sur la sortie standard la variance de la valeur courante de la variable",
-    en_EN   = "Print on standard output the variance of the current value of the variable",
-    order   = "next",
+    name="ValueVariance",
+    content="""import numpy\nprint(str(info)+' '+str(numpy.nanvar(var[-1])))""",
+    fr_FR="Imprime sur la sortie standard la variance de la valeur courante de la variable",
+    en_EN="Print on standard output the variance of the current value of the variable",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueL2Norm",
-    content = """import numpy\nv = numpy.ravel( var[-1] )\nprint(str(info)+' '+str(float( numpy.linalg.norm(v) )))""",
-    fr_FR   = "Imprime sur la sortie standard la norme L2 de la valeur courante de la variable",
-    en_EN   = "Print on standard output the L2 norm of the current value of the variable",
-    order   = "next",
+    name="ValueL2Norm",
+    content="""import numpy\nv = numpy.ravel( var[-1] )\nprint(str(info)+' '+str(float( numpy.linalg.norm(v) )))""",
+    fr_FR="Imprime sur la sortie standard la norme L2 de la valeur courante de la variable",
+    en_EN="Print on standard output the L2 norm of the current value of the variable",
+    order="next",
 )
 ObserverTemplates.store(
-    name    = "ValueRMS",
-    content = """import numpy\nv = numpy.ravel( var[-1] )\nprint(str(info)+' '+str(float( numpy.sqrt((1./v.size)*numpy.dot(v,v)) )))""",
-    fr_FR   = "Imprime sur la sortie standard la racine de la moyenne des carrés (RMS), ou moyenne quadratique, de la valeur courante de la variable",
-    en_EN   = "Print on standard output the root mean square (RMS), or quadratic mean, of the current value of the variable",
-    order   = "next",
+    name="ValueRMS",
+    content="""import numpy\nv = numpy.ravel( var[-1] )\nprint(str(info)+' '+str(float( numpy.sqrt((1./v.size)*numpy.dot(v,v)) )))""",
+    fr_FR="Imprime sur la sortie standard la racine de la moyenne des carrés (RMS), ou moyenne quadratique, de la valeur courante de la variable",
+    en_EN="Print on standard output the root mean square (RMS), or quadratic mean, of the current value of the variable",
+    order="next",
 )
 
 # ==============================================================================
 UserPostAnalysisTemplates = TemplateStorage()
 
 UserPostAnalysisTemplates.store(
-    name    = "AnalysisPrinter",
-    content = """print('# Post-analysis')\nimport numpy\nxa=ADD.get('Analysis')[-1]\nprint('Analysis',xa)""",
-    fr_FR   = "Imprime sur la sortie standard la valeur optimale",
-    en_EN   = "Print on standard output the optimal value",
-    order   = "next",
+    name="AnalysisPrinter",
+    content="""print('# Post-analysis')\nimport numpy\nxa=ADD.get('Analysis')[-1]\nprint('Analysis',xa)""",
+    fr_FR="Imprime sur la sortie standard la valeur optimale",
+    en_EN="Print on standard output the optimal value",
+    order="next",
 )
 UserPostAnalysisTemplates.store(
-    name    = "AnalysisSaver",
-    content = """print('# Post-analysis')\nimport numpy\nxa=ADD.get('Analysis')[-1]\nf='/tmp/analysis.txt'\nprint('Analysis saved in \"%s\"'%f)\nnumpy.savetxt(f,xa)""",
-    fr_FR   = "Enregistre la valeur optimale dans un fichier du répertoire '/tmp' nommé 'analysis.txt'",
-    en_EN   = "Save the optimal value in a file of the '/tmp' directory named 'analysis.txt'",
-    order   = "next",
+    name="AnalysisSaver",
+    content="""print('# Post-analysis')\nimport numpy\nxa=ADD.get('Analysis')[-1]\nf='/tmp/analysis.txt'\nprint('Analysis saved in \"%s\"'%f)\nnumpy.savetxt(f,xa)""",
+    fr_FR="Enregistre la valeur optimale dans un fichier du répertoire '/tmp' nommé 'analysis.txt'",
+    en_EN="Save the optimal value in a file of the '/tmp' directory named 'analysis.txt'",
+    order="next",
 )
 UserPostAnalysisTemplates.store(
-    name    = "AnalysisPrinterAndSaver",
-    content = """print('# Post-analysis')\nimport numpy\nxa=ADD.get('Analysis')[-1]\nprint('Analysis',xa)\nf='/tmp/analysis.txt'\nprint('Analysis saved in \"%s\"'%f)\nnumpy.savetxt(f,xa)""",
-    fr_FR   = "Imprime sur la sortie standard et, en même temps enregistre dans un fichier du répertoire '/tmp', la valeur optimale",
-    en_EN   = "Print on standard output and, in the same time save in a file of the '/tmp' directory, the optimal value",
-    order   = "next",
+    name="AnalysisPrinterAndSaver",
+    content="""print('# Post-analysis')\nimport numpy\nxa=ADD.get('Analysis')[-1]\nprint('Analysis',xa)\nf='/tmp/analysis.txt'\nprint('Analysis saved in \"%s\"'%f)\nnumpy.savetxt(f,xa)""",
+    fr_FR="Imprime sur la sortie standard et, en même temps enregistre dans un fichier du répertoire '/tmp', la valeur optimale",
+    en_EN="Print on standard output and, in the same time save in a file of the '/tmp' directory, the optimal value",
+    order="next",
 )
 UserPostAnalysisTemplates.store(
-    name    = "AnalysisSeriePrinter",
-    content = """print('# Post-analysis')\nimport numpy\nxa=ADD.get('Analysis')\nprint('Analysis',xa)""",
-    fr_FR   = "Imprime sur la sortie standard la série des valeurs optimales",
-    en_EN   = "Print on standard output the optimal value series",
-    order   = "next",
+    name="AnalysisSeriePrinter",
+    content="""print('# Post-analysis')\nimport numpy\nxa=ADD.get('Analysis')\nprint('Analysis',xa)""",
+    fr_FR="Imprime sur la sortie standard la série des valeurs optimales",
+    en_EN="Print on standard output the optimal value series",
+    order="next",
 )
 UserPostAnalysisTemplates.store(
-    name    = "AnalysisSerieSaver",
-    content = """print('# Post-analysis')\nimport numpy\nxa=ADD.get('Analysis')\nf='/tmp/analysis.txt'\nprint('Analysis saved in \"%s\"'%f)\nnumpy.savetxt(f,xa)""",
-    fr_FR   = "Enregistre la série des valeurs optimales dans un fichier du répertoire '/tmp' nommé 'analysis.txt'",
-    en_EN   = "Save the optimal value series in a file of the '/tmp' directory named 'analysis.txt'",
-    order   = "next",
+    name="AnalysisSerieSaver",
+    content="""print('# Post-analysis')\nimport numpy\nxa=ADD.get('Analysis')\nf='/tmp/analysis.txt'\nprint('Analysis saved in \"%s\"'%f)\nnumpy.savetxt(f,xa)""",
+    fr_FR="Enregistre la série des valeurs optimales dans un fichier du répertoire '/tmp' nommé 'analysis.txt'",
+    en_EN="Save the optimal value series in a file of the '/tmp' directory named 'analysis.txt'",
+    order="next",
 )
 UserPostAnalysisTemplates.store(
-    name    = "AnalysisSeriePrinterAndSaver",
-    content = """print('# Post-analysis')\nimport numpy\nxa=ADD.get('Analysis')\nprint('Analysis',xa)\nf='/tmp/analysis.txt'\nprint('Analysis saved in \"%s\"'%f)\nnumpy.savetxt(f,xa)""",
-    fr_FR   = "Imprime sur la sortie standard et, en même temps enregistre dans un fichier du répertoire '/tmp', la série des valeurs optimales",
-    en_EN   = "Print on standard output and, in the same time save in a file of the '/tmp' directory, the optimal value series",
-    order   = "next",
+    name="AnalysisSeriePrinterAndSaver",
+    content="""print('# Post-analysis')\nimport numpy\nxa=ADD.get('Analysis')\nprint('Analysis',xa)\nf='/tmp/analysis.txt'\nprint('Analysis saved in \"%s\"'%f)\nnumpy.savetxt(f,xa)""",
+    fr_FR="Imprime sur la sortie standard et, en même temps enregistre dans un fichier du répertoire '/tmp', la série des valeurs optimales",
+    en_EN="Print on standard output and, in the same time save in a file of the '/tmp' directory, the optimal value series",
+    order="next",
 )
 
 # ==============================================================================
diff --git a/src/daComposant/daNumerics/Models/Lorenz1963.py b/src/daComposant/daNumerics/Models/Lorenz1963.py
new file mode 100644 (file)
index 0000000..8c8a774
--- /dev/null
@@ -0,0 +1,106 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2008-2024 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
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+# Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
+
+import sys
+import unittest
+import math
+import numpy
+from daCore.BasicObjects import DynamicalSimulator
+
+
+# ==============================================================================
+class Lorenz1963(DynamicalSimulator):
+    """
+    Three-dimensional parametrized nonlinear ODE system depending on µ=(σ,ρ,β):
+
+        ∂x/∂t = σ (y − x)
+        ∂y/∂t = ρ x − y − x z
+        ∂z/∂t = x y − β z
+
+        with t ∈ [0, 40] the time interval, x(t), y(t), z(t) the dependent
+        variables, and with σ=10, ρ=28, and β=8/3 the commonly used parameter
+        values. The initial conditions for (x, y, z) at t=0 for the reference
+        case are (0, 1, 0).
+
+    This is the well known parametrized coupled system of three nonlinear
+    ordinary differential equations:
+        Lorenz, E. N. (1963). Deterministic nonperiodic flow. Journal of the
+        Atmospheric Sciences, 20, 130–141.
+        doi:10.1175/1520-0469(1963)020<0130:DNF>2.0.CO;2
+    """
+
+    def set_canonical_description(self):
+        self.set_mu((10.0, 28.0, 8.0 / 3.0))  # µ = (σ, ρ, β)
+        self.set_integrator("rk4")
+        self.set_dt(0.01)
+        self.set_t0(0.0)
+        self.set_tf(40)
+        self.set_y0((0.0, 1.0, 0.0))
+        self.set_autonomous(True)
+        return True
+
+    def ODEModel(self, t, Y):
+        "ODE dY/dt = F(Y,t)"
+        sigma, rho, beta = self.set_mu()
+        x, y, z = map(float, Y)
+        #
+        rx = sigma * (y - x)
+        ry = x * rho - y - x * z
+        rz = x * y - beta * z
+        #
+        return numpy.array([rx, ry, rz])
+
+
+# ==============================================================================
+class LocalTest(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        print("\nAUTODIAGNOSTIC\n==============\n")
+        print("    " + Lorenz1963().__doc__.strip())
+
+    def test001(self):
+        numpy.random.seed(123456789)
+        ODE = Lorenz1963()  # Default parameters
+        trajectory = ODE.ForecastedPath()
+        #
+        print()
+        self.assertTrue(trajectory.shape[0] == 1 + int(ODE.set_tf() / ODE.set_dt()))
+        self.assertTrue(
+            abs(
+                max(
+                    trajectory[-1]
+                    - numpy.array([16.48799962, 14.01693428, 40.30448848])
+                )
+            )
+            <= 1.0e-8,
+            msg="    Last value is not equal to the reference one",
+        )
+        print("    Last value is equal to the reference one")
+
+    def tearDown(cls):
+        print("\n    Tests are finished\n")
+
+
+# ==============================================================================
+if __name__ == "__main__":
+    sys.stderr = sys.stdout
+    unittest.main(verbosity=0)
index 052d3eb3f744acc382da53559a7c721dd2918ae4..08ef395780d6400e91e2294c9c495b6c0274c5f6 100644 (file)
 #
 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
 
-import sys, unittest, numpy
+import sys
+import unittest
+import numpy
+
 
 # ==============================================================================
 class TwoDimensionalInverseDistanceCS2010:
@@ -36,19 +39,20 @@ class TwoDimensionalInverseDistanceCS2010:
         Nonlinear Model Reduction via Discrete Empirical Interpolation,
         SIAM Journal on Scientific Computing, 32(5), pp. 2737-2764 (2010).
     """
+
     def __init__(self, nx: int = 20, ny: int = 20):
         "Définition du maillage spatial"
-        self.nx  = max(1, nx)
-        self.ny  = max(1, ny)
-        self.x   = numpy.linspace(0.1, 0.9, self.nx, dtype=float)
-        self.y   = numpy.linspace(0.1, 0.9, self.ny, dtype=float)
+        self.nx = max(1, nx)
+        self.ny = max(1, ny)
+        self.x = numpy.linspace(0.1, 0.9, self.nx, dtype=float)
+        self.y = numpy.linspace(0.1, 0.9, self.ny, dtype=float)
 
-    def FieldG(self, mu ):
+    def FieldG(self, mu):
         "Fonction simulation pour un paramètre donné"
-        mu1, mu2 = numpy.ravel( mu )
+        mu1, mu2 = numpy.ravel(mu)
         #
-        x, y = numpy.meshgrid( self.x, self.y )
-        sxymu = 1. / numpy.sqrt( (x - mu1)**2 + (y - mu2)**2 + 0.1**2 )
+        x, y = numpy.meshgrid(self.x, self.y)
+        sxymu = 1.0 / numpy.sqrt((x - mu1) ** 2 + (y - mu2) ** 2 + 0.1**2)
         #
         return sxymu
 
@@ -83,18 +87,19 @@ class TwoDimensionalInverseDistanceCS2010:
 
     OneRealisation = FieldG
 
+
 # ==============================================================================
 class LocalTest(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
-        print('\nAUTODIAGNOSTIC\n==============\n')
+        print("\nAUTODIAGNOSTIC\n==============\n")
         print("    " + TwoDimensionalInverseDistanceCS2010().__doc__.strip())
 
     def test001(self):
         numpy.random.seed(123456789)
         Equation = TwoDimensionalInverseDistanceCS2010()
         for mu in Equation.get_sample_of_mu(5, 5):
-            solution = Equation.OneRealisation( mu )
+            solution = Equation.OneRealisation(mu)
             # Nappe maximale au coin (0,0)
             self.assertTrue(numpy.max(solution.flat) <= solution[0, 0])
             # Nappe minimale au coin [-1,-1]
@@ -103,6 +108,7 @@ class LocalTest(unittest.TestCase):
     def tearDown(cls):
         print("\n    Tests OK\n")
 
+
 # ==============================================================================
 if __name__ == "__main__":
     sys.stderr = sys.stdout
index 7f7b27a68e402db0709387ff2533181ee77949d4..655f757c48418db766a4a0da37b93e1b7115bb06 100644 (file)
 #
 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
 
-import sys, unittest, math, numpy
+import sys
+import unittest
+import math
+import numpy
+
 
 # ==============================================================================
 class TwoDimensionalRosenbrockFunctionR1960:
@@ -29,33 +33,35 @@ class TwoDimensionalRosenbrockFunctionR1960:
 
         f(x,y) = (a - x)² + b (y -x²)²
 
-        with (x,y) ∈ [-2,2]x[-1,3]² and usually a=1, b=100. There is a
-        global minimum at (x,y) = (a,a²) for which f(x,y) = 0.
+        with (x,y) ∈ [-2,2]x[-1,3]² and a=1, b=100 the commonly used parameter
+        values. There exists a global minimum at (x,y) = (a,a²) for which
+        f(x,y) = 0.
 
     This is the non-linear non-convex parametric function of the reference:
         Rosenbrock, H. H., An Automatic Method for Finding the Greatest or
         Least Value of a Function, The Computer Journal, 3(3), pp.175–184,
         (1960)
     """
+
     def __init__(self, nx: int = 40, ny: int = 40):
         "Définition du maillage spatial"
-        self.nx  = max(1, nx)
-        self.ny  = max(1, ny)
-        self.x   = numpy.linspace(-2, 2, self.nx, dtype=float)
-        self.y   = numpy.linspace(-1, 3, self.ny, dtype=float)
+        self.nx = max(1, nx)
+        self.ny = max(1, ny)
+        self.x = numpy.linspace(-2, 2, self.nx, dtype=float)
+        self.y = numpy.linspace(-1, 3, self.ny, dtype=float)
 
-    def FieldZ(self, mu ):
+    def FieldZ(self, mu):
         "Fonction simulation pour un paramètre donné"
-        a, b = numpy.ravel( mu )
+        a, b = numpy.ravel(mu)
         #
-        x, y = numpy.meshgrid( self.x, self.y )
-        sxymu = (a - x)**2 + b * (y - x**2)**2
+        x, y = numpy.meshgrid(self.x, self.y)
+        sxymu = (a - x) ** 2 + b * (y - x**2) ** 2
         #
         return sxymu
 
-    def FunctionH(self, xy, a = 1, b = 100):
+    def FunctionH(self, xy, a=1, b=100):
         "Construit la fonction de Rosenbrock en L2 (Scipy 1.8.1 p.1322)"
-        xy = numpy.ravel( xy ).reshape((-1, 2))  # Deux colonnes
+        xy = numpy.ravel(xy).reshape((-1, 2))  # Deux colonnes
         x = xy[:, 0]
         y = xy[:, 1]
         return numpy.array([(a - x), math.sqrt(b) * (y - x**2)])
@@ -91,26 +97,28 @@ class TwoDimensionalRosenbrockFunctionR1960:
 
     OneRealisation = FieldZ
 
+
 # ==============================================================================
 class LocalTest(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
-        print('\nAUTODIAGNOSTIC\n==============\n')
+        print("\nAUTODIAGNOSTIC\n==============\n")
         print("    " + TwoDimensionalRosenbrockFunctionR1960().__doc__.strip())
 
     def test001(self):
         numpy.random.seed(123456789)
         Equation = TwoDimensionalRosenbrockFunctionR1960()
 
-        optimum = Equation.FunctionH( [1, 1] )
-        self.assertTrue( max(optimum.flat) <= 0.)
+        optimum = Equation.FunctionH([1, 1])
+        self.assertTrue(max(optimum.flat) <= 0.0)
 
-        optimum = Equation.FunctionH( [0.5, 0.25], a=0.5 )
-        self.assertTrue( max(optimum.flat) <= 0.)
+        optimum = Equation.FunctionH([0.5, 0.25], a=0.5)
+        self.assertTrue(max(optimum.flat) <= 0.0)
 
     def tearDown(cls):
         print("\n    Tests OK\n")
 
+
 # ==============================================================================
 if __name__ == "__main__":
     sys.stderr = sys.stdout
index 1bbcbc5351488e9964f3d5927c0ccc6284a52f07..6b502f5677a9ade91beac64f098c9c7d20e91713 100644 (file)
@@ -24,7 +24,7 @@
 
 import os, sys
 
-# print "import des prefs de Adao"
+# print ("import des prefs de Adao")
 #
 # Configuration de Eficas
 # =======================