We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Bug]: Install dependencies for testing: Could not build wheels for ruamel.yaml
### What happened?

The install dependencies for testing fails due to ruamel.yaml package, see: 

https://github.com/spectrochempy/spectrochempy/actions/runs/7918492722/job/21660419471?pr=734
https://github.com/spectrochempy/spectrochempy/actions/runs/7918492722/job/21660419097?pr=734

### What did you expect to happen?

the install should go smoothly

### Minimal Complete Verifiable Example

_No response_

### Relevant log output

_No response_

### Anything else we need to know?

_No response_

### Environment

N/A

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `spectrochempy/analysis/decomposition/fast_ica.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # ======================================================================================
3 # Copyright (©) 2015-2023 LCS - Laboratoire Catalyse et Spectrochimie, Caen, France.
4 # CeCILL-B FREE SOFTWARE LICENSE AGREEMENT
5 # See full LICENSE agreement in the root directory.
6 # ======================================================================================
7 """
8 Implementation of FastICA model (using scikit-learn library)
9 """
10 
11 import traitlets as tr
12 from numpy.random import RandomState
13 from sklearn import decomposition
14 
15 from spectrochempy.analysis._base._analysisbase import (
16     DecompositionAnalysis,
17     _wrap_ndarray_output_to_nddataset,
18 )
19 from spectrochempy.utils.decorators import signature_has_configurable_traits
20 from spectrochempy.utils.docstrings import _docstring
21 from spectrochempy.utils.traits import NDDatasetType
22 
23 __all__ = ["FastICA"]
24 __configurables__ = ["FastICA"]
25 
26 
27 # ======================================================================================
28 # class FastICA
29 # ======================================================================================
30 @signature_has_configurable_traits
31 class FastICA(DecompositionAnalysis):
32     _docstring.delete_params("DecompositionAnalysis.see_also", "FastICA")
33 
34     __doc__ = _docstring.dedent(
35         r"""
36     Fast algorithm for Independent Component Analysis (FastICA).
37 
38     A wrapper of `sklearn.decomposition.FastICA`\ .
39 
40     :term:`ICA` (Independent Component Analysis) extracts the underlying sources of
41     the variability of a set of spectra :math:`X` into the spectral profiles :math:`S^t`
42     of the underelying sources and a mixing matrix :math:`A`\ .
43 
44     In terms of matrix equation:
45 
46     .. math:: X = \bar{X} + A \cdot S^t + E
47 
48     where :math:`\bar{X}` is the mean of the dataset and :math:`E` is the matrix of
49     residuals.
50 
51     Parameters
52     ----------
53     %(AnalysisConfigurable.parameters)s
54 
55     See Also
56     --------
57     %(DecompositionAnalysis.see_also.no_FastICA)s
58     """
59     )
60 
61     # ----------------------------------------------------------------------------------
62     # Runtime Parameters,
63     # only those specific to FastICA, the other being defined in AnalysisConfigurable.
64     # ----------------------------------------------------------------------------------
65     # define here only the variable that you use in fit or transform functions
66     _fastica = tr.Instance(
67         decomposition.FastICA,
68         help="The instance of sklearn.decomposition.FastICA used in this model",
69     )
70 
71     # ----------------------------------------------------------------------------------
72     # Configuration parameters
73     # ----------------------------------------------------------------------------------
74 
75     n_components = tr.Integer(
76         default_value=None,
77         allow_none=True,
78         help="Number of components (sources) to use.",
79     ).tag(config=True)
80 
81     algorithm = tr.Enum(
82         ["parallel", "deflation"],
83         default_value="parallel",
84         help=("""Specify which algorithm to use for FastICA."""),
85     ).tag(config=True)
86 
87     whiten = tr.Union(
88         (tr.Enum(["arbitrary-variance", "unit-variance"]), tr.Bool(False)),
89         default_value="arbitrary-variance",
90         allow_none=True,
91         help=(
92             """Specify the whitening strategy to use.
93 
94 - ``"arbitrary-variance"``\ : a whitening with variance arbitrary is used.
95 - "unit-variance" : the whitening matrix is rescaled to ensure that each recovered
96   source has unit variance.
97 - False : the data is already considered to be whitened, and no whitening is performed.
98 """
99         ),
100     ).tag(config=True)
101 
102     fun = tr.Union(
103         (tr.Enum(["logcosh", "exp", "cube"]), tr.Callable(), tr.Unicode()),
104         default_value="logcosh",
105         allow_none=True,
106         help=(
107             r"""The functional form of the function used in the approximation to neg-entropy.
108 
109 - ``string``\ : could be either ``"logcosh"``\ , ``"exp"``\ , or ``"cube"``\ .
110 - ``callable``\ : You can provide your own function. It should return a tuple containing
111   the value of the function, and of its derivative, in the point. The derivative should
112   be averaged along its last dimension.
113 
114 .. code-block::
115 
116     def my_g(x):
117         return x ** 3, (3 * x ** 2).mean(axis=-1)
118 
119 .. note::
120     ``fun`` can be also a serialized function created using dill and base64
121     python libraries. Normally not used directly, it is here for internal
122     process. """
123         ),
124     ).tag(config=True)
125 
126     fun_args = tr.Dict(
127         default_value=None,
128         allow_none=True,
129         help=(
130             """Arguments to send to the functional form.
131 
132 If empty or None and if ``fun=="logcosh"`` , `fun_args` will take value
133 ``{alpha : 1.0}``."""
134         ),
135     ).tag(config=True)
136 
137     tol = tr.Float(
138         default_value=1e-4,
139         help="Tolerance at which the un-mixing matrix is considered to have converged.",
140     ).tag(config=True)
141 
142     max_iter = tr.Integer(
143         default_value=200, help="Maximum number of iterations before timing out."
144     ).tag(config=True)
145 
146     w_init = tr.Union(
147         (NDDatasetType(),),
148         default_value=None,
149         allow_none=True,
150         help=(
151             r"""Initial un-mixing array.
152 
153 NDDataset or array-like of shape (n_components, n_components). If w_init=None, then an
154 array of values drawn from a normal distribution is used."""
155         ),
156     ).tag(config=True)
157 
158     whiten_solver = tr.Enum(
159         ["svd", "eigh"],
160         default_value="svd",
161         help=(
162             """The solver to use for whitening.
163 
164 - ``"svd"``\ : is more stable numerically if the problem is degenerate, and often faster
165   when :term:`n_observations` <= :term:`n_features`\ .
166 - ``"eigh"``\ : is generally more memory efficient when
167   :term:`n_observations` >= :term:`n_features`\ , and can be faster when
168   :term:`n_observations` >= 50 * :term:`n_features`\ . """
169         ),
170     ).tag(config=True)
171 
172     random_state = tr.Union(
173         (tr.Integer(), tr.Instance(RandomState)),
174         allow_none=True,
175         default_value=None,
176         help=(
177             "Used to initialize ``w_init`` when not specified, with a normal"
178             "distribution. Pass an ``int``, for reproducible results across "
179             "multiple function calls."
180         ),
181     ).tag(config=True)
182 
183     # ----------------------------------------------------------------------------------
184     # Initialization
185     # ----------------------------------------------------------------------------------
186     def __init__(
187         self,
188         *,
189         log_level="WARNING",
190         warm_start=False,
191         **kwargs,
192     ):
193         # call the super class for initialisation of the configuration parameters
194         # to do before anything else!
195         super().__init__(
196             log_level=log_level,
197             warm_start=warm_start,
198             **kwargs,
199         )
200 
201         # initialize sklearn Fast!ICA
202         self._fast_ica = decomposition.FastICA(
203             n_components=self.n_components,
204             algorithm=self.algorithm,
205             whiten=self.whiten,
206             fun=self.fun,
207             fun_args=self.fun_args,
208             tol=self.tol,
209             max_iter=self.max_iter,
210             w_init=self.w_init,
211             whiten_solver=self.whiten_solver,
212             random_state=self.random_state,
213         )
214 
215     # ----------------------------------------------------------------------------------
216     # Private methods (overloading abstract classes)
217     # ----------------------------------------------------------------------------------
218     def _fit(self, X, Y=None):
219         # this method is called by the abstract class fit.
220         # Input X is a np.ndarray
221         # Y is ignored in this model
222 
223         # call the sklearn _fit function on data
224         # _outfit is a tuple handle the eventual output of _fit for further processing.
225 
226         # The _outfit members are np.ndarrays
227         _outfit = self._fast_ica.fit(X)
228         self._n_components = int(
229             self._fast_ica.n_components
230         )  # cast the returned int64 to int
231         return _outfit
232 
233     def _transform(self, X):
234         return self._fast_ica.transform(X)
235 
236     def _inverse_transform(self, X_transform):
237         # we need to  set self._fast_ica.components_ to a compatible size but without
238         # destroying the full matrix:
239         store_components_ = self._fast_ica.components_
240         self._fast_ica.components_ = self._fast_ica.components_[: X_transform.shape[1]]
241         X = self._fast_ica.inverse_transform(X_transform)
242         # restore
243         self._fast_ica.components_ = store_components_
244         return X
245 
246     def _get_components(self):
247         self._components = self._fast_ica.components_
248         return self._components
249 
250     _docstring.keep_params("analysis_fit.parameters", "X")
251 
252     @_docstring.dedent
253     def fit(self, X):
254         """
255         Fit the FastICA model on X.
256 
257         Parameters
258         ----------
259         %(analysis_fit.parameters.X)s
260 
261         Returns
262         -------
263         %(analysis_fit.returns)s
264 
265         See Also
266         --------
267         %(analysis_fit.see_also)s
268         """
269         return super().fit(X, Y=None)
270 
271     @property
272     @_wrap_ndarray_output_to_nddataset(
273         units=None, title=None, typey="features", typex="components"
274     )
275     def mixing(self):
276         """
277         The pseudo inverse of components.
278 
279         NDDataset of size (`n_features`\ , `n_components`\ ). It is the linear operator
280         that maps independent sources to the data, and the transpose of `St`\ .
281         """
282         return self._fast_ica.mixing_
283 
284     @property
285     @_wrap_ndarray_output_to_nddataset(
286         units=None,
287         title=None,
288         typey="components",
289     )
290     def St(self):
291         """
292         The spectral profiles of the independant sources.
293 
294         NDDataset of size (`n_components`\ , `n_features`\ ). It is the transpose of the
295         ``mixing_`` matrix returned by Scikit-Learn.
296         """
297         return self._fast_ica.mixing_.T
298 
299     @property
300     @_wrap_ndarray_output_to_nddataset(
301         units=None,
302         title=None,
303         typex="components",
304     )
305     def A(self):
306         """
307         The mixing system A.
308 
309         NDDataset of size (`n_observations`\ , `n_components`\ ). It is the matrix
310         returned by the `transform()` method.
311         """
312         return self._fast_ica.transform(self.X.data)
313 
314     @property
315     @_wrap_ndarray_output_to_nddataset()
316     def mean(self):
317         """
318         The mean of X over features.
319 
320         Only set if `whiten` is True, it is needed (and used) to reconstruct a dataset
321         by ``inverse_transform(A)``\ .
322         """
323         return self._fast_ica.mean_
324 
325     @property
326     def n_iter(self):
327         """
328         Number of iterations.
329 
330         If the algorithm is “deflation”, n_iter is the maximum number of iterations run
331         across all components. Else they are just the number of iterations taken to
332         converge.
333         """
334         return self._fast_ica.n_iter_
335 
336     @property
337     @_wrap_ndarray_output_to_nddataset(
338         units=None,
339         title=None,
340         typey="components",
341     )
342     def whitening(self):
343         """
344         NDDataset of shape (n_components, n_features).
345 
346         Only set if whiten is not None. This is the pre-whitening matrix that projects
347         data onto the first n_components principal components.
348         """
349         if self.whiten:
350             return self._fast_ica.whitening_
351
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/spectrochempy/analysis/decomposition/fast_ica.py b/spectrochempy/analysis/decomposition/fast_ica.py
--- a/spectrochempy/analysis/decomposition/fast_ica.py
+++ b/spectrochempy/analysis/decomposition/fast_ica.py
@@ -39,7 +39,7 @@
 
     :term:`ICA` (Independent Component Analysis) extracts the underlying sources of
     the variability of a set of spectra :math:`X` into the spectral profiles :math:`S^t`
-    of the underelying sources and a mixing matrix :math:`A`\ .
+    of the underlying sources and a mixing matrix :math:`A`\ .
 
     In terms of matrix equation:
 
@@ -86,7 +86,7 @@
 
     whiten = tr.Union(
         (tr.Enum(["arbitrary-variance", "unit-variance"]), tr.Bool(False)),
-        default_value="arbitrary-variance",
+        default_value="unit-variance",
         allow_none=True,
         help=(
             """Specify the whitening strategy to use.

{"golden_diff": "diff --git a/spectrochempy/analysis/decomposition/fast_ica.py b/spectrochempy/analysis/decomposition/fast_ica.py\n--- a/spectrochempy/analysis/decomposition/fast_ica.py\n+++ b/spectrochempy/analysis/decomposition/fast_ica.py\n@@ -39,7 +39,7 @@\n \n     :term:`ICA` (Independent Component Analysis) extracts the underlying sources of\n     the variability of a set of spectra :math:`X` into the spectral profiles :math:`S^t`\n-    of the underelying sources and a mixing matrix :math:`A`\\ .\n+    of the underlying sources and a mixing matrix :math:`A`\\ .\n \n     In terms of matrix equation:\n \n@@ -86,7 +86,7 @@\n \n     whiten = tr.Union(\n         (tr.Enum([\"arbitrary-variance\", \"unit-variance\"]), tr.Bool(False)),\n-        default_value=\"arbitrary-variance\",\n+        default_value=\"unit-variance\",\n         allow_none=True,\n         help=(\n             \"\"\"Specify the whitening strategy to use.\n", "issue": "[Bug]: Install dependencies for testing: Could not build wheels for ruamel.yaml\n### What happened?\n\nThe install dependencies for testing fails due to ruamel.yaml package, see: \r\n\r\nhttps://github.com/spectrochempy/spectrochempy/actions/runs/7918492722/job/21660419471?pr=734\r\nhttps://github.com/spectrochempy/spectrochempy/actions/runs/7918492722/job/21660419097?pr=734\n\n### What did you expect to happen?\n\nthe install should go smoothly\n\n### Minimal Complete Verifiable Example\n\n_No response_\n\n### Relevant log output\n\n_No response_\n\n### Anything else we need to know?\n\n_No response_\n\n### Environment\n\nN/A\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# ======================================================================================\n# Copyright (\u00a9) 2015-2023 LCS - Laboratoire Catalyse et Spectrochimie, Caen, France.\n# CeCILL-B FREE SOFTWARE LICENSE AGREEMENT\n# See full LICENSE agreement in the root directory.\n# ======================================================================================\n\"\"\"\nImplementation of FastICA model (using scikit-learn library)\n\"\"\"\n\nimport traitlets as tr\nfrom numpy.random import RandomState\nfrom sklearn import decomposition\n\nfrom spectrochempy.analysis._base._analysisbase import (\n    DecompositionAnalysis,\n    _wrap_ndarray_output_to_nddataset,\n)\nfrom spectrochempy.utils.decorators import signature_has_configurable_traits\nfrom spectrochempy.utils.docstrings import _docstring\nfrom spectrochempy.utils.traits import NDDatasetType\n\n__all__ = [\"FastICA\"]\n__configurables__ = [\"FastICA\"]\n\n\n# ======================================================================================\n# class FastICA\n# ======================================================================================\n@signature_has_configurable_traits\nclass FastICA(DecompositionAnalysis):\n    _docstring.delete_params(\"DecompositionAnalysis.see_also\", \"FastICA\")\n\n    __doc__ = _docstring.dedent(\n        r\"\"\"\n    Fast algorithm for Independent Component Analysis (FastICA).\n\n    A wrapper of `sklearn.decomposition.FastICA`\\ .\n\n    :term:`ICA` (Independent Component Analysis) extracts the underlying sources of\n    the variability of a set of spectra :math:`X` into the spectral profiles :math:`S^t`\n    of the underelying sources and a mixing matrix :math:`A`\\ .\n\n    In terms of matrix equation:\n\n    .. math:: X = \\bar{X} + A \\cdot S^t + E\n\n    where :math:`\\bar{X}` is the mean of the dataset and :math:`E` is the matrix of\n    residuals.\n\n    Parameters\n    ----------\n    %(AnalysisConfigurable.parameters)s\n\n    See Also\n    --------\n    %(DecompositionAnalysis.see_also.no_FastICA)s\n    \"\"\"\n    )\n\n    # ----------------------------------------------------------------------------------\n    # Runtime Parameters,\n    # only those specific to FastICA, the other being defined in AnalysisConfigurable.\n    # ----------------------------------------------------------------------------------\n    # define here only the variable that you use in fit or transform functions\n    _fastica = tr.Instance(\n        decomposition.FastICA,\n        help=\"The instance of sklearn.decomposition.FastICA used in this model\",\n    )\n\n    # ----------------------------------------------------------------------------------\n    # Configuration parameters\n    # ----------------------------------------------------------------------------------\n\n    n_components = tr.Integer(\n        default_value=None,\n        allow_none=True,\n        help=\"Number of components (sources) to use.\",\n    ).tag(config=True)\n\n    algorithm = tr.Enum(\n        [\"parallel\", \"deflation\"],\n        default_value=\"parallel\",\n        help=(\"\"\"Specify which algorithm to use for FastICA.\"\"\"),\n    ).tag(config=True)\n\n    whiten = tr.Union(\n        (tr.Enum([\"arbitrary-variance\", \"unit-variance\"]), tr.Bool(False)),\n        default_value=\"arbitrary-variance\",\n        allow_none=True,\n        help=(\n            \"\"\"Specify the whitening strategy to use.\n\n- ``\"arbitrary-variance\"``\\ : a whitening with variance arbitrary is used.\n- \"unit-variance\" : the whitening matrix is rescaled to ensure that each recovered\n  source has unit variance.\n- False : the data is already considered to be whitened, and no whitening is performed.\n\"\"\"\n        ),\n    ).tag(config=True)\n\n    fun = tr.Union(\n        (tr.Enum([\"logcosh\", \"exp\", \"cube\"]), tr.Callable(), tr.Unicode()),\n        default_value=\"logcosh\",\n        allow_none=True,\n        help=(\n            r\"\"\"The functional form of the function used in the approximation to neg-entropy.\n\n- ``string``\\ : could be either ``\"logcosh\"``\\ , ``\"exp\"``\\ , or ``\"cube\"``\\ .\n- ``callable``\\ : You can provide your own function. It should return a tuple containing\n  the value of the function, and of its derivative, in the point. The derivative should\n  be averaged along its last dimension.\n\n.. code-block::\n\n    def my_g(x):\n        return x ** 3, (3 * x ** 2).mean(axis=-1)\n\n.. note::\n    ``fun`` can be also a serialized function created using dill and base64\n    python libraries. Normally not used directly, it is here for internal\n    process. \"\"\"\n        ),\n    ).tag(config=True)\n\n    fun_args = tr.Dict(\n        default_value=None,\n        allow_none=True,\n        help=(\n            \"\"\"Arguments to send to the functional form.\n\nIf empty or None and if ``fun==\"logcosh\"`` , `fun_args` will take value\n``{alpha : 1.0}``.\"\"\"\n        ),\n    ).tag(config=True)\n\n    tol = tr.Float(\n        default_value=1e-4,\n        help=\"Tolerance at which the un-mixing matrix is considered to have converged.\",\n    ).tag(config=True)\n\n    max_iter = tr.Integer(\n        default_value=200, help=\"Maximum number of iterations before timing out.\"\n    ).tag(config=True)\n\n    w_init = tr.Union(\n        (NDDatasetType(),),\n        default_value=None,\n        allow_none=True,\n        help=(\n            r\"\"\"Initial un-mixing array.\n\nNDDataset or array-like of shape (n_components, n_components). If w_init=None, then an\narray of values drawn from a normal distribution is used.\"\"\"\n        ),\n    ).tag(config=True)\n\n    whiten_solver = tr.Enum(\n        [\"svd\", \"eigh\"],\n        default_value=\"svd\",\n        help=(\n            \"\"\"The solver to use for whitening.\n\n- ``\"svd\"``\\ : is more stable numerically if the problem is degenerate, and often faster\n  when :term:`n_observations` <= :term:`n_features`\\ .\n- ``\"eigh\"``\\ : is generally more memory efficient when\n  :term:`n_observations` >= :term:`n_features`\\ , and can be faster when\n  :term:`n_observations` >= 50 * :term:`n_features`\\ . \"\"\"\n        ),\n    ).tag(config=True)\n\n    random_state = tr.Union(\n        (tr.Integer(), tr.Instance(RandomState)),\n        allow_none=True,\n        default_value=None,\n        help=(\n            \"Used to initialize ``w_init`` when not specified, with a normal\"\n            \"distribution. Pass an ``int``, for reproducible results across \"\n            \"multiple function calls.\"\n        ),\n    ).tag(config=True)\n\n    # ----------------------------------------------------------------------------------\n    # Initialization\n    # ----------------------------------------------------------------------------------\n    def __init__(\n        self,\n        *,\n        log_level=\"WARNING\",\n        warm_start=False,\n        **kwargs,\n    ):\n        # call the super class for initialisation of the configuration parameters\n        # to do before anything else!\n        super().__init__(\n            log_level=log_level,\n            warm_start=warm_start,\n            **kwargs,\n        )\n\n        # initialize sklearn Fast!ICA\n        self._fast_ica = decomposition.FastICA(\n            n_components=self.n_components,\n            algorithm=self.algorithm,\n            whiten=self.whiten,\n            fun=self.fun,\n            fun_args=self.fun_args,\n            tol=self.tol,\n            max_iter=self.max_iter,\n            w_init=self.w_init,\n            whiten_solver=self.whiten_solver,\n            random_state=self.random_state,\n        )\n\n    # ----------------------------------------------------------------------------------\n    # Private methods (overloading abstract classes)\n    # ----------------------------------------------------------------------------------\n    def _fit(self, X, Y=None):\n        # this method is called by the abstract class fit.\n        # Input X is a np.ndarray\n        # Y is ignored in this model\n\n        # call the sklearn _fit function on data\n        # _outfit is a tuple handle the eventual output of _fit for further processing.\n\n        # The _outfit members are np.ndarrays\n        _outfit = self._fast_ica.fit(X)\n        self._n_components = int(\n            self._fast_ica.n_components\n        )  # cast the returned int64 to int\n        return _outfit\n\n    def _transform(self, X):\n        return self._fast_ica.transform(X)\n\n    def _inverse_transform(self, X_transform):\n        # we need to  set self._fast_ica.components_ to a compatible size but without\n        # destroying the full matrix:\n        store_components_ = self._fast_ica.components_\n        self._fast_ica.components_ = self._fast_ica.components_[: X_transform.shape[1]]\n        X = self._fast_ica.inverse_transform(X_transform)\n        # restore\n        self._fast_ica.components_ = store_components_\n        return X\n\n    def _get_components(self):\n        self._components = self._fast_ica.components_\n        return self._components\n\n    _docstring.keep_params(\"analysis_fit.parameters\", \"X\")\n\n    @_docstring.dedent\n    def fit(self, X):\n        \"\"\"\n        Fit the FastICA model on X.\n\n        Parameters\n        ----------\n        %(analysis_fit.parameters.X)s\n\n        Returns\n        -------\n        %(analysis_fit.returns)s\n\n        See Also\n        --------\n        %(analysis_fit.see_also)s\n        \"\"\"\n        return super().fit(X, Y=None)\n\n    @property\n    @_wrap_ndarray_output_to_nddataset(\n        units=None, title=None, typey=\"features\", typex=\"components\"\n    )\n    def mixing(self):\n        \"\"\"\n        The pseudo inverse of components.\n\n        NDDataset of size (`n_features`\\ , `n_components`\\ ). It is the linear operator\n        that maps independent sources to the data, and the transpose of `St`\\ .\n        \"\"\"\n        return self._fast_ica.mixing_\n\n    @property\n    @_wrap_ndarray_output_to_nddataset(\n        units=None,\n        title=None,\n        typey=\"components\",\n    )\n    def St(self):\n        \"\"\"\n        The spectral profiles of the independant sources.\n\n        NDDataset of size (`n_components`\\ , `n_features`\\ ). It is the transpose of the\n        ``mixing_`` matrix returned by Scikit-Learn.\n        \"\"\"\n        return self._fast_ica.mixing_.T\n\n    @property\n    @_wrap_ndarray_output_to_nddataset(\n        units=None,\n        title=None,\n        typex=\"components\",\n    )\n    def A(self):\n        \"\"\"\n        The mixing system A.\n\n        NDDataset of size (`n_observations`\\ , `n_components`\\ ). It is the matrix\n        returned by the `transform()` method.\n        \"\"\"\n        return self._fast_ica.transform(self.X.data)\n\n    @property\n    @_wrap_ndarray_output_to_nddataset()\n    def mean(self):\n        \"\"\"\n        The mean of X over features.\n\n        Only set if `whiten` is True, it is needed (and used) to reconstruct a dataset\n        by ``inverse_transform(A)``\\ .\n        \"\"\"\n        return self._fast_ica.mean_\n\n    @property\n    def n_iter(self):\n        \"\"\"\n        Number of iterations.\n\n        If the algorithm is \u201cdeflation\u201d, n_iter is the maximum number of iterations run\n        across all components. Else they are just the number of iterations taken to\n        converge.\n        \"\"\"\n        return self._fast_ica.n_iter_\n\n    @property\n    @_wrap_ndarray_output_to_nddataset(\n        units=None,\n        title=None,\n        typey=\"components\",\n    )\n    def whitening(self):\n        \"\"\"\n        NDDataset of shape (n_components, n_features).\n\n        Only set if whiten is not None. This is the pre-whitening matrix that projects\n        data onto the first n_components principal components.\n        \"\"\"\n        if self.whiten:\n            return self._fast_ica.whitening_\n", "path": "spectrochempy/analysis/decomposition/fast_ica.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# ======================================================================================\n# Copyright (\u00a9) 2015-2023 LCS - Laboratoire Catalyse et Spectrochimie, Caen, France.\n# CeCILL-B FREE SOFTWARE LICENSE AGREEMENT\n# See full LICENSE agreement in the root directory.\n# ======================================================================================\n\"\"\"\nImplementation of FastICA model (using scikit-learn library)\n\"\"\"\n\nimport traitlets as tr\nfrom numpy.random import RandomState\nfrom sklearn import decomposition\n\nfrom spectrochempy.analysis._base._analysisbase import (\n    DecompositionAnalysis,\n    _wrap_ndarray_output_to_nddataset,\n)\nfrom spectrochempy.utils.decorators import signature_has_configurable_traits\nfrom spectrochempy.utils.docstrings import _docstring\nfrom spectrochempy.utils.traits import NDDatasetType\n\n__all__ = [\"FastICA\"]\n__configurables__ = [\"FastICA\"]\n\n\n# ======================================================================================\n# class FastICA\n# ======================================================================================\n@signature_has_configurable_traits\nclass FastICA(DecompositionAnalysis):\n    _docstring.delete_params(\"DecompositionAnalysis.see_also\", \"FastICA\")\n\n    __doc__ = _docstring.dedent(\n        r\"\"\"\n    Fast algorithm for Independent Component Analysis (FastICA).\n\n    A wrapper of `sklearn.decomposition.FastICA`\\ .\n\n    :term:`ICA` (Independent Component Analysis) extracts the underlying sources of\n    the variability of a set of spectra :math:`X` into the spectral profiles :math:`S^t`\n    of the underlying sources and a mixing matrix :math:`A`\\ .\n\n    In terms of matrix equation:\n\n    .. math:: X = \\bar{X} + A \\cdot S^t + E\n\n    where :math:`\\bar{X}` is the mean of the dataset and :math:`E` is the matrix of\n    residuals.\n\n    Parameters\n    ----------\n    %(AnalysisConfigurable.parameters)s\n\n    See Also\n    --------\n    %(DecompositionAnalysis.see_also.no_FastICA)s\n    \"\"\"\n    )\n\n    # ----------------------------------------------------------------------------------\n    # Runtime Parameters,\n    # only those specific to FastICA, the other being defined in AnalysisConfigurable.\n    # ----------------------------------------------------------------------------------\n    # define here only the variable that you use in fit or transform functions\n    _fastica = tr.Instance(\n        decomposition.FastICA,\n        help=\"The instance of sklearn.decomposition.FastICA used in this model\",\n    )\n\n    # ----------------------------------------------------------------------------------\n    # Configuration parameters\n    # ----------------------------------------------------------------------------------\n\n    n_components = tr.Integer(\n        default_value=None,\n        allow_none=True,\n        help=\"Number of components (sources) to use.\",\n    ).tag(config=True)\n\n    algorithm = tr.Enum(\n        [\"parallel\", \"deflation\"],\n        default_value=\"parallel\",\n        help=(\"\"\"Specify which algorithm to use for FastICA.\"\"\"),\n    ).tag(config=True)\n\n    whiten = tr.Union(\n        (tr.Enum([\"arbitrary-variance\", \"unit-variance\"]), tr.Bool(False)),\n        default_value=\"unit-variance\",\n        allow_none=True,\n        help=(\n            \"\"\"Specify the whitening strategy to use.\n\n- ``\"arbitrary-variance\"``\\ : a whitening with variance arbitrary is used.\n- \"unit-variance\" : the whitening matrix is rescaled to ensure that each recovered\n  source has unit variance.\n- False : the data is already considered to be whitened, and no whitening is performed.\n\"\"\"\n        ),\n    ).tag(config=True)\n\n    fun = tr.Union(\n        (tr.Enum([\"logcosh\", \"exp\", \"cube\"]), tr.Callable(), tr.Unicode()),\n        default_value=\"logcosh\",\n        allow_none=True,\n        help=(\n            r\"\"\"The functional form of the function used in the approximation to neg-entropy.\n\n- ``string``\\ : could be either ``\"logcosh\"``\\ , ``\"exp\"``\\ , or ``\"cube\"``\\ .\n- ``callable``\\ : You can provide your own function. It should return a tuple containing\n  the value of the function, and of its derivative, in the point. The derivative should\n  be averaged along its last dimension.\n\n.. code-block::\n\n    def my_g(x):\n        return x ** 3, (3 * x ** 2).mean(axis=-1)\n\n.. note::\n    ``fun`` can be also a serialized function created using dill and base64\n    python libraries. Normally not used directly, it is here for internal\n    process. \"\"\"\n        ),\n    ).tag(config=True)\n\n    fun_args = tr.Dict(\n        default_value=None,\n        allow_none=True,\n        help=(\n            \"\"\"Arguments to send to the functional form.\n\nIf empty or None and if ``fun==\"logcosh\"`` , `fun_args` will take value\n``{alpha : 1.0}``.\"\"\"\n        ),\n    ).tag(config=True)\n\n    tol = tr.Float(\n        default_value=1e-4,\n        help=\"Tolerance at which the un-mixing matrix is considered to have converged.\",\n    ).tag(config=True)\n\n    max_iter = tr.Integer(\n        default_value=200, help=\"Maximum number of iterations before timing out.\"\n    ).tag(config=True)\n\n    w_init = tr.Union(\n        (NDDatasetType(),),\n        default_value=None,\n        allow_none=True,\n        help=(\n            r\"\"\"Initial un-mixing array.\n\nNDDataset or array-like of shape (n_components, n_components). If w_init=None, then an\narray of values drawn from a normal distribution is used.\"\"\"\n        ),\n    ).tag(config=True)\n\n    whiten_solver = tr.Enum(\n        [\"svd\", \"eigh\"],\n        default_value=\"svd\",\n        help=(\n            \"\"\"The solver to use for whitening.\n\n- ``\"svd\"``\\ : is more stable numerically if the problem is degenerate, and often faster\n  when :term:`n_observations` <= :term:`n_features`\\ .\n- ``\"eigh\"``\\ : is generally more memory efficient when\n  :term:`n_observations` >= :term:`n_features`\\ , and can be faster when\n  :term:`n_observations` >= 50 * :term:`n_features`\\ . \"\"\"\n        ),\n    ).tag(config=True)\n\n    random_state = tr.Union(\n        (tr.Integer(), tr.Instance(RandomState)),\n        allow_none=True,\n        default_value=None,\n        help=(\n            \"Used to initialize ``w_init`` when not specified, with a normal\"\n            \"distribution. Pass an ``int``, for reproducible results across \"\n            \"multiple function calls.\"\n        ),\n    ).tag(config=True)\n\n    # ----------------------------------------------------------------------------------\n    # Initialization\n    # ----------------------------------------------------------------------------------\n    def __init__(\n        self,\n        *,\n        log_level=\"WARNING\",\n        warm_start=False,\n        **kwargs,\n    ):\n        # call the super class for initialisation of the configuration parameters\n        # to do before anything else!\n        super().__init__(\n            log_level=log_level,\n            warm_start=warm_start,\n            **kwargs,\n        )\n\n        # initialize sklearn Fast!ICA\n        self._fast_ica = decomposition.FastICA(\n            n_components=self.n_components,\n            algorithm=self.algorithm,\n            whiten=self.whiten,\n            fun=self.fun,\n            fun_args=self.fun_args,\n            tol=self.tol,\n            max_iter=self.max_iter,\n            w_init=self.w_init,\n            whiten_solver=self.whiten_solver,\n            random_state=self.random_state,\n        )\n\n    # ----------------------------------------------------------------------------------\n    # Private methods (overloading abstract classes)\n    # ----------------------------------------------------------------------------------\n    def _fit(self, X, Y=None):\n        # this method is called by the abstract class fit.\n        # Input X is a np.ndarray\n        # Y is ignored in this model\n\n        # call the sklearn _fit function on data\n        # _outfit is a tuple handle the eventual output of _fit for further processing.\n\n        # The _outfit members are np.ndarrays\n        _outfit = self._fast_ica.fit(X)\n        self._n_components = int(\n            self._fast_ica.n_components\n        )  # cast the returned int64 to int\n        return _outfit\n\n    def _transform(self, X):\n        return self._fast_ica.transform(X)\n\n    def _inverse_transform(self, X_transform):\n        # we need to  set self._fast_ica.components_ to a compatible size but without\n        # destroying the full matrix:\n        store_components_ = self._fast_ica.components_\n        self._fast_ica.components_ = self._fast_ica.components_[: X_transform.shape[1]]\n        X = self._fast_ica.inverse_transform(X_transform)\n        # restore\n        self._fast_ica.components_ = store_components_\n        return X\n\n    def _get_components(self):\n        self._components = self._fast_ica.components_\n        return self._components\n\n    _docstring.keep_params(\"analysis_fit.parameters\", \"X\")\n\n    @_docstring.dedent\n    def fit(self, X):\n        \"\"\"\n        Fit the FastICA model on X.\n\n        Parameters\n        ----------\n        %(analysis_fit.parameters.X)s\n\n        Returns\n        -------\n        %(analysis_fit.returns)s\n\n        See Also\n        --------\n        %(analysis_fit.see_also)s\n        \"\"\"\n        return super().fit(X, Y=None)\n\n    @property\n    @_wrap_ndarray_output_to_nddataset(\n        units=None, title=None, typey=\"features\", typex=\"components\"\n    )\n    def mixing(self):\n        \"\"\"\n        The pseudo inverse of components.\n\n        NDDataset of size (`n_features`\\ , `n_components`\\ ). It is the linear operator\n        that maps independent sources to the data, and the transpose of `St`\\ .\n        \"\"\"\n        return self._fast_ica.mixing_\n\n    @property\n    @_wrap_ndarray_output_to_nddataset(\n        units=None,\n        title=None,\n        typey=\"components\",\n    )\n    def St(self):\n        \"\"\"\n        The spectral profiles of the independant sources.\n\n        NDDataset of size (`n_components`\\ , `n_features`\\ ). It is the transpose of the\n        ``mixing_`` matrix returned by Scikit-Learn.\n        \"\"\"\n        return self._fast_ica.mixing_.T\n\n    @property\n    @_wrap_ndarray_output_to_nddataset(\n        units=None,\n        title=None,\n        typex=\"components\",\n    )\n    def A(self):\n        \"\"\"\n        The mixing system A.\n\n        NDDataset of size (`n_observations`\\ , `n_components`\\ ). It is the matrix\n        returned by the `transform()` method.\n        \"\"\"\n        return self._fast_ica.transform(self.X.data)\n\n    @property\n    @_wrap_ndarray_output_to_nddataset()\n    def mean(self):\n        \"\"\"\n        The mean of X over features.\n\n        Only set if `whiten` is True, it is needed (and used) to reconstruct a dataset\n        by ``inverse_transform(A)``\\ .\n        \"\"\"\n        return self._fast_ica.mean_\n\n    @property\n    def n_iter(self):\n        \"\"\"\n        Number of iterations.\n\n        If the algorithm is \u201cdeflation\u201d, n_iter is the maximum number of iterations run\n        across all components. Else they are just the number of iterations taken to\n        converge.\n        \"\"\"\n        return self._fast_ica.n_iter_\n\n    @property\n    @_wrap_ndarray_output_to_nddataset(\n        units=None,\n        title=None,\n        typey=\"components\",\n    )\n    def whitening(self):\n        \"\"\"\n        NDDataset of shape (n_components, n_features).\n\n        Only set if whiten is not None. This is the pre-whitening matrix that projects\n        data onto the first n_components principal components.\n        \"\"\"\n        if self.whiten:\n            return self._fast_ica.whitening_\n", "path": "spectrochempy/analysis/decomposition/fast_ica.py"}]}