def __init__(
        self,
        add_encoders: dict,
        input_chunk_length: Optional[int] = None,
        output_chunk_length: Optional[int] = None,
        lags_past_covariates: Optional[list[int]] = None,
        lags_future_covariates: Optional[list[int]] = None,
        takes_past_covariates: bool = False,
        takes_future_covariates: bool = False,
    ) -> None:
        """
        SequentialEncoder automatically creates encoder objects from parameter `add_encoders`. `add_encoders` can also
        be set directly in all of Darts' `ForecastingModels`. This will automatically set up a
        :class:`SequentialEncoder` tailored to the settings of the underlying forecasting model.

        The `add_encoders` dict must follow this convention:
            `{encoder keyword: {temporal keyword: List[attributes]}, ..., transformer keyword: transformer object}`
        Supported encoder keywords:
            `'cyclic'` for cyclic temporal encoder. See the docs
            :meth:`CyclicTemporalEncoder <darts.dataprocessing.encoders.CyclicTemporalEncoder>`;
            `'datetime_attribute'` for adding scalar information of pd.DatetimeIndex attribute. See the docs
            :meth:`DatetimeAttributeEncoder <darts.dataprocessing.encoders.DatetimeAttributeEncoder>`
            `'position'` for integer index position encoder. See the docs
            :meth:`IntegerIndexEncoder <darts.dataprocessing.encoders.IntegerIndexEncoder>`;
            `'custom'` for encoding index with custom callables (functions). See the docs
            :meth:`CallableIndexEncoder <darts.dataprocessing.encoders.CallableIndexEncoder>`;
        Supported temporal keywords:
            'past' for adding encoding as past covariates
            'future' for adding encoding as future covariates
        Supported attributes:
            for attributes read the referred docs for the corresponding encoder from above
        Supported transformers:
            a transformer can be added with transformer keyword 'transformer'. The transformer object must be an
            instance of Darts' :meth:`FittableDataTransformer
            <darts.dataprocessing.transformers.fittable_data_transformer.FittableDataTransformer>` such as Scaler() or
            BoxCox(). The transformers will be fitted on the training dataset when calling calling `model.fit()`.
            The training, validation and inference datasets are then transformed equally.
        Supported time zone:
            Optionally, apply a time zone conversion with keyword 'tz'. This converts the time zone-naive index to a
            timezone `'tz'` before applying the `'cyclic'` or `'datetime_attribute'` temporal encoders.

        An example of a valid `add_encoders` dict for hourly data:

            .. highlight:: python
            .. code-block:: python

                from darts.dataprocessing.transformers import Scaler
                add_encoders={
                    'cyclic': {'future': ['month']},
                    'datetime_attribute': {'past': ['hour'], 'future': ['year', 'dayofweek']},
                    'position': {'past': ['relative'], 'future': ['relative']},
                    'custom': {'past': [lambda idx: (idx.year - 1950) / 50]},
                    'transformer': Scaler(),
                    'tz': 'CET',
                }

        Tuples of `(encoder_id, attribute)` are extracted from `add_encoders` to instantiate the `SingleEncoder`
        objects:

        * The `encoder_id` is extracted as follows:
            str(encoder_kw) + str(temporal_kw) -> 'cyclic' + 'past' -> `encoder_id` = 'cyclic_past'
            The `encoder_id` is used to map the parameters with the corresponding `SingleEncoder` objects.
        * The `attribute` is extracted from the values given by values under `temporal_kw`
            `attribute` = 'month'
            ...
            The `attribute` tells the `SingleEncoder` which attribute of the index to encode

        New encoders can be added by appending them to the mapping property `SequentialEncoder.encoder_map()`

        Parameters
        ----------
        add_encoders
            A dictionary with the encoder settings.
        input_chunk_length
            Optionally, the number of input target time steps per chunk. Only required for
            :class:`TorchForecastingModel`, and :class:`SKLearnModel`.
            Corresponds to parameter `input_chunk_length` from :class:`TorchForecastingModel`, or to the absolute
            minimum target lag value `abs(min(lags))` for :class:`SKLearnModel`.
        output_chunk_length
            Optionally, the number of output target time steps per chunk. Only required for
            :class:`TorchForecastingModel`, and :class:`SKLearnModel`.
            Corresponds to parameter `output_chunk_length` from both :class:`TorchForecastingModel`, and
            :class:`SKLearnModel`.
        lags_past_covariates
            Optionally, a list of integers representing the past covariate lags. Accepts integer lag values <= -1.
            Only required for :class:`SKLearnModel`.
            Corresponds to the lag values from parameter `lags_past_covariates` of :class:`SKLearnModel`.
        lags_future_covariates
            Optionally, a list of integers representing the future covariate lags. Accepts all integer values.
            Only required for :class:`SKLearnModel`.
            Corresponds to the lag values from parameter `lags_future_covariates` from :class:`SKLearnModel`.
        takes_past_covariates
            Whether to encode/generate past covariates.
        takes_future_covariates
            Whether to encode/generate future covariates.
        """
        super().__init__()
        self.params = add_encoders
        self.input_chunk_length = input_chunk_length
        self.output_chunk_length = output_chunk_length
        self.encoding_available = False
        self.takes_past_covariates = takes_past_covariates
        self.takes_future_covariates = takes_future_covariates
        self.lags_past_covariates = lags_past_covariates
        self.lags_future_covariates = lags_future_covariates

        # encoders
        self._past_encoders: list[SingleEncoder] = []
        self._past_components: pd.Index = pd.Index([])
        self._future_encoders: list[SingleEncoder] = []
        self._future_components: pd.Index = pd.Index([])

        # transformer
        self._past_transformer: Optional[SequentialEncoderTransformer] = None
        self._future_transformer: Optional[SequentialEncoderTransformer] = None

        # setup encoders and transformer
        self._setup_encoders(self.params)
        self._setup_transformer(self.params)

        SequentialEncoder automatically creates encoder objects from parameter `add_encoders`. `add_encoders` can also
        be set directly in all of Darts' `ForecastingModels`. This will automatically set up a
        :class:`SequentialEncoder` tailored to the settings of the underlying forecasting model.

        The `add_encoders` dict must follow this convention:
            `{encoder keyword: {temporal keyword: List[attributes]}, ..., transformer keyword: transformer object}`
        Supported encoder keywords:
            `'cyclic'` for cyclic temporal encoder. See the docs
            :meth:`CyclicTemporalEncoder <darts.dataprocessing.encoders.CyclicTemporalEncoder>`;
            `'datetime_attribute'` for adding scalar information of pd.DatetimeIndex attribute. See the docs
            :meth:`DatetimeAttributeEncoder <darts.dataprocessing.encoders.DatetimeAttributeEncoder>`
            `'position'` for integer index position encoder. See the docs
            :meth:`IntegerIndexEncoder <darts.dataprocessing.encoders.IntegerIndexEncoder>`;
            `'custom'` for encoding index with custom callables (functions). See the docs
            :meth:`CallableIndexEncoder <darts.dataprocessing.encoders.CallableIndexEncoder>`;
        Supported temporal keywords:
            'past' for adding encoding as past covariates
            'future' for adding encoding as future covariates
        Supported attributes:
            for attributes read the referred docs for the corresponding encoder from above
        Supported transformers:
            a transformer can be added with transformer keyword 'transformer'. The transformer object must be an
            instance of Darts' :meth:`FittableDataTransformer
            <darts.dataprocessing.transformers.fittable_data_transformer.FittableDataTransformer>` such as Scaler() or
            BoxCox(). The transformers will be fitted on the training dataset when calling calling `model.fit()`.
            The training, validation and inference datasets are then transformed equally.
        Supported time zone:
            Optionally, apply a time zone conversion with keyword 'tz'. This converts the time zone-naive index to a
            timezone `'tz'` before applying the `'cyclic'` or `'datetime_attribute'` temporal encoders.

        An example of a valid `add_encoders` dict for hourly data:

            .. highlight:: python
            .. code-block:: python

                from darts.dataprocessing.transformers import Scaler
                add_encoders={
                    'cyclic': {'future': ['month']},
                    'datetime_attribute': {'past': ['hour'], 'future': ['year', 'dayofweek']},
                    'position': {'past': ['relative'], 'future': ['relative']},
                    'custom': {'past': [lambda idx: (idx.year - 1950) / 50]},
                    'transformer': Scaler(),
                    'tz': 'CET',
                }

        Tuples of `(encoder_id, attribute)` are extracted from `add_encoders` to instantiate the `SingleEncoder`
        objects:

        * The `encoder_id` is extracted as follows:
            str(encoder_kw) + str(temporal_kw) -> 'cyclic' + 'past' -> `encoder_id` = 'cyclic_past'
            The `encoder_id` is used to map the parameters with the corresponding `SingleEncoder` objects.
        * The `attribute` is extracted from the values given by values under `temporal_kw`
            `attribute` = 'month'
            ...
            The `attribute` tells the `SingleEncoder` which attribute of the index to encode

        New encoders can be added by appending them to the mapping property `SequentialEncoder.encoder_map()`

        Parameters
        ----------
        add_encoders
            A dictionary with the encoder settings.
        input_chunk_length
            Optionally, the number of input target time steps per chunk. Only required for
            :class:`TorchForecastingModel`, and :class:`SKLearnModel`.
            Corresponds to parameter `input_chunk_length` from :class:`TorchForecastingModel`, or to the absolute
            minimum target lag value `abs(min(lags))` for :class:`SKLearnModel`.
        output_chunk_length
            Optionally, the number of output target time steps per chunk. Only required for
            :class:`TorchForecastingModel`, and :class:`SKLearnModel`.
            Corresponds to parameter `output_chunk_length` from both :class:`TorchForecastingModel`, and
            :class:`SKLearnModel`.
        lags_past_covariates
            Optionally, a list of integers representing the past covariate lags. Accepts integer lag values <= -1.
            Only required for :class:`SKLearnModel`.
            Corresponds to the lag values from parameter `lags_past_covariates` of :class:`SKLearnModel`.
        lags_future_covariates
            Optionally, a list of integers representing the future covariate lags. Accepts all integer values.
            Only required for :class:`SKLearnModel`.
            Corresponds to the lag values from parameter `lags_future_covariates` from :class:`SKLearnModel`.
        takes_past_covariates
            Whether to encode/generate past covariates.
        takes_future_covariates
            Whether to encode/generate future covariates.
        
darts/dataprocessing/encoders/encoders.py