


"""simple docstring"""







# Lint as: python3
import sys
from collections.abc import Mapping
from typing import TYPE_CHECKING, Dict, Optional

import numpy as np
import pyarrow as pa

from .. import config
from ..utils.logging import get_logger
from ..utils.py_utils import map_nested
from .formatting import TensorFormatter


if TYPE_CHECKING:
     import jax
     import jaxlib

lowerCAmelCase__				    =       get_logger()

lowerCAmelCase__				    =       None


class 				SCREAMING_SNAKE_CASE__    (		TensorFormatter[Mapping, "jax.Array", Mapping]    ):
       """simple docstring"""


       def __init__(						self		,					snake_case__=None		,					snake_case__=None		,					**snake_case__						):






         """simple docstring"""





         super().__init__(features=snake_case__						)
         import jax
         from jaxlib.xla_client import Device

         if isinstance(snake_case__		,					snake_case__						):
           raise ValueError(
               f"""Expected {device} to be a `str` not {type(snake_case__						)}, as `jaxlib.xla_extension.Device` """
               "is not serializable neither with `pickle` nor with `dill`. Instead you can surround "
               "the device with `str()` to get its string identifier that will be internally mapped "
               "to the actual `jaxlib.xla_extension.Device`."						)
         lowerCAmelCase					:					List[str]								=							device if isinstance(snake_case__		,					snake_case__						) else str(jax.devices()[0]						)
         # using global variable since `jaxlib.xla_extension.Device` is not serializable neither
         # with `pickle` nor with `dill`, so we need to use a global variable instead
         global DEVICE_MAPPING
         if DEVICE_MAPPING is None:
           lowerCAmelCase					:					Optional[Any]								=							self._map_devices_to_str()
         if self.device not in list(DEVICE_MAPPING.keys()						):
           logger.warning(
               f"""Device with string identifier {self.device} not listed among the available """
               f"""devices: {list(DEVICE_MAPPING.keys()						)}, so falling back to the default """
               f"""device: {str(jax.devices()[0]						)}."""						)
           lowerCAmelCase					:					Dict								=							str(jax.devices()[0]						)
         lowerCAmelCase					:					Union[str, Any]								=							jnp_array_kwargs

       @staticmethod
       def 	lowercase__							(						):






         """simple docstring"""





         import jax

         return {str(snake_case__						): device for device in jax.devices()}

       def 	lowercase__							(						self		,					snake_case__						):






         """simple docstring"""





         import jax
         import jax.numpy as jnp

         if isinstance(snake_case__		,					snake_case__						) and column:
           if all(
               isinstance(snake_case__		,					jax.Array						) and x.shape == column[0].shape and x.dtype == column[0].dtype for x in column						):
             return jnp.stack(snake_case__		,					axis=0						)
         return column

       def 	lowercase__							(						self		,					snake_case__						):






         """simple docstring"""





         import jax
         import jax.numpy as jnp

         if isinstance(snake_case__		,					(str, bytes, type(snake_case__						))						):
           return value
         elif isinstance(snake_case__		,					(np.character, np.ndarray)						) and np.issubdtype(value.dtype		,					np.character						):
           return value.tolist()

         lowerCAmelCase					:					Tuple								=							{}

         if isinstance(snake_case__		,					(np.number, np.ndarray)						) and np.issubdtype(value.dtype		,					np.integer						):
           # the default int precision depends on the jax config
           # see https://jax.readthedocs.io/en/latest/notebooks/Common_Gotchas_in_JAX.html#double-64bit-precision
           if jax.config.jax_enable_xaa:
             lowerCAmelCase					:					List[Any]								=							{"dtype": jnp.intaa}
           else:
             lowerCAmelCase					:					Optional[Any]								=							{"dtype": jnp.intaa}
         elif isinstance(snake_case__		,					(np.number, np.ndarray)						) and np.issubdtype(value.dtype		,					np.floating						):
           lowerCAmelCase					:					int								=							{"dtype": jnp.floataa}
         elif config.PIL_AVAILABLE and "PIL" in sys.modules:
           import PIL.Image

           if isinstance(snake_case__		,					PIL.Image.Image						):
             lowerCAmelCase					:					Dict								=							np.asarray(snake_case__						)

        # using global variable since `jaxlib.xla_extension.Device` is not serializable neither
        # with `pickle` nor with `dill`, so we need to use a global variable instead
         global DEVICE_MAPPING
         if DEVICE_MAPPING is None:
           lowerCAmelCase					:					str								=							self._map_devices_to_str()

         with jax.default_device(DEVICE_MAPPING[self.device]						):
           # calling jnp.array on a np.ndarray does copy the data
           # see https://github.com/google/jax/issues/4486
           return jnp.array(snake_case__		,					**{**default_dtype, **self.jnp_array_kwargs}						)

       def 	lowercase__							(						self		,					snake_case__						):






         """simple docstring"""





         import jax

         # support for torch, tf, jax etc.
         if config.TORCH_AVAILABLE and "torch" in sys.modules:
           import torch

           if isinstance(snake_case__		,					torch.Tensor						):
             return self._tensorize(data_struct.detach().cpu().numpy()[()]						)
         if hasattr(snake_case__		,					"__array__"						) and not isinstance(snake_case__		,					jax.Array						):
           lowerCAmelCase					:					Dict								=							data_struct.__array__()
         # support for nested types like struct of list of struct
         if isinstance(snake_case__		,					np.ndarray						):
           if data_struct.dtype == object:  # jax arrays cannot be instantied from an array of objects
             return self._consolidate([self.recursive_tensorize(snake_case__						) for substruct in data_struct]						)
         elif isinstance(snake_case__		,					(list, tuple)						):
           return self._consolidate([self.recursive_tensorize(snake_case__						) for substruct in data_struct]						)
         return self._tensorize(snake_case__						)

       def 	lowercase__							(						self		,					snake_case__						):






         """simple docstring"""





         return map_nested(self._recursive_tensorize		,					snake_case__		,					map_list=snake_case__						)

       def 	lowercase__							(						self		,					snake_case__						):






         """simple docstring"""





         lowerCAmelCase					:					List[Any]								=							self.numpy_arrow_extractor().extract_row(snake_case__						)
         lowerCAmelCase					:					Tuple								=							self.python_features_decoder.decode_row(snake_case__						)
         return self.recursive_tensorize(snake_case__						)

       def 	lowercase__							(						self		,					snake_case__						):






         """simple docstring"""





         lowerCAmelCase					:					Optional[int]								=							self.numpy_arrow_extractor().extract_column(snake_case__						)
         lowerCAmelCase					:					Dict								=							self.python_features_decoder.decode_column(snake_case__		,					pa_table.column_names[0]						)
         lowerCAmelCase					:					Optional[Any]								=							self.recursive_tensorize(snake_case__						)
         lowerCAmelCase					:					Dict								=							self._consolidate(snake_case__						)
         return column







       def 	lowercase__							(						self		,					snake_case__						):






         """simple docstring"""





         lowerCAmelCase					:					Optional[Any]								=							self.numpy_arrow_extractor().extract_batch(snake_case__						)
         lowerCAmelCase					:					str								=							self.python_features_decoder.decode_batch(snake_case__						)
         lowerCAmelCase					:					Tuple								=							self.recursive_tensorize(snake_case__						)
         for column_name in batch:
           lowerCAmelCase					:					Optional[int]								=							self._consolidate(batch[column_name]						)
         return batch









