o
    .wi                     @   sx   d dl mZmZmZmZ d dlZd dlmZ d dlm	Z	 d dl
mZ G dd deZG dd	 d	eZG d
d deZdS )    )AnyCallableOptionalUnionN)MetricCollection)Metric)WrapperMetricc                       s   e Zd ZdZdeeef deee	f ddf fddZ
dejdejfd	d
ZdejdejfddZdejdeejdf fddZdejdeee	f ddfddZde	fddZdejdeee	f de	fddZd fddZ  ZS )MetricInputTransformerzAbstract base class for metric input transformations.

    Input transformations are characterized by them applying a transformation to the input data of a metric, and then
    forwarding all calls to the wrapped metric with modifications applied.

    wrapped_metrickwargsreturnNc                    s8   t  jdi | t|ttfstd| || _d S )NzsExpected wrapped metric to be an instance of `torchmetrics.Metric` or `torchmetrics.MetricsCollection`but received  )super__init__
isinstancer   r   	TypeErrorr
   )selfr
   r   	__class__r   b/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/wrappers/transformations.pyr      s   
zMetricInputTransformer.__init__predc                 C      |S )zuDefine transform operations on the prediction data.

        Overridden by subclasses. Identity by default.

        r   )r   r   r   r   r   transform_pred(      z%MetricInputTransformer.transform_predtargetc                 C   r   )zqDefine transform operations on the target data.

        Overridden by subclasses. Identity by default.

        r   r   r   r   r   r   transform_target0   r   z'MetricInputTransformer.transform_targetargs.c                 G   sn   t |dkr| |d fS t |dkr"| |d | |d fS | |d | |d g|dd R S )zWWrap transformation functions to dispatch args to their individual transform functions.   r      N)lenr   r   )r   r   r   r   r   _wrap_transform8   s
   *z&MetricInputTransformer._wrap_transformc                 O   s    | j | }| jj|i | dS )z.Wrap the update call of the underlying metric.N)r!   r
   updater   r   r   r   r   r   r"   @   s   
zMetricInputTransformer.updatec                 C   s
   | j  S )z/Wrap the compute call of the underlying metric.)r
   computer   r   r   r   r$   E   s   
zMetricInputTransformer.computec                 O   s   | j | }| jj|i |S )z/Wrap the forward call of the underlying metric.)r!   r
   forwardr#   r   r   r   r&   I   s   
zMetricInputTransformer.forwardc                    s   | j   t   dS )z-Wrap the reset call of the underlying metric.N)r
   resetr   r%   r   r   r   r'   N   s   
zMetricInputTransformer.reset)r   N)__name__
__module____qualname____doc__r   r   r   dictstrr   r   torchTensorr   r   tupler!   r"   r$   r&   r'   __classcell__r   r   r   r   r	      s    *	  r	   c                       s`   e Zd ZdZ		d
dedeeejgejf  deeejgejf  de	ddf
 fdd	Z
  ZS )LambdaInputTransformera1  Wrapper class for transforming a metrics' inputs given a user-defined lambda function.

    Args:
        wrapped_metric:
            The underlying `Metric` or `MetricCollection`.
        transform_pred:
            The function to apply to the predictions before computing the metric.
        transform_target:
            The function to apply to the target before computing the metric.

    Raises:
        TypeError:
            If `transform_pred` is not a Callable.
        TypeError:
            If `transform_target` is not a Callable.

    Example:
        >>> import torch
        >>> from torchmetrics.classification import BinaryAccuracy
        >>> from torchmetrics.wrappers import LambdaInputTransformer
        >>>
        >>> preds = torch.tensor([0.9, 0.8, 0.7, 0.6, 0.5, 0.6, 0.7, 0.8, 0.5, 0.4])
        >>> targets = torch.tensor([1,0,0,0,0,1,1,0,0,0])
        >>>
        >>> metric = LambdaInputTransformer(BinaryAccuracy(), lambda preds: 1 - preds)
        >>> metric.update(preds, targets)
        >>> metric.compute()
        tensor(0.6000)

    Nr
   r   r   r   r   c                    sh   t  j|fi | |d urt|std| d|| _|d ur2t|s-td| d|| _d S d S )NzAExpected `transform_pred` to be of type `Callable` but received ``zCExpected `transform_target` to be of type `Callable` but received `)r   r   callabler   r   r   )r   r
   r   r   r   r   r   r   r   t   s   

zLambdaInputTransformer.__init__)NN)r(   r)   r*   r+   r   r   r   r.   r/   r   r   r1   r   r   r   r   r2   T   s    "r2   c                	       sR   e Zd ZdZddeeef dededdf fdd	Z	d
e
jde
jfddZ  ZS )BinaryTargetTransformera  Wrapper class for computing a metric on binarized targets.

    Useful when the given ground-truth targets are continuous, but the metric requires binary targets.

    Args:
        wrapped_metric:
            The underlying `Metric` or `MetricCollection`.
        threshold:
            The binarization threshold for the targets. Targets values `t` are cast to binary with `t > threshold`.

    Raises:
        TypeError:
            If `threshold` is not an `int` or `float`.

    Example:
        >>> import torch
        >>> from torchmetrics.retrieval import RetrievalMRR
        >>> from torchmetrics.wrappers import BinaryTargetTransformer
        >>>
        >>> preds = torch.tensor([0.9, 0.8, 0.7, 0.6, 0.5, 0.6, 0.7, 0.8, 0.5, 0.4])
        >>> targets = torch.tensor([1,0,0,0,0,2,1,0,0,0])
        >>> topics = torch.tensor([0,0,0,0,0,1,1,1,1,1])
        >>>
        >>> metric = BinaryTargetTransformer(RetrievalMRR())
        >>> metric.update(preds, targets, indexes=topics)
        >>> metric.compute()
        tensor(0.7500)

    r   r
   	thresholdr   r   Nc                    s<   t  j|fi | t|ttfstd| d|| _d S )NzBExpected `threshold` to be of type `int` or `float` but received `r3   )r   r   r   intfloatr   r6   )r   r
   r6   r   r   r   r   r      s   
z BinaryTargetTransformer.__init__r   c                 C   s   | | j|jS )zyCast the target tensor to binary values according to the threshold.

        Output assumes same type as input.

        )gtr6   todtyper   r   r   r   r      s   z(BinaryTargetTransformer.transform_target)r   )r(   r)   r*   r+   r   r   r   r8   r   r   r.   r/   r   r1   r   r   r   r   r5      s    (r5   )typingr   r   r   r   r.   torchmetrics.collectionsr   torchmetrics.metricr   torchmetrics.wrappers.abstractr   r	   r2   r5   r   r   r   r   <module>   s   =5