U Phc;@sddlmZddlmZmZddlmZddlmZddl Z ddl m Z ddl m Z mZdd d d gZGd ddeZGd d d eZGdd d ZGdd d eeZdS)) annotations)ABCabstractmethod)Sequence)AnyN) TensorOrList)convert_data_typeevenly_divisible_all_gatherMetricIterationMetric CumulativeCumulativeIterationMetricc@s.eZdZdZeddddddZddZdS) r z Base class for metric computation for evaluating the performance of a model. `__call__` is designed to execute the computation. rargskwargsreturncOstd|jjddS)zz This method should take raw model outputs as inputs, and return values that measure the models' quality. Subclass  must implement this method.NNotImplementedError __class____name__selfrrrI/home/dell461/cl/sdc2/HISourceFinder-master-l/src/monai/metrics/metric.py__call__!szMetric.__call__cCs|jjSN)rrrrrr__str__(szMetric.__str__N)r __module__ __qualname____doc__rrrrrrrr sc@sVeZdZdZdddddddd Zddddd dd d Zedd ddddddZdS)r ax Base class for metrics computation at the iteration level, that is, on a min-batch of samples usually using the model outcome of one iteration. `__call__` is designed to handle `y_pred` and `y` (optional) in torch tensors or a list/tuple of tensors. Subclasses typically implement the `_compute_tensor` function for the actual tensor computation logic. NrTensorOrList | Noner>torch.Tensor | Sequence[torch.Tensor | Sequence[torch.Tensor]]y_predyrrcKspt|ttfst|ttfr,|j||f|St|tjrdt|tjrL|nd}|j||f|StddS)a Execute basic computation for model prediction `y_pred` and ground truth `y` (optional). It supports inputs of a list of "channel-first" Tensor and a "batch-first" Tensor. Args: y_pred: the raw model prediction data at one iteration, must be a list of `channel-first` Tensor or a `batch-first` Tensor. y: the ground truth to compute, must be a list of `channel-first` Tensor or a `batch-first` Tensor. kwargs: additional parameters for specific metric computation logic (e.g. ``spacing`` for SurfaceDistanceMetric, etc.). Returns: The computed metric values at the iteration level. The output shape could be a `batch-first` tensor or a list of `batch-first` tensors. When it's a list of tensors, each item in the list can represent a specific type of metric. NzVy_pred or y must be a list/tuple of `channel-first` Tensors or a `batch-first` Tensor.) isinstancelisttuple _compute_listtorchTensordetach_compute_tensor ValueError)rr&r'ry_rrrr6s  zIterationMetric.__call__z:torch.Tensor | list[torch.Tensor | Sequence[torch.Tensor]]c s|dk r$fddt||D}nfdd|D}t|dtjrVtj|ddSt|dttfrtdd|dDrd dt|DS|S) a Execute the metric computation for `y_pred` and `y` in a list of "channel-first" tensors. The return value is a "batch-first" tensor, or a list of "batch-first" tensors. When it's a list of tensors, each item in the list can represent a specific type of metric values. For example, `self._compute_tensor` may be implemented as returning a list of `batch_size` items, where each item is a tuple of three values `tp`, `fp`, `fn` for true positives, false positives, and false negatives respectively. This function will return a list of three items, (`tp_batched`, `fp_batched`, `fn_batched`), where each item is a `batch_size`-length tensor. Note: subclass may enhance the operation to have multi-thread support. Ncs4g|],\}}j|d|dfqSrr/r. unsqueeze).0pr1rrrr dsz1IterationMetric._compute_list..cs&g|]}j|ddfqS)rNr3)r5p_r7rrr8isrdimcss|]}t|tjVqdSr)r(r,r-)r5irrr osz0IterationMetric._compute_list..cSsg|]}tj|ddqS)rr:)r,cat)r5batch_irrrr8ps)zipr(r,r-r>r)r*allrr&r'rretrr7rr+Ss (zIterationMetric._compute_listz torch.Tensorztorch.Tensor | NonecKstd|jjddS)a Computation logic for `y_pred` and `y` of an iteration, the data should be "batch-first" Tensors. A subclass should implement its own computation logic. The return value is usually a "batch_first" tensor, or a list of "batch_first" tensors. rrNr)rr&r'rrrrr/sszIterationMetric._compute_tensor)N)N)N)rr r!r"rr+rr/rrrrr ,s  c@steZdZdZddddZddZddd d d Zddd d d ZeddddddZ ddZ ddZ ddZ dS)r a: Utility class for the typical cumulative computation process based on PyTorch Tensors. It provides interfaces to accumulate values in the local buffers, synchronize buffers across distributed nodes, and aggregate the buffered values. In multi-processing, PyTorch programs usually distribute data to multiple nodes. Each node runs with a subset of the data, adds values to its local buffers. Calling `get_buffer` could gather all the results and `aggregate` can further handle the results to generate the final outcomes. Users can implement their own `aggregate` method to handle the results, using `get_buffer` to get the buffered contents. Note: the data list should have the same length every time calling `add()` in a round, it will automatically create buffers according to the length of data list. Typically, this class is expected to execute the following steps: .. code-block:: python from monai.metrics import Cumulative c = Cumulative() c.append(1) # adds a value c.extend([2, 3]) # adds a batch of values c.extend([4, 5, 6]) # adds a batch of values print(c.get_buffer()) # tensor([1, 2, 3, 4, 5, 6]) print(len(c)) # 6 c.reset() print(len(c)) # 0 The following is an example of maintaining two internal buffers: .. code-block:: python from monai.metrics import Cumulative c = Cumulative() c.append(1, 2) # adds a value to two buffers respectively c.extend([3, 4], [5, 6]) # adds batches of values print(c.get_buffer()) # [tensor([1, 3, 4]), tensor([2, 5, 6])] print(len(c)) The following is an example of extending with variable length data: .. code-block:: python import torch from monai.metrics import Cumulative c = Cumulative() c.extend(torch.zeros((8, 2)), torch.zeros((6, 2))) # adds batches c.append(torch.zeros((2, ))) # adds a value print(c.get_buffer()) # [torch.zeros((9, 2)), torch.zeros((6, 2))] print(len(c)) None)rcCsd|_d|_d|_|dS)z Initialize the internal buffers. `self._buffers` are local buffers, they are not usually used directly. `self._sync_buffers` are the buffers with all the results across all the nodes. NF)_buffers_synced_tensors_syncedresetrrrr__init__szCumulative.__init__cCsd|_d|_d|_dS)zS Reset the buffers for cumulative tensors and the synced results. NF)rErFrGrrrrrHszCumulative.resetr)datarc Gs|jdkrdd|D|_t|j|D]\}}t|tjdd^}}z$|ddtj|ddd DWq&ttt fk r}zt |d t ||W5d}~XYq&Xq&d |_ dS) a Extend the local buffers with new ("batch-first") data. A buffer will be allocated for each `data` item. Compared with `self.append`, this method adds a "batch" of data to the local buffers. Args: data: each item can be a "batch-first" tensor or a list of "channel-first" tensors. they will be concatenated at the 0-th dimension when `get_buffer()` is called. NcSsg|]}gqSrrr5_rrrr8sz%Cumulative.extend..T output_type wrap_sequencecSsg|] }|dqSr2rr5xrrrr8srr:zP. `data` should be a batch-first tensor or a list of channel-first tensors, got F) rEr@rr,r-extendsplitAttributeError IndexError RuntimeError TypeErrortyperG)rrJbdd_trLerrrrSs $zCumulative.extendcGsX|jdkrdd|D|_t|j|D]&\}}t|tjdd^}}||q&d|_dS)a Add samples to the local cumulative buffers. A buffer will be allocated for each `data` item. Compared with `self.extend`, this method adds a single sample (instead of a "batch") to the local buffers. Args: data: each item will be converted into a torch tensor. they will be stacked at the 0-th dim with a new dimension when `get_buffer()` is called. NcSsg|]}gqSrrrKrrrr8sz%Cumulative.append..TrMF)rEr@rr,r-appendrG)rrJrZr[r\rLrrrr^s  zCumulative.appendrcOstd|jjddS)z Aggregate final results based on the gathered buffers. This method is expected to use `get_buffer` to gather the local buffer contents. rrNrrrrr aggregateszCumulative.aggregatec Csv|js|jdkrdSzdd|jD|_Wn@tttfk rj}zt|d|jd|W5d}~XYnXd|_dS)z All gather the buffers across distributed ranks for aggregating. Each buffer will be concatenated as a PyTorch Tensor. NcSs"g|]}ttj|ddddqS)rr:T)concat)r r,stack)r5rZrrrr8 sz$Cumulative._sync..z". unable to sync buffer contents: .T)rGrErFrWrXr0)rr]rrr_syncs *zCumulative._synccCs*||jdkrdStdd|jDS)z Return the length of the largest buffer. Note that the method will trigger synchronization of the local buffers. Nrcss|]}|dk rt|VqdSr)lenrPrrrr=sz%Cumulative.__len__..)rcrFmaxrrrr__len__s zCumulative.__len__cCs@||jdkr|jSdd|jD}t|dkr<|dS|S)z Get the synchronized list of buffers. A typical usage is to generate the metrics report based on the raw metric details. Each buffer is a PyTorch Tensor. NcSs(g|] }t|tjr |n|qSr)r(r,r-r.clonerPrrrr8$sz)Cumulative.get_buffer..rRr)rcrFrd)rbuffersrrr get_buffers  zCumulative.get_bufferN) rr r!r"rIrHrSr^rr_rcrfrirrrrr }s9   cs.eZdZdZd dddddfdd ZZS) r a4 Base class of cumulative metric which collects metrics on each mini-batch data at the iteration level. Typically, it computes some intermediate results for each iteration, adds them to the buffers, then the buffer contents could be gathered and aggregated for the final result when epoch completed. Currently,``Cumulative.aggregate()`` and ``IterationMetric._compute_tensor()`` are expected to be implemented. For example, `MeanDice` inherits this class and the usage is as follows: .. code-block:: python dice_metric = DiceMetric(include_background=True, reduction="mean") for val_data in val_loader: val_outputs = model(val_data["img"]) val_outputs = [postprocessing_transform(i) for i in decollate_batch(val_outputs)] # compute metric for current iteration dice_metric(y_pred=val_outputs, y=val_data["seg"]) # callable to add metric to the buffer # aggregate the final mean dice result metric = dice_metric.aggregate().item() # reset the status for next computation round dice_metric.reset() And to load `predictions` and `labels` from files, then compute metrics with multi-processing, please refer to: https://github.com/Project-MONAI/tutorials/blob/master/modules/compute_metric.py. Nrr#rr$r%c s@tjf||d|}t|ttfr2|j|n |||S)a Execute basic computation for model prediction and ground truth. It can support both `list of channel-first Tensor` and `batch-first Tensor`. Users call this API to execute computation on every batch of data, then accumulate the results, or accumulate the original `y_pred` and `y`, then execute on the accumulated data. Args: y_pred: the model prediction data to compute, must be a list of `channel-first` Tensor or a `batch-first` Tensor. y: the ground truth to compute, must be a list of `channel-first` Tensor or a `batch-first` Tensor. kwargs: additional parameters for specific metric computation logic (e.g. ``spacing`` for SurfaceDistanceMetric, etc.). Returns: The computed metric values at the iteration level. The output shape should be a `batch-first` tensor (BC[HWD]) or a list of `batch-first` tensors. )r&r')superrr(r*r)rSrBrrrrGs   z"CumulativeIterationMetric.__call__)N)rr r!r"r __classcell__rrrkrr (s) __future__rabcrrcollections.abcrtypingrr, monai.configr monai.utilsrr __all__r r r r rrrr s     Q,