def _get_values_or_raise(
    series_a: TimeSeries,
    series_b: TimeSeries,
    intersect: bool,
    q: Optional[tuple[Sequence[float], Union[Optional[pd.Index]]]] = None,
    remove_nan_union: bool = False,
    is_insample: bool = False,
) -> tuple[np.ndarray, np.ndarray]:
    """Returns the processed numpy values of two time series. Processing can be customized with arguments
    `intersect, q, remove_nan_union`.

    Parameters
    ----------
    series_a
        A deterministic ``TimeSeries`` instance. If `is_insample=False`, it is the `actual_series`.
        Otherwise, it is the `insample` series.
    series_b
        A deterministic or stochastic ``TimeSeries`` instance (the predictions `pred_series`).
    intersect
        A boolean for whether to only consider the time intersection between `series_a` and `series_b`
    q
        Optionally, for predicted stochastic or quantile series, return deterministic quantile values.
        If not `None`, must a tuple with (quantile values,
        `None` if `pred_series` is stochastic else the quantile component names).
    remove_nan_union
        By setting `remove_non_union` to True, sets all values from `series_a` and `series_b` to `np.nan` at indices
        where any of the two series contain a NaN value. Only effective when `is_insample=False`.
    is_insample
        Whether `series_a` corresponds to the `insample` series for scaled metrics.

    Raises
    ------
    ValueError
        If `is_insample=False` and the two time series do not have at least a partially overlapping time index.
    """
    make_copy = False
    if not is_insample:
        # get the time intersection and values of the two series (corresponds to `actual_series` and `pred_series`
        if series_a.has_same_time_as(series_b) or not intersect:
            vals_a_common = series_a.all_values(copy=make_copy)
            vals_b_common = series_b.all_values(copy=make_copy)
        else:
            vals_a_common = series_a.slice_intersect_values(series_b, copy=make_copy)
            vals_b_common = series_b.slice_intersect_values(series_a, copy=make_copy)

        vals_b = _get_values(
            vals=vals_b_common,
            vals_components=series_b.components,
            actual_components=series_a.components,
            q=q,
        )
    else:
        # for `insample` series we extract only values up until before start of `pred_series`
        # find how many steps `insample` overlaps into `series_b`
        end = (
            n_steps_between(
                end=series_b.start_time(), start=series_a.end_time(), freq=series_a.freq
            )
            - 1
        )
        if end > 0 or abs(end) >= len(series_a):
            raise_log(
                ValueError(
                    "The `insample` series must start before the `pred_series` and "
                    "extend at least until one time step before the start of `pred_series`."
                ),
                logger=logger,
            )
        end = end or None
        vals_a_common = series_a.all_values(copy=make_copy)[:end]
        vals_b = None
    vals_a = _get_values(
        vals=vals_a_common,
        vals_components=series_a.components,
        actual_components=series_a.components,
        q=([0.5], None),
    )

    if not remove_nan_union or is_insample:
        return vals_a, vals_b

    isnan_mask = np.expand_dims(
        np.logical_or(np.isnan(vals_a), np.isnan(vals_b)).any(axis=SMPL_AX), axis=-1
    )
    isnan_mask_pred = np.repeat(isnan_mask, vals_b.shape[SMPL_AX], axis=SMPL_AX)
    return np.where(isnan_mask, np.nan, vals_a), np.where(
        isnan_mask_pred, np.nan, vals_b
    )
Returns the processed numpy values of two time series. Processing can be customized with arguments
    `intersect, q, remove_nan_union`.

    Parameters
    ----------
    series_a
        A deterministic ``TimeSeries`` instance. If `is_insample=False`, it is the `actual_series`.
        Otherwise, it is the `insample` series.
    series_b
        A deterministic or stochastic ``TimeSeries`` instance (the predictions `pred_series`).
    intersect
        A boolean for whether to only consider the time intersection between `series_a` and `series_b`
    q
        Optionally, for predicted stochastic or quantile series, return deterministic quantile values.
        If not `None`, must a tuple with (quantile values,
        `None` if `pred_series` is stochastic else the quantile component names).
    remove_nan_union
        By setting `remove_non_union` to True, sets all values from `series_a` and `series_b` to `np.nan` at indices
        where any of the two series contain a NaN value. Only effective when `is_insample=False`.
    is_insample
        Whether `series_a` corresponds to the `insample` series for scaled metrics.

    Raises
    ------
    ValueError
        If `is_insample=False` and the two time series do not have at least a partially overlapping time index.
    
darts/metrics/metrics.py