SPPAS 4.22

https://sppas.org/

Module sppas.src.annotations

Class sppasIVA

Description

Estimate IVA on a tier.

Get or create segments then map them into a dictionary where:

  • key is a label assigned to the segment;
  • value is the list of observed values in the segment.

Constructor

Create a new sppasIVA instance.

Parameters
  • log: (sppasLog) Human-readable logs.
View Source
def __init__(self, log=None):
    """Create a new sppasIVA instance.

    :param log: (sppasLog) Human-readable logs.

    """
    super(sppasIVA, self).__init__('iva.json', log)
    self._separators = ['#', '+', '*', '@', 'dummy']

Public functions

fix_options

Fix all options.

Parameters
  • options: (sppasOption)
View Source
def fix_options(self, options):
    """Fix all options.

        :param options: (sppasOption)

        """
    for opt in options:
        key = opt.get_key()
        if 'iva_prefix_label' == key:
            self.set_sgmt_prefix_label(opt.get_value())
        elif 'values' == key:
            self.set_input_tiername_values(opt.get_value())
        elif 'segments' == key:
            self.set_input_tiername_segments(opt.get_value())
        elif 'separators' == key:
            self.set_segments_separators(opt.get_value())
        elif 'occ' == key:
            self.set_eval(occ=opt.get_value())
        elif 'total' == key:
            self.set_eval(total=opt.get_value())
        elif 'mean' == key:
            self.set_eval(mean=opt.get_value())
        elif 'median' == key:
            self.set_eval(median=opt.get_value())
        elif 'stdev' == key:
            self.set_eval(stdev=opt.get_value())
        elif 'linreg' == key:
            self.set_eval(linreg=opt.get_value())
        elif 'pattern' in key:
            self._options[key] = opt.get_value()
        else:
            raise AnnotationOptionError(key)

set_sgmt_prefix_label

Fix the prefix to add to each segment.

Parameters
  • prefix: (str) Default is 'sgmt_'
View Source
def set_sgmt_prefix_label(self, prefix):
    """Fix the prefix to add to each segment.

        :param prefix: (str) Default is 'sgmt_'

        """
    sp = sppasUnicode(prefix)
    tg = sp.to_strip()
    if len(tg) > 0:
        self._options['iva_prefix_label'] = tg

set_input_tiername_values

Fix the name of the tier with values.

Parameters
  • tiername: (str) Default is 'PitchTier'
View Source
def set_input_tiername_values(self, tiername):
    """Fix the name of the tier with values.

        :param tiername: (str) Default is 'PitchTier'

        """
    sp = sppasUnicode(tiername)
    tg = sp.to_strip()
    if len(tg) > 0:
        self._options['values'] = tg

set_input_tiername_segments

Fix the name of the tier with segments.

Parameters
  • tiername: (str) Default is 'TokensAlign'
View Source
def set_input_tiername_segments(self, tiername):
    """Fix the name of the tier with segments.

        :param tiername: (str) Default is 'TokensAlign'

        """
    sp = sppasUnicode(tiername)
    tg = sp.to_strip()
    if len(tg) > 0:
        self._options['segments'] = tg

set_segments_separators

Fix the separators to create segments.

Parameters
  • entry: (str) Entries separated by whitespace.
View Source
def set_segments_separators(self, entry):
    """Fix the separators to create segments.

        :param entry: (str) Entries separated by whitespace.

        """
    sp = sppasUnicode(entry)
    tg = sp.to_strip()
    if len(tg) > 0:
        self._separators = tg.split()
    else:
        self._separators = list()

set_eval

Set IVA evaluations to perform.

Parameters
  • total: (bool) Estimates total of values in segments.
  • mean: (bool) Estimates mean of values in segments.
  • median: (bool) Estimates median of values in segments.
  • stdev: (bool) Estimates standard deviation of values in segments.
  • linreg: (bool) Estimates linear regression of values in segments.
View Source
def set_eval(self, occ=None, total=None, mean=None, median=None, stdev=None, linreg=None):
    """Set IVA evaluations to perform.

        :param total: (bool) Estimates total of values in segments.
        :param mean: (bool) Estimates mean of values in segments.
        :param median: (bool) Estimates median of values in segments.
        :param stdev: (bool) Estimates standard deviation of values in segments.
        :param linreg: (bool) Estimates linear regression of values in segments.

        """
    if occ is not None:
        self._options['occ'] = bool(occ)
    if total is not None:
        self._options['total'] = bool(total)
    if mean is not None:
        self._options['mean'] = bool(mean)
    if median is not None:
        self._options['median'] = bool(median)
    if stdev is not None:
        self._options['stdev'] = bool(stdev)
    if linreg is not None:
        self._options['linreg'] = bool(linreg)

tier_to_segments

Create segment intervals.

