Repository: Project-MONAI/MONAI
File: monai/transforms/compose.py (Python)

Code before:
            map_items=self.map_items,
            unpack_items=self.unpack_items,
            lazy_evaluation=self.lazy_evaluation,
            overrides=self.overrides,
            override_keys=self.override_keys,
            threading=threading,
            log_stats=self.log_stats,
            verbose=self.verbose,
        )

    def inverse(self, data):
        invertible_transforms = [t for t in self.flatten().transforms if isinstance(t, InvertibleTransform)]
        if not invertible_transforms:
            warnings.warn("inverse has been called but no invertible transforms have been supplied")

        # loop backwards over transforms
        for t in reversed(invertible_transforms):
            data = apply_transform(t.inverse, data, self.map_items, self.unpack_items, self.log_stats)
        return data


class OneOf(Compose):
    """
    ``OneOf`` provides the ability to randomly choose one transform out of a
    list of callables with pre-defined probabilities for each.

    Args:
        transforms: sequence of callables.
        weights: probabilities corresponding to each callable in transforms.
            Probabilities are normalized to sum to one.
        map_items: whether to apply transform to each item in the input `data` if `data` is a list or tuple.
            defaults to `True`.
        unpack_items: whether to unpack input `data` with `*` as parameters for the callable function of transform.
            defaults to `False`.
        log_stats: whether to log the detailed information of data and applied transform when error happened,
            for NumPy array and PyTorch Tensor, log the data shape and value range,
            for other metadata, log the values directly. default to `False`.
        lazy_evaluation: whether to enable lazy evaluation for lazy transforms. If True, all lazy transforms will
            be executed by accumulating changes and resampling as few times as possible. If False, transforms will be
            carried out on a transform by transform basis.
            A `monai.transforms.Identity[D]` transform in the pipeline will trigger the evaluation of
            the pending operations and make the primary data up-to-date.
        overrides: this optional parameter allows you to specify a dictionary of parameters that should be overridden
            when executing a pipeline. These each parameter that is compatible with a given transform is then applied
            to that transform before it is executed. Note that overrides are currently only applied when lazy_evaluation
            is True. If lazy_evaluation is False they are ignored.
            currently supported args are:
            {``"mode"``, ``"padding_mode"``, ``"dtype"``, ``"align_corners"``, ``"resample_mode"``, ``device``},
            please see also :py:func:`monai.transforms.lazy.apply_transforms` for more details.
        override_keys: this optional parameter specifies the keys to which ``overrides`` are to be applied. If
            ``overrides`` is set, ``override_keys`` must also be set.

Review comment (suggestion):
Since we only flatten when the sub-transform is `Compose`, will the index returned here be correct, if the transform list contains `SomeOf` or `RandomOrder`?
https://github.com/Project-MONAI/MONAI/blob/0223e6262239b6390b57b630f2ceca3fea9a70bf/monai/transforms/compose.py#L279

Code after:

        Example:
            c = Compose([Flip(...), Rotate90(...), Zoom(...), RandRotate(...), Resize(...)])

            print(c.get_index_of_first(lambda t: isinstance(t, RandomTrait)))
            >>> 3
            print(c.get_index_of_first(lambda t: isinstance(t, Compose)))
            >>> None

        Note:
            This is only performed on the transforms directly held by this instance. If this
            instance has nested ``Compose`` transforms or other transforms that contain transforms,
            it does not iterate into them.


        Args:
            predicate: a callable that takes a single argument and returns a bool. When called
            it is passed a transform from the sequence of transforms contained by this compose
            instance.

        Returns:
            The index of the first transform in the sequence for which ``predicate`` returns
            True. None if no transform satisfies the ``predicate``

        """
        for i in range(len(self.transforms)):
            if predicate(self.transforms[i]):
                return i
        return None

    def flatten(self):
        """Return a Composition with a simple list of transforms, as opposed to any nested Compositions.

        e.g., `t1 = Compose([x, x, x, x, Compose([Compose([x, x]), x, x])]).flatten()`
        will result in the equivalent of `t1 = Compose([x, x, x, x, x, x, x, x])`.

        """
        new_transforms = []
        for t in self.transforms:
            if type(t) is Compose:  # nopep8
                new_transforms += t.flatten().transforms
            else:
                new_transforms.append(t)

        return Compose(new_transforms)

    def __len__(self):
        """Return number of transformations."""
        return len(self.flatten().transforms)

    def evaluate_with_overrides(self, input_, upcoming_xform):