def detection_subset(
    dataset: SupportedDetectionDataset,
    indices: Optional[Sequence[int]] = None,
    *,
    class_mapping: Optional[Sequence[int]] = None,
    transform: Optional[XTransform] = None,
    target_transform: Optional[YTransform] = None,
    transform_groups: Optional[Mapping[str, Tuple[XTransform, YTransform]]] = None,
    initial_transform_group: Optional[str] = None,
    task_labels: Optional[Union[int, Sequence[int]]] = None,
    targets: Optional[Sequence[TTargetType]] = None,
    collate_fn: Optional[Callable[[List], Any]] = None
) -> Union[DetectionDataset, SupervisedDetectionDataset]:
    """Creates an ``AvalancheSubset`` instance.

    For simple subset operations you should use the method
    `dataset.subset(indices)`.
    Use this constructor only if you need to redefine transformation or
    class/task labels.

    A Dataset that behaves like a PyTorch :class:`torch.utils.data.Subset`.
    This Dataset also supports transformations, slicing, advanced indexing,
    the targets field, class mapping and all the other goodies listed in
    :class:`AvalancheDataset`.

    :param dataset: The whole dataset.
    :param indices: Indices in the whole set selected for subset. Can
        be None, which means that the whole dataset will be returned.
    :param class_mapping: A list that, for each possible class label value,
        contains its corresponding remapped value. Can be None.
    :param transform: A function/transform that takes the X value of a
        pattern from the original dataset and returns a transformed version.
    :param target_transform: A function/transform that takes in the target
        and transforms it.
    :param transform_groups: A dictionary containing the transform groups.
        Transform groups are used to quickly switch between training and
        eval (test) transformations. This becomes useful when in need to
        test on the training dataset as test transformations usually don't
        contain random augmentations. ``AvalancheDataset`` natively supports
        the 'train' and 'eval' groups by calling the ``train()`` and
        ``eval()`` methods. When using custom groups one can use the
        ``with_transforms(group_name)`` method instead. Defaults to None,
        which means that the current transforms will be used to
        handle both 'train' and 'eval' groups (just like in standard
        ``torchvision`` datasets).
    :param initial_transform_group: The name of the initial transform group
        to be used. Defaults to None, which means that the current group of
        the input dataset will be used (if an AvalancheDataset). If the
        input dataset is not an AvalancheDataset, then 'train' will be
        used.
    :param task_labels: The task label for each instance. Must be a sequence
        of ints, one for each instance in the dataset. This can either be a
        list of task labels for the original dataset or the list of task
        labels for the instances of the subset (an automatic detection will
        be made). In the unfortunate case in which the original dataset and
        the subset contain the same amount of instances, then this parameter
        is considered to contain the task labels of the subset.
        Alternatively can be a single int value, in which case
        that value will be used as the task label for all the instances.
        Defaults to None, which means that the dataset will try to
        obtain the task labels from the original dataset. If no task labels
        could be found, a default task label 0 will be applied to all
        instances.
    :param targets: The target dictionary of each pattern. Defaults to None,
        which means that the targets will be retrieved from the dataset (if
        possible). This can either be a list of target dictionaries for the
        original dataset or the list of target dictionaries for the instances
        of the subset (an automatic detection will be made). In the
        unfortunate case in which the original dataset and the subset contain
        the same amount of instances, then this parameter is considered to
        contain the target dictionaries of the subset.
    :param collate_fn: The function to use when slicing to merge single
        patterns. This function is the function used in the data loading
        process, too. If None, the constructor will check if a
        `collate_fn` field exists in the dataset. If no such field exists,
        the default collate function for detection will be used
    """

    is_supervised = isinstance(dataset, SupervisedDetectionDataset)

    if isinstance(dataset, DetectionDataset):
        if (
            class_mapping is None
            and transform is None
            and target_transform is None
            and transform_groups is None
            and initial_transform_group is None
            and task_labels is None
            and targets is None
            and collate_fn is None
        ):
            return dataset.subset(indices)

    targets_data: Optional[DataAttribute[TTargetType]] = _init_targets(
        dataset, targets, check_shape=False
    )
    task_labels_data: Optional[DataAttribute[int]] = _init_task_labels(
        dataset, task_labels, check_shape=False
    )

    del task_labels
    del targets

    transform_gs = _init_transform_groups(
        transform_groups,
        transform,
        target_transform,
        initial_transform_group,
        dataset,
    )

    if initial_transform_group is not None and isinstance(dataset, AvalancheDataset):
        dataset = dataset.with_transforms(initial_transform_group)

    if class_mapping is not None:  # update targets
        if targets_data is None:
            # Should not happen
            # The following line usually fails
            targets_data = dataset.targets  # type: ignore

        assert (
            targets_data is not None
        ), "To execute the class mapping, a list of targets is required."

        tgs = [
            _detection_class_mapping_transform(class_mapping, example_target_dict)
            for example_target_dict in targets_data
        ]

        targets_data = DataAttribute(tgs, "targets")

    if class_mapping is not None:
        mapping_fn = partial(_detection_class_mapping_transform, class_mapping)
        frozen_transform_groups = DefaultTransformGroups((None, mapping_fn))
    else:
        frozen_transform_groups = None

    das: List[DataAttribute] = []
    if targets_data is not None:
        das.append(targets_data)
    if task_labels_data is not None:
        das.append(task_labels_data)

    # Check if supervision data has been added
    is_supervised = is_supervised or (
        targets_data is not None and task_labels_data is not None
    )

    if collate_fn is None:
        collate_fn = detection_collate_fn

    if is_supervised:
        return SupervisedDetectionDataset(
            [dataset],
            indices=list(indices) if indices is not None else None,
            data_attributes=das if len(das) > 0 else None,
            transform_groups=transform_gs,
            frozen_transform_groups=frozen_transform_groups,
            collate_fn=collate_fn,
        )
    else:
        return DetectionDataset(
            [dataset],
            indices=list(indices) if indices is not None else None,
            data_attributes=das if len(das) > 0 else None,
            transform_groups=transform_gs,
            frozen_transform_groups=frozen_transform_groups,
            collate_fn=collate_fn,
        )
