def __init__(
        self,
        name: str = "BaseDataTransformer",
        n_jobs: int = 1,
        verbose: bool = False,
        parallel_params: Union[bool, Sequence[str]] = False,
        mask_components: bool = True,
    ):
        """Abstract class for data transformers.

        All the deriving classes have to implement the static method :func:`ts_transform`; this implemented
        method can then be applied to ``TimeSeries`` or ``Sequence[TimeSeries]`` inputs by calling the
        :func:`transform()` method. Internally, :func:`transform()` parallelizes func:`ts_transform` over all
        of the ``TimeSeries`` inputs passed to it. See the func:`ts_transform` method documentation
        for further details on how to implement this method in a user-defined class.

        Data transformers requiring to be fit first before calling :func:`transform` should derive
        from :class:`.FittableDataTransformer` instead. Data transformers that are invertible should derive
        from :class:`.InvertibleDataTransformer` instead. Transformers which are both fittable and invertible
        should inherit from both :class:`.FittableDataTransformer` and :class:`.InvertibleDataTransformer`.

        All Data Transformers can store *fixed parameters* that are automatically passed to func:`ts_transform`;
        the fixed parameters of a data transformer object are taken to be all those attributes defined
        in the `__init__` method of the child-most class *before* `super().__init__` is called. The fixed parameter
        values can then be accessed within the func:`ts_transform` method through the `params` dictionary
        argument. More specifically, `params['fixed']` stores a dictionary with all of the fixed parameter
        values, where the keys are simply the attribute names of each fixed parameter (e.g. the `self._my_param`
        fixed parameter attribute is accessed through `params['fixed']['_my_param']`).

        Data Transformers which inherit from :class:`.FittableDataTransformer` can also store fitted parameters
        alongside fixed parameters; please refer to the :class:`.FittableDataTransformer` documentation for
        further details.

        Note: the :func:`ts_transform` method is designed to be a static method instead of a instance method to allow an
        efficient parallelisation also when the scaler instance is storing a non-negligible amount of data. Using
        an instance method would imply copying the instance's data through multiple processes, which can easily
        introduce a bottleneck and nullify parallelisation benefits.

        Parameters
        ----------
        name
            The data transformer's name
        n_jobs
            The number of jobs to run in parallel. Parallel jobs are created only when a ``Sequence[TimeSeries]``
            is passed as input to a method, parallelising operations regarding different TimeSeries.
            Defaults to `1` (sequential). Setting the parameter to `-1` means using all the available processors.
            Note: for a small amount of data, the parallelisation overhead could end up increasing the total
            required amount of time.
        verbose
            Optionally, whether to print operations progress
        parallel_params
            Optionally, specifies which fixed parameters (i.e. the attributes initialized in the child-most
            class's `__init__`) take on different values for different parallel jobs. Fixed parameters specified
            by `parallel_params` are assumed to be a `Sequence` of values that should be used for that parameter
            in each parallel job; the length of this `Sequence` should equal the number of parallel jobs. If
            `parallel_params=True`, every fixed parameter will take on a different value for each
            parallel job. If `parallel_params=False`, every fixed parameter will take on the same value for
            each parallel job. If `parallel_params` is a `Sequence` of fixed attribute names, only those
            attribute names specified will take on different values between different parallel jobs.
        mask_components
            Optionally, whether to automatically apply any provided `component_mask`s to the
            `TimeSeries` inputs passed to `transform`, `fit`, `inverse_transform`, or `fit_transform`.
            If `True`, any specified `component_mask` will be applied to each input timeseries
            before passing them to the called method; the masked components will also be automatically
            'unmasked' in the returned `TimeSeries`. If `False`, then `component_mask` (if provided) will
            be passed as a keyword argument, but won't automatically be applied to the input timeseries.
            See `apply_component_mask` for further details.

        Example
        --------
        >>> from darts.dataprocessing.transformers import BaseDataTransformer
        >>> from darts.utils.timeseries_generation import linear_timeseries
        >>>
        >>> class SimpleTransform(BaseDataTransformer):
        >>>
        >>>         def __init__(self, a):
        >>>             self._a = a
        >>>             super().__init__()
        >>>
        >>>         @staticmethod
        >>>         def ts_transform(series, params, **kwargs):
        >>>             a = params['fixed']['_a']
        >>>             b = kwargs.pop('b')
        >>>             return a*series + b
        >>>
        >>> series = linear_timeseries(length=5)
        >>> print(series)
        <TimeSeries (DataArray) (time: 5, component: 1, sample: 1)>
        array([[[0.  ]],

            [[0.25]],

            [[0.5 ]],

            [[0.75]],

            [[1.  ]]])
        Coordinates:
        * time       (time) datetime64[ns] 2000-01-01 2000-01-02 ... 2000-01-05
        * component  (component) object 'linear'
        Dimensions without coordinates: sample
        Attributes:
            static_covariates:  None
            hierarchy:          None
        >>> series = SimpleTransform(a=2).transform(series, b=3)
        >>> print(series)
        <TimeSeries (DataArray) (time: 5, component: 1, sample: 1)>
        array([[[3. ]],

            [[3.5]],

            [[4. ]],

            [[4.5]],

            [[5. ]]])
        Coordinates:
        * time       (time) datetime64[ns] 2000-01-01 2000-01-02 ... 2000-01-05
        * component  (component) object 'linear'
        Dimensions without coordinates: sample
        Attributes:
            static_covariates:  None
            hierarchy:          None
        """
        # Assume `super().__init__` called at *very end* of
        # child-most class's `__init__`, so `vars(self)` contains
        # only attributes of this child-most class:
        self._fixed_params = vars(self).copy()
        # If `parallel_params = True`, but not a list of key values:
        if parallel_params and not isinstance(parallel_params, Sequence):
            parallel_params = self._fixed_params.keys()
        # If `parallel_params = False`:
        elif not parallel_params:
            parallel_params = tuple()
        self._parallel_params = parallel_params
        self._mask_components = mask_components
        self._name = name
        self._verbose = verbose
        self._n_jobs = n_jobs