Parameters
  • input_tier: (sppasTier)
Returns
  • (sppasTier)
View Source
def tier_to_segments(self, input_tier):
    """Create segment intervals.

        :param input_tier: (sppasTier)
        :returns: (sppasTier)

        """
    if len(self._separators) > 0:
        intervals = input_tier.export_to_intervals(self._separators)
    else:
        intervals = input_tier.copy()
    intervals.set_name('IVA-Segments')
    for i, tg in enumerate(intervals):
        tag_str = self._options['iva_prefix_label']
        tag_str += str(i + 1)
        tg.set_labels([sppasLabel(sppasTag(tag_str))])
    return intervals

tier_to_labelled_segments

Create the segment intervals within the values.

Parameters
  • segments: (sppasTier) segment intervals to get values
  • inputtiervalues: (sppasTier) tags are float/int values
Returns
  • (dict, sppasTier) dict of segment/values, labelled segments
View Source
def tier_to_labelled_segments(self, segments, input_tier_values):
    """Create the segment intervals within the values.

        :param segments: (sppasTier) segment intervals to get values
        :param input_tier_values: (sppasTier) tags are float/int values
        :returns: (dict, sppasTier) dict of segment/values, labelled segments

        """
    intervals_tier = segments.copy()
    intervals_tier.gen_id()
    intervals_tier.set_name('IVA-Values')
    for i, tg in enumerate(intervals_tier):
        tg.set_labels(None)
    iva_items = dict()
    for i, tg in enumerate(intervals_tier):
        iva_ann = segments[i]
        iva_label = serialize_labels(iva_ann.get_labels())
        values_anns = input_tier_values.find(tg.get_lowest_localization(), tg.get_highest_localization())
        all_labels = list()
        for ann in values_anns:
            ann_labels = ann.get_labels()
            all_labels.extend(ann_labels)
        tg.set_labels(all_labels)
        iva_items[iva_label] = list()
        for label in all_labels:
            for tag, score in label:
                ttag = tag.get_typed_content()
                iva_items[iva_label].append(ttag)
    return (iva_items, intervals_tier)

iva_to_tier

Create a tier from one of the IVA result (mean, sd, ...).

Parameters
  • iva_result: One of the results of TGA
  • sgmts_tier: (sppasTier) Tier with the segments
  • tier_name: (str) Name of the output tier
  • tag_type: (str) Type of the sppasTag to be included
Returns
  • (sppasTier)
View Source
@staticmethod
def iva_to_tier(iva_result, sgmts_tier, tier_name, tag_type='float'):
    """Create a tier from one of the IVA result (mean, sd, ...).

        :param iva_result: One of the results of TGA
        :param sgmts_tier: (sppasTier) Tier with the segments
        :param tier_name: (str) Name of the output tier
        :param tag_type: (str) Type of the sppasTag to be included

        :returns: (sppasTier)

        """
    tier = sppasTier(tier_name)
    for iva_ann in sgmts_tier:
        iva_label = serialize_labels(iva_ann.get_labels())
        tag_value = iva_result[iva_label]
        if tag_type == 'float':
            tag_value = round(tag_value, 5)
        tier.create_annotation(iva_ann.get_location().copy(), sppasLabel(sppasTag(tag_value, tag_type)))
    return tier

iva_to_tier_reglin

Create tiers of intercept,slope from the IVA result.

Parameters
  • iva_result: intercept,slope result of IVA
  • sgmts_tier: (sppasTier) Tier with the segments
  • intercept: (boolean) Export the intercept. If False, export Slope.
Returns
  • (sppasTier)
View Source
@staticmethod
def iva_to_tier_reglin(iva_result, sgmts_tier, intercept=True):
    """Create tiers of intercept,slope from the IVA result.

        :param iva_result: intercept,slope result of IVA
        :param sgmts_tier: (sppasTier) Tier with the segments
        :param intercept: (boolean) Export the intercept.
        If False, export Slope.

        :returns: (sppasTier)

        """
    if intercept is True:
        tier = sppasTier('IVA-Intercept')
    else:
        tier = sppasTier('IVA-Slope')
    for iva_ann in sgmts_tier:
        iva_label = serialize_labels(iva_ann.get_labels())
        loc = iva_ann.get_location().copy()
        if intercept is True:
            tag_value = iva_result[iva_label][0]
        else:
            tag_value = iva_result[iva_label][1]
        tag_value = round(tag_value, 5)
        tier.create_annotation(loc, sppasLabel(sppasTag(tag_value, 'float')))
    return tier

convert

Estimate IVA on the given input tier with values.

Parameters
  • inputtiervalues: (sppasTier) Tier with numerical values.
  • inputtiersegments: (sppasTier) Tier with intervals.
Returns
  • (sppasTranscription)