Creates an ``AvalancheSubset`` instance.

    For simple subset operations you should use the method
    `dataset.subset(indices)`.
    Use this constructor only if you need to redefine transformation or
    class/task labels.

    A Dataset that behaves like a PyTorch :class:`torch.utils.data.Subset`.
    This Dataset also supports transformations, slicing, advanced indexing,
    the targets field, class mapping and all the other goodies listed in
    :class:`AvalancheDataset`.

    :param dataset: The whole dataset.
    :param indices: Indices in the whole set selected for subset. Can
        be None, which means that the whole dataset will be returned.
    :param class_mapping: A list that, for each possible class label value,
        contains its corresponding remapped value. Can be None.
    :param transform: A function/transform that takes the X value of a
        pattern from the original dataset and returns a transformed version.
    :param target_transform: A function/transform that takes in the target
        and transforms it.
    :param transform_groups: A dictionary containing the transform groups.
        Transform groups are used to quickly switch between training and
        eval (test) transformations. This becomes useful when in need to
        test on the training dataset as test transformations usually don't
        contain random augmentations. ``AvalancheDataset`` natively supports
        the 'train' and 'eval' groups by calling the ``train()`` and
        ``eval()`` methods. When using custom groups one can use the
        ``with_transforms(group_name)`` method instead. Defaults to None,
        which means that the current transforms will be used to
        handle both 'train' and 'eval' groups (just like in standard
        ``torchvision`` datasets).
    :param initial_transform_group: The name of the initial transform group
        to be used. Defaults to None, which means that the current group of
        the input dataset will be used (if an AvalancheDataset). If the
        input dataset is not an AvalancheDataset, then 'train' will be
        used.
    :param task_labels: The task label for each instance. Must be a sequence
        of ints, one for each instance in the dataset. This can either be a
        list of task labels for the original dataset or the list of task
        labels for the instances of the subset (an automatic detection will
        be made). In the unfortunate case in which the original dataset and
        the subset contain the same amount of instances, then this parameter
        is considered to contain the task labels of the subset.
        Alternatively can be a single int value, in which case
        that value will be used as the task label for all the instances.
        Defaults to None, which means that the dataset will try to
        obtain the task labels from the original dataset. If no task labels
        could be found, a default task label 0 will be applied to all
        instances.
    :param targets: The target dictionary of each pattern. Defaults to None,
        which means that the targets will be retrieved from the dataset (if
        possible). This can either be a list of target dictionaries for the
        original dataset or the list of target dictionaries for the instances
        of the subset (an automatic detection will be made). In the
        unfortunate case in which the original dataset and the subset contain
        the same amount of instances, then this parameter is considered to
        contain the target dictionaries of the subset.
    :param collate_fn: The function to use when slicing to merge single
        patterns. This function is the function used in the data loading
        process, too. If None, the constructor will check if a
        `collate_fn` field exists in the dataset. If no such field exists,
        the default collate function for detection will be used
    
avalanche/benchmarks/utils/detection_dataset.py