o
    i*                     @  s   d dl mZ d dlmZ d dlmZ d dlZd dlZd dl	m
Z
mZmZmZ d dlmZmZ ddlmZ d	d
gZG dd	 d	eZ					d d!dd
Z	d"d#ddZdS )$    )annotations)Sequence)AnyN)do_metric_reductionget_edge_surface_distanceignore_backgroundprepare_spacing)MetricReductionconvert_data_type   )CumulativeIterationMetricHausdorffDistanceMetriccompute_hausdorff_distancec                      sJ   e Zd ZdZddddejdfd fddZdddZ	d d!ddZ  Z	S )"r   a  
    Compute Hausdorff Distance between two tensors. It can support both multi-classes and multi-labels tasks.
    It supports both directed and non-directed Hausdorff distance calculation. In addition, specify the `percentile`
    parameter can get the percentile of the distance. Input `y_pred` is compared with ground truth `y`.
    `y_preds` is expected to have binarized predictions and `y` should be in one-hot format.
    You can use suitable transforms in ``monai.transforms.post`` first to achieve binarized values.
    `y_preds` and `y` can be a list of channel-first Tensor (CHW[D]) or a batch-first Tensor (BCHW[D]).
    The implementation refers to `DeepMind's implementation <https://github.com/deepmind/surface-distance>`_.

    Example of the typical execution steps of this metric class follows :py:class:`monai.metrics.metric.Cumulative`.

    Args:
        include_background: whether to include distance computation on the first channel of
            the predicted output. Defaults to ``False``.
        distance_metric: : [``"euclidean"``, ``"chessboard"``, ``"taxicab"``]
            the metric used to compute surface distance. Defaults to ``"euclidean"``.
        percentile: an optional float number between 0 and 100. If specified, the corresponding
            percentile of the Hausdorff Distance rather than the maximum result will be achieved.
            Defaults to ``None``.
        directed: whether to calculate directed Hausdorff distance. Defaults to ``False``.
        reduction: define mode of reduction to the metrics, will only apply reduction on `not-nan` values,
            available reduction modes: {``"none"``, ``"mean"``, ``"sum"``, ``"mean_batch"``, ``"sum_batch"``,
            ``"mean_channel"``, ``"sum_channel"``}, default to ``"mean"``. if "none", will not do reduction.
        get_not_nans: whether to return the `not_nans` count, if True, aggregate() returns (metric, not_nans).
            Here `not_nans` count the number of not nans for the metric, thus its shape equals to the shape of the metric.

    F	euclideanNinclude_backgroundbooldistance_metricstr
percentilefloat | Nonedirected	reductionMetricReduction | strget_not_nansreturnNonec                   s2   t    || _|| _|| _|| _|| _|| _d S N)super__init__r   r   r   r   r   r   )selfr   r   r   r   r   r   	__class__ b/home/dell461/cl/sdc2/last_ska_mid/HISourceFinder-master-l/src/monai/metrics/hausdorff_distance.pyr   9   s   
	
z HausdorffDistanceMetric.__init__y_predtorch.Tensorykwargsr   c              
   K  s<   |  }|dk rtdt||| j| j| j| j|ddS )a  
        Args:
            y_pred: input data to compute, typical segmentation model output.
                It must be one-hot format and first dim is batch, example shape: [16, 3, 32, 32]. The values
                should be binarized.
            y: ground truth to compute the distance. It must be one-hot format and first dim is batch.
                The values should be binarized.
            kwargs: additional parameters, e.g. ``spacing`` should be passed to correctly compute the metric.
                ``spacing``: spacing of pixel (or voxel). This parameter is relevant only
                if ``distance_metric`` is set to ``"euclidean"``.
                If a single number, isotropic spacing with that value is used for all images in the batch. If a sequence of numbers,
                the length of the sequence must be equal to the image dimensions.
                This spacing will be used for all images in the batch.
                If a sequence of sequences, the length of the outer sequence must be equal to the batch size.
                If inner sequence has length 1, isotropic spacing with that value is used for all images in the batch,
                else the inner sequence length must be equal to the image dimensions. If ``None``, spacing of unity is used
                for all images in batch. Defaults to ``None``.

        Raises:
            ValueError: when `y_pred` has less than three dimensions.
           z-y_pred should have at least three dimensions.spacing)r$   r&   r   r   r   r   r)   )
