U
    ¤PÓhº  ã                   @  sŠ   d dl mZ d dlZd dlmZmZ d dlmZ dddddœd	d
„Zdddddœdd„Zddddddœdd„Z	dddddddœdd„Z
dS )é    )ÚannotationsN)ÚTensorÚnn)ÚSlidingWindowInfererzdict[str, list[Tensor]]zlist[str] | NoneÚNone)Úhead_outputsÚkeysÚreturnc                 C  sd   |dkrt |  ¡ ƒ}|D ]F}| | }t|tƒr:|g| |< qt|d tƒrVt |ƒ| |< qtdƒ‚qdS )a¼  
    An in-place function. We expect ``head_outputs`` to be Dict[str, List[Tensor]].
    Yet if it is Dict[str, Tensor], this func converts it to Dict[str, List[Tensor]].
    It will be modified in-place.

    Args:
        head_outputs: a Dict[str, List[Tensor]] or Dict[str, Tensor], will be modifier in-place
        keys: the keys in head_output that need to have value type List[Tensor]. If not provided, will use head_outputs.keys().
    Nr   zMThe output of network should be Dict[str, List[Tensor]] or Dict[str, Tensor].)Úlistr   Ú
isinstancer   Ú
ValueError)r   r   ÚkZvalue_k© r   ú]/home/dell461/cl/sdc2/HISourceFinder-master-l/src/monai/apps/detection/utils/predict_utils.pyÚensure_dict_value_to_list_   s    

r   c                   sV   |dkrt ˆ  ¡ ƒ}‡ fdd„|D ƒ}t t |¡¡}t|ƒdkrRtd|› dƒ‚dS )ai  
    We expect the values in ``head_outputs``: Dict[str, List[Tensor]] to have the same length.
    Will raise ValueError if not.

    Args:
        head_outputs: a Dict[str, List[Tensor]] or Dict[str, Tensor]
        keys: the keys in head_output that need to have values (List) with same length.
            If not provided, will use head_outputs.keys().
    Nc                   s   g | ]}t ˆ | ƒ‘qS r   )Úlen)Ú.0r   ©r   r   r   Ú
<listcomp>9   s     z1check_dict_values_same_length.<locals>.<listcomp>é   z>The values in the input dict should have the same length, Got Ú.)r
   r   ÚtorchÚuniqueÚtensorr   r   )r   r   Znum_output_levels_listÚnum_output_levelsr   r   r   Úcheck_dict_values_same_length,   s    
r   r   z	nn.Modulezlist[Tensor])ÚimagesÚnetworkr   r	   c                 C  sh   || ƒ}t |ttfƒrt|ƒS t||ƒ |dkr<t| ¡ ƒ}t||ƒ g }|D ]}|t|| ƒ7 }qN|S )aA  
    Decompose the output of network (a dict) into a list.

    Args:
        images: input of the network
        keys: the keys in the network output whose values will be output in this func.
            If not provided, will use all keys.

    Return:
        network output values concat to a single List[Tensor]
    N)r   Útupler
   r   r   r   )r   r   r   r   Úhead_outputs_sequencer   r   r   r   Ú_network_sequence_output?   s    

r    z	list[str]zSlidingWindowInferer | None)r   r   r   Úinfererr	   c           	      C  sj   |dkrt dƒ‚|| t||d}t|ƒt|ƒ }i }t|ƒD ](\}}t||| ||d  … ƒ||< q<|S )aB  
    Predict network dict output with an inferer. Compared with directly output network(images),
    it enables a sliding window inferer that can be used to handle large inputs.

    Args:
        images: input of the network, Tensor sized (B, C, H, W) or  (B, C, H, W, D)
        network: a network that takes an image Tensor sized (B, C, H, W) or (B, C, H, W, D) as input
            and outputs a dictionary Dict[str, List[Tensor]] or Dict[str, Tensor].
        keys: the keys in the output dict, should be network output keys or a subset of them.
        inferer: a SlidingWindowInferer to handle large inputs.

    Return:
        The predicted head_output from network, a Dict[str, List[Tensor]]

    Example:
        .. code-block:: python

            # define a naive network
            import torch
            import monai
            class NaiveNet(torch.nn.Module):
                def __init__(self, ):
                    super().__init__()

                def forward(self, images: torch.Tensor):
                    return {"cls": torch.randn(images.shape), "box_reg": [torch.randn(images.shape)]}

            # create a predictor
            network = NaiveNet()
            inferer = monai.inferers.SlidingWindowInferer(
                roi_size = (128, 128, 128),
                overlap = 0.25,
                cache_roi_weight_map = True,
            )
            network_output_keys=["cls", "box_reg"]
            images = torch.randn((2, 3, 512, 512, 512))  # a large input
            head_outputs = predict_with_inferer(images, network, network_output_keys, inferer)

    NzFPlease set inferer as a monai.inferers.inferer.SlidingWindowInferer(*))r   r   )r   r    r   Ú	enumerater
   )	r   r   r   r!   r   r   r   Úir   r   r   r   Úpredict_with_inferer\   s    *"r$   )N)N)N)N)Ú
__future__r   r   r   r   Úmonai.inferersr   r   r   r    r$   r   r   r   r   Ú<module>   s    ÿ