def test_metric_quantile_interval(self, config):
        """Test output types and shapes for time aggregated metrics with quantile intervals:
        for single and multiple univariate or multivariate series, in combination
        with different component and series reduction functions."""
        np.random.seed(42)
        metric, is_univar, is_single = config
        params = inspect.signature(metric).parameters

        n_comp = 1 if is_univar else 2

        qs_all = [0.1, 0.5, 0.8]
        components = [str(i) for i in range(n_comp)]

        series_vals = np.random.random((10, n_comp, 1))
        pred_prob_vals = np.random.random((10, n_comp, 100))

        pred_vals_qs = []
        for i in range(n_comp):
            pred_vals_qs.append(
                np.quantile(pred_prob_vals[:, [i]], qs_all, axis=2).transpose(1, 0, 2)
            )
        pred_vals_qs = np.concatenate(pred_vals_qs, axis=1)
        pred_components = likelihood_component_names(
            components=components, parameter_names=quantile_names(q=qs_all)
        )

        series = TimeSeries.from_values(series_vals, columns=components)
        pred_prob = TimeSeries.from_values(pred_prob_vals, columns=components)
        pred_qs = TimeSeries.from_values(pred_vals_qs, columns=pred_components)
        shape_time = (len(pred_qs),) if "time_reduction" in params else tuple()

        if not is_single:
            series = [series] * 2
            pred_prob = [pred_prob] * 2
            pred_qs = [pred_qs] * 2

        kwargs = {"actual_series": series}

        def check_res(
            pred_prob_, pred_qs_, shape_exp, series_reduction=None, **test_kwargs
        ):
            res_prob = metric(
                actual_series=series,
                pred_series=pred_prob_,
                series_reduction=series_reduction,
                **test_kwargs,
            )
            res_qs = metric(
                actual_series=series,
                pred_series=pred_qs_,
                series_reduction=series_reduction,
                **test_kwargs,
            )
            if is_single or series_reduction is not None:
                res_prob = [res_prob]
                res_qs = [res_qs]
            if series_reduction is None and not is_single:
                assert len(res_prob) == len(res_qs) == len(pred_prob_)

            for res_p, res_q in zip(res_prob, res_qs):
                assert res_p.shape == res_q.shape == shape_exp
                np.testing.assert_array_almost_equal(res_p, res_q)
            return res_qs

        # one interval as tuple
        res = check_res(pred_prob, pred_qs, shape_time, q_interval=(0.1, 0.5))
        # one interval in list
        res2 = check_res(pred_prob, pred_qs, shape_time, q_interval=[(0.1, 0.5)])
        np.testing.assert_array_almost_equal(res, res2)
        # multiple intervals
        check_res(
            pred_prob, pred_qs, shape_time + (2,), q_interval=[(0.1, 0.5), (0.5, 0.8)]
        )
        # all intervals
        check_res(
            pred_prob,
            pred_qs,
            shape_time + (3,),
            q_interval=[(0.1, 0.5), (0.5, 0.8), (0.1, 0.8)],
        )
        q_intervals = [(0.1, 0.5), (0.5, 0.8)]
        # component and series reduction
        check_res(
            pred_prob,
            pred_qs,
            shape_time + (len(q_intervals),),
            q_interval=q_intervals,
            component_reduction=np.mean,
            series_reduction=np.mean,
        )
        # no component reduction
        check_res(
            pred_prob,
            pred_qs,
            shape_time + (len(q_intervals) * n_comp,),
            q_interval=q_intervals,
            component_reduction=None,
            series_reduction=np.mean,
        )
        # no series reduction
        check_res(
            pred_prob,
            pred_qs,
            shape_time + (len(q_intervals),),
            q_interval=q_intervals,
            component_reduction=np.mean,
            series_reduction=None,
        )
        # no series and component reduction
        check_res(
            pred_prob,
            pred_qs,
            shape_time + (len(q_intervals) * n_comp,),
            q_interval=q_intervals,
            component_reduction=None,
            series_reduction=None,
        )

        # check that we get identical results as when computing intervals separately (on the time aggregated case)
        if "time_reduction" in params:
            kwargs["time_reduction"] = np.mean
        res_lo = metric(
            pred_series=pred_qs,
            component_reduction=None,
            q_interval=(0.1, 0.5),
            **kwargs,
        )
        res_hi = metric(
            pred_series=pred_qs,
            component_reduction=None,
            q_interval=(0.5, 0.8),
            **kwargs,
        )
        res_multi = metric(
            pred_series=pred_qs,
            component_reduction=None,
            q_interval=[(0.1, 0.5), (0.5, 0.8)],
            **kwargs,
        )
        if is_single:
            res_lo = [res_lo]
            res_hi = [res_hi]
            res_multi = [res_multi]
        res_lo_hi = []
        for res_lo_, res_hi_ in zip(res_lo, res_hi):
            if res_lo_.ndim == 0:
                res_lo_ = np.expand_dims(res_lo_, -1)
                res_hi_ = np.expand_dims(res_hi_, -1)
                res_lo_hi_ = np.concatenate([res_lo_, res_hi_])
            else:
                res_lo_hi_ = np.concatenate(
                    [(res_lo_[i], res_hi_[i]) for i in range(n_comp)],
                )
            res_lo_hi.append(res_lo_hi_)
        np.testing.assert_array_almost_equal(res_lo_hi, res_multi)
Test output types and shapes for time aggregated metrics with quantile intervals:
        for single and multiple univariate or multivariate series, in combination
        with different component and series reduction functions.
darts/tests/metrics/test_metrics.py