Abstract class for data transformers.

        All the deriving classes have to implement the static method :func:`ts_transform`; this implemented
        method can then be applied to ``TimeSeries`` or ``Sequence[TimeSeries]`` inputs by calling the
        :func:`transform()` method. Internally, :func:`transform()` parallelizes func:`ts_transform` over all
        of the ``TimeSeries`` inputs passed to it. See the func:`ts_transform` method documentation
        for further details on how to implement this method in a user-defined class.

        Data transformers requiring to be fit first before calling :func:`transform` should derive
        from :class:`.FittableDataTransformer` instead. Data transformers that are invertible should derive
        from :class:`.InvertibleDataTransformer` instead. Transformers which are both fittable and invertible
        should inherit from both :class:`.FittableDataTransformer` and :class:`.InvertibleDataTransformer`.

        All Data Transformers can store *fixed parameters* that are automatically passed to func:`ts_transform`;
        the fixed parameters of a data transformer object are taken to be all those attributes defined
        in the `__init__` method of the child-most class *before* `super().__init__` is called. The fixed parameter
        values can then be accessed within the func:`ts_transform` method through the `params` dictionary
        argument. More specifically, `params['fixed']` stores a dictionary with all of the fixed parameter
        values, where the keys are simply the attribute names of each fixed parameter (e.g. the `self._my_param`
        fixed parameter attribute is accessed through `params['fixed']['_my_param']`).

        Data Transformers which inherit from :class:`.FittableDataTransformer` can also store fitted parameters
        alongside fixed parameters; please refer to the :class:`.FittableDataTransformer` documentation for
        further details.

        Note: the :func:`ts_transform` method is designed to be a static method instead of a instance method to allow an
        efficient parallelisation also when the scaler instance is storing a non-negligible amount of data. Using
        an instance method would imply copying the instance's data through multiple processes, which can easily
        introduce a bottleneck and nullify parallelisation benefits.

        Parameters
        ----------
        name
            The data transformer's name
        n_jobs
            The number of jobs to run in parallel. Parallel jobs are created only when a ``Sequence[TimeSeries]``
            is passed as input to a method, parallelising operations regarding different TimeSeries.
            Defaults to `1` (sequential). Setting the parameter to `-1` means using all the available processors.
            Note: for a small amount of data, the parallelisation overhead could end up increasing the total
            required amount of time.
        verbose
            Optionally, whether to print operations progress
        parallel_params
            Optionally, specifies which fixed parameters (i.e. the attributes initialized in the child-most
            class's `__init__`) take on different values for different parallel jobs. Fixed parameters specified
            by `parallel_params` are assumed to be a `Sequence` of values that should be used for that parameter
            in each parallel job; the length of this `Sequence` should equal the number of parallel jobs. If
            `parallel_params=True`, every fixed parameter will take on a different value for each
            parallel job. If `parallel_params=False`, every fixed parameter will take on the same value for
            each parallel job. If `parallel_params` is a `Sequence` of fixed attribute names, only those
            attribute names specified will take on different values between different parallel jobs.
        mask_components
            Optionally, whether to automatically apply any provided `component_mask`s to the
            `TimeSeries` inputs passed to `transform`, `fit`, `inverse_transform`, or `fit_transform`.
            If `True`, any specified `component_mask` will be applied to each input timeseries
            before passing them to the called method; the masked components will also be automatically
            'unmasked' in the returned `TimeSeries`. If `False`, then `component_mask` (if provided) will
            be passed as a keyword argument, but won't automatically be applied to the input timeseries.
            See `apply_component_mask` for further details.

        Example
        --------
        >>> from darts.dataprocessing.transformers import BaseDataTransformer
        >>> from darts.utils.timeseries_generation import linear_timeseries
        >>>
        >>> class SimpleTransform(BaseDataTransformer):
        >>>
        >>>         def __init__(self, a):
        >>>             self._a = a
        >>>             super().__init__()
        >>>
        >>>         @staticmethod
        >>>         def ts_transform(series, params, **kwargs):
        >>>             a = params['fixed']['_a']
        >>>             b = kwargs.pop('b')
        >>>             return a*series + b
        >>>
        >>> series = linear_timeseries(length=5)
        >>> print(series)
        <TimeSeries (DataArray) (time: 5, component: 1, sample: 1)>
        array([[[0.  ]],

            [[0.25]],

            [[0.5 ]],

            [[0.75]],

            [[1.  ]]])
        Coordinates:
        * time       (time) datetime64[ns] 2000-01-01 2000-01-02 ... 2000-01-05
        * component  (component) object 'linear'
        Dimensions without coordinates: sample
        Attributes:
            static_covariates:  None
            hierarchy:          None
        >>> series = SimpleTransform(a=2).transform(series, b=3)
        >>> print(series)
        <TimeSeries (DataArray) (time: 5, component: 1, sample: 1)>
        array([[[3. ]],

            [[3.5]],

            [[4. ]],

            [[4.5]],

            [[5. ]]])
        Coordinates:
        * time       (time) datetime64[ns] 2000-01-01 2000-01-02 ... 2000-01-05
        * component  (component) object 'linear'
        Dimensions without coordinates: sample
        Attributes:
            static_covariates:  None
            hierarchy:          None
        
darts/dataprocessing/transformers/base_data_transformer.py