"""simple docstring"""






from typing import Dict, List, Optional, Union

import numpy as np

from .feature_extraction_utils import BatchFeature, FeatureExtractionMixin
from .utils import PaddingStrategy, TensorType, is_tf_tensor, is_torch_tensor, logging, to_numpy


__A			   = logging.get_logger(__name__)


class     UpperCAmelCase						(_UpperCAmelCase  ):



    """simple docstring"""

    def __init__(   self    ,			_UpperCAmelCase    ,			_UpperCAmelCase    ,			_UpperCAmelCase    ,			**_UpperCAmelCase							):
       lowercase__:   Union[str, Any]					=      feature_size
       lowercase__:   Optional[Any]					=      sampling_rate
       lowercase__:   int					=      padding_value

       lowercase__:   str					=      kwargs.pop('''padding_side'''    ,			'''right'''							)
       lowercase__:   int					=      kwargs.pop('''return_attention_mask'''    ,			_UpperCAmelCase							)

       super().__init__(**_UpperCAmelCase							)






    def _snake_case			(   self    ,			_UpperCAmelCase    ,			_UpperCAmelCase = True    ,			_UpperCAmelCase = None    ,			_UpperCAmelCase = False    ,			_UpperCAmelCase = None    ,			_UpperCAmelCase = None    ,			_UpperCAmelCase = None    ,			):
       # If we have a list of dicts, let's convert it in a dict of lists
       # We do this to allow using this method as a collate_fn function in PyTorch Dataloader
       if isinstance(_UpperCAmelCase    ,			(list, tuple)							) and isinstance(processed_features[0]    ,			(dict, BatchFeature)							):
          lowercase__:   Union[str, Any]					=      {
              key: [example[key] for example in processed_features] for key in processed_features[0].keys()
          }

       # The model's main input name, usually `input_values`, has be passed for padding
       if self.model_input_names[0] not in processed_features:
          raise ValueError(
              '''You should supply an instance of `transformers.BatchFeature` or list of `transformers.BatchFeature`'''
              F""" to this method that includes {self.model_input_names[0]}, but you provided"""
              F""" {list(processed_features.keys()							)}"""							)

       lowercase__:   Optional[Any]					=      processed_features[self.model_input_names[0]]
       lowercase__:   Union[str, Any]					=      (
           return_attention_mask if return_attention_mask is not None else self.return_attention_mask
       )

       if len(_UpperCAmelCase							) == 0:
          if return_attention_mask:
             lowercase__:   int					=      []
          return processed_features

       # If we have PyTorch/TF tensors or lists as inputs, we cast them as Numpy arrays
       # and rebuild them afterwards if no return_tensors is specified
       # Note that we lose the specific device the tensor may be on for PyTorch

       lowercase__:   Union[str, Any]					=      required_input[0]
       if isinstance(_UpperCAmelCase    ,			(list, tuple)							):
          # first_element might be an empty list/tuple in some edge cases so we grab the first non empty element.
          lowercase__:   Any					=      0
          while len(required_input[index]							) == 0:
             index += 1
          if index < len(_UpperCAmelCase							):
             lowercase__:   Union[str, Any]					=      required_input[index][0]

       if return_tensors is None:
          if is_tf_tensor(_UpperCAmelCase							):
             lowercase__:   List[str]					=      '''tf'''
          elif is_torch_tensor(_UpperCAmelCase							):
             lowercase__:   Any					=      '''pt'''
          elif isinstance(_UpperCAmelCase    ,			(int, float, list, tuple, np.ndarray)							):
             lowercase__:   str					=      '''np'''
          else:
             raise ValueError(
                 F"""type of {first_element} unknown: {type(_UpperCAmelCase							)}. """
                 '''Should be one of a python, numpy, pytorch or tensorflow object.'''							)

       for key, value in processed_features.items():
          if isinstance(value[0]    ,			(int, float)							):
             lowercase__:   Dict					=      to_numpy(_UpperCAmelCase							)
          else:
             lowercase__:   Dict					=      [to_numpy(_UpperCAmelCase							) for v in value]

        # Convert padding_strategy in PaddingStrategy
       lowercase__:   List[Any]					=      self._get_padding_strategies(padding=_UpperCAmelCase    ,			max_length=_UpperCAmelCase							)

       lowercase__:   List[Any]					=      processed_features[self.model_input_names[0]]

       lowercase__:   int					=      len(_UpperCAmelCase							)
       if not all(len(_UpperCAmelCase							) == batch_size for v in processed_features.values()							):
          raise ValueError('''Some items in the output dictionary have a different batch size than others.'''							)

       lowercase__:   Optional[Any]					=      []
       for i in range(_UpperCAmelCase							):
          lowercase__:   Tuple					=      {k: v[i] for k, v in processed_features.items()}
          # truncation
          lowercase__:   List[str]					=      self._truncate(
              _UpperCAmelCase    ,			max_length=_UpperCAmelCase    ,			pad_to_multiple_of=_UpperCAmelCase    ,			truncation=_UpperCAmelCase    ,			)
          truncated_inputs.append(_UpperCAmelCase							)

       if padding_strategy == PaddingStrategy.LONGEST:
          # make sure that `max_length` cannot be longer than the longest truncated length
          lowercase__:   List[Any]					=      max(len(input_slice[self.model_input_names[0]]							) for input_slice in truncated_inputs							)
          lowercase__:   Union[str, Any]					=      PaddingStrategy.MAX_LENGTH

       lowercase__:   Tuple					=      {}
       for i in range(_UpperCAmelCase							):
          # padding
          lowercase__:   List[str]					=      self._pad(
              truncated_inputs[i]    ,			max_length=_UpperCAmelCase    ,			padding_strategy=_UpperCAmelCase    ,			pad_to_multiple_of=_UpperCAmelCase    ,			return_attention_mask=_UpperCAmelCase    ,			)

          for key, value in outputs.items():
             if key not in batch_outputs:
                lowercase__:   Union[str, Any]					=      []
             if value.dtype is np.dtype(np.floataa							):
                lowercase__:   Dict					=      value.astype(np.floataa							)
             batch_outputs[key].append(_UpperCAmelCase							)

       return BatchFeature(_UpperCAmelCase    ,			tensor_type=_UpperCAmelCase							)






    def _snake_case			(   self    ,			_UpperCAmelCase    ,			_UpperCAmelCase = None    ,			_UpperCAmelCase = PaddingStrategy.DO_NOT_PAD    ,			_UpperCAmelCase = None    ,			_UpperCAmelCase = None    ,			):
       lowercase__:   Tuple					=      processed_features[self.model_input_names[0]]

       if padding_strategy == PaddingStrategy.LONGEST:
          lowercase__:   Tuple					=      len(_UpperCAmelCase							)

       if max_length is not None and pad_to_multiple_of is not None and (max_length % pad_to_multiple_of != 0):
          lowercase__:   int					=      ((max_length // pad_to_multiple_of) + 1) * pad_to_multiple_of

       lowercase__:   Dict					=      padding_strategy != PaddingStrategy.DO_NOT_PAD and len(_UpperCAmelCase							) < max_length

       if return_attention_mask and "attention_mask" not in processed_features:
          lowercase__:   Optional[int]					=      np.ones(len(_UpperCAmelCase							)    ,			dtype=np.intaa							)

       if needs_to_be_padded:
          lowercase__:   List[Any]					=      max_length - len(_UpperCAmelCase							)
          if self.padding_side == "right":
             if return_attention_mask:
                lowercase__:   Optional[int]					=      np.pad(
                    processed_features['''attention_mask''']    ,			(0, difference)							)
             lowercase__:   Optional[int]					=      ((0, difference), (0, 0)) if self.feature_size > 1 else (0, difference)
             lowercase__:   Union[str, Any]					=      np.pad(
                 _UpperCAmelCase    ,			_UpperCAmelCase    ,			'''constant'''    ,			constant_values=self.padding_value							)
          elif self.padding_side == "left":
             if return_attention_mask:
                lowercase__:   str					=      np.pad(
                    processed_features['''attention_mask''']    ,			(difference, 0)							)
             lowercase__:   str					=      ((difference, 0), (0, 0)) if self.feature_size > 1 else (difference, 0)
             lowercase__:   List[Any]					=      np.pad(
                 _UpperCAmelCase    ,			_UpperCAmelCase    ,			'''constant'''    ,			constant_values=self.padding_value							)
          else:
             raise ValueError('''Invalid padding strategy:''' + str(self.padding_side							)							)

       return processed_features






    def _snake_case			(   self    ,			_UpperCAmelCase    ,			_UpperCAmelCase = None    ,			_UpperCAmelCase = None    ,			_UpperCAmelCase = None    ,			):
       if not truncation:
          return processed_features
       elif truncation and max_length is None:
          raise ValueError('''When setting ``truncation=True``, make sure that ``max_length`` is defined.'''							)

       lowercase__:   Any					=      processed_features[self.model_input_names[0]]

       # find `max_length` that fits `pad_to_multiple_of`
       if max_length is not None and pad_to_multiple_of is not None and (max_length % pad_to_multiple_of != 0):
          lowercase__:   Optional[int]					=      ((max_length // pad_to_multiple_of) + 1) * pad_to_multiple_of

       lowercase__:   int					=      len(_UpperCAmelCase							) > max_length

       if needs_to_be_truncated:
          lowercase__:   Any					=      processed_features[self.model_input_names[0]][:max_length]
          if "attention_mask" in processed_features:
             lowercase__:   Tuple					=      processed_features['''attention_mask'''][:max_length]

       return processed_features






    def _snake_case			(   self    ,			_UpperCAmelCase=False    ,			_UpperCAmelCase=None							):

       # Get padding strategy
       if padding is not False:
          if padding is True:
             lowercase__:   Union[str, Any]					=      PaddingStrategy.LONGEST  # Default to pad to the longest sequence in the batch
          elif not isinstance(_UpperCAmelCase    ,			_UpperCAmelCase							):
             lowercase__:   str					=      PaddingStrategy(_UpperCAmelCase							)
          elif isinstance(_UpperCAmelCase    ,			_UpperCAmelCase							):
             lowercase__:   Any					=      padding
       else:
          lowercase__:   str					=      PaddingStrategy.DO_NOT_PAD

       # Set max length if needed
       if max_length is None:
          if padding_strategy == PaddingStrategy.MAX_LENGTH:
             raise ValueError(
                 F"""When setting ``padding={PaddingStrategy.MAX_LENGTH}``, make sure that max_length is defined"""							)

        # Test if we have a padding value
       if padding_strategy != PaddingStrategy.DO_NOT_PAD and (self.padding_value is None):
          raise ValueError(
              '''Asking to pad but the feature_extractor does not have a padding value. Please select a value to use'''
              ''' as `padding_value`. For example: `feature_extractor.padding_value = 0.0`.'''							)

       return padding_strategy

"""simple docstring"""






from jiwer import compute_measures

import datasets


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

__A			   = "\\nWord error rate (WER) is a common metric of the performance of an automatic speech recognition system.\n\nThe general difficulty of measuring performance lies in the fact that the recognized word sequence can have a different length from the reference word sequence (supposedly the correct one). The WER is derived from the Levenshtein distance, working at the word level instead of the phoneme level. The WER is a valuable tool for comparing different systems as well as for evaluating improvements within one system. This kind of measurement, however, provides no details on the nature of translation errors and further work is therefore required to identify the main source(s) of error and to focus any research effort.\n\nThis problem is solved by first aligning the recognized word sequence with the reference (spoken) word sequence using dynamic string alignment. Examination of this issue is seen through a theory called the power law that states the correlation between perplexity and word error rate.\n\nWord error rate can then be computed as:\n\nWER = (S + D + I) / N = (S + D + I) / (S + D + C)\n\nwhere\n\nS is the number of substitutions,\nD is the number of deletions,\nI is the number of insertions,\nC is the number of correct words,\nN is the number of words in the reference (N=S+D+C).\n\nThis value indicates the average number of errors per reference word. The lower the value, the better the\nperformance of the ASR system with a WER of 0 being a perfect score.\n"

__A			   = "\nCompute WER score of transcribed segments against references.\n\nArgs:\n    references: List of references for each speech input.\n    predictions: List of transcriptions to score.\n    concatenate_texts (bool, default=False): Whether to concatenate all input texts or compute WER iteratively.\n\nReturns:\n    (float): the word error rate\n\nExamples:\n\n    >>> predictions = [\"this is the prediction\", \"there is an other sample\"]\n    >>> references = [\"this is the reference\", \"there is another one\"]\n    >>> wer = datasets.load_metric(\"wer\")\n    >>> wer_score = wer.compute(predictions=predictions, references=references)\n    >>> print(wer_score)\n    0.5\n"


@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION    ,_KWARGS_DESCRIPTION  )
class     UpperCAmelCase						(datasets.Metric  ):



    """simple docstring"""

    def _snake_case			(   self							):
       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''',
           ]    ,			)






    def _snake_case			(   self    ,			_UpperCAmelCase=None    ,			_UpperCAmelCase=None    ,			_UpperCAmelCase=False							):
       if concatenate_texts:
          return compute_measures(_UpperCAmelCase    ,			_UpperCAmelCase							)["wer"]
       else:
          lowercase__:   Dict					=      0
          lowercase__:   Union[str, Any]					=      0
          for prediction, reference in zip(_UpperCAmelCase    ,			_UpperCAmelCase							):
             lowercase__:   Tuple					=      compute_measures(_UpperCAmelCase    ,			_UpperCAmelCase							)
             incorrect += measures["substitutions"] + measures["deletions"] + measures["insertions"]
             total += measures["substitutions"] + measures["deletions"] + measures["hits"]
          return incorrect / total
