SPPAS 4.22

https://sppas.org/

Module sppas.src.analysis

Class sppasTierFilters

Description

This class implements the 'SPPAS tier filter system'.

Search in tiers. The class sppasTierFilters() allows to apply several types of filter (tag, duration, ...), and the class sppasAnnSet() is a data set manager, i.e. it contains the annotations selected by a filter and a string representing the filter.

Example
 > # Create a filter:
 >>> f = sppasTierFilters(tier)

then, apply a filter with some pattern like in the following examples. sppasAnnSet() can be combined with operators & and |, like for any other 'set' in Python, 'an unordered collection of distinct hashable objects'.

Example
 > # extract silences:
 >>> f.tag(exact=u('#')))
Example
 > # extract silences more than 200ms
 >>> f.tag(exact=u("#")) & f.dur(gt=0.2)
Example
 > # find the annotations with at least a label with a tag
 > # starting by "pa" and ending by "a" like "pa", "papa", "pasta", etc:
 >>> f.tag(startswith="pa", endswith='a')
 > # It's equivalent to write:
 >>> f.tag(startswith="pa", endswith='a', logic_bool="and")

The classical "and" and "or" logical boolean predicates are accepted; "and" is the default one. It defines whether all the functions must be True ("and") or any of them ("or").

The result of the two previous lines of code is the same, but two times faster, compared to use this one.

Example
 >>> f.tag(startswith="pa") & f.tag(endswith='a')

In the first case, for each tag, the method applies the logical boolean between two predicates and creates the data set matching the combined condition. In the second case, each call to the method creates a data set matching each individual condition, then the data sets are combined.

Example
 > # find annotations with more than 1 label
 >>> f.nlab(lge=1))

Constructor

Create a sppasTierFilters instance.

Parameters
  • obj: (sppasTier) The tier to be filtered.
View Source
def __init__(self, obj):
    """Create a sppasTierFilters instance.

    :param obj: (sppasTier) The tier to be filtered.

    """
    if isinstance(obj, sppasTier) is False:
        raise AnnDataTypeError(obj, 'sppasTier')
    super(sppasTierFilters, self).__init__(obj)

Public functions

tag

Apply functions on all tags of all labels of annotations.

Each argument is made of a function name and its expected value. Each function can be prefixed with 'not_', like in the next example.

Example
 >>> f.tag(startswith="pa", not_endswith='a', logic_bool="and")
 >>> f.tag(startswith="pa") & f.tag(not_endswith='a')
 >>> f.tag(startswith="pa") | f.tag(startswith="ta")
Parameters
  • kwargs: logic_bool/any sppasTagCompare() method.
Returns
  • (sppasAnnSet)
View Source
def tag(self, **kwargs):
    """Apply functions on all tags of all labels of annotations.

        Each argument is made of a function name and its expected value.
        Each function can be prefixed with 'not_', like in the next example.

        :Example:
        >>> f.tag(startswith="pa", not_endswith='a', logic_bool="and")
        >>> f.tag(startswith="pa") & f.tag(not_endswith='a')
        >>> f.tag(startswith="pa") | f.tag(startswith="ta")

        :param kwargs: logic_bool/any sppasTagCompare() method.
        :returns: (sppasAnnSet)

        """
    comparator = sppasTagCompare()
    sppasBaseFilters.test_args(comparator, **kwargs)
    tag_logic_bool = sppasBaseFilters.fix_logic_bool(**kwargs)
    label_logic_bool = sppasBaseFilters.fix_logic_bool_label(**kwargs)
    tag_fct_values = sppasBaseFilters.fix_function_values(comparator, **kwargs)
    tag_functions = sppasBaseFilters.fix_functions(comparator, **kwargs)
    data = sppasAnnSet()
    for annotation in self.obj:
        is_matching = False
        for label in annotation.get_labels():
            is_matching = label.match(tag_functions, tag_logic_bool)
            if is_matching is True and label_logic_bool == 'any':
                break
            if is_matching is False and label_logic_bool == 'all':
                break
        if is_matching is True:
            data.append(annotation, tag_fct_values)
    return data

