import numpy as np

import datasets


A__           =							"""
Compute the Mahalanobis Distance

Mahalonobis distance is the distance between a point and a distribution.
And not between two distinct points. It is effectively a multivariate equivalent of the Euclidean distance.
It was introduced by Prof. P. C. Mahalanobis in 1936
and has been used in various statistical applications ever since
[source: https://www.machinelearningplus.com/statistics/mahalanobis-distance/]
"""

A__           =							"""\
@article{de2000mahalanobis,
  title={The mahalanobis distance},
  author={De Maesschalck, Roy and Jouan-Rimbaud, Delphine and Massart, D{\'e}sir{\'e} L},
  journal={Chemometrics and intelligent laboratory systems},
  volume={50},
  number={1},
  pages={1--18},
  year={2000},
  publisher={Elsevier}
}
"""

A__           =							"""
Args:
    X: List of datapoints to be compared with the `reference_distribution`.
    reference_distribution: List of datapoints from the reference distribution we want to compare to.
Returns:
    mahalanobis: The Mahalonobis distance for each datapoint in `X`.
Examples:

    >>> mahalanobis_metric = datasets.load_metric(\"mahalanobis\")
    >>> results = mahalanobis_metric.compute(reference_distribution=[[0, 1], [1, 0]], X=[[0, 1]])
    >>> print(results)
    {'mahalanobis': array([0.5])}
"""
@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION      ,   _KWARGS_DESCRIPTION				)
class   _lowerCAmelCase		(     datasets.Metric				):







							def 				snake_case  (				self     :    Optional[int]		):
										return datasets.MetricInfo(
										    description=_DESCRIPTION	,					citation=_CITATION	,					inputs_description=_KWARGS_DESCRIPTION	,					features=datasets.Features(
										        {
										            '''X''': datasets.Sequence(datasets.Value('''float'''	,					id='''sequence'''		)	,					id='''X'''		),
										        }		)	,					)







							def 				snake_case  (				self     :    List[Any]	,					__snake_case     :    str	,					__snake_case     :    Union[str, Any]		):
										# convert to numpy arrays
										lowerCamelCase						:List[Any]						  =     np.array(__snake_case		)
										lowerCamelCase						:str						  =     np.array(__snake_case		)

										# Assert that arrays are 2D
										if len(X.shape		) != 2:
													raise ValueError('''Expected `X` to be a 2D vector'''		)
										if len(reference_distribution.shape		) != 2:
													raise ValueError('''Expected `reference_distribution` to be a 2D vector'''		)
										if reference_distribution.shape[0] < 2:
													raise ValueError(
													    '''Expected `reference_distribution` to be a 2D vector with more than one element in the first dimension'''		)

										# Get mahalanobis distance for each prediction
										lowerCamelCase						:Dict						  =     X - np.mean(__snake_case		)
										lowerCamelCase						:Optional[int]						  =     np.cov(reference_distribution.T		)
										try:
													lowerCamelCase						:List[Any]						  =     np.linalg.inv(__snake_case		)
										except np.linalg.LinAlgError:
													lowerCamelCase						:int						  =     np.linalg.pinv(__snake_case		)
										lowerCamelCase						:Optional[Any]						  =     np.dot(__snake_case	,					__snake_case		)
										lowerCamelCase						:Optional[int]						  =     np.dot(__snake_case	,					X_minus_mu.T		).diagonal()

										return {"mahalanobis": mahal_dist}




import unittest

from transformers import is_vision_available
from transformers.pipelines import pipeline
from transformers.testing_utils import (
    is_pipeline_test,
    nested_simplify,
    require_tf,
    require_torch,
    require_vision,
    slow,
)

from .test_pipelines_common import ANY


if is_vision_available():
			from PIL import Image
else:
			class   _lowerCAmelCase		:







										@staticmethod
										def 				snake_case  (				*__snake_case     :    str	,					**__snake_case     :    str		):
													pass