"""simple docstring"""







from typing import List

import jiwer
import jiwer.transforms as tr
from packaging import version

import datasets
from datasets.config import PY_VERSION


if PY_VERSION < version.parse('''3.8'''):
     import importlib_metadata
else:
     import importlib.metadata as importlib_metadata


lowerCAmelCase__				    =       ''''''


if version.parse(importlib_metadata.version('''jiwer''')) < version.parse('''2.3.0'''):


     class 				SCREAMING_SNAKE_CASE__    (		tr.AbstractTransform    ):
            """simple docstring"""


            def __init__(						self		,					snake_case__ = " "						):






              """simple docstring"""





              lowerCAmelCase					:					List[Any]								=							sentence_delimiter

            def 	lowercase__							(						self		,					snake_case__						):






              """simple docstring"""





              return list(snake_case__						)







            def 	lowercase__							(						self		,					snake_case__						):






              """simple docstring"""





              lowerCAmelCase					:					Any								=							[]
              for sent_idx, sentence in enumerate(snake_case__						):
                chars.extend(self.process_string(snake_case__						)						)
                if self.sentence_delimiter is not None and self.sentence_delimiter != "" and sent_idx < len(snake_case__						) - 1:
                  chars.append(self.sentence_delimiter						)
              return chars

     lowerCAmelCase__				    =       tr.Compose(
         [tr.RemoveMultipleSpaces(), tr.Strip(), SentencesToListOfCharacters(SENTENCE_DELIMITER)]
     )
