Copy specified items from data dictionary and save with different key names. It can copy several items together and copy several times.
| 907 | |
| 908 | |
| 909 | class CopyItemsd(MapTransform): |
| 910 | """ |
| 911 | Copy specified items from data dictionary and save with different key names. |
| 912 | It can copy several items together and copy several times. |
| 913 | """ |
| 914 | |
| 915 | backend = [TransformBackends.TORCH, TransformBackends.NUMPY] |
| 916 | |
| 917 | def __init__( |
| 918 | self, |
| 919 | keys: KeysCollection, |
| 920 | times: int = 1, |
| 921 | names: KeysCollection | None = None, |
| 922 | allow_missing_keys: bool = False, |
| 923 | ) -> None: |
| 924 | """ |
| 925 | Args: |
| 926 | keys: keys of the corresponding items to be transformed. |
| 927 | See also: :py:class:`monai.transforms.compose.MapTransform` |
| 928 | times: expected copy times, for example, if keys is "img", times is 3, |
| 929 | it will add 3 copies of "img" data to the dictionary, default to 1. |
| 930 | names: the names corresponding to the newly copied data, |
| 931 | the length should match `len(keys) x times`. for example, if keys is ["img", "seg"] |
| 932 | and times is 2, names can be: ["img_1", "seg_1", "img_2", "seg_2"]. |
| 933 | if None, use "{key}_{index}" as key for copy times `N`, index from `0` to `N-1`. |
| 934 | allow_missing_keys: don't raise exception if key is missing. |
| 935 | |
| 936 | Raises: |
| 937 | ValueError: When ``times`` is nonpositive. |
| 938 | ValueError: When ``len(names)`` is not ``len(keys) * times``. Incompatible values. |
| 939 | |
| 940 | """ |
| 941 | super().__init__(keys, allow_missing_keys) |
| 942 | if times < 1: |
| 943 | raise ValueError(f"times must be positive, got {times}.") |
| 944 | self.times = times |
| 945 | names = [f"{k}_{i}" for k in self.keys for i in range(self.times)] if names is None else ensure_tuple(names) |
| 946 | if len(names) != (len(self.keys) * times): |
| 947 | raise ValueError( |
| 948 | "len(names) must match len(keys) * times, " |
| 949 | f"got len(names)={len(names)} len(keys) * times={len(self.keys) * times}." |
| 950 | ) |
| 951 | self.names = names |
| 952 | |
| 953 | def __call__(self, data: Mapping[Hashable, NdarrayOrTensor]) -> dict[Hashable, NdarrayOrTensor]: |
| 954 | """ |
| 955 | Raises: |
| 956 | KeyError: When a key in ``self.names`` already exists in ``data``. |
| 957 | |
| 958 | """ |
| 959 | d = dict(data) |
| 960 | key_len = len(self.keys) |
| 961 | for i in range(self.times): |
| 962 | for key, new_key in self.key_iterator(d, self.names[i * key_len : (i + 1) * key_len]): |
| 963 | if new_key in d: |
| 964 | raise KeyError(f"Key {new_key} already exists in data.") |
| 965 | val = d[key] |
| 966 | d[new_key] = MetaObj.copy_items(val) if isinstance(val, (torch.Tensor, np.ndarray)) else deepcopy(val) |
no outgoing calls
searching dependent graphs…