a
    d!                     @   s   d dl mZmZmZmZmZ d dlmZmZ d dl	m
Z
 d dlmZmZmZmZ d dlmZ d dlmZ esrdgZG dd deZd	S )
    )AnyLiteralOptionalTupleUnion)Tensornn)_LPIPS)GeneratorType*_perceptual_path_length_validate_arguments_validate_generator_modelperceptual_path_length)Metric)_TORCHVISION_AVAILABLEPerceptualPathLengthc                       s   e Zd ZU dZdZeed< dZee ed< dZ	eed< de
ee
ed eee
 ee ee eejed f edd fddZeddddZeeeef dddZ  ZS )r   a  Computes the perceptual path length (`PPL`_) of a generator model.

    The perceptual path length can be used to measure the consistency of interpolation in latent-space models. It is
    defined as

    .. math::
        PPL = \mathbb{E}\left[\frac{1}{\epsilon^2} D(G(I(z_1, z_2, t)), G(I(z_1, z_2, t+\epsilon)))\right]

    where :math:`G` is the generator, :math:`I` is the interpolation function, :math:`D` is a similarity metric,
    :math:`z_1` and :math:`z_2` are two sets of latent points, and :math:`t` is a parameter between 0 and 1. The metric
    thus works by interpolating between two sets of latent points, and measuring the similarity between the generated
    images. The expectation is approximated by sampling :math:`z_1` and :math:`z_2` from the generator, and averaging
    the calculated distanced. The similarity metric :math:`D` is by default the `LPIPS`_ metric, but can be changed by
    setting the `sim_net` argument.

    The provided generator model must have a `sample` method with signature `sample(num_samples: int) -> Tensor` where
    the returned tensor has shape `(num_samples, z_size)`. If the generator is conditional, it must also have a
    `num_classes` attribute. The `forward` method of the generator must have signature `forward(z: Tensor) -> Tensor`
    if `conditional=False`, and `forward(z: Tensor, labels: Tensor) -> Tensor` if `conditional=True`. The returned
    tensor should have shape `(num_samples, C, H, W)` and be scaled to the range [0, 255].

    .. note:: using this metric with the default feature extractor requires that ``torchvision`` is installed.
        Either install as ``pip install torchmetrics[image]`` or ``pip install torchvision``

    As input to ``forward`` and ``update`` the metric accepts the following input

    - ``generator`` (:class:`~torch.nn.Module`):  Generator model, with specific requirements. See above.

    As output of `forward` and `compute` the metric returns the following output

    - ``ppl_mean`` (:class:`~torch.Tensor`): float scalar tensor with mean PPL value over distances
    - ``ppl_std`` (:class:`~torch.Tensor`): float scalar tensor with std PPL value over distances
    - ``ppl_raw`` (:class:`~torch.Tensor`): float scalar tensor with raw PPL distances

    Args:
        num_samples: Number of samples to use for the PPL computation.
        conditional: Whether the generator is conditional or not (i.e. whether it takes labels as input).
        batch_size: Batch size to use for the PPL computation.
        interpolation_method: Interpolation method to use. Choose from 'lerp', 'slerp_any', 'slerp_unit'.
        epsilon: Spacing between the points on the path between latent points.
        resize: Resize images to this size before computing the similarity between generated images.
        lower_discard: Lower quantile to discard from the distances, before computing the mean and standard deviation.
        upper_discard: Upper quantile to discard from the distances, before computing the mean and standard deviation.
        sim_net: Similarity network to use. Can be a `nn.Module` or one of 'alex', 'vgg', 'squeeze', where the three
            latter options correspond to the pretrained networks from the `LPIPS`_ paper.
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        ModuleNotFoundError:
            If ``torch-fidelity`` is not installed.
        ValueError:
            If ``num_samples`` is not a positive integer.
        ValueError:
            If `conditional` is not a boolean.
        ValueError:
            If ``batch_size`` is not a positive integer.
        ValueError:
            If ``interpolation_method`` is not one of 'lerp', 'slerp_any', 'slerp_unit'.
        ValueError:
            If ``epsilon`` is not a positive float.
        ValueError:
            If ``resize`` is not a positive integer.
        ValueError:
            If ``lower_discard`` is not a float between 0 and 1 or None.
        ValueError:
            If ``upper_discard`` is not a float between 0 and 1 or None.

    Example::
        >>> from torchmetrics.image import PerceptualPathLength
        >>> import torch
        >>> _ = torch.manual_seed(42)
        >>> class DummyGenerator(torch.nn.Module):
        ...    def __init__(self, z_size) -> None:
        ...       super().__init__()
        ...       self.z_size = z_size
        ...       self.model = torch.nn.Sequential(torch.nn.Linear(z_size, 3*128*128), torch.nn.Sigmoid())
        ...    def forward(self, z):
        ...       return 255 * (self.model(z).reshape(-1, 3, 128, 128) + 1)
        ...    def sample(self, num_samples):
        ...      return torch.randn(num_samples, self.z_size)
        >>> generator = DummyGenerator(2)
        >>> ppl = PerceptualPathLength(num_samples=10)
        >>> ppl(generator)  # doctest: +SKIP
        (tensor(0.2371),
        tensor(0.1763),
        tensor([0.3502, 0.1362, 0.2535, 0.0902, 0.1784, 0.0769, 0.5871, 0.0691, 0.3921]))

    Fis_differentiableThigher_is_betterfull_state_update'     lerp-C6?@   {Gz?Gz?vgg)r   Z	slerp_anyZ
slerp_unitZalexr   ZsqueezeN)num_samplesconditional
batch_sizeinterpolation_methodepsilonresizelower_discardupper_discardsim_netkwargsreturnc
              	      s   t  jf i |
 tstdt|||||||| || _|| _|| _|| _|| _	|| _
|| _|| _t|	tjrx|	| _n(|	dv rtd|	|d| _ntd|	 d S )NzMetric `PerceptualPathLength` requires torchvision which is not installed.Install with `pip install torchvision` or `pip install torchmetrics[image]`r   T)Z
pretrainednetr"   zDsim_net must be a nn.Module or one of 'alex', 'vgg', 'squeeze', got )super__init__r   ModuleNotFoundErrorr   r   r   r   r    r!   r"   r#   r$   
isinstancer   Moduler(   r	   
ValueError)selfr   r   r   r    r!   r"   r#   r$   r%   r&   	__class__ r/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/image/perceptual_path_length.pyr*   }   s*    zPerceptualPathLength.__init__)	generatorr'   c                 C   s   t || j || _dS )zUpdate the generator model.N)r   r   r4   )r/   r4   r2   r2   r3   update   s    zPerceptualPathLength.update)r'   c                 C   s0   t | j| j| j| j| j| j| j| j| j	| j
d
S )z#Compute the perceptual path length.)
r4   r   r   r    r!   r"   r#   r$   r%   device)r   r4   r   r   r    r!   r"   r#   r$   r(   r6   )r/   r2   r2   r3   compute   s    zPerceptualPathLength.compute)	r   Fr   r   r   r   r   r   r   )__name__
__module____qualname____doc__r   bool__annotations__r   r   r   intr   floatr   r   r-   r   r*   r
   r5   r   r   r7   __classcell__r2   r2   r0   r3   r       s8   
X         &N)typingr   r   r   r   r   Ztorchr   r   Z#torchmetrics.functional.image.lpipsr	   Z4torchmetrics.functional.image.perceptual_path_lengthr
   r   r   r   Ztorchmetrics.metricr   Ztorchmetrics.utilities.importsr   Z__doctest_skip__r   r2   r2   r2   r3   <module>   s   