else:
     lowerCAmelCase__				    =       tr.Compose(
         [
             tr.RemoveMultipleSpaces(),
             tr.Strip(),
             tr.ReduceToSingleSentence(SENTENCE_DELIMITER),
             tr.ReduceToListOfListOfChars(),
         ]
     )


lowerCAmelCase__				    =       '''\
@inproceedings{inproceedings,
    author = {Morris, Andrew and Maier, Viktoria and Green, Phil},
    year = {2004},
    month = {01},
    pages = {},
    title = {From WER and RIL to MER and WIL: improved evaluation measures for connected speech recognition.}
}
'''

lowerCAmelCase__				    =       '''\
Character error rate (CER) is a common metric of the performance of an automatic speech recognition system.

CER is similar to Word Error Rate (WER), but operates on character instead of word. Please refer to docs of WER for further information.

Character error rate can be computed as:

CER = (S + D + I) / N = (S + D + I) / (S + D + C)

where

S is the number of substitutions,
D is the number of deletions,
I is the number of insertions,
C is the number of correct characters,
N is the number of characters in the reference (N=S+D+C).

CER\'s output is not always a number between 0 and 1, in particular when there is a high number of insertions. This value is often associated to the percentage of characters that were incorrectly predicted. The lower the value, the better the
performance of the ASR system with a CER of 0 being a perfect score.
'''

lowerCAmelCase__				    =       '''
Computes CER score of transcribed segments against references.
Args:
    references: list of references for each speech input.
    predictions: list of transcribtions to score.
    concatenate_texts: Whether or not to concatenate sentences before evaluation, set to True for more accurate result.
Returns:
    (float): the character error rate

Examples:

    >>> predictions = ["this is the prediction", "there is an other sample"]
    >>> references = ["this is the reference", "there is another one"]
    >>> cer = datasets.load_metric("cer")
    >>> cer_score = cer.compute(predictions=predictions, references=references)
    >>> print(cer_score)
    0.34146341463414637
'''


@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION       ,   _KWARGS_DESCRIPTION    )
class 				SCREAMING_SNAKE_CASE__    (		datasets.Metric    ):
       """simple docstring"""


       def 	lowercase__							(						self						):






         """simple docstring"""





         return datasets.MetricInfo(
             description=_DESCRIPTION		,					citation=_CITATION		,					inputs_description=_KWARGS_DESCRIPTION		,					features=datasets.Features(
                 {
                     "predictions": datasets.Value("string"		,					id="sequence"						),
                     "references": datasets.Value("string"		,					id="sequence"						),
                 }						)		,					codebase_urls=["https://github.com/jitsi/jiwer/"]		,					reference_urls=[
                 "https://en.wikipedia.org/wiki/Word_error_rate",
                 "https://sites.google.com/site/textdigitisation/qualitymeasures/computingerrorrates",
             ]		,					)







       def 	lowercase__							(						self		,					snake_case__		,					snake_case__		,					snake_case__=False						):






         """simple docstring"""





         if concatenate_texts:
           return jiwer.compute_measures(
               snake_case__		,					snake_case__		,					truth_transform=snake_case__		,					hypothesis_transform=snake_case__		,					)["wer"]

         lowerCAmelCase					:					List[Any]								=							0
         lowerCAmelCase					:					Optional[Any]								=							0
         for prediction, reference in zip(snake_case__		,					snake_case__						):
           lowerCAmelCase					:					Optional[int]								=							jiwer.compute_measures(
               snake_case__		,					snake_case__		,					truth_transform=snake_case__		,					hypothesis_transform=snake_case__		,					)
           incorrect += measures["substitutions"] + measures["deletions"] + measures["insertions"]
           total += measures["substitutions"] + measures["deletions"] + measures["hits"]

         return incorrect / total





