def test_explainer_multiple_multivariate_series(self, test_case):
        """Test TFTExplainer with multiple multivaraites series and a combination of encoders, covariates,
        and addition of relative index."""
        series_option, cov_option, add_relative_idx, use_encoders = test_case
        series, pc, fc = self.helper_get_input(series_option)
        cov_test_case = dict()
        use_pc, use_fc = False, False
        if "past_covariates" in cov_option:
            cov_test_case["past_covariates"] = pc
            use_pc = True
        if "future_covariates" in cov_option:
            cov_test_case["future_covariates"] = fc
            use_fc = True

        # expected number of features for past covs, future covs, and static covs, and encoder/decoder
        n_target_expected = series[0].n_components
        n_pc_expected = 1 if "past_covariates" in cov_test_case else 0
        n_fc_expected = 1 if "future_covariates" in cov_test_case else 0
        n_sc_expected = 2
        # encoder is number of past and future covs plus 4 optional encodings (future and past)
        # plus 1 univariate target plus 1 optional relative index
        n_enc_expected = (
            n_pc_expected
            + n_fc_expected
            + n_target_expected
            + (4 if use_encoders else 0)
            + (1 if add_relative_idx else 0)
        )
        # encoder is number of future covs plus 2 optional encodings (future)
        # plus 1 optional relative index
        n_dec_expected = (
            n_fc_expected + (2 if use_encoders else 0) + (1 if add_relative_idx else 0)
        )
        model = self.helper_create_model(
            use_encoders=use_encoders, add_relative_idx=add_relative_idx
        )
        # TFTModel requires future covariates
        if (
            not add_relative_idx
            and "future_covariates" not in cov_test_case
            and not use_encoders
        ):
            with pytest.raises(ValueError):
                model.fit(series=series, **cov_test_case)
            return

        model.fit(series=series, **cov_test_case)
        # explainer requires background if model trained on multiple time series
        with pytest.raises(ValueError):
            explainer = TFTExplainer(model)
        explainer = TFTExplainer(
            model,
            background_series=series,
            background_past_covariates=pc if use_pc else None,
            background_future_covariates=fc if use_fc else None,
        )
        assert hasattr(explainer, "model")
        assert explainer.background_series, series
        if use_pc:
            assert explainer.background_past_covariates == pc
            assert explainer.background_past_covariates[0].n_components == n_pc_expected
        else:
            assert explainer.background_past_covariates is None
        if use_fc:
            assert explainer.background_future_covariates == fc
            assert (
                explainer.background_future_covariates[0].n_components == n_fc_expected
            )
        else:
            assert explainer.background_future_covariates is None
        result = explainer.explain()
        assert isinstance(result, TFTExplainabilityResult)

        enc_imp = result.get_encoder_importance()
        dec_imp = result.get_decoder_importance()
        stc_imp = result.get_static_covariates_importance()
        imps = [enc_imp, dec_imp, stc_imp]
        assert all([isinstance(imp, list) for imp in imps])
        assert all([len(imp) == len(series) for imp in imps])
        assert all([isinstance(imp_, pd.DataFrame) for imp in imps for imp_ in imp])
        # importances must sum up to 100 percent
        assert all([
            imp_.squeeze().sum() == pytest.approx(100.0, abs=0.21)
            for imp in imps
            for imp_ in imp
        ])
        # importances must have the expected number of columns
        assert all([
            len(imp_.columns) == n
            for imp, n in zip(imps, [n_enc_expected, n_dec_expected, n_sc_expected])
            for imp_ in imp
        ])

        attention = result.get_attention()
        assert isinstance(attention, list)
        assert len(attention) == len(series)
        assert all([isinstance(att, TimeSeries) for att in attention])
        # input chunk length + output chunk length = 5 + 2 = 7
        icl, ocl = 5, 2
        freq = series[0].freq
        assert all([len(att) == icl + ocl for att in attention])
        assert all([
            att.start_time() == series_.end_time() - (icl - 1) * freq
            for att, series_ in zip(attention, series)
        ])
        assert all([
            att.end_time() == series_.end_time() + ocl * freq
            for att, series_ in zip(attention, series)
        ])
        assert all([att.n_components == ocl for att in attention])
Test TFTExplainer with multiple multivaraites series and a combination of encoders, covariates,
        and addition of relative index.
darts/tests/explainability/test_tft_explainer.py