View Source
def convert(self, input_tier_values, input_tier_segments):
    """Estimate IVA on the given input tier with values.

        :param input_tier_values: (sppasTier) Tier with numerical values.
        :param input_tier_segments: (sppasTier) Tier with intervals.
        :returns: (sppasTranscription)

        """
    trs_out = sppasTranscription('IntervalValuesAnalysis')
    segments = self.tier_to_segments(input_tier_segments)
    segments.set_meta('segments_of_tier', input_tier_segments.get_name())
    trs_out.append(segments)
    iva_items, val_segs_tier = self.tier_to_labelled_segments(segments, input_tier_values)
    trs_out.append(val_segs_tier)
    ts = IntervalValuesAnalysis(iva_items)
    if self._options['occ'] is True:
        tier = sppasIVA.iva_to_tier(ts.len(), segments, 'IVA-Occurrences', 'int')
        trs_out.append(tier)
    if self._options['total'] is True:
        tier = sppasIVA.iva_to_tier(ts.total(), segments, 'IVA-Total')
        trs_out.append(tier)
    if self._options['mean'] is True:
        tier = sppasIVA.iva_to_tier(ts.mean(), segments, 'IVA-Mean')
        trs_out.append(tier)
    if self._options['median'] is True:
        tier = sppasIVA.iva_to_tier(ts.median(), segments, 'IVA-Median')
        trs_out.append(tier)
    if self._options['stdev'] is True:
        tier = sppasIVA.iva_to_tier(ts.stdev(), segments, 'IVA-StdDev')
        trs_out.append(tier)
    if self._options['linreg'] is True:
        tier = sppasIVA.iva_to_tier_reglin(ts.intercept_slope(), segments, True)
        trs_out.append(tier)
        tier = sppasIVA.iva_to_tier_reglin(ts.intercept_slope(), segments, False)
        trs_out.append(tier)
    return trs_out

get_input_tiers

Return tiers with values and segments.

Parameters
  • input_files: (list)
View Source
def get_input_tiers(self, input_files):
    """Return tiers with values and segments.

        :param input_files: (list)

        """
    tier_values_input = None
    tier_segments_input = None
    for filename in input_files:
        parser = sppasTrsRW(filename)
        trs_input = parser.read()
        if tier_values_input is None:
            tier_values_input = trs_input.find(self._options['values'])
        if tier_segments_input is None:
            tier_segments_input = trs_input.find(self._options['segments'])
    if tier_values_input is None:
        logging.error('Tier with values not found: {:s}'.format(self._options['values']))
        raise NoTierInputError
    if tier_segments_input is None:
        logging.error('Tier with segments not found: {:s}'.format(self._options['segments']))
        raise NoTierInputError
    if tier_segments_input.is_interval() is False:
        logging.error('The tier with segments should be of type: Interval')
        raise BadInputError
    if any((tier_values_input.is_float(), tier_values_input.is_int())) is False:
        raise BadInputError
    return (tier_values_input, tier_segments_input)

run

Run the automatic annotation process on an input.

Parameters
  • input_files: (list of str) Values and Segments in a single file or in different ones
  • output: (str) the output file name
Returns
  • (sppasTranscription)
View Source
def run(self, input_files, output=None):
    """Run the automatic annotation process on an input.

        :param input_files: (list of str) Values and Segments in a single file or in different ones
        :param output: (str) the output file name
        :returns: (sppasTranscription)

        """
    tier_values, tier_segments = self.get_input_tiers(input_files)
    trs_output = self.convert(tier_values, tier_segments)
    trs_output.set_meta('iva_result_of', input_files[0])
    if output is not None:
        if len(trs_output) > 0:
            output_file = self.fix_out_file_ext(output)
            parser = sppasTrsRW(output_file)
            parser.write(trs_output)
            return [output_file]
        else:
            raise EmptyOutputError
    return trs_output

get_output_pattern

Pattern this annotation uses in an output filename.

View Source
def get_output_pattern(self):
    """Pattern this annotation uses in an output filename."""
    return self._options.get('outputpattern', '-iva')

get_input_patterns

Pattern this annotation expects for its input filename.

View Source
def get_input_patterns(self):
    """Pattern this annotation expects for its input filename."""
    return [self._options.get('inputpattern1', ''), self._options.get('inputpattern2', '-palign')]

get_input_extensions

Extensions that the annotation expects for its input filename.

An annotated file with measure values (pitch, intensity...), and An annotated file with a sppasTier of type 'interval'.

View Source
@staticmethod
def get_input_extensions():
    """Extensions that the annotation expects for its input filename.

        An annotated file with measure values (pitch, intensity...), and
        An annotated file with a sppasTier of type 'interval'.

        """
    return [sppasFiles.get_informat_extensions('ANNOT_MEASURE'), sppasFiles.get_informat_extensions('ANNOT_ANNOT')]