Functional implementation of padding a MetaTensor. This function operates eagerly or lazily according to ``lazy`` (default ``False``). `torch.nn.functional.pad` is used unless the mode or kwargs are not available in torch, in which case `np.pad` will be used. Args: img
(
img: torch.Tensor,
to_pad: tuple[tuple[int, int]],
transform_info: dict,
mode: str = PytorchPadMode.CONSTANT,
lazy: bool = False,
**kwargs,
)
| 153 | |
| 154 | |
| 155 | def pad_func( |
| 156 | img: torch.Tensor, |
| 157 | to_pad: tuple[tuple[int, int]], |
| 158 | transform_info: dict, |
| 159 | mode: str = PytorchPadMode.CONSTANT, |
| 160 | lazy: bool = False, |
| 161 | **kwargs, |
| 162 | ) -> torch.Tensor: |
| 163 | """ |
| 164 | Functional implementation of padding a MetaTensor. This function operates eagerly or lazily according |
| 165 | to ``lazy`` (default ``False``). |
| 166 | |
| 167 | `torch.nn.functional.pad` is used unless the mode or kwargs are not available in torch, |
| 168 | in which case `np.pad` will be used. |
| 169 | |
| 170 | Args: |
| 171 | img: data to be transformed, assuming `img` is channel-first and padding doesn't apply to the channel dim. |
| 172 | to_pad: the amount to be padded in each dimension [(low_H, high_H), (low_W, high_W), ...]. |
| 173 | note that it including channel dimension. |
| 174 | transform_info: a dictionary with the relevant information pertaining to an applied transform. |
| 175 | mode: available modes: (Numpy) {``"constant"``, ``"edge"``, ``"linear_ramp"``, ``"maximum"``, |
| 176 | ``"mean"``, ``"median"``, ``"minimum"``, ``"reflect"``, ``"symmetric"``, ``"wrap"``, ``"empty"``} |
| 177 | (PyTorch) {``"constant"``, ``"reflect"``, ``"replicate"``, ``"circular"``}. |
| 178 | One of the listed string values or a user supplied function. Defaults to ``"constant"``. |
| 179 | See also: https://numpy.org/doc/stable/reference/generated/numpy.pad.html |
| 180 | https://pytorch.org/docs/stable/generated/torch.nn.functional.pad.html |
| 181 | lazy: a flag indicating whether the operation should be performed in a lazy fashion or not. |
| 182 | transform_info: a dictionary with the relevant information pertaining to an applied transform. |
| 183 | kwargs: other arguments for the `np.pad` or `torch.pad` function. |
| 184 | note that `np.pad` treats channel dimension as the first dimension. |
| 185 | """ |
| 186 | extra_info = {"padded": to_pad, "mode": f"{mode}"} |
| 187 | img_size = img.peek_pending_shape() if isinstance(img, MetaTensor) else img.shape[1:] |
| 188 | spatial_rank = img.peek_pending_rank() if isinstance(img, MetaTensor) else 3 |
| 189 | do_pad = np.asarray(to_pad).any() |
| 190 | if do_pad: |
| 191 | to_pad_list = [(int(p[0]), int(p[1])) for p in to_pad] |
| 192 | if len(to_pad_list) < len(img.shape): |
| 193 | to_pad_list += [(0, 0)] * (len(img.shape) - len(to_pad_list)) |
| 194 | to_shift = [-s[0] for s in to_pad_list[1:]] # skipping the channel pad |
| 195 | xform = create_translate(spatial_rank, to_shift) |
| 196 | shape = [d + s + e for d, (s, e) in zip(img_size, to_pad_list[1:])] |
| 197 | else: |
| 198 | shape = img_size |
| 199 | xform = torch.eye(int(spatial_rank) + 1, device=torch.device("cpu"), dtype=torch.float64) |
| 200 | meta_info = TraceableTransform.track_transform_meta( |
| 201 | img, |
| 202 | sp_size=shape, |
| 203 | affine=xform, |
| 204 | extra_info=extra_info, |
| 205 | orig_size=img_size, |
| 206 | transform_info=transform_info, |
| 207 | lazy=lazy, |
| 208 | ) |
| 209 | out = convert_to_tensor(img.as_tensor() if isinstance(img, MetaTensor) else img, track_meta=get_track_meta()) |
| 210 | if lazy: |
| 211 | return out.copy_meta_from(meta_info) if isinstance(out, MetaTensor) else meta_info # type: ignore |
| 212 | out = pad_nd(out, to_pad_list, mode, **kwargs) if do_pad else out |
no test coverage detected
searching dependent graphs…