ndimension
ValueErrorr   r   r   r   r   get)r   r$   r&   r'   dimsr"   r"   r#   _compute_tensorJ   s   z'HausdorffDistanceMetric._compute_tensorMetricReduction | str | None0torch.Tensor | tuple[torch.Tensor, torch.Tensor]c                 C  sB   |   }t|tjstdt||p| j\}}| jr||fS |S )a  
        Execute reduction logic for the output of `compute_hausdorff_distance`.

        Args:
            reduction: define mode of reduction to the metrics, will only apply reduction on `not-nan` values,
                available reduction modes: {``"none"``, ``"mean"``, ``"sum"``, ``"mean_batch"``, ``"sum_batch"``,
                ``"mean_channel"``, ``"sum_channel"``}, default to `self.reduction`. if "none", will not do reduction.

        z-the data to aggregate must be PyTorch Tensor.)
get_buffer
isinstancetorchTensorr+   r   r   r   )r   r   datafnot_nansr"   r"   r#   	aggregateo   s
   z!HausdorffDistanceMetric.aggregate)r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r$   r%   r&   r%   r'   r   r   r%   r   )r   r/   r   r0   )
__name__
__module____qualname____doc__r	   MEANr   r.   r8   __classcell__r"   r"   r    r#   r      s    
&Fr   r$   np.ndarray | torch.Tensorr&   r   r   r   r   r   r   r   r)   \int | float | np.ndarray | Sequence[int | float | np.ndarray | Sequence[int | float]] | Noner   r%   c              	     s   |s
t | |d\} }t| tjtjdd } t|tjtjdd }|j| jkr3td| j d|j d| jdd \}}tj||ftj| jd	}	| j	d }
t
|||
d
}t||D ]3\}}t| ||f |||f ||| | |d\}}} fdd|D }tt|}||	||f< qZ|	S )a*  
    Compute the Hausdorff distance.

    Args:
        y_pred: input data to compute, typical segmentation model output.
            It must be one-hot format and first dim is batch, example shape: [16, 3, 32, 32]. The values
            should be binarized.
        y: ground truth to compute mean the distance. It must be one-hot format and first dim is batch.
            The values should be binarized.
        include_background: whether to include distance computation on the first channel of
            the predicted output. Defaults to ``False``.
        distance_metric: : [``"euclidean"``, ``"chessboard"``, ``"taxicab"``]
            the metric used to compute surface distance. Defaults to ``"euclidean"``.
        percentile: an optional float number between 0 and 100. If specified, the corresponding
            percentile of the Hausdorff Distance rather than the maximum result will be achieved.
            Defaults to ``None``.
        directed: whether to calculate directed Hausdorff distance. Defaults to ``False``.
        spacing: spacing of pixel (or voxel). This parameter is relevant only if ``distance_metric`` is set to ``"euclidean"``.
            If a single number, isotropic spacing with that value is used for all images in the batch. If a sequence of numbers,
            the length of the sequence must be equal to the image dimensions. This spacing will be used for all images in the batch.
            If a sequence of sequences, the length of the outer sequence must be equal to the batch size.
            If inner sequence has length 1, isotropic spacing with that value is used for all images in the batch,
            else the inner sequence length must be equal to the image dimensions. If ``None``, spacing of unity is used
            for all images in batch. Defaults to ``None``.
    )r$   r&   )output_typedtyper   z*y_pred and y should have same shapes, got z and .N   rB   device)r)   
batch_sizeimg_dim)r   r)   	symmetricclass_indexc                   s   g | ]}t | qS r"   )&_compute_percentile_hausdorff_distance).0dr   r"   r#   
<listcomp>   s    z.compute_hausdorff_distance.<locals>.<listcomp>)r   r
   r3   r4   floatshaper+   emptyrF   ndimr   npndindexr   maxstack)r$   r&   r   r   r   r   r)   rG   n_classhdrH   Zspacing_listbc_	distancesZpercentile_distancesmax_distancer"   rN   r#   r      s.   #


surface_distancec                 C  sd   | j dkrtjtjtj| jdS |s|  S d|  kr dkr*n nt| |d S t	d| d)zB
    This function is used to compute the Hausdorff distance.
    )r   rE   r   d   z4percentile should be a value between 0 and 100, get rC   )
rQ   r3   tensorrT   nanrP   rF   rV   quantiler+   )r_   r   r"   r"   r#   rK      s   
rK   )Fr   NFN)r$   r?   r&   r?   r   r   r   r   r   r   r   r   r)   r@   r   r%   r   )r_   r%   r   r   r   r%   )
__future__r   collections.abcr   typingr   numpyrT   r3   monai.metrics.utilsr   r   r   r   monai.utilsr	   r
   metricr   __all__r   r   rK   r"   r"   r"   r#   <module>   s$   kA