dur

Apply functions on durations of the location of annotations.

Parameters
  • kwargs: logic_bool/any sppasDurationCompare() method.
Returns
  • (sppasAnnSet)
Example
 >>> f.dur(ge=0.03) & f.dur(le=0.07)
 >>> f.dur(ge=0.03, le=0.07, logic_bool="and")
View Source
def dur(self, **kwargs):
    """Apply functions on durations of the location of annotations.

        :param kwargs: logic_bool/any sppasDurationCompare() method.
        :return: (sppasAnnSet)

        :Example:
        >>> f.dur(ge=0.03) & f.dur(le=0.07)
        >>> f.dur(ge=0.03, le=0.07, logic_bool="and")

        """
    comparator = sppasDurationCompare()
    sppasBaseFilters.test_args(comparator, **kwargs)
    logic_bool = sppasBaseFilters.fix_logic_bool(**kwargs)
    dur_fct_values = sppasBaseFilters.fix_function_values(comparator, **kwargs)
    dur_functions = sppasBaseFilters.fix_functions(comparator, **kwargs)
    data = sppasAnnSet()
    for annotation in self.obj:
        location = annotation.get_location()
        is_matching = location.match_duration(dur_functions, logic_bool)
        if is_matching is True:
            data.append(annotation, dur_fct_values)
    return data

loc

Apply functions on localizations of annotations.

Parameters
  • kwargs: logic_bool/any sppasLocalizationCompare() method.
Returns
  • (sppasAnnSet)
Example
 >>> f.loc(rangefrom=3.01) & f.loc(rangeto=10.07)
 >>> f.loc(rangefrom=3.01, rangeto=10.07, logic_bool="and")
View Source
def loc(self, **kwargs):
    """Apply functions on localizations of annotations.

        :param kwargs: logic_bool/any sppasLocalizationCompare() method.
        :returns: (sppasAnnSet)

        :Example:
        >>> f.loc(rangefrom=3.01) & f.loc(rangeto=10.07)
        >>> f.loc(rangefrom=3.01, rangeto=10.07, logic_bool="and")

        """
    comparator = sppasLocalizationCompare()
    sppasBaseFilters.test_args(comparator, **kwargs)
    logic_bool = sppasBaseFilters.fix_logic_bool(**kwargs)
    loc_fct_values = sppasBaseFilters.fix_function_values(comparator, **kwargs)
    loc_functions = sppasBaseFilters.fix_functions(comparator, **kwargs)
    data = sppasAnnSet()
    for annotation in self.obj:
        location = annotation.get_location()
        is_matching = location.match_localization(loc_functions, logic_bool)
        if is_matching is True:
            data.append(annotation, loc_fct_values)
    return data

nlab

Apply functions on number of labels in annotations.

Parameters
  • kwargs: logic_bool/any sppasListCompare() method.
Returns
  • (sppasAnnSet)
Example
 >>> f.nlab(leq=1)
View Source
def nlab(self, **kwargs):
    """Apply functions on number of labels in annotations.

        :param kwargs: logic_bool/any sppasListCompare() method.
        :returns: (sppasAnnSet)

        :Example:
        >>> f.nlab(leq=1)

        """
    comparator = sppasListCompare()
    sppasBaseFilters.test_args(comparator, **kwargs)
    logic_bool = sppasBaseFilters.fix_logic_bool(**kwargs)
    nlab_fct_values = sppasBaseFilters.fix_function_values(comparator, **kwargs)
    nlab_functions = sppasBaseFilters.fix_functions(comparator, **kwargs)
    data = sppasAnnSet()
    for annotation in self.obj:
        labels = annotation.get_labels()
        matches = list()
        for func, value, logical_not in nlab_functions:
            if logical_not is True:
                matches.append(not func(labels, value))
            else:
                matches.append(func(labels, value))
        if logic_bool == 'and':
            is_matching = all(matches)
        else:
            is_matching = any(matches)
        if is_matching is True:
            data.append(annotation, nlab_fct_values)
    return data