@is_pipeline_test
@require_vision
class   _lowerCAmelCase		(     unittest.TestCase				):







							@require_torch
							def 				snake_case  (				self     :    Union[str, Any]		):
										lowerCamelCase						:Optional[int]						  =     pipeline(
										    model='''hf-internal-testing/tiny-random-clip-zero-shot-image-classification'''	,					)
										lowerCamelCase						:List[str]						  =     Image.open('''./tests/fixtures/tests_samples/COCO/000000039769.png'''		)
										lowerCamelCase						:Dict						  =     image_classifier(__snake_case	,					candidate_labels=['''a''', '''b''', '''c''']		)

										# The floating scores are so close, we enter floating error approximation and the order is not guaranteed across
										# python and torch versions.
										self.assertIn(
										    nested_simplify(__snake_case		)	,					[
										        [{'''score''': 0.3_3_3, '''label''': '''a'''}, {'''score''': 0.3_3_3, '''label''': '''b'''}, {'''score''': 0.3_3_3, '''label''': '''c'''}],
										        [{'''score''': 0.3_3_3, '''label''': '''a'''}, {'''score''': 0.3_3_3, '''label''': '''c'''}, {'''score''': 0.3_3_3, '''label''': '''b'''}],
										    ]	,					)

										lowerCamelCase						:Tuple						  =     image_classifier([image] * 5	,					candidate_labels=['''A''', '''B''', '''C''']	,					batch_size=2		)
										self.assertEqual(
										    nested_simplify(__snake_case		)	,					[
										        [
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										        ],
										        [
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										        ],
										        [
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										        ],
										        [
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										        ],
										        [
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										        ],
										    ]	,					)







							@require_tf
							def 				snake_case  (				self     :    Tuple		):
										lowerCamelCase						:Tuple						  =     pipeline(
										    model='''hf-internal-testing/tiny-random-clip-zero-shot-image-classification'''	,					framework='''tf'''		)
										lowerCamelCase						:List[str]						  =     Image.open('''./tests/fixtures/tests_samples/COCO/000000039769.png'''		)
										lowerCamelCase						:Optional[Any]						  =     image_classifier(__snake_case	,					candidate_labels=['''a''', '''b''', '''c''']		)

										self.assertEqual(
										    nested_simplify(__snake_case		)	,					[{'''score''': 0.3_3_3, '''label''': '''a'''}, {'''score''': 0.3_3_3, '''label''': '''b'''}, {'''score''': 0.3_3_3, '''label''': '''c'''}]	,					)

										lowerCamelCase						:int						  =     image_classifier([image] * 5	,					candidate_labels=['''A''', '''B''', '''C''']	,					batch_size=2		)
										self.assertEqual(
										    nested_simplify(__snake_case		)	,					[
										        [
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										        ],
										        [
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										        ],
										        [
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										        ],
										        [
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										        ],
										        [
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										            {'''score''': 0.3_3_3, '''label''': ANY(__snake_case		)},
										        ],
										    ]	,					)







							@slow
							@require_torch
							def 				snake_case  (				self     :    Any		):
										lowerCamelCase						:str						  =     pipeline(
										    task='''zero-shot-image-classification'''	,					model='''openai/clip-vit-base-patch32'''	,					)
										# This is an image of 2 cats with remotes and no planes
										lowerCamelCase						:List[str]						  =     Image.open('''./tests/fixtures/tests_samples/COCO/000000039769.png'''		)
										lowerCamelCase						:Optional[Any]						  =     image_classifier(__snake_case	,					candidate_labels=['''cat''', '''plane''', '''remote''']		)

										self.assertEqual(
										    nested_simplify(__snake_case		)	,					[
										        {'''score''': 0.5_1_1, '''label''': '''remote'''},
										        {'''score''': 0.4_8_5, '''label''': '''cat'''},
										        {'''score''': 0.0_0_4, '''label''': '''plane'''},
										    ]	,					)

										lowerCamelCase						:Any						  =     image_classifier([image] * 5	,					candidate_labels=['''cat''', '''plane''', '''remote''']	,					batch_size=2		)
										self.assertEqual(
										    nested_simplify(__snake_case		)	,					[
										        [
										            {'''score''': 0.5_1_1, '''label''': '''remote'''},
										            {'''score''': 0.4_8_5, '''label''': '''cat'''},
										            {'''score''': 0.0_0_4, '''label''': '''plane'''},
										        ],
										    ]
										    * 5	,					)







							@slow
							@require_tf
							def 				snake_case  (				self     :    Optional[Any]		):
										lowerCamelCase						:Union[str, Any]						  =     pipeline(
										    task='''zero-shot-image-classification'''	,					model='''openai/clip-vit-base-patch32'''	,					framework='''tf'''		)
										# This is an image of 2 cats with remotes and no planes
										lowerCamelCase						:Dict						  =     Image.open('''./tests/fixtures/tests_samples/COCO/000000039769.png'''		)
										lowerCamelCase						:Dict						  =     image_classifier(__snake_case	,					candidate_labels=['''cat''', '''plane''', '''remote''']		)
										self.assertEqual(
										    nested_simplify(__snake_case		)	,					[
										        {'''score''': 0.5_1_1, '''label''': '''remote'''},
										        {'''score''': 0.4_8_5, '''label''': '''cat'''},
										        {'''score''': 0.0_0_4, '''label''': '''plane'''},
										    ]	,					)

										lowerCamelCase						:Any						  =     image_classifier([image] * 5	,					candidate_labels=['''cat''', '''plane''', '''remote''']	,					batch_size=2		)
										self.assertEqual(
										    nested_simplify(__snake_case		)	,					[
										        [
										            {'''score''': 0.5_1_1, '''label''': '''remote'''},
										            {'''score''': 0.4_8_5, '''label''': '''cat'''},
										            {'''score''': 0.0_0_4, '''label''': '''plane'''},
										        ],
										    ]
										    * 5	,					)



