U Ph!@s2dZddlmZddlZddlZddlZddlZddlmZm Z ddl m Z ddl m Z ddlmZmZddlZddlZddlmZddlmZdd lmZdd lmZdd lmZdd lmZm Z dd l!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)ddl*m+Z+ddl,m-Z-ddl.m/Z/m0Z0m1Z1m2Z2ddl3m4Z4m5Z5m6Z6m7Z7ddl8m9Z9m:Z:m;Z;mZ>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGddlHmIZIddlJmKZKddlLmMZMmNZNeGddd\ZOZPeGddd\ZQZReGd\ZSZTddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;ddde0ZWGd?dde2ZXGd@d d e2ZYGdAd"d"e2ZZGdBd#d#e2Z[GdCd$d$e2e-Z\GdDd%d%e2Z]GdEd&d&e2Z^GdFd!d!e2Z_GdGd'd'e2Z`GdHd:d:e2ZaGdId(d(e2ZbGdJd)d)e2ZcGdKd*d*e2ZdGdLd+d+e2ZeGdMd,d,e2ZfGdNd-d-e+ZgGdOd.d.ege1ZhGdPd/d/e2ZiGdQd0d0e2e-ZjGdRd1d1e2e-ZkGdSd2d2e2ZlGdTd3d3e/e2ZmGdUd4d4ZnGdVd5d5ZoGdWd6d6e2ZpGdXd7d7e2ZqGdYd8d8e2ZrGdZd9d9ere0ZsGd[dde2ZtGd\d;d;e2ZuGd]d<deZdZdZejejgZd dddddZddd d d Z d S)r:am Change the channel dimension of the image to the last dimension. Some of other 3rd party transforms assume the input image is in the channel-last format with shape (spatial_dim_1[, spatial_dim_2, ...], num_channels). This transform could be used to convert, for example, a channel-first image array in shape (num_channels, spatial_dim_1[, spatial_dim_2, ...]) into the channel-last format, so that MONAI transforms can construct a chain with other 3rd party transforms together. Args: channel_dim: which dimension of input image is the channel, default is the first dimension. rintNone) channel_dimr[cCs,t|tr|dks"td|d||_dS)Nzinvalid channel dimension (z).) isinstancern ValueErrorrp)r`rpr^r^ra__init__szAsChannelLast.__init__r rYcCstt||jdtd}|S)r]rq track_meta)r*r#rpr r`rZoutr^r^rarbszAsChannelLast.__call__N)r rdrerfrgr/rhrirjrtrbr^r^r^rar:s c@sBeZdZdZejejgZddddddZdd d d d d d Z dS)r<a Adjust or add the channel dimension of input data to ensure `channel_first` shape. This extracts the `original_channel_dim` info from provided meta_data dictionary or MetaTensor input. This value should state which dimension is the channel dimension so that it can be moved forward, or contain "no_channel" to state no dimension is the channel and so a 1-size first dimension is to be added. Args: strict_check: whether to raise an error when the meta information is insufficient. channel_dim: This argument can be used to specify the original channel dimension (integer) of the input array. It overrides the `original_channel_dim` from provided MetaTensor input. If the input array doesn't have a channel dim, this value should be ``'no_channel'``. If this is set to `None`, this class relies on `img` or `meta_dict` to provide the channel dimension. TNboolzNone | str | int) strict_checkrpcCs||_||_dSrl)r{input_channel_dim)r`r{rpr^r^rartszEnsureChannelFirst.__init__ torch.TensorMapping | NonerZ meta_dictr[cCst|tsFt|tsF|jdkr>d}|jr0t|t||St|}t|trV|j}t|trn| t j dnd}|jdk r|jdkrt dn|j}|dkrd}|jrt|t||St|t r||t j <t|r|d}nt|t|d}t|tdS)r]NzNMetadata not available and channel_dim=None, EnsureChannelFirst is not in use. no_channelnanzYUnknown original_channel_dim in the MetaTensor meta dict or `meta_dict` or `channel_dim`.rru)rrr rr|r{rswarningswarnmetagetr%ORIGINAL_CHANNEL_DIMfloatdictr r#rnr*r )r`rZrmsgrpresultr^r^rarbs2        zEnsureChannelFirst.__call__)TN)Nryr^r^r^rar<s c@s8eZdZdZejgZdddddZdddd d Zd S) r>a5 Repeat channel data to construct expected input shape for models. The `repeats` count includes the origin data, for example: ``RepeatChannel(repeats=2)([[1, 2], [3, 4]])`` generates: ``[[1, 2], [1, 2], [3, 4], [3, 4]]`` Args: repeats: the number of repetitions for each element. rnrorepeatsr[cCs"|dkrtd|d||_dSNrz*repeats count must be greater than 0, got .rsrr`rr^r^rartszRepeatChannel.__init__r rYcCs0t|tjrtjntj}t|||jdtdS)Z Apply the transform to `img`, assuming `img` is a "channel-first" array. rru) rrtorchTensorrepeat_interleavenprepeatr*rr )r`rZZ repeat_fnr^r^rarbszRepeatChannel.__call__N rdrerfrgr/rhrjrtrbr^r^r^rar>s c@s<eZdZdZejejgZdddddZdddd d Z d S) r?aK RemoveRepeatedChannel data to undo RepeatChannel The `repeats` count specifies the deletion of the origin data, for example: ``RemoveRepeatedChannel(repeats=2)([[1, 2], [1, 2], [3, 4], [3, 4]])`` generates: ``[[1, 2], [3, 4]]`` Args: repeats: the number of repetitions to be deleted for each element. rnrorcCs"|dkrtd|d||_dSrrrr^r^rart szRemoveRepeatedChannel.__init__r rYcCsJ|jddkr$td|jddt|dd|jddftd}|S)rrz+Image must have more than one channel, got z channels.Nru)shapersr*rr rwr^r^rarbs"zRemoveRepeatedChannel.__call__Nryr^r^r^rar?s c@s@eZdZdZejejgZddddddd Zd d d d dZ dS)r@aV Given an image of size X along a certain dimension, return a list of length X containing images. Useful for converting 3D images into a stack of 2D images, splitting multichannel inputs into single channels, for example. Note: `torch.split`/`np.split` is used, so the outputs are views of the input (shallow copy). Args: dim: dimension on which to split keepdim: if `True`, output will have singleton in the split dimension. If `False`, this dimension will be squeezed. update_meta: whether to update the MetaObj in each split result. rqTrnrzro)dimkeepdimr[cCs||_||_||_dSrl)rr update_meta)r`rrrr^r^rart/szSplitDim.__init__r}zlist[torch.Tensor]rYcCs|j|j}t|tjr.tt|d|j}nt|||j}t|D]\}}|j sd| |j||<|j rFt|t rFt|t st ||j d}|jdkrqFt|j}tj||jj|jjd}|||jddf<|j||_qF|S)r])rr)devicedtyperq)rrrrrrlistsplitr enumeratersqueezerr rlenaffineeyerr)r`rZn_outoutputsidxitemndimshiftr^r^rarb4s"     zSplitDim.__call__N)rqTTryr^r^r^rar@s c@sDeZdZdZejejgZej fddddZ d dddd d d Z dS) rAa Cast the Numpy data to specified numpy data type, or cast the PyTorch Tensor to specified PyTorch data type. Example: >>> import numpy as np >>> import torch >>> transform = CastToType(dtype=np.float32) >>> # Example with a numpy array >>> img_np = np.array([0, 127, 255], dtype=np.uint8) >>> img_np_casted = transform(img_np) >>> img_np_casted array([ 0. , 127. , 255. ], dtype=float32) >>> # Example with a PyTorch tensor >>> img_tensor = torch.tensor([0, 127, 255], dtype=torch.uint8) >>> img_tensor_casted = transform(img_tensor) >>> img_tensor_casted tensor([ 0., 127., 255.]) # dtype is float32 ro)r[cCs ||_dS)zd Args: dtype: convert image to this data type, default is `np.float32`. N)r)r`rr^r^rarteszCastToType.__init__Nr DtypeLike | torch.dtype)rZrr[cCst|t||p|jddS)a+ Apply the transform to `img`, assuming `img` is a numpy array or PyTorch Tensor. Args: dtype: convert image to this data type, default is `self.dtype`. Raises: TypeError: When ``img`` type is not in ``Union[numpy.ndarray, torch.Tensor]``. ) output_typerr)r'typer)r`rZrr^r^rarbls zCastToType.__call__)N) rdrerfrgr/rhrirjrfloat32rtrbr^r^r^rarALs csFeZdZdZejgZddddddd fd d Zd d ddZZ S)rBa Converts the input image to a tensor without applying any other transformations. Input data can be PyTorch Tensor, numpy array, list, dictionary, int, float, bool, str, etc. Will convert Tensor, Numpy array, float, int, bool to Tensor, strings and objects keep the original. For dictionary, list or tuple, convert every item to a Tensor if applicable and `wrap_sequence=False`. Args: dtype: target data type to when converting to Tensor. device: target device to put the converted Tensor data. wrap_sequence: if `False`, then lists will recursively call this function, default to `True`. E.g., if `False`, `[1, 2]` -> `[tensor(1), tensor(2)]`, if `True`, then `[1, 2]` -> `tensor([1, 2])`. track_meta: whether to convert to `MetaTensor` or regular tensor, default to `None`, use the return value of ``get_track_meta``. NTztorch.dtype | Noneztorch.device | str | Nonerz bool | Nonero)rr wrap_sequencervr[cs8t||_||_||_|dkr*tnt||_dSrl)superrtrrrr rzrv)r`rrrrv __class__r^rarts  zToTensor.__init__r rZcCs*t|trg|_t||j|j|j|jdS)F Apply the transform to `img` and make it contiguous. )rrrrv)rrr applied_operationsr*rrrrvr_r^r^rarbs zToTensor.__call__)NNTN rdrerfrgr/rhrjrtrb __classcell__r^r^rrarBzs c@sHeZdZdZejejgZdddddd d d d d ZddddddZ dS)r=a Ensure the input data to be a PyTorch Tensor or numpy array, support: `numpy array`, `PyTorch Tensor`, `float`, `int`, `bool`, `string` and `object` keep the original. If passing a dictionary, list or tuple, still return dictionary, list or tuple will recursively convert every item to the expected data type if `wrap_sequence=False`. Args: data_type: target data type to convert, should be "tensor" or "numpy". dtype: target data content type to convert, for example: np.float32, torch.float, etc. device: for Tensor data type, specify the target device. wrap_sequence: if `False`, then lists will recursively call this function, default to `True`. track_meta: if `True` convert to ``MetaTensor``, otherwise to Pytorch ``Tensor``, if ``None`` behave according to return value of py:func:`monai.data.meta_obj.get_track_meta`. Example with wrap_sequence=True: >>> import numpy as np >>> import torch >>> transform = EnsureType(data_type="tensor", wrap_sequence=True) >>> # Converting a list to a tensor >>> data_list = [1, 2., 3] >>> tensor_data = transform(data_list) >>> tensor_data tensor([1., 2., 3.]) # All elements have dtype float32 Example with wrap_sequence=False: >>> transform = EnsureType(data_type="tensor", wrap_sequence=False) >>> # Converting each element in a list to individual tensors >>> data_list = [1, 2, 3] >>> tensors_list = transform(data_list) >>> tensors_list [tensor(1), tensor(2.), tensor(3)] # Only second element is float32 rest are int64 tensorNTstrrztorch.device | Nonerzrro) data_typerrrrvr[cCsBt|ddh|_||_||_||_|dkr4tnt||_dS)Nrnumpy) r,lowerrrrrr rzrv)r`rrrrrvr^r^rarts zEnsureType.__init__r )rkrcCsN|jdkr|jrtntj}ntj}t|||dkr6|jn||j |j d^}}|S)a Args: data: input data can be PyTorch Tensor, numpy array, list, dictionary, int, float, bool, str, etc. will ensure Tensor, Numpy array, float, int, bool as Tensors or numpy arrays, strings and objects keep the original. for dictionary, list or tuple, ensure every item as expected type if applicable and `wrap_sequence=False`. dtype: target data content type to convert, for example: np.float32, torch.float, etc. rN)rkrrrr) rrvr rrrndarrayr'rrr)r`rkrrrx_r^r^rarbs  zEnsureType.__call__)rNNTN)Nryr^r^r^rar=s! csBeZdZdZejgZdddddfdd Zd d d d ZZ S)rCa Converts the input data to numpy array, can support list or tuple of numbers and PyTorch Tensor. Args: dtype: target data type when converting to numpy array. wrap_sequence: if `False`, then lists will recursively call this function, default to `True`. E.g., if `False`, `[1, 2]` -> `[array(1), array(2)]`, if `True`, then `[1, 2]` -> `array([1, 2])`. NTr rzrorrr[cst||_||_dSrlrrtrrr`rrrr^rarts zToNumpy.__init__r rcCst||j|jdS)rrr)r)rrr_r^r^rarbszToNumpy.__call__)NT) rdrerfrgr/rirjrtrbrr^r^rrarCs csBeZdZdZejgZdddddfdd Zd d d d ZZ S)rVaA Converts the input data to CuPy array, can support list or tuple of numbers, NumPy and PyTorch Tensor. Args: dtype: data type specifier. It is inferred from the input by default. if not None, must be an argument of `numpy.dtype`, for more details: https://docs.cupy.dev/en/stable/reference/generated/cupy.array.html. wrap_sequence: if `False`, then lists will recursively call this function, default to `True`. E.g., if `False`, `[1, 2]` -> `[array(1), array(2)]`, if `True`, then `[1, 2]` -> `array([1, 2])`. NTznp.dtype | Nonerzrorcst||_||_dSrlrrrr^rarts zToCupy.__init__r rkcCst||j|jdS)zH Create a CuPy array from `data` and make it contiguous r)r(rrrmr^r^rarbszToCupy.__call__)NT) rdrerfrgr/CUPYrjrtrbrr^r^rrarV s c@s eZdZdZejgZddZdS)rDz^ Converts the input image (in the form of NumPy array or PyTorch Tensor) to PIL image cCs2t|tr|St|tjr*|}t|Sr\)rr PILImageImagerrdetachcpurpil_image_fromarrayr_r^r^rarb+s   zToPIL.__call__N)rdrerfrgr/rirjrbr^r^r^rarD$sc@s8eZdZdZejgZdddddZdddd d Zd S) rEzU Transposes the input image based on the given `indices` dimension ordering. Sequence[int] | Nonero)indicesr[cCs|dkr dnt||_dSrl)tupler)r`rr^r^rart=szTranspose.__init__r rYcCs2t|td}||jp.tt|jdddS)r]ruNrq)r*r permuterrrangerr_r^r^rarb@szTranspose.__call__Nrr^r^r^rarE6sc@s>eZdZdZejejgZddddddZd d d d d Z d S)rFz& Squeeze a unitary dimension. rT int | Nonero)rr[cCs8|dk r(t|ts(tdt|jd||_||_dS)aI Args: dim: dimension to be squeezed. Default = 0 "None" works when the input is numpy array. update_meta: whether to update the meta info if the input is a metatensor. Default is ``True``. Raises: TypeError: When ``dim`` is not an ``Optional[int]``. Nz!dim must be None or a int but is r)rrrn TypeErrorrrdrr)r`rrr^r^rartOs zSqueezeDim.__init__r rYcCst|td}|jdkr0|jr(td|S|jdkrJ|jt|jn|j}|j|dkr|t d|j|d|jd||}|jr~t |t r~|dkr~t|j jd kr~|j j\}}|j t |j t jr|j jnd}}||kr |t jd||d |dk}||kr8|ddt jd||d |dkf}|jd|jdkrxtjt|d d sxtd |j d||_ |S)z[ Args: img: numpy arrays with required dimension `dim` removed ruNz*update_meta=True is ignored when dim=None.rrz0Can only squeeze singleton dimension, got shape z of rrrT)rz,After SqueezeDim, img.affine is ill-posed: )r*r rrrrrrrrsrrr rrrrarangerlinalgdetr))r`rZrhwrrr^r^rarb_s(    0 "  $,zSqueezeDim.__call__N)rTryr^r^r^rarFHs c @sXeZdZdZejejgZddddddddd d d d Zdd ddddddd dddZ dS)rGaJ Utility transform to show the statistics of data for debug or analysis. It can be inserted into any place of a transform chain and check results of previous transforms. It support both `numpy.ndarray` and `torch.tensor` as input data, so it can be used in pre-processing and post-processing. It gets logger from `logging.getLogger(name)`, we can setup a logger outside first with the same `name`. If the log level of `logging.RootLogger` is higher than `INFO`, will add a separate `StreamHandler` log handler with `INFO` level and record to `stdout`. DataTFNrrzCallable | Nonero)prefixr data_shape value_range data_valueadditional_infor5r[c Cst|tstdt|d||_||_||_||_||_|dk rbt |sbt dt|j d||_ ||_ t|j }|tjtjtjkrtdd|jD} | sttj} | tjd| _|| dS)a Args: prefix: will be printed in format: "{prefix} statistics". data_type: whether to show the type of input data. data_shape: whether to show the shape of input data. value_range: whether to show the value range of input data. data_value: whether to show the raw value of input data. a typical example is to print some properties of Nifti image: affine, pixdim, etc. additional_info: user can define callable function to extract additional info from input data. name: identifier of `logging.logger` to use, defaulting to "DataStats". Raises: TypeError: When ``additional_info`` is not an ``Optional[Callable]``. zprefix must be a string, got rNz0additional_info must be None or callable but is css|]}t|do|jVqdS)is_data_stats_handlerN)hasattrr).0rr^r^ra sz%DataStats.__init__..T)rrrrsrrrrrrcallablerrdr _logger_namelogging getLoggersetLevelINFOrootgetEffectiveLevelanyhandlers StreamHandlersysstdoutr addHandler) r`rrrrrrr5_loggerZhas_console_handlerconsoler^r^rarts,     zDataStats.__init__r z str | Noner)rZrrrrrrr[c Cs|p|jdg}|dkr"|jrPn|rP|dt|dt|drF|jnd|dkr`|jrn|r|dt|drz|jnd|dkr|jrn|rt |t j r|dt |d t |d nJt |tjr|dt |d t |d n|d t|d |dkr,|jrBn|rB|d ||dkrR|jn|}|dk rt|d ||d} | |} t|j| |S)zk Apply the transform to `img`, optionally take arguments similar to the class constructor. z statistics:NzType:  rzShape: rzValue range: (z, )z2Value range: (not a PyTorch or Numpy array, type: zValue: zAdditional info:  )rrappendrrrrrrrrrrminmaxrrrrjoinrrrinfo) r`rZrrrrrrlines separatoroutputr^r^rarbs( *  &&  zDataStats.__call__)rTTTFNrG)NNNNNNryr^r^r^rarG{s" 5csJeZdZdZejejgZddddfdd Zdd d d d d d Z Z S)rHa This is a pass through transform to be used for testing purposes. It allows adding fake behaviors that are useful for testing purposes to simulate how large datasets behave without needing to test on large data sets. For example, simulating slow NFS data transfers, or slow network transfers in testing by adding explicit timing delays. Testing of small test data can lead to incomplete understanding of real world issues, and may lead to sub-optimal design choices. rro) delay_timer[cst||_dS)z Args: delay_time: The minimum amount of time, in fractions of seconds, to accomplish this delay task. N)rrtr)r`rrr^rarts zSimulateDelay.__init__Nr z float | None)rZrr[cCst|dkr|jn||S)z Args: img: data remain unchanged throughout this transform. delay_time: The minimum amount of time, in fractions of seconds, to accomplish this delay task. N)timesleepr)r`rZrr^r^rarbszSimulateDelay.__call__)r)N) rdrerfrgr/rhrirjrtrbrr^r^rrarHs  c@sXeZdZdZejejgZdedfdddddd d Z dd dd d dZ ddddZ dS)rIa Apply a user-defined lambda as a transform. For example: .. code-block:: python :emphasize-lines: 2 image = np.ones((10, 2, 2)) lambd = Lambda(func=lambda x: x[:4, :, :]) print(lambd(image).shape) (4, 2, 2) Args: func: Lambda/function to be applied. inv_func: Lambda/function of inverse operation, default to `lambda x: x`. track_meta: If `False`, then standard data objects will be returned (e.g., torch.Tensor` and `np.ndarray`) as opposed to MONAI's enhanced objects. By default, this is `True`. Raises: TypeError: When ``func`` is not an ``Optional[Callable]``. NTrrrzro)funcinv_funcrvr[cCs<|dk r&t|s&tdt|jd||_||_||_dS)N%func must be None or callable but is r)rrrrdrrrvr`rrrvr^r^rarts zLambda.__init__r rZrcCsz|dk r |n|j}t|s0tdt|jd||}t|tjtj frbt|t sb|j rbt |}t|t rv| ||S)z Apply `self.func` to `img`. Args: func: Lambda/function to be applied. Defaults to `self.func`. Raises: TypeError: When ``func`` is not an ``Optional[Callable]``. Nrr) rrrrrdrrrrrrr rvpush_transform)r`rZrfnrxr^r^rarb's "  zLambda.__call__r}rcCst|tr||||Srl)rrr pop_transformrrmr^r^rainverse=s  zLambda.inverse)N) rdrerfrgr/rhrirjrrtrbr r^r^r^rarIs  csbeZdZdZejZddedfddddd d d d Zdd ddfdd Zddfdd Z Z S)rJa Randomizable version :py:class:`monai.transforms.Lambda`, the input `func` may contain random logic, or randomly execute the function based on `prob`. Args: func: Lambda/function to be applied. prob: probability of executing the random function, default to 1.0, with 100% probability to execute. inv_func: Lambda/function of inverse operation, default to `lambda x: x`. track_meta: If `False`, then standard data objects will be returned (e.g., torch.Tensor` and `np.ndarray`) as opposed to MONAI's enhanced objects. By default, this is `True`. For more details, please check :py:class:`monai.transforms.Lambda`. N?Trrrrzro)rprobrrvr[cCs$tj||||dtj||ddS)Nr)r`r)rIrtr)r`rrrrvr^r^rartTszRandLambda.__init__r rcsn||t|jr t||n|}t|ts>|jr>t|}t|trj|jrX||ni}|j ||d|S)N) extra_info) randomizer _do_transformrrbrrr rvr r )r`rZrrxZ lambda_inforr^rarb^s  zRandLambda.__call__r}rcs2||tj}|r$t|}n |||Srl)get_most_recent_transformpopr& DO_TRANSFORMrr r )r`rk do_transformrr^rar is  zRandLambda.inverse)N) rdrerfrgrIrjrrtrbr rr^r^rrarJCs  c@sFeZdZdZejejgZdddddddZdd d dd d d dZ d S)rKa Convert labels to mask for other tasks. A typical usage is to convert segmentation labels to mask data to pre-process images and then feed the images into classification network. It can support single channel labels or One-Hot labels with specified `select_labels`. For example, users can select `label value = [2, 3]` to construct mask data, or select the second and the third channels of labels to construct mask data. The output mask data can be a multiple channels binary data or a single channel binary data that merges all the channels. Args: select_labels: labels to generate mask from. for 1 channel label, the `select_labels` is the expected label values, like: [1, 2, 3]. for One-Hot format label, the `select_labels` is the expected channel indices. merge_channels: whether to use `np.any()` to merge the result on channel dim. if yes, will return a single channel mask with binary data. FzSequence[int] | intrzro) select_labelsmerge_channelsr[cCst||_||_dSrl)r+rr)r`rrr^r^rarts zLabelToMask.__init__Nr zSequence[int] | int | None)rZrrr[cCs t|td}|dkr|j}nt|}|jddkr@||}n|t|tjrRtjnt j}t|tjsnt t dr|t ||dd |j}n2|t ||t j d|jdt j d|jd |j}|s|jrt|tjst t dr|ddS|t jddtS|S) a Args: select_labels: labels to generate mask from. for 1 channel label, the `select_labels` is the expected label values, like: [1, 2, 3]. for One-Hot format label, the `select_labels` is the expected channel indices. merge_channels: whether to use `np.any()` to merge the result on channel dim. if yes, will return a single channel mask with binary data. ruNrr)rrTFr)r*r rr+rrrrrwhererr0r"reshaperrrrtouint8rz)r`rZrrrkrr^r^rarbs*   zLabelToMask.__call__)F)NFryr^r^r^rarKrs c@sFeZdZdZejejgZddddddd Zdd d dd d ddZ dS)rLa Compute foreground and background of the input label data, return the indices. If no output_shape specified, output data will be 1 dim indices after flattening. This transform can help pre-compute foreground and background regions for other transforms. A typical usage is to randomly select foreground and background to crop. The main logic is based on :py:class:`monai.transforms.utils.map_binary_to_indices`. Args: image_threshold: if enabled `image` at runtime, use ``image > image_threshold`` to determine the valid image content area and select background only in this area. output_shape: expected shape of output indices. if not None, unravel indices to specified shape. rNrrro)image_threshold output_shaper[cCs||_||_dSrl)rr)r`rrr^r^rartszFgBgToIndices.__init__r NdarrayOrTensor | Nonez'tuple[NdarrayOrTensor, NdarrayOrTensor]labelimagerr[cCsD|dkr|j}t|||j\}}|dk r image_threshold`` to define background. so the output items will not map to all the voxels in the label. output_shape: expected shape of output indices. if None, use `self.output_shape` instead. N)rrrr$)r`r!r"r fg_indices bg_indicesr^r^rarbs   zFgBgToIndices.__call__)rN)NN) rdrerfrgr/rirhrjrtrbr^r^r^rarLs  c@sFeZdZejejgZddddddddd Zdd d dd d ddZdS)rMNrrrrro) num_classesrrmax_samples_per_classr[cCs||_||_||_||_dS)a Compute indices of every class of the input label data, return a list of indices. If no output_shape specified, output data will be 1 dim indices after flattening. This transform can help pre-compute indices of the class regions for other transforms. A typical usage is to randomly select indices of classes to crop. The main logic is based on :py:class:`monai.transforms.utils.map_classes_to_indices`. Args: num_classes: number of classes for argmax label, not necessary for One-Hot label. image_threshold: if enabled `image` at runtime, use ``image > image_threshold`` to determine the valid image content area and select only the indices of classes in this area. output_shape: expected shape of output indices. if not None, unravel indices to specified shape. max_samples_per_class: maximum length of indices to sample in each class to reduce memory consumption. Default is None, no subsampling. N)r%rrr&)r`r%rrr&r^r^rartszClassesToIndices.__init__r rzlist[NdarrayOrTensor]r csBdkr|jt||j||j|j}dk r>fdd|D}|S)ai Args: label: input data to compute the indices of every class. image: if image is not None, use ``image > image_threshold`` to define valid region, and only select the indices within the valid region. output_shape: expected shape of output indices. if None, use `self.output_shape` instead. Ncsg|]}t|qSr^)r$)r cls_indicesrr^ra sz-ClassesToIndices.__call__..)rr r%rr&)r`r!r"rrr^r(rarbs zClassesToIndices.__call__)NrNN)NN) rdrerfr/rirhrjrtrbr^r^r^rarMs c@s,eZdZdZejejgZdddddZdS)rNa% Convert labels to multi channels based on brats18 classes: label 1 is the necrotic and non-enhancing tumor core label 2 is the peritumoral edema label 4 is the GD-enhancing tumor The possible classes are TC (Tumor core), WT (Whole tumor) and ET (Enhancing tumor). r rYcCsx|jdkr"|jddkr"|d}|dk|dkB|dk|dkB|dkB|dkg}t|tjrjtj|ddStj|ddS)Nrrr)raxis)rrrrrrrstackr)r`rZrr^r^rarbs .z1ConvertToMultiChannelBasedOnBratsClasses.__call__Nrcr^r^r^rarNs c@sVeZdZdZejgZddddddd Zd dd d d Zdd ddddd dddZ dS)rOar Add extreme points of label to the image as a new channel. This transform generates extreme point from label and applies a gaussian filter. The pixel values in points image are rescaled to range [rescale_min, rescale_max] and added as a new channel to input image. The algorithm is described in Roth et al., Going to Extremes: Weakly Supervised Medical Image Segmentation https://arxiv.org/abs/2009.11988. This transform only supports single channel labels (1, spatial_dim1, [spatial_dim2, ...]). The background ``index`` is ignored when calculating extreme points. Args: background: Class index of background label, defaults to 0. pert: Random perturbation amount to add to the points, defaults to 0.0. Raises: ValueError: When no label image provided. ValueError: When label image is not single channel. rrrnrro) backgroundpertr[cCs||_||_g|_dSrl) _background_pert_points)r`r.r/r^r^rart@sz AddExtremePointsChannel.__init__r )r!r[cCst||j|j|jd|_dS)N) rand_stater.r/)rRr0r1r2)r`r!r^r^rarEsz!AddExtremePointsChannel.randomizeN@r rz?Sequence[float] | float | Sequence[torch.Tensor] | torch.Tensor)rZr!sigma rescale_min rescale_maxr[cCsn|dkrtd|jddkr&td||dddft|j||||d}t||^}}t||fddS)a` Args: img: the image that we want to add new channel to. label: label image to get extreme points from. Shape must be (1, spatial_dim1, [, spatial_dim2, ...]). Doesn't support one-hot labels. sigma: if a list of values, must match the count of spatial dimensions of input data, and apply every value in the list to 1 spatial dimension. if only 1 value provided, use it for all spatial dimensions. rescale_min: minimum value of output data. rescale_max: maximum value of output data. Nz&This transform requires a label array!rrz$Only supports single channel labels!)pointsr!r7r8r9r+)rsrrrr2r1r!)r`rZr!r7r8r9 points_imagerr^r^rarbHsz AddExtremePointsChannel.__call__)rr)Nr5r6r ) rdrerfrgr/rhrjrtrrbr^r^r^rarO*scs>eZdZdZejgZdddfdd Zddd d ZZ S) rPaY This is a wrapper transform for PyTorch TorchVision transform based on the specified transform name and args. As most of the TorchVision transforms only work for PIL image and PyTorch Tensor, this transform expects input data to be PyTorch Tensor, users can easily call `ToTensor` transform to convert a Numpy array to Tensor. rror5r[cs4t||_tddt|d\}}||||_dS)z Args: name: The transform name in TorchVision package. args: parameters for the TorchVision transform. kwargs: parameters for the TorchVision transform. ztorchvision.transformsz0.8.0r4N)rrtr5r.r-trans)r`r5argskwargs transformrrr^rartts zTorchVision.__init__r rcCs.t|tj^}}||}t||d^}}|S)z\ Args: img: PyTorch Tensor data for the TorchVision transform. )srcdst)r'rrr=r1)r`rZimg_trrxr^r^rarbs zTorchVision.__call__rr^r^rrarPjs c@sDeZdZdZejejgZej fdddddddZ dd d d Z d S) rQaW Utility to map label values to another set of values. For example, map [3, 2, 1] to [0, 1, 2], [1, 2, 3] -> [0.5, 1.5, 2.5], ["label3", "label2", "label1"] -> [0, 1, 2], [3.5, 2.5, 1.5] -> ["label0", "label1", "label2"], etc. The label data must be numpy array or array-like data and the output data will be numpy array. rr ro) orig_labels target_labelsrr[cCst|t|krtd||_||_tddt|j|jD|_t|}t|dddkrrd|_ t |t j d|_ nd |_ t |tjd|_ d S) a^ Args: orig_labels: original labels that map to others. target_labels: expected label values, 1: 1 map to the `orig_labels`. dtype: convert the output data to dtype, default to float32. if dtype is from PyTorch, the transform will use the pytorch backend, else with numpy backend. z8orig_labels and target_labels must have the same length.css"|]\}}||kr||fVqdSrlr^)rotr^r^rarsz)MapLabelValue.__init__..rerF)rTN)rrsrDrErzippairrgetattr use_numpyr2rrrrr)r`rDrErZ type_dtyper^r^rarts zMapLabelValue.__init__r rc Cs|jrt|tj^}}|j}|}z||j}Wn&tk rZtj |j|jd}YnX|j D]\}}||||k<qb| |} n@t|t j ^} }| |j} |j D]\}}|| | |k<qt| ||jd^} }| S)N)rr)rArBr)rLr'rrrflattenastyperrszerosrJrrrrclonerr1) r`rZimg_nprZ _out_shapeimg_flatout_flatrFrGout_trCrxr^r^rarbs" zMapLabelValue.__call__N) rdrerfrgr/rirhrjrrrtrbr^r^r^rarQs c@sDeZdZdZejgZdddddddd Zdd d d ddddZd S)rRa9 Compute statistics for the intensity values of input image and store into the metadata dictionary. For example: if `ops=[lambda x: np.mean(x), "max"]` and `key_prefix="orig"`, may generate below stats: `{"orig_custom_0": 1.5, "orig_max": 3.0}`. Args: ops: expected operations to compute statistics for the intensity. if a string, will map to the predefined operations, supported: ["mean", "median", "max", "min", "std"] mapping to `np.nanmean`, `np.nanmedian`, `np.nanmax`, `np.nanmin`, `np.nanstd`. if a callable function, will execute the function on input image. key_prefix: the prefix to combine with `ops` name to generate the key to store the results in the metadata dictionary. if some `ops` are callable functions, will use "{key_prefix}_custom_{index}" as the key, where index counts from 0. channel_wise: whether to compute statistics for every channel of input image separately. if True, return a list of values for every operation, default to False. FzSequence[str | Callable]rrzro)ops key_prefix channel_wiser[cCst||_||_||_dSrl)r+rUrVrW)r`rUrVrWr^r^rarts zIntensityStats.__init__Nr dict | Noneznp.ndarray | Noneztuple[NdarrayOrTensor, dict])rZ meta_datamaskr[c s"t|tj^}}|dkri}|dk rn|j|jkrJtd|jd|jd|jtkrftd|jd||}tjtj tj tj tj d}ddd fd d }d }j D]r} t| trt| |} ||| ||jd | <qt| r|| ||jdt|<|d7}qtdq||fS)a Compute statistics for the intensity of input image. Args: img: input image to compute intensity stats. meta_data: metadata dictionary to store the statistics data, if None, will create an empty dictionary. mask: if not None, mask the image to extract only the interested area to compute statistics. mask must have the same shape as input `img`. Nz2mask must have the same shape as input `img`, got z and rz"mask must be bool array, got type )meanmedianrrstdrz np.ndarrayoprkcs jrfdd|DS|S)Ncsg|] }|qSr^r^)rcr_r^rar)sz=IntensityStats.__call__.._compute..)rWr^r`rara_computesz)IntensityStats.__call__.._computerrZ_custom_rzFops must be key string for predefined operations or callable function.)r'rrrrsrrzrnanmean nanmediannanmaxnanminnanstdrUrrrr,keysrVr) r`rZrYrZrQrZ supported_opsrcZ custom_indexrFr^rbrarbs4        zIntensityStats.__call__)F)NN rdrerfrgr/rirjrtrbr^r^r^rarRs c@s6eZdZdZejgZdddddZddd d Zd S) rSa Move PyTorch Tensor to the specified device. It can help cache data into GPU and execute following logic on GPU directly. Note: If moving data to GPU device in the multi-processing workers of DataLoader, may got below CUDA error: "RuntimeError: Cannot re-initialize CUDA in forked subprocess. To use CUDA with multiprocessing, you must use the 'spawn' start method." So usually suggest to set `num_workers=0` in the `DataLoader` or `ThreadDataLoader`. ztorch.device | strro)rr[cKs||_||_dS)a  Args: device: target device to move the Tensor, for example: "cuda:1". kwargs: other args for the PyTorch `Tensor.to()` API, for more details: https://pytorch.org/docs/stable/generated/torch.Tensor.to.html. N)rr?)r`rr?r^r^rart"szToDevice.__init__r}rcCs&t|tjstd|j|jf|jS)NzTimg must be PyTorch Tensor, consider converting img by `EnsureType` transform first.)rrrrrsrrr?r_r^r^rarb-s zToDevice.__call__Nrr^r^r^rarSs  cs0eZdZdZdddfdd ZddZZS) rTa% Wrap a non-randomized cuCIM transform, defined based on the transform name and args. For randomized transforms use :py:class:`monai.transforms.RandCuCIM`. Args: name: the transform name in CuCIM package args: parameters for the CuCIM transform kwargs: parameters for the CuCIM transform Note: CuCIM transform only work with CuPy arrays, so this transform expects input data to be `cupy.ndarray`. Users can call `ToCuPy` transform to convert a numpy array or torch tensor to cupy array. rror<cs2t||_td|d\|_}||_||_dS)Nz&cucim.core.operations.expose.transformr4)rrtr5r.r@r>r?)r`r5r>r?rrr^rartCs  zCuCIM.__init__cCs|j|f|j|jS)z Args: data: a CuPy array (`cupy.ndarray`) for the cuCIM transform Returns: `cupy.ndarray` )r@r>r?rmr^r^rarbJs zCuCIM.__call__)rdrerfrgrtrbrr^r^rrarT4sc@s eZdZdZdddddZdS)rUa Wrap a randomized cuCIM transform, defined based on the transform name and args For deterministic non-randomized transforms use :py:class:`monai.transforms.CuCIM`. Args: name: the transform name in CuCIM package. args: parameters for the CuCIM transform. kwargs: parameters for the CuCIM transform. Note: - CuCIM transform only work with CuPy arrays, so this transform expects input data to be `cupy.ndarray`. Users can call `ToCuPy` transform to convert a numpy array or torch tensor to cupy array. - If the random factor of the underlying cuCIM transform is not derived from `self.R`, the results may not be deterministic. See Also: :py:class:`monai.transforms.Randomizable`. rror<cOstj||f||dSrl)rTrt)r`r5r>r?r^r^rartgszRandCuCIM.__init__N)rdrerfrgrtr^r^r^rarUVsc@s8eZdZdZejgZdddddZdddd d Zd S) r;a Appends additional channels encoding coordinates of the input. Useful when e.g. training using patch-based sampling, to allow feeding of the patch's location into the network. This can be seen as a input-only version of CoordConv: Liu, R. et al. An Intriguing Failing of Convolutional Neural Networks and the CoordConv Solution, NeurIPS 2018. Args: spatial_dims: the spatial dimensions that are to have their coordinates encoded in a channel and appended to the input image. E.g., `(0, 1, 2)` represents `H, W, D` dims and append three channels to the input image, encoding the coordinates of the input's three spatial dimensions. z Sequence[int]ro) spatial_dimsr[cCs ||_dSrl)rk)r`rkr^r^rart}szAddCoordinateChannels.__init__r rYcCst|j|jdks"t|jdkr8td|jdd|jdd}ttjt dd|Dd d i}t ||^}}|t |j}t ||fdd S) za Args: img: data to be transformed, assuming `img` is channel first. rrz)`spatial_dims` values must be within [0, ]rNcss|]}tdd|VqdS)gg?N)rlinspace)rsr^r^rarsz1AddCoordinateChannels.__call__..indexingijr+) rrkrrrsrrarraymeshgridrr1rr!)r`rZ spatial_sizeZcoord_channelsrr^r^rarbs"$zAddCoordinateChannels.__call__Nrjr^r^r^rar;ksc @seZdZdZejejgZedddddddd gZ d+d d d dddZ d,dddddddZ dd dddZ d-d d d dddZ d dd ddd Zd!d"d"d#d$d%d&Zd'd'd(d)d*Zd S).rWat Applies a convolution filter to the input image. Args: filter: A string specifying the filter, a custom filter as ``torch.Tenor`` or ``np.ndarray`` or a ``nn.Module``. Available options for string are: ``mean``, ``laplace``, ``elliptical``, ``sobel``, ``sharpen``, ``median``, ``gauss`` See below for short explanations on every filter. filter_size: A single integer value specifying the size of the quadratic or cubic filter. Computational complexity scales to the power of 2 (2D filter) or 3 (3D filter), which should be considered when choosing filter size. kwargs: Additional arguments passed to filter function, required by ``sobel`` and ``gauss``. See below for details. Raises: ValueError: When ``filter_size`` is not an uneven integer ValueError: When ``filter`` is an array and ``ndim`` is not in [1,2,3] ValueError: When ``filter`` is an array and any dimension has an even shape NotImplementedError: When ``filter`` is a string and not in ``self.supported_filters`` KeyError: When necessary ``kwargs`` are not passed to a filter that requires additional arguments. **Mean Filtering:** ``filter='mean'`` Mean filtering can smooth edges and remove aliasing artifacts in an segmentation image. See also py:func:`monai.networks.layers.simplelayers.MeanFilter` Example 2D filter (5 x 5):: [[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]] If smoothing labels with this filter, ensure they are in one-hot format. **Outline Detection:** ``filter='laplace'`` Laplacian filtering for outline detection in images. Can be used to transform labels to contours. See also py:func:`monai.networks.layers.simplelayers.LaplaceFilter` Example 2D filter (5x5):: [[-1., -1., -1., -1., -1.], [-1., -1., -1., -1., -1.], [-1., -1., 24., -1., -1.], [-1., -1., -1., -1., -1.], [-1., -1., -1., -1., -1.]] **Dilation:** ``filter='elliptical'`` An elliptical filter can be used to dilate labels or label-contours. Example 2D filter (5x5):: [[0., 0., 1., 0., 0.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [0., 0., 1., 0., 0.]] **Edge Detection:** ``filter='sobel'`` This filter allows for additional arguments passed as ``kwargs`` during initialization. See also py:func:`monai.transforms.post.SobelGradients` *kwargs* * ``spatial_axes``: the axes that define the direction of the gradient to be calculated. It calculates the gradient along each of the provide axis. By default it calculate the gradient for all spatial axes. * ``normalize_kernels``: if normalize the Sobel kernel to provide proper gradients. Defaults to True. * ``normalize_gradients``: if normalize the output gradient to 0 and 1. Defaults to False. * ``padding_mode``: the padding mode of the image when convolving with Sobel kernels. Defaults to ``"reflect"``. Acceptable values are ``'zeros'``, ``'reflect'``, ``'replicate'`` or ``'circular'``. See ``torch.nn.Conv1d()`` for more information. * ``dtype``: kernel data type (torch.dtype). Defaults to ``torch.float32``. **Sharpening:** ``filter='sharpen'`` Sharpen an image with a 2D or 3D filter. Example 2D filter (5x5):: [[ 0., 0., -1., 0., 0.], [-1., -1., -1., -1., -1.], [-1., -1., 17., -1., -1.], [-1., -1., -1., -1., -1.], [ 0., 0., -1., 0., 0.]] **Gaussian Smooth:** ``filter='gauss'`` Blur/smooth an image with 2D or 3D gaussian filter. This filter requires additional arguments passed as ``kwargs`` during initialization. See also py:func:`monai.networks.layers.simplelayers.GaussianFilter` *kwargs* * ``sigma``: std. could be a single value, or spatial_dims number of values. * ``truncated``: spreads how many stds. * ``approx``: discrete Gaussian kernel type, available options are "erf", "sampled", and "scalespace". **Median Filter:** ``filter='median'`` Blur an image with 2D or 3D median filter to remove noise. Useful in image preprocessing to improve results of later processing. See also py:func:`monai.networks.layers.simplelayers.MedianFilter` **Savitzky Golay Filter:** ``filter = 'savitzky_golay'`` Convolve a Tensor along a particular axis with a Savitzky-Golay kernel. This filter requires additional arguments passed as ``kwargs`` during initialization. See also py:func:`monai.networks.layers.simplelayers.SavitzkyGolayFilter` *kwargs* * ``order``: Order of the polynomial to fit to each window, must be less than ``window_length``. * ``axis``: (optional): Axis along which to apply the filter kernel. Default 2 (first spatial dimension). * ``mode``: (string, optional): padding mode passed to convolution class. ``'zeros'``, ``'reflect'``, ``'replicate'`` or ``'circular'``. Default: ``'zeros'``. See torch.nn.Conv1d() for more information. r[laplace ellipticalsobelsharpenr\gausssavitzky_golayNz!str | NdarrayOrTensor | nn.Modulerro)filter filter_sizer[cKs0||||j|f|||_||_||_dSrl)_check_filter_format_check_kwargs_are_presentrzr{additional_args_for_filter)r`rzr{r?r^r^rarts  zImageFilter.__init__r rXz list | None)rZrrr[c Cst|tr|j}|j}t|tj\}}}|jd}t|jt rT| |j|j ||_n t|jtjt j frtt|j|_||}|dk s|dk rt|||d}nt|||^}}|S)ay Args: img: torch tensor data to apply filter to with shape: [channels, height, width[, depth]] meta_dict: An optional dictionary with metadata applied_operations: An optional list of operations that have been applied to the data Returns: A MetaTensor with the same shape as `img` and identical metadata rN)rr)rrr rrr'rrrrzr_get_filter_from_stringr{rrr _apply_filter) r`rZrrimg_ prev_typerrrr^r^rarbs     zImageFilter.__call__r)xr[cCs(|D]}|ddkrtd|qdS)Nrrz6Only uneven filters are supported, but filter size is )rs)r`rvaluer^r^ra_check_all_values_uneven<s z$ImageFilter._check_all_values_unevencCst|trL|std|ddkr*td||jkrt|d|jdnTt|tjtjfr~|j dkrptd| |j n"t|t j tfstt|d dS) NzB`filter_size` must be specified when specifying filters by string.rrz0`filter_size` should be a single uneven integer.z. Supported filters are r)rrz*Only 1D, 2D, and 3D filters are supported.z is not supported.Supported types are `class 'str'`, `class 'torch.Tensor'`, `class 'np.ndarray'`, `class 'torch.nn.modules.module.Module'`, `class 'monai.transforms.Transform'`)rrrrssupported_filtersNotImplementedErrorrrrrrrrnnModulerrr)r`rzr{r^r^rar|As     z ImageFilter._check_filter_formatr)rzr?r[cKsJt|tsdS|dkr*d|kr*td|dkrFd|krFtddS)a Perform sanity checks on the kwargs if the filter contains the required keys. If the filter is ``gauss``, kwargs should contain ``sigma``. If the filter is ``savitzky_golay``, kwargs should contain ``order``. Args: filter: A string specifying the filter, a custom filter as ``torch.Tenor`` or ``np.ndarray`` or a ``nn.Module``. kwargs: additional arguments defining the filter. Raises: KeyError if the filter doesn't contain the requirement key. Nrxr7zA`filter='gauss', requires the additional keyword argument `sigma`ryorderzJ`filter='savitzky_golay', requires the additional keyword argument `order`)rrrriKeyError)r`rzr?r^r^rar}Ts  z%ImageFilter._check_kwargs_are_presentrrnznn.Module | Callable)rzsizerr[cs(|dkrt||S|dkr$t||S|dkr6t||S|dkrzddlm}|jjfdd|j D}||f|S|d krt ||S|d krt jjfd d|j D}t |f|S|d krt t ||d S|dkrtjjfdd|j D}t|f|Std|ddS)Nr[rtrurvr)SobelGradientscsi|]\}}|kr||qSr^r^rkv allowed_keysr^ra tsz7ImageFilter._get_filter_from_string..rwrxcsi|]\}}|kr||qSr^r^rrr^rarzsr\) kernel_sizerkrycsi|]\}}|kr||qSr^r^rrr^rarszFilter z not implemented)rrrZmonai.transforms.post.arrayrrt__annotations__rir~itemsrrrrrr)r`rzrrrr?r^rraris0            z#ImageFilter._get_filter_from_stringr}rYcCs4t|jtr||}n||d}|d}|S)Nr)rrrzr unsqueezer_r^r^rars   zImageFilter._apply_filter)N)NN)N)rdrerfrgr/rhrirjsortedrrtrbrr|r}rrr^r^r^rarWs csHeZdZdZejZddddddfd d Zdd d d d ddZZS)rXa Randomly apply a convolutional filter to the input data. Args: filter: A string specifying the filter or a custom filter as `torch.Tenor` or `np.ndarray`. Available options are: `mean`, `laplace`, `elliptical`, `gaussian`` See below for short explanations on every filter. filter_size: A single integer value specifying the size of the quadratic or cubic filter. Computational complexity scales to the power of 2 (2D filter) or 3 (3D filter), which should be considered when choosing filter size. prob: Probability the transform is applied to the data N皙?zstr | NdarrayOrTensorrrro)rzr{rr[c s t|t||f||_dSrl)rrtrWrz)r`rzr{rr?rr^rarts zRandImageFilter.__init__r r~rcCs|d|jr||}|S)a Args: img: torch tensor data to apply filter to with shape: [channels, height, width[, depth]] meta_dict: An optional dictionary with metadata kwargs: optional arguments required by specific filters. E.g. `sigma`if filter is `gauss`. see py:func:`monai.transforms.utility.array.ImageFilter` for more details Returns: A MetaTensor with the same shape as `img` and identical metadata N)rrrz)r`rZrr^r^rarbs  zRandImageFilter.__call__)Nr)N) rdrerfrgrWrjrtrbrr^r^rrarXs )wrg __future__rrrrrcollections.abcrrcopyr functoolsrtypingrrrrrtorch.nnr monai.configr monai.config.type_definitionsr monai.data.meta_objr monai.data.meta_tensorr monai.data.utilsr rZ"monai.networks.layers.simplelayersrrrrrrrrmonai.transforms.inversermonai.transforms.traitsrmonai.transforms.transformrrrrmonai.transforms.utilsrrrr 0monai.transforms.utils_pytorch_numpy_unificationr!r"r#r$ monai.utilsr%r&r'r(r)r*r+r,r-r.monai.utils.enumsr/monai.utils.miscr0monai.utils.type_conversionr1r2rhas_pilrrcphas_cp__all__r8r9r:r<r>r?r@rArBr=rCrVrDrErFrGrHrIrJrKrLrMrNrOrPrQrRrSrTrUr;rWrXr^r^r^ra s        (  0   % >..+K3f"@/A)7@$8M!"$