rel

Apply functions of relations between localizations of annotations.

Parameters
  • other_tier: the tier to be in relation with.
  • args: any sppasIntervalCompare() method.
  • kwargs: any option of the methods.
Returns
  • (sppasAnnSet)
Example
 >>> f.rel(other_tier, "equals", "overlaps", "overlappedby",
 >>> overlap_min=0.04, overlapped_min=0.02)

kwargs can be:

  • max_delay=value, used by before, after
  • overlap_min=value, used by overlap,
  • overlapped_min=value, used by overlappedby
  • percent=boolean, used by overlap, overlappedby to define the overlapmin is a percentage
View Source
def rel(self, other_tier, *args, **kwargs):
    """Apply functions of relations between localizations of annotations.

        :param other_tier: the tier to be in relation with.
        :param args: any sppasIntervalCompare() method.
        :param kwargs: any option of the methods.
        :returns: (sppasAnnSet)

        :Example:
        >>> f.rel(other_tier, "equals", "overlaps", "overlappedby",
        >>>       overlap_min=0.04, overlapped_min=0.02)

        kwargs can be:

        - max_delay=value, used by before, after
        - overlap_min=value, used by overlap,
        - overlapped_min=value, used by overlappedby
        - percent=boolean, used by overlap, overlapped_by to define the overlap_min is a percentage

        """
    comparator = sppasIntervalCompare()
    rel_functions = sppasTierFilters.__fix_relation_functions(comparator, *args)
    data = sppasAnnSet()
    for annotation in self.obj:
        location = annotation.get_location()
        match_values = sppasTierFilters.__connect(location, other_tier, rel_functions, **kwargs)
        if len(match_values) > 0:
            data.append(annotation, list(set(match_values)))
    return data

cast_data

Return an entry into the appropriate type.

Parameters
  • tier: (sppasTier)
  • sfilter: (str) Name of the filter (tag, loc, ...)
  • entry: (str) The entry to cast
Returns
  • typed entry
View Source
@staticmethod
def cast_data(tier, sfilter, entry):
    """Return an entry into the appropriate type.

        :param tier: (sppasTier)
        :param sfilter: (str) Name of the filter (tag, loc, ...)
        :param entry: (str) The entry to cast
        :return: typed entry

        """
    if sfilter == 'tag':
        if tier.is_float():
            return float(entry)
        elif tier.is_int():
            return int(entry)
        elif tier.is_bool():
            return bool(entry)
    elif sfilter == 'loc':
        p = tier.get_first_point()
        if isinstance(p.get_midpoint(), int):
            return int(entry)
        else:
            return float(entry)
    elif sfilter == 'dur':
        return float(entry)
    return u(entry)

Protected functions

__fix_relation_functions

Parse the arguments to get the list of function/complement.

Parameters
  • comparator
View Source
@staticmethod
def __fix_relation_functions(comparator, *args):
    """Parse the arguments to get the list of function/complement."""
    f_functions = list()
    for func_name in args:
        logical_not = False
        if func_name.startswith('not_'):
            logical_not = True
            func_name = func_name[4:]
        if func_name in comparator.get_function_names():
            f_functions.append((comparator.get(func_name), logical_not))
        else:
            raise sppasKeyError('rel filter args function name', func_name)
    return f_functions

__connect

Find connections between location and the other tier.

Parameters
  • location
  • other_tier
  • rel_functions
View Source
@staticmethod
def __connect(location, other_tier, rel_functions, **kwargs):
    """Find connections between location and the other tier."""
    values = list()
    for other_ann in other_tier:
        for localization, score in location:
            for other_loc, other_score in other_ann.get_location():
                for func_name, complement in rel_functions:
                    is_connected = func_name(localization, other_loc, **kwargs)
                    if is_connected:
                        values.append(func_name.__name__)
    return values