<commit_before>#!/usr/bin/env python
# encoding: utf-8

# The MIT License (MIT)

# Copyright (c) 2012-2017 CNRS

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# AUTHORS
# <NAME> - http://herve.niderb.fr


from __future__ import unicode_literals
from __future__ import print_function


import scipy.stats
import pandas as pd
import numpy as np


class BaseMetric(object):
    """
    :class:`BaseMetric` is the base class for most pyannote evaluation metrics.

    Parameters
    ----------
    parallel : bool, optional
        Defaults to True

    Attributes
    ----------
    name : str
        Human-readable name of the metric (eg. 'diarization error rate')
    """

    @classmethod
    def metric_name(cls):
        raise NotImplementedError(
            cls.__name__ + " is missing a 'metric_name' class method. "
            "It should return the name of the metric as string.")

    @classmethod
    def metric_components(cls):
        raise NotImplementedError(
            cls.__name__ + " is missing a 'metric_components' class method. "
            "It should return the list of names of metric components.")

    def __init__(self, parallel=True, **kwargs):
        super(BaseMetric, self).__init__()
        self.parallel = parallel
        self.metric_name_ = self.__class__.metric_name()
        self.components_ = set(self.__class__.metric_components())
        self.reset()

    def init_components(self):
        return {value: 0. for value in self.components_}

    def reset(self):
        """Reset accumulated components and metric values"""
        if self.parallel:
            from pyannote.metrics import manager_
            self.accumulated_ = manager_.dict()
            self.results_ = manager_.list()
        else:
            self.accumulated_ = dict()
            self.results_ = list()
        for value in self.components_:
            self.accumulated_[value] = 0.


    def __get_name(self):
        return self.__class__.metric_name()
    name = property(fget=__get_name, doc="Metric name.")

    def __call__(self, reference, hypothesis, detailed=False, **kwargs):
        """Compute metric value and accumulate components

        Parameters
        ----------
        reference : type depends on the metric
            Manual `reference`
        hypothesis : same as `reference`
            Evaluated `hypothesis`
        detailed : bool, optional
            By default (False), return metric value only.

            Set `detailed` to True to return dictionary where keys are
            components names and values are component values

        Returns
        -------
        value : float (if `detailed` is False)
            Metric value
        components : dict (if `detailed` is True)
            `components` updated with metric value

        """

        # compute metric components
        components = self.compute_components(reference, hypothesis, **kwargs)

        # compute rate based on components
        components[self.metric_name_] = self.compute_metric(components)

        # keep track of this computation
        self.results_.append((reference.uri, components))
<commit_msg>feat: keep track of multiple calls to same 'uri'<commit_after>#!/usr/bin/env python
# encoding: utf-8

# The MIT License (MIT)

# Copyright (c) 2012-2017 CNRS

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# AUTHORS
# <NAME> - http://herve.niderb.fr


from __future__ import unicode_literals
from __future__ import print_function


import scipy.stats
import pandas as pd
import numpy as np


class BaseMetric(object):
    """
    :class:`BaseMetric` is the base class for most pyannote evaluation metrics.

    Parameters
    ----------
    parallel : bool, optional
        Defaults to True

    Attributes
    ----------
    name : str
        Human-readable name of the metric (eg. 'diarization error rate')
    """

    @classmethod
    def metric_name(cls):
        raise NotImplementedError(
            cls.__name__ + " is missing a 'metric_name' class method. "
            "It should return the name of the metric as string.")

    @classmethod
    def metric_components(cls):
        raise NotImplementedError(
            cls.__name__ + " is missing a 'metric_components' class method. "
            "It should return the list of names of metric components.")

    def __init__(self, parallel=True, **kwargs):
        super(BaseMetric, self).__init__()
        self.parallel = parallel
        self.metric_name_ = self.__class__.metric_name()
        self.components_ = set(self.__class__.metric_components())
        self.reset()

    def init_components(self):
        return {value: 0. for value in self.components_}

    def reset(self):
        """Reset accumulated components and metric values"""
        if self.parallel:
            from pyannote.metrics import manager_
            self.accumulated_ = manager_.dict()
            self.results_ = manager_.list()
            self.uris_ = manager_.dict()
        else:
            self.accumulated_ = dict()
            self.results_ = list()
            self.uris_ = dict()
        for value in self.components_:
            self.accumulated_[value] = 0.


    def __get_name(self):
        return self.__class__.metric_name()
    name = property(fget=__get_name, doc="Metric name.")

    def __call__(self, reference, hypothesis, detailed=False, **kwargs):
        """Compute metric value and accumulate components

        Parameters
        ----------
        reference : type depends on the metric
            Manual `reference`
        hypothesis : same as `reference`
            Evaluated `hypothesis`
        detailed : bool, optional
            By default (False), return metric value only.

            Set `detailed` to True to return dictionary where keys are
            components names and values are component values

        Returns
        -------
        value : float (if `detailed` is False)
            Metric value
        components : dict (if `detailed` is True)
            `components` updated with metric value

        """

        # compute metric components
        components = self.compute_components(reference, hypothesis, **kwargs)

        # compute rate based on components
        components[self.metric_name_] = self.compute_metric(components)

        # keep track of this computation
        uri = reference.uri
        if uri not in self.uris_:
            self.uris_[uri] = 1
        else:
            self.uris_[uri] += 1
            uri = uri + ' #{0:d}'.format(self.uris_[uri])

        self.results_.append((uri, components))

{'fraction_non_alphanumeric': 0.08217108321710832, 'fraction_numerical': 0.002905625290562529, 'mean_word_length': 2.5809404910528504, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3481593', 'n_tokens_mistral': 2238, 'n_tokens_neox': 2121, 'n_words': 875}