o  iO=@sLdZddlmZddlZddlZddlZddlZddlmZm Z m Z ddl m Z ddl mZddlmZmZmZddlZddlZddlmZddlmZdd lmZdd lmZdd lmZdd l m!Z!m"Z"m#Z#dd l$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,ddl-m.Z.m/Z/ddl0m1Z1ddl2m3Z3m4Z4m5Z5m6Z6ddl7m8Z8m9Z9m:Z:m;Z;mZ>m?Z?m@Z@mAZAmBZBddlCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMddlNmOZOddlPmQZQmRZRmSZSeMddd\ZTZUeMddd\ZVZWeMd\ZXZYgdZZGddde6Z[Gddde4Z\Gd d!d!e6Z]Gd"d#d#e6Z^Gd$d%d%e6Z_Gd&d'd'e6Z`Gd(d)d)e6e1ZaGd*d+d+e6ZbGd,d-d-e6ZcGd.d/d/e6ZdGd0d1d1e6ZeGd2d3d3e6ZfGd4d5d5e6ZgGd6d7d7e6ZhGd8d9d9e6ZiGd:d;d;e6ZjGdd?d?e.ZlGd@dAdAele5ZmGdBdCdCe6ZnGdDdEdEe6e1ZoGdFdGdGe6e1ZpGdHdIdIe6ZqGdJdKdKe3e6ZrGdLdMdMe6ZsGdNdOdOe6e4ZtGdPdQdQe6ZuGdRdSdSe6e4ZvGdTdUdUZwGdVdWdWe6ZxGdXdYdYe6ZyGdZd[d[e6ZzGd\d]d]eze4Z{Gd^d_d_e6Z|Gd`dadae6Z}Gdbdcdce5Z~Gdddedee.e6ZdS)fz= A collection of "vanilla" transforms for utility functions. ) annotationsN)HashableMappingSequence)deepcopy)partial)AnyCallableUnion) DtypeLike)NdarrayOrTensor)get_track_meta) MetaTensor) is_no_channel no_collationorientation_ras_lps) ApplyFilterEllipticalFilterGaussianFilter LaplaceFilter MeanFilterSavitzkyGolayFilter SharpenFilter median_filter)InvertibleTransformTraceableTransform)MultiSampleTrait) RandomizableRandomizableTraitRandomizableTransform Transform)apply_affine_to_pointsextreme_points_to_imageget_extreme_pointsmap_binary_to_indicesmap_classes_to_indices) concatenatein1d linalg_invmoveaxisunravel_indices) MetaKeys TraceKeysconvert_data_typeconvert_to_cupyconvert_to_numpyconvert_to_tensor ensure_tuplelook_up_option min_versionoptional_import)TransformBackends)convert_to_dst_typeget_dtype_stringget_equivalent_dtypez PIL.ImageImagename fromarraycupy)%Identity RandIdentity AsChannelLastAddCoordinateChannelsEnsureChannelFirst EnsureType RepeatChannelRemoveRepeatedChannelSplitDim CastToTypeToTensorToNumpyToPIL Transpose SqueezeDim DataStats SimulateDelayLambda RandLambda LabelToMask FgBgToIndicesClassesToIndices(ConvertToMultiChannelBasedOnBratsClassesAddExtremePointsChannel TorchVisionTorchIO MapLabelValueIntensityStatsToDeviceCuCIM RandCuCIM RandTorchIORandTorchVisionToCupy ImageFilterRandImageFilterApplyTransformToPointsc@&eZdZdZejejgZdddZdS) r>z Do nothing to the data. As the output value is same as input, it can be used as a testing tool to verify the transform chain, Compose or transform adaptor, etc. imgr returncC|S/ Apply the transform to `img`. selfrdriri`/home/dell461/cl/sdc2/last_ska_mid/HISourceFinder-master-l/src/monai/transforms/utility/array.py__call__}szIdentity.__call__Nrdr rer __name__ __module__ __qualname____doc__r5TORCHNUMPYbackendrmriririrlr>ts r>c@rc) r?z Do nothing to the data. This transform is random, so can be used to stop the caching of any subsequent transforms. datarrecCrfNrirkrwririrlrmszRandIdentity.__call__N)rwrrerroriririrlr?s r?c@s2eZdZdZejejgZddddZdd 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. r channel_dimintreNonecCs,t|tr |dkstd|d||_dS)Nzinvalid channel dimension (z).) isinstancer{ ValueErrorrz)rkrzririrl__init__s zAsChannelLast.__init__rdr cCstt||jdtd}|S)rhr} track_meta)r0r)rzr rkrdoutririrlrmszAsChannelLast.__call__N)r)rzr{rer|rn rprqrrrsr5rtrurvrrmriririrlr@   r@c@s4eZdZdZejejgZdddd ZddddZ dS)rBa 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. TN strict_checkboolrzNone | str | intcC||_||_dSrx)rinput_channel_dim)rkrrzririrlr zEnsureChannelFirst.__init__rd torch.Tensor meta_dictMapping | NonerecCst|ts#t|ts#|jdurd}|jrt|t||St|}t|tr+|j}t|tr7| t j dnd}|jdurJ|jdkrGt dn|j}|dur^d}|jrWt|t||St|t rh||t j <t|rq|d}nt|t|d}t|tdS)rhNzNMetadata 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`.rr)r~rrrrrwarningswarnmetagetr+ORIGINAL_CHANNEL_DIMfloatdictrr)r{r0r )rkrdrmsgrzresultririrlrms2        zEnsureChannelFirst.__call__)TN)rrrzrrx)rdrrrrerrriririrlrBs   rBc@,eZdZdZejgZd ddZdd d Zd S)rDa5 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. repeatsr{rer|cC"|dkr td|d||_dSNrz*repeats count must be greater than 0, got .rrrkrririrlrs zRepeatChannel.__init__rdr cCs0t|tjr tjntj}t|||jdtdS)Z Apply the transform to `img`, assuming `img` is a "channel-first" array. rr) r~torchTensorrepeat_interleavenprepeatr0rr )rkrdZ repeat_fnririrlrmszRepeatChannel.__call__Nrr{rer|rn rprqrrrsr5rtrvrrmriririrlrDs  rDc@s0eZdZdZejejgZd ddZdd d Z d S)rEaK 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. rr{rer|cCrrrrririrlrs zRemoveRepeatedChannel.__init__rdr cCsJ|jddkrtd|jddt|dd|jddftd}|S)rrz+Image must have more than one channel, got z channels.Nr)shaperr0rr rririrlrms"zRemoveRepeatedChannel.__call__NrrnrriririrlrEs  rEc@s2eZdZdZejejgZddd d ZdddZ dS)rFaV 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. r}Tdimr{keepdimrrer|cCs||_||_||_dSrx)rr update_meta)rkrrrririrlr3 zSplitDim.__init__rdrlist[torch.Tensor]cCs|j|j}t|tjrtt|d|j}nt|||j}t|D]I\}}|j s2| |j||<|j rlt|t rlt|t sFt ||j d}|jdkrLq#t|j}tj||jj|jjd}|||jddf<|j||_q#|S)rh)rr)devicedtyper})rrr~rrlistsplitr enumeratersqueezerrrlenaffineeyerr)rkrdn_outoutputsidxitemndimshiftririrlrm8s$      zSplitDim.__call__N)r}TT)rr{rrrer|)rdrrerrriririrlrF"rrFc@s8eZdZdZejejgZej fd ddZ ddd d Z dS)rGa 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 rer|cCs ||_dS)zd Args: dtype: convert image to this data type, default is `np.float32`. Nr)rkrririrlris zCastToType.__init__Nrdr rDtypeLike | torch.dtypecCst|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)rkrdrririrlrmps zCastToType.__call__)rer|rx)rdr rrrer ) rprqrrrsr5rtrurvrfloat32rrmriririrlrGPs  rGcs>eZdZdZejgZ    ddfdd ZdddZZ S)rHa 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``. NTrtorch.dtype | Nonertorch.device | str | None wrap_sequencerr bool | Nonerer|cs>t||_||_||_|durt|_dSt||_dSrx)superrrrrr rr)rkrrrr __class__rirlrs "zToTensor.__init__rdr cCs*t|trg|_t||j|j|j|jdS)F Apply the transform to `img` and make it contiguous. )rrrr)r~rapplied_operationsr0rrrrrjririrlrms zToTensor.__call__)NNTN) rrrrrrrrrer|rdr rprqrrrsr5rtrvrrm __classcell__ririrrlrH~s rHc@s>eZdZdZejejgZ     ddddZddddZ dS)rCa 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 tensorNT data_typestrrrrtorch.device | Nonerrrrrer|cCsHt|ddh|_||_||_||_|durt|_dSt||_dS)Nrnumpy) r2lowerrrrrr rr)rkrrrrrririrlrs "zEnsureType.__init__rwr cCsN|jdkr|jr tntj}ntj}t|||dur|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)rwrrrr) rrrrrrndarrayr-rrr)rkrwrrr_ririrlrms  zEnsureType.__call__)rNNTN) rrrrrrrrrrrer|rx)rwr rrrriririrlrCs ! rCc6eZdZdZejgZddfd d ZdddZZ S)rIa 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])`. NTrr rrrer|ct||_||_dSrxrrrrrkrrrrirlr  zToNumpy.__init__rdr cCt||j|jdS)rrr)r/rrrjririrlrmzToNumpy.__call__NT)rr rrrer|r) rprqrrrsr5rurvrrmrririrrlrIs  rIcr)r_aA 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])`. NTrnp.dtype | Nonerrrer|crrxrrrrirlrrzToCupy.__init__rwr cCr)zH Create a CuPy array from `data` and make it contiguous r)r.rrryririrlrm!rzToCupy.__call__r)rrrrrer|)rwr ) rprqrrrsr5CUPYrvrrmrririrrlr_ s  r_c@s eZdZdZejgZddZdS)rJz^ Converts the input image (in the form of NumPy array or PyTorch Tensor) to PIL image cCs2t|tr|St|tjr|}t|Srg)r~ PILImageImagerrdetachcpurpil_image_fromarrayrjririrlrm/s  zToPIL.__call__N)rprqrrrsr5rurvrmriririrlrJ(s rJc@r)rKzU Transposes the input image based on the given `indices` dimension ordering. indicesSequence[int] | Nonerer|cCs |dur d|_dSt||_dSrx)tupler)rkrririrlrAs zTranspose.__init__rdr cCs2t|td}||jptt|jdddS)rhrNr})r0r permuterrrangerrjririrlrmDs$zTranspose.__call__N)rrrer|rnrriririrlrK:s  rKc@s2eZdZdZejejgZdddd Zdd d Z dS)rLz& Squeeze a unitary dimension. rTr int | Nonerer|cCs8|durt|tstdt|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)r~r{ TypeErrorrrprr)rkrrririrlrSs  zSqueezeDim.__init__rdr cCsrt|td}|jdur|jrtd|S|jdkr%|jt|jn|j}|j|dkr>t d|j|d|jd||}|jrt |t r|dkrt|j jd kr|j j\}}|j t |j t jrj|j jnd}}||kr|t jd||d |dk}||kr|ddt jd||d |dkf}|jd|jdkrtjt|d d std |j d||_ |S)z[ Args: img: numpy arrays with required dimension `dim` removed rNz*update_meta=True is ignored when dim=None.rrz0Can only squeeze singleton dimension, got shape z of rr)rT)rz,After SqueezeDim, img.affine is ill-posed: )r0r rrrrrrrrr~rrrrrarangerlinalgdetr/)rkrdrhwrrririrlrmcs(    ( "$(zSqueezeDim.__call__N)rT)rrrer|rnrriririrlrLLs   rLc@sReZdZdZejejgZ        ddddZ       ddddZ dS)rMaJ 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`. DataTFNprefixrrr data_shape value_range data_value meta_infoadditional_infoCallable | Noner;rer|c Cst|tstdt|d||_||_||_||_||_||_ |dur4t |s4t dt|j d||_ ||_t|j} | tjtjtjkrptdd| jD} | srttj} | tjd| _| | dSdSdS)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. meta_info: whether to show the data of MetaTensor. 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).0rririrl s z%DataStats.__init__..T)r~rrrrrrrrrcallablerrpr _logger_namelogging getLoggersetLevelINFOrootgetEffectiveLevelanyhandlers StreamHandlersysstdoutr addHandler) rkrrrrrrrr;_loggerZhas_console_handlerconsoleririrlrs2     zDataStats.__init__rdr str | Nonerc Cs|p|jdg} |dur|jr(n|r(| dt|dt|dr#|jnd|dur0|jrBn|rB| dt|dr=|jnd|durJ|jrn|rt |t j re| dt |d t |d n$t |tjr~| dt |d t |d n | d t|d |dur|jrn|r| d ||dur|jrn|rt|d d} | dt| |dur|jn|}|dur| 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: rz(input is not a MetaTensor)z Meta info: zAdditional info:  )rrappendrrrrrrr~rrminmaxrrrrgetattrreprrjoinrrrinfo) rkrdrrrrrrrlinesmetadata separatoroutputririrlrms.*  & &  zDataStats.__call__)rTTTFFNrM)rrrrrrrrrrrrrrr;rrer|)NNNNNNN)rdr rrrrrrrrrrrrrrrer rriririrlrMs(  8rMcs<eZdZdZejejgZddfdd Zddd dZ Z S)rNa 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. delay_timerrer|cst||_dS)z Args: delay_time: The minimum amount of time, in fractions of seconds, to accomplish this delay task. N)rrr!)rkr!rrirlrs  zSimulateDelay.__init__Nrdr float | NonecCs"t|dur |j|S||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!)rkrdr!ririrlrmszSimulateDelay.__call__)r )r!rrer|rx)rdr r!r"rer ) rprqrrrsr5rtrurvrrmrririrrlrNs   rNc@sDeZdZdZejejgZdedfdd d Z ddddZ dddZ dS)rOa 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]``. NTfuncrinv_funcr rrrer|cCs<|durt|stdt|jd||_||_||_dS)N%func must be None or callable but is r)rrrrpr%r&rrkr%r&rririrlr)s  zLambda.__init__rdr cCsz|dur|n|j}t|stdt|jd||}t|tjtj fr1t|t s1|j r1t |}t|t r;| ||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]``. Nr'r) r%rrrrpr~rrrrrrpush_transform)rkrdr%fnrririrlrm2s "  zLambda.__call__rwrcCst|tr ||||Srx)r~r pop_transformr&ryririrlinverseHs   zLambda.inverse)r%rr&r rrrer|rxrdr r%rrwr) rprqrrrsr5rtrurvrrrmr,riririrlrOs  rOcsLeZdZdZejZddedfdddZddfdd Zdfdd Z Z S)rPa 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?Tr%rprobrr&r rrrer|cCs$tj||||dtj||ddS)Nr()rkr0)rOrr)rkr%r0r&rririrlr_szRandLambda.__init__rdr csn||t|jrt||n|}t|ts|jrt|}t|tr5|jr,||ni}|j ||d|S)N) extra_info) randomizer _do_transformrrmr~rrr+r))rkrdr%rZ lambda_inforrirlrmis  zRandLambda.__call__rwrcs4||tj}|rt|}|S|||Srx)get_most_recent_transformpopr, DO_TRANSFORMrr,r+)rkrw do_transformrrirlr,ts   zRandLambda.inverse) r%rr0rr&r rrrer|rxr-r.) rprqrrrsrOrvrrrmr,rririrrlrPNs   rPc@s8eZdZdZejejgZ ddd d Z ddddZ d S)rQa 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. F select_labelsSequence[int] | intmerge_channelsrrer|cCst||_||_dSrx)r1r8r:)rkr8r:ririrlrs  zLabelToMask.__init__Nrdr Sequence[int] | int | NonecCst|td}|dur|j}nt|}|jddkr!|g|}nt|tjr*tjnt j}|t ||dd |j}|s?|j rF| ddS|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. rNrrTF)r0r r8r1rr~rrwhererr'reshaper:r )rkrdr8r:rwr<ririrlrms  zLabelToMask.__call__F)r8r9r:rrer|)NF)rdr r8r;r:rrer rriririrlrQ}s  rQc@s6eZdZdZejejgZddd d Z ddddZ dS)rRa 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. r Nimage_thresholdr output_shaperrer|cCrrx)r?r@)rkr?r@ririrlrrzFgBgToIndices.__init__labelr imageNdarrayOrTensor | None'tuple[NdarrayOrTensor, NdarrayOrTensor]cCsD|dur|j}t|||j\}}|durt||}t||}||fS)a Args: label: input data to compute foreground and background indices. image: if image is not None, use ``label = 0 & image > 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)r@r$r?r*)rkrArBr@ fg_indices bg_indicesririrlrms   zFgBgToIndices.__call__)r N)r?rr@rrer|NN)rAr rBrCr@rrerD) rprqrrrsr5rurtrvrrmriririrlrRs   rRc@s:eZdZejejgZ    ddd d Z ddddZdS)rSNr  num_classesrr?rr@rmax_samples_per_classrer|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)rHr?r@rI)rkrHr?r@rIririrlrs zClassesToIndices.__init__rAr rBrClist[NdarrayOrTensor]csBdur|jt||j||j|j}durfdd|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|qSri)r*)r cls_indicesr@rirl sz-ClassesToIndices.__call__..)r@r%rHr?rI)rkrArBr@rrirLrlrms zClassesToIndices.__call__)Nr NN) rHrr?rr@rrIrrer|rG)rAr rBrCr@rrerJ) rprqrrr5rurtrvrrmriririrlrSs  rSc@rc) rTa Convert labels to multi channels based on `brats18 `_ classes, which include TC (Tumor core), WT (Whole tumor) and ET (Enhancing tumor): label 1 is the necrotic and non-enhancing tumor core, which should be counted under TC and WT subregion, label 2 is the peritumoral edema, which is counted only under WT subregion, label 4 is the GD-enhancing tumor, which should be counted under ET, TC, WT subregions. rdr recCsx|jdkr|jddkr|d}|dk|dkB|dk|dkB|dkB|dkg}t|tjr5tj|ddStj|ddS)Nrrr)raxis)rrrr~rrstackr)rkrdrririrlrm s .(z1ConvertToMultiChannelBasedOnBratsClasses.__call__NrnroriririrlrTs rTc@sBeZdZdZejgZddd d ZdddZ    dd ddZ dS)!rUar 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. rr  backgroundr{pertrrer|cCs||_||_g|_dSrx) _background_pert_points)rkrRrSririrlrArz AddExtremePointsChannel.__init__rAr cCst||j|j|jd|_dS)N) rand_staterRrS)r#RrTrUrV)rkrAririrlr2Fsz!AddExtremePointsChannel.randomizeN@r/rdrCsigma?Sequence[float] | float | Sequence[torch.Tensor] | torch.Tensor rescale_min rescale_maxcCsn|durtd|jddkrtd||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!)pointsrAr[r]r^rO)rrr2r"rVr6r&)rkrdrAr[r]r^ points_imagerririrlrmIs z AddExtremePointsChannel.__call__)rr )rRr{rSrrer|)rAr rer|)NrYrZr/) rdr rArCr[r\r]rr^rrer ) rprqrrrsr5rtrvrr2rmriririrlrU+s  rUc4eZdZdZejgZd fdd Zd d d ZZ S)rVz This is a wrapper transform for PyTorch TorchVision non-randomized transform based on the specified transform name and args. Data is converted to a torch.tensor before applying the transform and then converted back to the original data type. r;rrer|c8t||_tddt|d\}}||i||_dSz Args: name: The transform name in TorchVision package. args: parameters for the TorchVision transform. kwargs: parameters for the TorchVision transform. ztorchvision.transformsz0.8.0r:Nrrr;r4r3transrkr;argskwargs transformrrrirlrs zTorchVision.__init__rdr cC.t|tj^}}||}t||d^}}|Sz\ Args: img: PyTorch Tensor data for the TorchVision transform. )srcdstr-rrrer6rkrdimg_trrririrlrm zTorchVision.__call__r;rrer|rrririrrlrVk  rVcra)r^z This is a wrapper transform for PyTorch TorchVision randomized transform based on the specified transform name and args. Data is converted to a torch.tensor before applying the transform and then converted back to the original data type. r;rrer|crbrcrdrfrrirlrrjzRandTorchVision.__init__rdr cCrkrlrorpririrlrmrrzRandTorchVision.__call__rsrrririrrlr^rtr^cra)rWz This is a wrapper for TorchIO non-randomized transforms based on the specified transform name and args. See https://torchio.readthedocs.io/transforms/transforms.html for more details. r;rrer|crbz Args: name: The transform name in TorchIO package. args: parameters for the TorchIO transform. kwargs: parameters for the TorchIO transform. ztorchio.transformsz0.18.0r:Nrdrfrrirlr zTorchIO.__init__rd:Union[NdarrayOrTensor, Mapping[Hashable, NdarrayOrTensor]]cC ||Sz Args: img: an instance of torchio.Subject, torchio.Image, numpy.ndarray, torch.Tensor, SimpleITK.Image, or dict containing 4D tensors as values rerjririrlrm zTorchIO.__call__rsrdrwrririrrlrWs  rWcra)r]aa This is a wrapper for TorchIO randomized transforms based on the specified transform name and args. See https://torchio.readthedocs.io/transforms/transforms.html for more details. Use this wrapper for all TorchIO transform inheriting from RandomTransform: https://torchio.readthedocs.io/transforms/augmentation.html#randomtransform r;rrer|crbrurdrfrrirlrrvzRandTorchIO.__init__rdrwcCrxryrzrjririrlrmr{zRandTorchIO.__call__rsr|rririrrlr]s  r]c@s6eZdZdZejejgZej fdd d Z dd dZ dS)rXaW 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. orig_labelsr target_labelsrr rer|cCst|t|kr td||_||_tddt|j|jD|_t|}t|dddkr:d|_ t |t j d|_ d Sd |_ 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||fVqdSrxri)rotririrlrs"z)MapLabelValue.__init__..rqrF)rTN)rrr}r~rzippairrr use_numpyr8rrrrr)rkr}r~rZ type_dtyperirirlrs zMapLabelValue.__init__rdr c Cs|jrAt|tj^}}|j}|}z||j}Wnty,tj |j|jd}Ynw|j D] \}}||||k<q0| |} n t|t j ^} }| |j} |j D] \}}|| | |k<qVt| ||jd^} }| S)N)rr)rmrnr)rr-rrrflattenastyperrzerosrr=rrrclonetor6) rkrdimg_nprZ _out_shapeimg_flatout_flatrrout_trqrririrlrms$  zMapLabelValue.__call__N)r}rr~rrr rer|r) rprqrrrsr5rurtrvrrrrmriririrlrXs  rXc@s2eZdZdZejgZddd d Z ddddZd S)rYa9 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. FopsSequence[str | Callable] key_prefixr channel_wiserrer|cCst||_||_||_dSrx)r1rrr)rkrrrririrlr:rzIntensityStats.__init__Nrdr meta_data dict | Nonemasknp.ndarray | Nonetuple[NdarrayOrTensor, dict]c st|tj^}}|duri}|dur7|j|jkr%td|jd|jd|jtkr3td|jd||}tjtj tj tj tj d}dfd d }d }j D]7} t| trmt| |} ||| ||jd| <qPt| r|| ||jdt|<|d7}qPtd||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 )meanmedianrrstdopr rw np.ndarraycs jr fdd|DS|S)Ncsg|]}|qSriri)rcrrirlrMasz=IntensityStats.__call__.._compute..)r)rrwrkrrl_compute_sz)IntensityStats.__call__.._computerrZ_custom_rzFops must be key string for predefined operations or callable function.)rr rwr)r-rrrrrrrnanmean nanmediannanmaxnanminnanstdrr~rr2keysrr) rkrdrrrrZ supported_opsrZ custom_indexrrirrlrm?s4      zIntensityStats.__call__r>)rrrrrrrer|rG)rdr rrrrrer rprqrrrsr5rurvrrmriririrlrY%s  rYc@r)rZa 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`. rtorch.device | strrer|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)rrh)rkrrhririrlrs zToDevice.__init__rdrcCs*t|tjs td|j|jfi|jS)NzTimg must be PyTorch Tensor, consider converting img by `EnsureType` transform first.)r~rrrrrrhrjririrlrms zToDevice.__call__N)rrrer|)rdrrriririrlrZrs   rZcs*eZdZdZd fdd Zdd ZZS) r[a% 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. r;rrer|cs2t||_td|d\|_}||_||_dS)Nz&cucim.core.operations.expose.transformr:)rrr;r4rirgrh)rkr;rgrhrrrirlrs  zCuCIM.__init__cCs|j|g|jRi|jS)z Args: data: a CuPy array (`cupy.ndarray`) for the cuCIM transform Returns: `cupy.ndarray` )rirgrhryririrlrms zCuCIM.__call__rs)rprqrrrsrrmrririrrlr[sr[c@seZdZdZd ddZdS) r\a 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`. r;rrer|cOstj||g|Ri|dSrx)r[r)rkr;rgrhririrlrszRandCuCIM.__init__Nrs)rprqrrrsrriririrlr\sr\c@r)rAa 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. spatial_dims Sequence[int]rer|cCs ||_dSrx)r)rkrririrlrs zAddCoordinateChannels.__init__rdr cCst|j|jdkst|jdkrtd|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)rsririrlrsz1AddCoordinateChannels.__call__..indexingijrO) rrrrrrrarraymeshgridrr6rr&)rkrd spatial_sizeZcoord_channelsrririrlrms"$zAddCoordinateChannels.__call__N)rrrer|rnrriririrlrAs  rAc@sveZdZdZejejgZegdZ d(d)d d Z d*d+ddZ d,ddZ d(d)ddZ d-ddZd.d#d$Zd/d&d'ZdS)0r`at 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. )rlaplace ellipticalsobelsharpenrgausssavitzky_golayNfilter!str | NdarrayOrTensor | nn.Module filter_sizerrer|cKs4||||j|fi|||_||_||_dSrx)_check_filter_format_check_kwargs_are_presentrradditional_args_for_filter)rkrrrhririrlrus  zImageFilter.__init__rdr rrr list | Nonec Cst|tr |j}|j}t|tj\}}}|jd}t|jt r*| |j|j ||_nt|jtjt j fr:t|j|_||}|dusG|durPt|||d}|St|||^}}|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)r~rrrr-rrrrr_get_filter_from_stringrrrr _apply_filter) rkrdrrimg_ prev_typerrrririrlrm|s     zImageFilter.__call__xrcCs(|D]}|ddkrtd|qdS)Nrrz6Only uneven filters are supported, but filter size is )r)rkrvalueririrl_check_all_values_unevens  z$ImageFilter._check_all_values_unevencCst|tr-|dkr|std|r|ddkrtd||jvr+t|d|jddSt|tjtjfrG|j dvr?td | |j dSt|t j tfsXtt|d dS) NrzB`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'`)r~rrsupported_filtersNotImplementedErrorrrrrrrrnnModuler rr)rkrrririrlrs"     z ImageFilter._check_filter_formatrhrcKsNt|tsdS|dkrd|vrtd|dkr#d|vr%tddSdS)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. Nrr[zA`filter='gauss', requires the additional keyword argument `sigma`rorderzJ`filter='savitzky_golay', requires the additional keyword argument `order`)r~rrKeyError)rkrrhririrlrs z%ImageFilter._check_kwargs_are_presentrsizer{rnn.Module | Callablecs.|dkr t||S|dkrt||S|dkrt||S|dkr?ddlm}|jjfdd|j D}||fi|S|d krHt ||S|d krft jjfd d|j D}t |fi|S|d krqt t ||d S|dkrtjjfdd|j D}t|fi|Std|d)Nrrrrr)SobelGradientsci|] \}}|vr||qSririrkv allowed_keysrirl z7ImageFilter._get_filter_from_string..rrcrririrrrirlrrr) kernel_sizerrcrririrrrirlrrzFilter z not implemented)rrrZmonai.transforms.post.arrayrr__annotations__rritemsrrrrrr)rkrrrrrhrirrlrs0        z#ImageFilter._get_filter_from_stringrcCs6t|jtr ||}|S||d}|d}|S)Nr)r~rr unsqueezerjririrlrs  zImageFilter._apply_filterrx)rrrrrer|rG)rdr rrrrrer )rrrer|)rrrhrrer|)rrrr{rr{rer)rdrrer)rprqrrrsr5rtrurvsortedrrrmrrrrrriririrlr`s      r`cs8eZdZdZejZ ddfd d ZddddZZS)raa 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皙?rstr | NdarrayOrTensorrrr0rrer|c s$t|t||fi||_dSrx)rrr`r)rkrrr0rhrrirlrs zRandImageFilter.__init__rdr rrcCs|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)r2r3r)rkrdrririrlrms  zRandImageFilter.__call__)Nr)rrrrr0rrer|rx)rdr rrrer ) rprqrrrsr`rvrrmrririrrlras rac@sTeZdZdZ    ddddZddddZ dd ddZdd!ddZd"ddZdS)#rba Transform points between image coordinates and world coordinates. The input coordinates are assumed to be in the shape (C, N, 2 or 3), where C represents the number of channels and N denotes the number of points. It will return a tensor with the same shape as the input. Args: dtype: The desired data type for the output. affine: A 3x3 or 4x4 affine transformation matrix applied to points. This matrix typically originates from the image. For 2D points, a 3x3 matrix can be provided, avoiding the need to add an unnecessary Z dimension. While a 4x4 matrix is required for 3D transformations, it's important to note that when applying a 4x4 matrix to 2D points, the additional dimensions are handled accordingly. The matrix is always converted to float64 for computation, which can be computationally expensive when applied to a large number of points. If None, will try to use the affine matrix from the input data. invert_affine: Whether to invert the affine transformation matrix applied to the points. Defaults to ``True``. Typically, the affine matrix is derived from an image and represents its location in world space, while the points are in world coordinates. A value of ``True`` represents transforming these world space coordinates to the image's coordinate space, and ``False`` the inverse of this operation. affine_lps_to_ras: Defaults to ``False``. Set to `True` if your point data is in the RAS coordinate system or you're using `ITKReader` with `affine_lps_to_ras=True`. This ensures the correct application of the affine transformation between LPS (left-posterior-superior) and RAS (right-anterior-superior) coordinate systems. This argument ensures the points and the affine matrix are in the same coordinate system. Use Cases: - Transforming points between world space and image space, and vice versa. - Automatically handling inverse transformations between image space and world space. - If points have an existing affine transformation, the class computes and applies the required delta affine transformation. NTFrDtypeLike | torch.dtype | Nonertorch.Tensor | None invert_affineraffine_lps_to_rasrer|cCs||_||_||_||_dSrx)rrrr)rkrrrrririrlr8s zApplyTransformToPoints.__init__rapplied_affinecCsBt|tjdd}|jrt|}|jrt|}|dur||}|S)a9 Compute the final affine transformation matrix to apply to the point data. Args: data: Input coordinates assumed to be in the shape (C, N, 2 or 3). affine: 3x3 or 4x4 affine transformation matrix. Returns: Final affine transformation matrix. rrN)r-rfloat64rrrr()rkrrririrl_compute_final_affineDs z,ApplyTransformToPoints._compute_final_affinerwtuple[torch.Tensor, dict]c Cst|td}|dur|jrtdt|dd}|dur|n|}|dur(td|||}t|||jd}|jt|j||j d}|j rKt t |nt |}t j ||||d}||fS) a" Transform coordinates using an affine transformation matrix. Args: data: The input coordinates are assumed to be in the shape (C, N, 2 or 3), where C represents the number of channels and N denotes the number of points. affine: 3x3 or 4x4 affine transformation matrix. The matrix is always converted to float64 for computation, which can be computationally expensive when applied to a large number of points. Returns: Transformed coordinates. rNz3affine must be provided when invert_affine is True.rz?affine must be provided if data does not have an affine matrix.r)rr image_affiner)rr1transform_info)r0r rrrrr!rr7rrr(rtrack_transform_metaget_transform_info) rkrwrrZ final_affinerr1xformrririrltransform_coordinates\s&   z,ApplyTransformToPoints.transform_coordinatescCs|jdks |jddvrtd|jd|dur|jn|}|dur0|jdvr0td|jd|||\}}t|trB||S|S) aD Args: data: The input coordinates are assumed to be in the shape (C, N, 2 or 3), where C represents the number of channels and N denotes the number of points. affine: A 3x3 or 4x4 affine transformation matrix, this argument will take precedence over ``self.affine``. rr})rrz,data should be in shape (C, N, 2 or 3), got rN))rr)rNrNz0affine should be in shape (3, 3) or (4, 4), got )rrrrrr~rcopy_meta_from)rkrwrrrririrlrmszApplyTransformToPoints.__call__cCs|||}t|tjd|tjd |tjdd}|d|||tjd}Wd|S1s7wY|S)Nrrr)rrrFr)r+rbr, EXTRA_INFOtrace_transform)rkrwriinverse_transformririrlr,s     zApplyTransformToPoints.inverse)NNTF) rrrrrrrrrer|rx)rrrrrer)rwrrrrer)rwrrr)rwrrer) rprqrrrsrrrrmr,riririrlrbs"  )rb)rs __future__rrr r#rcollections.abcrrrcopyr functoolsrtypingrr r rrrtorch.nnr monai.configr monai.config.type_definitionsr monai.data.meta_objr monai.data.meta_tensorrmonai.data.utilsrrrZ"monai.networks.layers.simplelayersrrrrrrrrmonai.transforms.inverserrmonai.transforms.traitsrmonai.transforms.transformrrrr monai.transforms.utilsr!r"r#r$r%0monai.transforms.utils_pytorch_numpy_unificationr&r'r(r)r* monai.utilsr+r,r-r.r/r0r1r2r3r4monai.utils.enumsr5monai.utils.type_conversionr6r7r8rhas_pilrrcphas_cp__all__r>r?r@rBrDrErFrGrHrCrIr_rJrKrLrMrNrOrPrQrRrSrTrUrVr^rWr]rXrYrZr[r\rAr`rarbriririrls        ( 0  ) >..+K3m"@/8)7@"" 8M!"$*