Esempio n. 1
0
def parseFile(path, fn):
	filename= fn.split(".")[0] #just name of file
	with open(path, "r") as f1:
		lines = f1.readlines()
	SAM = getSAM(lines)
	allSegs = getMAU(lines, SAM, filename)
	if allSegs is None:
		return
	segs = []
	for seg in allSegs:
		
		#print("%f %f %s %s"%(seg.start, seg.end, seg.segment, seg.index))
		tup = getSegInfo(seg)
		segs.append(tup)
	words = getWords(lines, allSegs, filename)


	maxtime = getMaxTime(allSegs)
	if maxtime == -1:
		return
	tg = TextGrid(maxTime = maxtime)
	wordtier = IntervalTier(name = 'words', maxTime = maxtime)
	phonetier = IntervalTier(name = 'phones', maxTime = maxtime)
	for interval in words:
		wordtier.add(*interval)
	for interval in segs:
		phonetier.add(*interval)
	tg.append(wordtier)
	tg.append(phonetier)
	outpath = "/Users/elias/Desktop/TextGrids/%s.TextGrid"%filename
	tg.write(outpath)
Esempio n. 2
0
    def from_ref_and_target(cls, ref_tg: BaseTextGridDocument,
                            target_tg: BaseTextGridDocument):
        """Simply interweaves the ref and target into one tg for annotations
                merging"""
        # checking first if both TG have the same amount of tiers, and the same names
        ref_names = sorted(ref_tg.textgrid.getNames())
        target_names = sorted(target_tg.textgrid.getNames())
        if len(ref_names) != len(target_names):
            error_log.log_structural(
                "The reference and target annotator's textgrids don't have the same amount of Tiers "
                "(%i for the reference, %i for the target)"
                % (len(ref_names), len(target_names)))
            return

        if ref_names != target_names:
            # TODO: maybe make this more helpful
            error_log.log_structural("The names of some of the tiers in the reference and target textgrids don't match")
            return

        #  TODO : add support for empty tiers deletion
        assert ref_tg.task == target_tg.task
        merged_tg = TextGrid(name=ref_tg.textgrid.name,
                             minTime=ref_tg.textgrid.minTime,
                             maxTime=ref_tg.textgrid.maxTime)
        for tier_name in ref_tg.textgrid.getNames():
            ref_tier: IntervalTier = deepcopy(ref_tg.textgrid.getFirst(tier_name))
            target_tier: IntervalTier = deepcopy(target_tg.textgrid.getFirst(tier_name))
            ref_tier.name = tier_name + "-ref"
            target_tier.name = tier_name + "-target"
            merged_tg.append(ref_tier)
            merged_tg.append(target_tier)
        new_doc = cls.from_textgrid(merged_tg, ref_tg.creators + target_tg.creators, ref_tg.task)
        return new_doc
Esempio n. 3
0
def ctm_to_textgrid(phone_ctm, out_directory, utt2dur, frameshift=0.01):
    textgrid_write_errors = {}
    frameshift = Decimal(str(frameshift))
    if not os.path.exists(out_directory):
        os.makedirs(out_directory)

    utt2dur_mapping = generate_utt2dur(utt2dur)

    for i, (k, v) in enumerate(sorted(phone_ctm.items())):
        maxtime = Decimal(str(utt2dur_mapping[k]))
        try:
            tg = TextGrid(maxTime=maxtime)
            phonetier = IntervalTier(name='phones', maxTime=maxtime)
            for interval in v:
                if maxtime - interval[1] < frameshift:
                    interval[1] = maxtime
                #remove B E I and stress (0,1) information from phoneme
                interval[2] = re.sub("\d+", "", interval[2].split('_')[0])
                phonetier.add(*interval)
            tg.append(phonetier)
            outpath = os.path.join(out_directory, k + '.TextGrid')
            tg.write(outpath)
        except Exception as e:
            exc_type, exc_value, exc_traceback = sys.exc_info()
            textgrid_write_errors[k] = '\n'.join(
                traceback.format_exception(exc_type, exc_value, exc_traceback))
    if textgrid_write_errors:
        error_log = os.path.join(out_directory, 'output_errors.txt')
        with io_open(error_log, 'w', encoding='utf-8') as f:
            f.write(
                u'The following exceptions were encountered during the ouput of the alignments to TextGrids:\n\n'
            )
            for k, v in textgrid_write_errors.items():
                f.write(u'{}:\n'.format(k))
                f.write(u'{}\n\n'.format(v))
    def export_segments(self, output_directory):
        from decimal import Decimal
        from textgrid import TextGrid, IntervalTier

        file_dict = {}
        for utt, segment in self.corpus.vad_segments.items():
            filename, utt_begin, utt_end = segment
            utt_begin = Decimal(utt_begin)
            utt_end = Decimal(utt_end)
            if filename not in file_dict:
                file_dict[filename] = {}
            speaker = 'segments'
            text = 'speech'
            if speaker not in file_dict[filename]:
                file_dict[filename][speaker] = []
            file_dict[filename][speaker].append([utt_begin, utt_end, text])
        for filename, speaker_dict in file_dict.items():
            try:
                speaker_directory = os.path.join(
                    output_directory,
                    self.corpus.file_directory_mapping[filename])
            except KeyError:
                speaker_directory = output_directory
            os.makedirs(speaker_directory, exist_ok=True)
            max_time = self.corpus.get_wav_duration(filename)
            tg = TextGrid(maxTime=max_time)
            for speaker in sorted(speaker_dict.keys()):
                words = speaker_dict[speaker]
                tier = IntervalTier(name=speaker, maxTime=max_time)
                for w in words:
                    if w[1] > max_time:
                        w[1] = max_time
                    tier.add(*w)
                tg.append(tier)
            tg.write(os.path.join(speaker_directory, filename + '.TextGrid'))
Esempio n. 5
0
    def check_times_merging(self):
        """Checks that paired tiers can be merged together. Outputs the partially merged textgrid as
        well as the merge conflicts."""
        from .tasks.double import MergeResults
        merged_times_tg = TextGrid(
            name=self.textgrid.name,
            maxTime=self.textgrid.maxTime,
            minTime=self.textgrid.minTime)
        merge_results = MergeResults()
        for tier in self.checking_scheme.all_tiers_names:
            merged_tier_name = tier + self.TOP_GROUP_SUFFIX
            target_tier_name = tier + self.BOTTOM_GROUP_SUFFIX
            merged_tier = self.textgrid.getFirst(merged_tier_name)
            target_tier = self.textgrid.getFirst(target_tier_name)
            # in case either tier is not present, we just skip this merge
            if merged_tier is None or target_tier is None:
                continue

            times_merged_tier, tier_merge = self.merge_tiers(merged_tier, target_tier)
            merge_results.tiers_merges.append(tier_merge)
            times_merged_tier.name = tier
            merged_times_tg.append(times_merged_tier)

        # logging conflicts as errors that could be displayed to the
        # annotator (in case of merge attempt)
        for conflict in merge_results.to_merge_conflicts_errors():
            error_log.log_merge(conflict)
        return merged_times_tg, merge_results
def convert_ctm_to_textgrid(ctm, textgrid):
    words = []
    phonemes = []
    with open(ctm, encoding='utf-8') as f:
        for l in f:
            tok = l.strip().split()
            text = tok[4]
            beg = float(tok[2])
            dur = float(tok[3])
            if tok[0][0] == '@':
                if besi.match(text):
                    text = text[:-2]
                phonemes.append((text, beg, dur))
            else:
                words.append((text, beg, dur))
    tw = IntervalTier(name='words')
    tp = IntervalTier(name='phonemes')
    for seg in words:
        try:
            tw.add(round(seg[1], 2), round(seg[1] + seg[2], 2), seg[0])
        except ValueError:
            print("Error in word seg: " + seg[0])
    for seg in phonemes:
        try:
            tp.add(round(seg[1], 2), round(seg[1] + seg[2], 2), seg[0])
        except ValueError:
            print("Error in phoneme seg: " + seg[0])
    tg = TextGrid()
    tg.append(tw)
    tg.append(tp)
    tg.write(textgrid)
def reorg_noncollapsed(f):
    padding = 0.1
    print(f)
    tg_path = os.path.join(noncollapsed_dir, f)
    tg = TextGrid()
    tg.read(tg_path)
    new_tg = TextGrid(maxTime=tg.maxTime)
    new_tg_path = tg_path.replace(noncollapsed_dir, data_dir)
    for tier in tg.tiers:
        new_tier = IntervalTier(name=tier.name, maxTime=tg.maxTime)
        for i in tier:
            new_mark = sub_pattern.sub(' ', i.mark).strip()
            if not new_mark:
                continue
            new_begin = i.minTime - padding
            if new_begin < 0:
                new_begin = 0
            new_end = i.maxTime + padding
            if new_end > tg.maxTime:
                new_end = tg.maxTime
            try:
                new_tier.add(new_begin, new_end, new_mark)
            except ValueError:
                new_tier[-1].maxTime = new_end
                new_tier[-1].mark += ' ' + new_mark
        print(len(new_tier))
        new_tg.append(new_tier)
    new_tg.write(new_tg_path)
    def gen_template_tg(self, duration: float, filename: str):
        new_tg = TextGrid(name=filename, minTime=0.0, maxTime=duration)
        for tier_name in self.tiers_specs.keys():
            new_tier = IntervalTier(name=tier_name,
                                    minTime=0.0,
                                    maxTime=duration)
            new_tg.append(new_tier)

        return new_tg
def createTextGrid(data, tierName = "words"):
	tier = IntervalTier(tierName)
	txtgrid = TextGrid()
	prevTime = 0
	for (name, time, dur, words) in data:
		tier.add(prevTime, prevTime+dur, makeSentence(words))
		prevTime += dur
	txtgrid.append(tier)
	return txtgrid
Esempio n. 10
0
def read_tg_from_str(tg_str, round_digits=DEFAULT_TEXTGRID_PRECISION):
    """
    Read the tiers contained in the Praat-formatted string tg_str into a
    TextGrid object.
    Times are rounded to the specified precision.

    Adapted from TextGrid.read()
    """
    source = StringIO(tg_str)
    tg = TextGrid()

    file_type, short = parse_header(source)
    if file_type != "TextGrid":
        raise ValueError("The file could not be parsed as a TextGrid as it is "
                         "lacking a proper header.")
    tg.minTime = parse_line(source.readline(), short, round_digits)
    tg.maxTime = parse_line(source.readline(), short, round_digits)
    source.readline()  # More header junk
    if short:
        m = int(source.readline().strip())  # Will be tg.n
    else:
        m = int(source.readline().strip().split()[2])  # Will be tg.n
    if not short:
        source.readline()
    for i in range(m):  # Loop over grids
        if not short:
            source.readline()
        if parse_line(source.readline(), short,
                      round_digits) == "IntervalTier":
            inam = parse_line(source.readline(), short, round_digits)
            imin = parse_line(source.readline(), short, round_digits)
            imax = parse_line(source.readline(), short, round_digits)
            itie = IntervalTier(inam, imin, imax)
            itie.strict = tg.strict
            n = int(parse_line(source.readline(), short, round_digits))
            for j in range(n):
                if not short:
                    source.readline().rstrip().split()  # Header junk
                jmin = parse_line(source.readline(), short, round_digits)
                jmax = parse_line(source.readline(), short, round_digits)
                jmrk = get_mark(source, short)
                if jmin < jmax:  # Non-null
                    itie.addInterval(Interval(jmin, jmax, jmrk))
            tg.append(itie)
        else:  # PointTier
            inam = parse_line(source.readline(), short, round_digits)
            imin = parse_line(source.readline(), short, round_digits)
            imax = parse_line(source.readline(), short, round_digits)
            itie = PointTier(inam)
            n = int(parse_line(source.readline(), short, round_digits))
            for j in range(n):
                source.readline().rstrip()  # Header junk
                jtim = parse_line(source.readline(), short, round_digits)
                jmrk = get_mark(source, short)
                itie.addPoint(Point(jtim, jmrk))
            tg.append(itie)
    return tg
Esempio n. 11
0
def ctm_to_textgrid(word_ctm,
                    phone_ctm,
                    out_directory,
                    corpus,
                    dictionary,
                    frameshift=0.01):
    textgrid_write_errors = {}
    frameshift = Decimal(str(frameshift))
    if not os.path.exists(out_directory):
        os.makedirs(out_directory, exist_ok=True)

    silences = {dictionary.optional_silence, dictionary.nonoptional_silence}
    for i, (filename, speaker_dict) in enumerate(sorted(word_ctm.items())):
        maxtime = corpus.get_wav_duration(filename)
        try:
            speaker_directory = os.path.join(
                out_directory, corpus.file_directory_mapping[filename])
            tg = TextGrid(maxTime=maxtime)
            for speaker in corpus.speaker_ordering[filename]:
                words = speaker_dict[speaker]
                word_tier_name = '{} - words'.format(speaker)
                phone_tier_name = '{} - phones'.format(speaker)
                word_tier = IntervalTier(name=word_tier_name, maxTime=maxtime)
                phone_tier = IntervalTier(name=phone_tier_name,
                                          maxTime=maxtime)
                for w in words:
                    word_tier.add(*w)
                for p in phone_ctm[filename][speaker]:
                    if len(phone_tier) > 0 and phone_tier[
                            -1].mark in silences and p[2] in silences:
                        phone_tier[-1].maxTime = p[1]
                    else:
                        if len(phone_tier) > 0 and p[2] in silences and p[
                                0] < phone_tier[-1].maxTime:
                            p = phone_tier[-1].maxTime, p[1], p[2]
                        elif len(phone_tier) > 0 and p[2] not in silences and p[0] < phone_tier[-1].maxTime and \
                                        phone_tier[-1].mark in silences:
                            phone_tier[-1].maxTime = p[0]
                        phone_tier.add(*p)
                tg.append(word_tier)
                tg.append(phone_tier)
            tg.write(os.path.join(speaker_directory, filename + '.TextGrid'))
        except Exception as e:
            exc_type, exc_value, exc_traceback = sys.exc_info()
            textgrid_write_errors[filename] = '\n'.join(
                traceback.format_exception(exc_type, exc_value, exc_traceback))
    if textgrid_write_errors:
        error_log = os.path.join(out_directory, 'output_errors.txt')
        with open(error_log, 'w', encoding='utf8') as f:
            f.write(
                'The following exceptions were encountered during the ouput of the alignments to TextGrids:\n\n'
            )
            for k, v in textgrid_write_errors.items():
                f.write('{}:\n'.format(k))
                f.write('{}\n\n'.format(v))
    def export_classification(self, output_directory):
        if self.cluster:
            self.cluster_utterances()
        else:
            self.get_classification_stats()
        from decimal import Decimal
        from textgrid import TextGrid, IntervalTier
        spk2utt_path = os.path.join(self.classify_directory, 'spk2utt')
        utt2spk_path = os.path.join(self.classify_directory, 'utt2spk')
        if self.corpus.segments:
            utt2spk = load_scp(utt2spk_path)
            file_dict = {}
            for utt, segment in self.corpus.segments.items():

                filename, utt_begin, utt_end = segment.split(' ')
                utt_begin = Decimal(utt_begin)
                utt_end = Decimal(utt_end)
                if filename not in file_dict:
                    file_dict[filename] = {}
                speaker = utt2spk[utt]
                text = self.corpus.text_mapping[utt]
                if speaker not in file_dict[filename]:
                    file_dict[filename][speaker] = []
                file_dict[filename][speaker].append([utt_begin, utt_end, text])
            for filename, speaker_dict in file_dict.items():
                try:
                    speaker_directory = os.path.join(
                        output_directory,
                        self.corpus.file_directory_mapping[filename])
                except KeyError:
                    speaker_directory = output_directory
                max_time = self.corpus.get_wav_duration(filename)
                tg = TextGrid(maxTime=max_time)
                for speaker in sorted(speaker_dict.keys()):
                    words = speaker_dict[speaker]
                    tier = IntervalTier(name=speaker, maxTime=max_time)
                    for w in words:
                        if w[1] > max_time:
                            w[1] = max_time
                        tier.add(*w)
                    tg.append(tier)
                tg.write(
                    os.path.join(speaker_directory, filename + '.TextGrid'))

        else:
            spk2utt = load_scp(spk2utt_path)
            for speaker, utts in spk2utt.items():
                speaker_dir = os.path.join(output_directory, speaker)
                os.makedirs(speaker_dir, exist_ok=True)
                with open(os.path.join(speaker_dir, 'utterances.txt'),
                          'w',
                          encoding='utf8') as f:
                    for u in utts:
                        f.write('{}\n'.format(u))
Esempio n. 13
0
def create_grid(wav_file: Path, text: str, tier_name: str,
                n_digits: int) -> TextGrid:
    assert wav_file.is_file()
    assert len(text) > 0
    duration_s = get_wav_duration_s(wav_file)
    duration_s = round(duration_s, n_digits)
    result = TextGrid(None, 0, duration_s)
    tier = IntervalTier(tier_name, 0, duration_s)
    symbols = list(text)
    tier.intervals.extend(get_intervals(symbols, duration_s, n_digits))
    result.append(tier)
    return result
Esempio n. 14
0
def fixTiers(source, tierlist, outfile):
    """Takes list of TextGrids, file with new tier orders, list of output file
    names, returns TextGrids with new tier order"""
    for line, tier, out in zip(source.readlines(), tierlist, outfile.readlines()):
            f = line.rstrip('\n')
            oldtg = TextGridFromFile(f)
            list_from_file = eval(tier)
            output = out.rstrip('\n')
            newtg = TextGrid('newtg')
            for n in list_from_file:
                ntier = oldtg.getFirst(n)
                newtg.append(ntier) 
            newtg.write(output)
Esempio n. 15
0
def fixTiers(source, tierlist, outfile):
    """Takes list of TextGrids, file with new tier orders, list of output file
    names, returns TextGrids with new tier order"""
    for line, tier, out in zip(source.readlines(), tierlist,
                               outfile.readlines()):
        f = line.rstrip('\n')
        oldtg = TextGridFromFile(f)
        list_from_file = eval(tier)
        output = out.rstrip('\n')
        newtg = TextGrid('newtg')
        for n in list_from_file:
            ntier = oldtg.getFirst(n)
            newtg.append(ntier)
        newtg.write(output)
Esempio n. 16
0
    def gen_merged_times(self):
        """Merges times"""
        merged_times_tg, merge_results = self.check_times_merging()
        new_tg = TextGrid(name=merged_times_tg.name,
                          maxTime=merged_times_tg.maxTime,
                          minTime=merged_times_tg.minTime)

        for tier_name in self.checking_scheme.all_tiers_names:
            merged_tier: IntervalTier = deepcopy(merged_times_tg.getFirst(tier_name))
            target_tier: IntervalTier = deepcopy(self.textgrid.getFirst(tier_name + "-target"))
            merged_tier.name = tier_name + "-merged"
            new_tg.append(merged_tier)
            new_tg.append(target_tier)

        return new_tg, merge_results
Esempio n. 17
0
def generator_textgrid(maxtime, lines, output):
    # Download Praat: https://www.fon.hum.uva.nl/praat/
    interval = maxtime / (len(lines) + 1)
    margin = 0.0001

    tg = TextGrid(maxTime=maxtime)
    linetier = IntervalTier(name="line", maxTime=maxtime)

    i = 0
    for l in lines:
        s, e, w = l.split()
        linetier.add(minTime=float(s) + margin, maxTime=float(e), mark=w)

    tg.append(linetier)
    print("successfully generator {}".format(output))
    tg.write(output)
def createNew(textgrid, tier_name, VERBOSE=False):
	tiers = textgrid.getList(tier_name)
	tier = tiers[0]
	new_tier = IntervalTier(tier_name+'_clean') 
	new_txtgrid = TextGrid()
	if VERBOSE == True:
		print ("Old tier: %s" % tier)
	for interval in tier:
		if isPause(interval.mark) == True:
			new_tier.add(interval.minTime, interval.maxTime, '')
		else:
			new_tier.add(interval.minTime, interval.maxTime, fixString(interval.mark))
	new_txtgrid.append(new_tier)
	if VERBOSE == True:
		print ("New tier: %s" % new_tier)
	return new_txtgrid
    def export_transcriptions(self, output_directory, source=None):
        transcripts = self._load_transcripts(source)
        print(self.corpus.file_directory_mapping)
        if not self.corpus.segments:
            for utt, t in transcripts.items():
                relative = self.corpus.file_directory_mapping[utt]
                if relative:
                    speaker_directory = os.path.join(output_directory,
                                                     relative)
                else:
                    speaker_directory = output_directory
                os.makedirs(speaker_directory, exist_ok=True)
                outpath = os.path.join(speaker_directory, utt + '.lab')
                with open(outpath, 'w', encoding='utf8') as f:
                    f.write(t)

        else:
            for filename in self.corpus.speaker_ordering.keys():
                maxtime = self.corpus.get_wav_duration(filename)
                try:
                    speaker_directory = os.path.join(
                        output_directory,
                        self.corpus.file_directory_mapping[filename])
                except KeyError:
                    speaker_directory = output_directory
                tiers = {}
                for speaker in self.corpus.speaker_ordering[filename]:
                    tiers[speaker] = IntervalTier(name=speaker,
                                                  maxTime=maxtime)

                tg = TextGrid(maxTime=maxtime)
                for utt_name, text in transcripts.items():
                    utt_filename, begin, end = self.corpus.segments[
                        utt_name].split(' ')
                    if utt_filename != filename:
                        continue
                    speaker = self.corpus.utt_speak_mapping[utt_name]
                    begin = float(begin)
                    end = float(end)
                    tiers[speaker].add(begin, end, text)
                for t in tiers.values():
                    tg.append(t)
                tg.write(
                    os.path.join(speaker_directory, filename + '.TextGrid'))
Esempio n. 20
0
def convert_ctm_to_textgrid(ctms, textgrid):
    for ctm in ctms:
        tiername = ctm.stem
        ret = []
        with open(ctm, encoding='utf-8') as f:
            for l in f:
                tok = l.strip().split()
                word = tok[4]
                beg = float(tok[2])
                dur = float(tok[3])
                ret.append((word, beg, dur))
        t = IntervalTier(name=tiername)
        for seg in ret:
            try:
                t.add(round(seg[1], 2), round(seg[1] + seg[2], 2), seg[0])
            except ValueError:
                print("Error in seg: " + seg[0])
        tg = TextGrid()
        tg.append(t)
        tg.write(textgrid)
def reorg_original(f):
    print(f)
    tg_path = os.path.join(noncollapsed_dir, f)
    tg = TextGrid()
    tg.read(tg_path)
    new_tg = TextGrid(maxTime=tg.maxTime)
    new_tg_path = tg_path.replace('_original.TextGrid', '.TextGrid')
    sentence_tier = tg.getFirst('Sentences')
    speaker_tier = tg.getFirst('Speakers')
    speaker_tiers = {}
    for i in speaker_tier:
        if i.mark == '':
            continue
        if ',' in i.mark:
            continue
        if i.mark == 'Tân.':
            continue
        speaker_tiers[i.mark] = IntervalTier(i.mark, maxTime=tg.maxTime)
    for i in sentence_tier:
        if not i.mark.strip():
            continue
        duration = i.maxTime - i.minTime
        mid_point = i.minTime + duration / 2
        speaker_int = speaker_tier.intervalContaining(mid_point)
        speaker = speaker_int.mark
        if speaker == 'Tân.':
            speaker = 'Tan'
        if speaker == '':
            continue
        if len(speaker_tiers[speaker]
               ) > 0 and speaker_tiers[speaker][-1].maxTime == i.minTime:
            speaker_tiers[speaker][-1].maxTime = i.maxTime
            speaker_tiers[speaker][
                -1].mark = speaker_tiers[speaker][-1].mark + ' ' + i.mark
        else:
            speaker_tiers[speaker].addInterval(i)
    for k, v in sorted(speaker_tiers.items()):
        new_tg.append(v)
    print(speaker_tiers.keys())
    new_tg.write(new_tg_path)
Esempio n. 22
0
                        'sp', '{OOV}'
                ] and w_tier[-1].maxTime > w.minTime:
                    w.minTime = w_tier[-1].maxTime
                #print(w)
                if w.maxTime > duration:
                    w.maxTime = duration
                w_tier.addInterval(w)
            for p in sorted(speaker_phone_tiers[s]):
                if len(p_tier) and p_tier[
                        -1].mark == 'sil' and p_tier[-1].maxTime > p.minTime:
                    p_tier[-1].maxTime = p.minTime
                if len(p_tier) and p.mark == 'sil' and p_tier[
                        -1].maxTime > p.minTime:
                    p.minTime = p_tier[-1].maxTime
                #print(p)
                if p.maxTime > duration:
                    p.maxTime = duration
                try:
                    p_tier.addInterval(p)
                except ValueError:
                    pass
            new_tg.append(w_tier)
            new_tg.append(p_tier)

        new_tg.write(out_path)
    except Exception as e:
        print(out_path)
        print(e)

    # print(tg)
Esempio n. 23
0
        label = ss[4]
        result.append([begin, end, label])
    return result


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('words_ctm')
    parser.add_argument('phones_ctm')
    parser.add_argument('output_textgrid')

    args = parser.parse_args()

    words = read_ctm(args.words_ctm)
    phones = read_ctm(args.phones_ctm)

    max_time = phones[-1][1]
    tg = TextGrid(maxTime=max_time)
    word_tier = IntervalTier(name="words", maxTime=max_time)
    phone_tier = IntervalTier(name="phones", maxTime=max_time)

    for w in words:
        word_tier.add(*w)
    for p in phones:
        phone_tier.add(*p)

    tg.append(word_tier)
    tg.append(phone_tier)

    tg.write(args.output_textgrid)
Esempio n. 24
0
class TextGrid(Module):
    '''
    Manages all the widgets related to TextGrid files, including the tier name
    and the text content of that tier at a given frame
    '''
    def __init__(self, app):
        '''
        Keep a reference to the master object for binding the widgets we create
        '''
        info(' - initializing module: TextGrid')
        self.app = app
        self.frame = Frame(self.app.BOTTOM)
        self.label_padx = 0
        self.canvas_frame = Frame(self.app.BOTTOM)  #, padx=self.label_padx)
        self.frame.grid(row=1, column=0, sticky='ne')
        self.canvas_frame.grid(row=1, column=1)
        self.TextGrid = None
        self.selectedTier = StringVar()
        self.tg_zoom_factor = 1.5
        self.canvas_width = 800
        self.canvas_height = 60
        self.collapse_height = 15
        self.selectedIntvlFrames = []
        self.selectedItem = None
        self.start = 0
        self.end = 0
        self.current = 0
        self.frame_shift = DoubleVar()

        self.startup()

        platform = util.get_platform()
        #bindings
        if platform == 'Linux':
            self.app.bind("<Control-n>", self.getBounds)
            self.app.bind("<Control-a>", self.getBounds)
            self.app.bind("<Control-i>", self.getBounds)
            self.app.bind("<Control-o>", self.getBounds)
            self.app.bind("<Control-f>", self.openSearch)
            # Command is Alt in Linux, apparently
            self.app.bind("<Command-Up>", self.changeTiers)
            self.app.bind("<Command-Down>", self.changeTiers)
            self.app.bind("<Command-Left>", self.changeIntervals)
            self.app.bind("<Command-Right>", self.changeIntervals)
        elif platform == 'Darwin':
            self.app.bind("<Command-n>", self.getBounds)
            self.app.bind("<Command-a>", self.getBounds)
            self.app.bind("<Command-i>", self.getBounds)
            self.app.bind("<Command-o>", self.getBounds)
            self.app.bind("<Command-f>", self.openSearch)
            self.app.bind("<Option-Up>", self.changeTiers)
            self.app.bind("<Option-Down>", self.changeTiers)
            self.app.bind("<Option-Left>", self.changeIntervals)
            self.app.bind("<Option-Right>", self.changeIntervals)
        #defaults (Command/Alt everything)
        else:
            self.app.bind("<Command-n>", self.getBounds)
            self.app.bind("<Command-a>", self.getBounds)
            self.app.bind("<Command-i>", self.getBounds)
            self.app.bind("<Command-o>", self.getBounds)
            self.app.bind("<Command-f>", self.openSearch)
            self.app.bind("<Command-Up>", self.changeTiers)
            self.app.bind("<Command-Down>", self.changeTiers)
            self.app.bind("<Command-Left>", self.changeIntervals)
            self.app.bind("<Command-Right>", self.changeIntervals)

        # these aren't Praat-like
        self.app.bind("<Shift-Left>", self.getBounds)
        self.app.bind("<Shift-Right>", self.getBounds)

    def setup(self):
        if LIBS_INSTALLED:
            self.loadOrGenerate()
            try:
                self.start = self.TextGrid.minTime
                self.end = self.TextGrid.maxTime
                self.app.frames = len(
                    self.TextGrid.getFirst(self.frameTierName))
                tiers = []
                for tier in self.TextGrid.getNames():
                    if tier != self.frameTierName and tier != self.frameTierName + '.original':
                        tiers.append(tier)
                if set(tiers) != self.tierNames:
                    self.tierNames = set(tiers)
                    self.TkWidgets = []
                    for label in self.frame.winfo_children():
                        label.destroy()
                    for canvas in self.canvas_frame.winfo_children():
                        canvas.destroy()
                    for tier in self.TextGrid.getNames():
                        if tier != self.frameTierName and tier != self.frameTierName + '.original':
                            self.TkWidgets.append(self.makeTierWidgets(tier))
                    self.makeFrameWidget()
                    self.makeTimeWidget()
                self.fillCanvases()
                self.firstFrame = int(
                    self.TextGrid.getFirst(self.frameTierName)[0].mark) + 1
                self.startFrame = self.firstFrame
                self.lastFrame = int(
                    self.TextGrid.getFirst(self.frameTierName)[-1].mark) + 1
                self.endFrame = self.lastFrame
                self.grid()
            except Exception as e:
                error(e)

    def startup(self):
        '''

        '''
        if LIBS_INSTALLED:
            self.tierNames = set()
            self.setup()

    def reset(self, event=None):
        '''
        Try to load a TextGrid file based on information stored in the metadata
        '''
        if LIBS_INSTALLED:
            self.selectedIntvlFrames = []
            self.selectedItem = None
            self.setup()

    def fromFile(self, filename):
        if LIBS_INSTALLED:
            try:
                return TextGridFile.fromFile(filename)
            except (TextGridError, UnicodeDecodeError) as e:
                f = open(filename, 'rb')
                contents = util.decode_bytes(f.read())
                f.close()
                if contents:
                    tmp = tempfile.NamedTemporaryFile()
                    tmp.write(contents.encode('utf-8'))
                    tmp.seek(0)
                    try:
                        return TextGridFile.fromFile(tmp.name)
                    except TextGridError as e:
                        error(e)
                        return None
                else:
                    error(
                        "can't load from file: unable to decode non-Unicode textgrid",
                        filename)
        else:
            error("can't load from file: textgrid lib not installed")
            return None

    def loadOrGenerate(self):
        fname = self.app.Data.checkFileLevel('.TextGrid', shoulderror=False)
        if fname:
            self.TextGrid = self.fromFile(fname)
        else:
            minTime = 0.
            if not hasattr(self.app.Audio, 'duration'):
                self.app.Audio.reset()
            try:
                maxTime = self.app.Audio.duration
            except:
                warn(
                    'Audio has no duration attribute after calling reset(), defaulting to 1 second'
                )
                maxTime = 1.
            self.TextGrid = TextGridFile(maxTime=maxTime)
            keys = self.app.Data.getFileLevel('all')
            if not ('.ult' in keys and '.txt' in keys):
                sentenceTier = IntervalTier("text")
                sentenceTier.add(minTime, maxTime, "text")
                self.TextGrid.append(sentenceTier)
            fname = self.app.Data.unrelativize(
                self.app.Data.getCurrentFilename() + '.TextGrid')
            self.app.Data.setFileLevel('.TextGrid', fname)
        names = self.TextGrid.getNames()
        for i, n in enumerate(names):
            if n in ALIGNMENT_TIER_NAMES:
                if len(self.TextGrid[i]) == 0:
                    self.TextGrid.pop(i)
                    break
                else:
                    self.frameTierName = n
                    return
        self.genFramesTier()

    def genFramesTier(self):
        debug('generating frames tier for %s' %
              self.app.Data.getCurrentFilename())
        self.frameTierName = 'frames'
        times = self.app.Dicom.getFrameTimes()
        self.app.Data.setFileLevel("NumberOfFrames", len(times))
        try:
            maxTime = max(self.app.Audio.duration, times[-1])
        except AttributeError:
            maxTime = times[-1]
        tier = PointTier('frames', maxTime=maxTime)
        for f, t in enumerate(times):
            tier.addPoint(Point(t, str(f)))
        if not self.TextGrid.maxTime or maxTime > self.TextGrid.maxTime:
            self.TextGrid.maxTime = maxTime
        self.TextGrid.append(tier)

        keys = self.app.Data.getFileLevel('all')
        if '.ult' in keys and '.txt' in keys:
            fname = self.app.Data.unrelativize(
                self.app.Data.getFileLevel('.txt'))
            f = open(fname, 'rb')
            s = util.decode_bytes(f.read())
            f.close()
            if s:
                line = s.splitlines()[0]
                sentenceTier = IntervalTier("sentence")
                sentenceTier.add(0, self.app.Audio.duration, line)
                self.TextGrid.append(sentenceTier)
                self.TextGrid.tiers = [self.TextGrid.tiers[-1]
                                       ] + self.TextGrid.tiers[:-1]

        path = self.app.Data.unrelativize(
            self.app.Data.getFileLevel('.TextGrid'))
        self.TextGrid.write(path)
        self.TextGrid = TextGridFile.fromFile(path)
        # reload to account for length changes due to frames tier being different length than audio

    @staticmethod
    def isIntervalTier(tier):
        if LIBS_INSTALLED:
            return isinstance(tier, IntervalTier)
        else:
            error("can't check if IntervalTier: textgrid lib not installed")
            return False

    def shiftFrames(self):
        '''
        Replicate original TextGrid point tier (renamed [tiername].original)
        Shift points on TextGrid tier in accordance with self.frame_shift
            Shift value is relative to 0, i.e. inputting the same shift amount a second time will not change the shift
        Redisplay shifted points
        '''
        self.app.focus()
        shift = self.frame_shift.get()
        if type(shift) == float:
            self.app.Data.setFileLevel('offset', shift)
            # diff = shift - self.app.Data.data['offset']
            originalTier = self.TextGrid.getFirst(self.frameTierName +
                                                  '.original')
            if originalTier: pass
            else:
                orig = copy.deepcopy(self.TextGrid.getFirst(
                    self.frameTierName))
                orig.name += '.original'
                self.TextGrid.append(orig)
                originalTier = self.TextGrid.getFirst(self.frameTierName +
                                                      '.original')

            oldTier = self.TextGrid.getFirst(self.frameTierName)
            allPoints = oldTier[:]
            for point in allPoints:
                oldTier.removePoint(point)

            for point in originalTier:
                new_time = point.time + shift / 1000  ## NOTE: currently in ms
                if self.TextGrid.minTime <= new_time <= self.TextGrid.maxTime:
                    self.TextGrid.getFirst(self.frameTierName).add(
                        new_time, point.mark)

            # self.app.frames = len(self.TextGrid.getFirst(self.frameTierName))         #FIXME I feel like I shouldn't have to run the getFirst function every time, but I'm not sure when I have to go back to the original textgrid, and when I can just use a variable...
            self.firstFrame = int(
                self.TextGrid.getFirst(self.frameTierName)[0].mark) + 1
            self.lastFrame = int(
                self.TextGrid.getFirst(self.frameTierName)[-1].mark) + 1
            self.app.Data.data['offset'] = shift
            # self.frame_shift.set(shift)
            self.app.Data.write()
            # newTier.write(self.TextGrid.getFirst(self.frameTierName))
            self.fillCanvases()
            self.TextGrid.write(
                self.app.Data.unrelativize(
                    self.app.Data.getFileLevel('.TextGrid')))

        #except ValueError:
        else:
            error('Not a float!')

    def makeTimeWidget(self):
        self.time_canvas = Canvas(self.canvas_frame,
                                  width=self.canvas_width,
                                  height=self.canvas_height / 3,
                                  highlightthickness=0)
        s = self.time_canvas.create_text(3, 0, anchor='nw', text=self.start)
        e = self.time_canvas.create_text(self.canvas_width,
                                         0,
                                         anchor='ne',
                                         text=self.end)
        c = self.time_canvas.create_text(self.canvas_width / 2,
                                         0,
                                         anchor='n',
                                         text=self.current)
        self.TkWidgets.append({'times': self.time_canvas})

    def makeFrameWidget(self):
        '''
        makes frame widget
        '''
        #make regular frame stuff -- label and tier
        self.frames_canvas = Canvas(self.canvas_frame,
                                    width=self.canvas_width,
                                    height=self.canvas_height,
                                    background='gray',
                                    highlightthickness=0)
        frames_label = Canvas(self.frame,
                              width=self.label_width,
                              height=self.canvas_height,
                              highlightthickness=0,
                              background='gray')
        frames_label.create_text(self.label_width,
                                 0,
                                 anchor='ne',
                                 justify='center',
                                 text='frames: ',
                                 width=self.label_width,
                                 activefill='blue')

        # make subframe to go on top of label canvas
        sbframe = Frame(frames_label)
        #put new widgets onto subframe
        offset = self.app.Data.getFileLevel('offset')
        if offset != None:
            self.frame_shift.set(offset)
        # for audio alignment
        go_btn = Button(sbframe,
                        text='Offset',
                        command=self.shiftFrames,
                        takefocus=0)
        # minmax = len(self.app.Audio.sfile)*1000
        txtbox = Spinbox(sbframe,
                         textvariable=self.frame_shift,
                         width=7,
                         from_=-10000000,
                         to=10000000)
        txtbox.bind('<Escape>', lambda ev: sbframe.focus())
        txtbox.bind('<Return>', lambda ev: self.shiftFrames())
        go_btn.grid(row=0, column=0, sticky='e')
        txtbox.grid(row=0, column=1, sticky='e')
        # put subframe on canvas
        window = frames_label.create_window(self.label_width * .3,
                                            self.canvas_height / 3,
                                            anchor='nw',
                                            window=sbframe)
        # ensure position of subframe gets updated
        frames_label.bind(
            '<Configure>',
            lambda e: frames_label.itemconfig(window, width=e.width))
        sbframe.bind(
            '<Configure>', lambda e: frames_label.configure(
                scrollregion=frames_label.bbox("all")))

        self.TkWidgets.append({
            'name': self.frameTierName,
            'frames': self.frames_canvas,
            'frames-label': frames_label
        })

        self.frames_canvas.bind("<Button-1>", self.getClickedFrame)

    def getFrameTierName(self):
        '''
        Handle some inconsistency in how we're naming our alignment tier
        '''
        for name in ALIGNMENT_TIER_NAMES:
            if name in self.TextGrid.getNames():
                return name
        raise NameError('Unable to find alignment tier')

    def getClickedFrame(self, event):
        '''
        Jumps to clicked frame
        '''
        item = self.my_find_closest(event.widget, event.x)
        self.setSelectedIntvlFrames((event.widget, item))
        frame = event.widget.gettags(item)[0][5:]
        self.app.frame = int(frame)
        if not frame in self.selectedIntvlFrames:
            self.selectedIntvlFrames = []
            self.wipeFill()
        self.app.framesUpdate()

    def makeTierWidgets(self, tier):
        '''
        Each tier should have two canvas widgets: `canvas-label` (the tier name),
        and `canvas` (the intervals on the tier with their marks)
        '''
        self.tier_pairs = {}  #ends up being format {label: canvas}

        # self.app.Trace.frame.update()
        self.label_width = 300  #self.app.Trace.frame.winfo_width()+self.label_padx
        self.end = self.TextGrid.maxTime  #float(self.TextGrid.maxTime)
        # self.first_frame = 1
        # self.last_frame = self.TextGrid.getFirst(self.frameTierName)[-1].mark
        tier_obj = self.TextGrid.getFirst(tier)
        widgets = {
            'name':
            tier,
            #'label':Label(self.frame, text=('- '+tier+':'), wraplength=200, justify='left'),
            'canvas-label':
            Canvas(self.frame,
                   width=self.label_width,
                   height=self.canvas_height,
                   highlightthickness=0),
            # 'text' :Label(self.frame, text='', wraplength=550, justify='left'),
            'canvas':
            Canvas(self.canvas_frame,
                   width=self.canvas_width,
                   height=self.canvas_height,
                   background='gray',
                   highlightthickness=0)
        }

        canvas = widgets['canvas']
        label = widgets['canvas-label']

        #builds tier label functionality
        label_text = label.create_text(self.label_width,
                                       self.canvas_height / 2,
                                       anchor='e',
                                       justify='center',
                                       text='temp',
                                       width=self.label_width / 2,
                                       activefill='blue')

        canvas.bind("<Button-1>", self.genFrameList)
        label.bind("<Button-1>", self.genFrameList)
        label.bind("<Double-Button-1>", self.collapse)
        label.bind("<Button-4>", self.collapse)
        label.bind("<Button-5>", self.collapse)
        label.bind("<MouseWheel>", self.collapse)
        canvas.bind("<Button-4>", self.collapse)
        canvas.bind("<Button-5>", self.collapse)
        canvas.bind("<MouseWheel>", self.collapse)

        return widgets

    def changeIntervals(self, event):
        '''

        '''
        if self.selectedItem:
            duration = self.end - self.start

            # There might be a more efficient way to get the tier name:
            widg = self.selectedItem[0]
            itm = self.selectedItem[1]
            for el in self.TkWidgets:
                if widg in el.values():
                    tier_name = el['name']
                    break

            #finding Interval mintime and maxtime
            oldMinTime = None
            oldMaxTime = None
            q = 0
            tags = widg.gettags(itm)
            while oldMinTime == None or oldMaxTime == None:
                if tags[q][:7] == 'minTime':
                    oldMinTime = float(tags[q][7:])
                elif tags[q][:7] == 'maxTime':
                    oldMaxTime = float(tags[q][7:])
                q += 1

            tier = self.TextGrid.getFirst(tier_name)
            intvl_i = tier.indexContaining(oldMaxTime -
                                           ((oldMaxTime - oldMinTime) / 2))

            if event.keysym == 'Left':
                new_intvl_i = intvl_i - 1
            elif event.keysym == 'Right':
                new_intvl_i = intvl_i + 1
            if 0 <= new_intvl_i < len(tier):
                #find characteristics of new adjacent interval
                newMinTime = tier[new_intvl_i].minTime
                newMaxTime = tier[new_intvl_i].maxTime
                itvlDuration = newMaxTime - newMinTime
                newCenter = newMinTime + itvlDuration / 2

                #figure out new window parameters based on new interval
                start = newCenter - duration / 2
                end = newCenter + duration / 2
                if start < 0:
                    self.start = 0
                    self.end = duration
                elif end > self.TextGrid.maxTime:
                    self.start = self.TextGrid.maxTime - duration
                    self.end = self.TextGrid.maxTime
                else:
                    self.start = newCenter - duration / 2
                    self.end = newCenter + duration / 2
                relDuration = self.end - self.start

                # select new item
                rel_time = newCenter - self.start
                x_loc = float(rel_time / relDuration * self.canvas_width)
                item = self.my_find_closest(widg, x_loc)
                self.selectedItem = (widg, item)
                self.setSelectedIntvlFrames(self.selectedItem)

                self.fillCanvases()
                self.genFrameList(widg=widg, x_loc=x_loc)

    def changeTiers(self, event):
        '''

        '''
        index = None
        if self.selectedItem:
            for i, el in enumerate(self.TkWidgets):
                if self.selectedItem[0] in el.values():
                    index = i

            if index != None:
                if event.keysym == 'Up' and 'canvas' in self.TkWidgets[index -
                                                                       1]:
                    new_widg = self.TkWidgets[index - 1]['canvas']
                elif event.keysym == 'Down' and 'canvas' in self.TkWidgets[
                        index + 1]:
                    new_widg = self.TkWidgets[index + 1]['canvas']
                else:
                    return

                new_item = new_widg.find_withtag("frame" +
                                                 str(self.app.frame))[0]
                self.selectedItem = (new_widg, new_item)

                self.fillCanvases()
                self.update()
                self.app.Spectrogram.update()

    def getMinMaxTime(self):
        '''
        Returns minTime and maxTime tags from selected interval
        If no minTime or maxTime, returns start or end time of viewed section of TextGrid
        '''
        start = None
        end = None

        for tag in self.selectedItem[0].gettags(self.selectedItem[1]):
            if tag[:7] == 'minTime':
                start = float(tag[7:])
            elif tag[:7] == 'maxTime':
                end = float(tag[7:])

        if start == None:
            start = self.start
        if end == None:
            end = self.end

        return (start, end)

    def getBounds(self, event):
        '''

        '''
        # debug(event.char, event.keysym, event.keycode)
        # debug(self.app.frame)
        f = self.tg_zoom_factor
        a = self.end - self.start
        z_out = (a - (a / f)) / 2
        z_in = ((f * a) - a) / 2
        old_start = self.start
        old_end = self.end

        if event.keysym == 'n':
            if self.selectedItem:
                self.start, self.end = self.getMinMaxTime()
            # for tag in self.selectedItem[0].gettags(self.selectedItem[1]):
            #   if tag[:7] == 'minTime':
            #       self.start = float(tag[7:])
            #   elif tag[:7] == 'maxTime':
            #       self.end = float(tag[7:])
        if event.keysym == 'a':
            self.start = 0
            self.end = self.TextGrid.maxTime
        if event.keysym == 'o':
            self.start = self.start - z_in
            self.end = self.end + z_in
        if event.keysym == 'i':
            self.start = self.start + z_out
            self.end = self.end - z_out
        if event.keysym == 'Left':
            start = self.start - a / (10 * f)
            end = self.end - a / (10 * f)
            if (start < 0):
                self.start = 0
                self.end = a
            else:
                self.start = start
                self.end = end
        if event.keysym == 'Right':
            start = self.start + a / (10 * f)
            end = self.end + a / (10 * f)
            if end > self.TextGrid.maxTime:
                self.start = self.TextGrid.maxTime - a
                self.end = self.TextGrid.maxTime
            else:
                self.start = start
                self.end = end

        self.fillCanvases()

    def getTracedFrames(self, frames):
        '''

        '''
        frames = [frame[5:]
                  for frame in frames]  #to get rid of word "frame in tag"
        tracedFrames = []
        for trace in self.app.Data.data['traces']:
            tracedFrames = tracedFrames + self.app.Data.tracesExist(trace)

        return set(frames).intersection(tracedFrames)

    def fillCanvases(self):
        '''

        '''
        if self.start < 0:
            self.start = 0.
        if self.end > self.TextGrid.maxTime:
            self.end = self.TextGrid.maxTime
        self.updateTimeLabels()

        if self.selectedItem:
            old_selected_tags = self.selectedItem[0].gettags(
                self.selectedItem[1])
        duration = self.end - self.start
        self.frameTier = self.TextGrid.getFirst(self.frameTierName)
        for el in self.TkWidgets:
            if 'name' in el:
                tier = self.TextGrid.getFirst(el['name'])
                # debug(tier)
            if 'canvas' in el:
                canvas = el['canvas']
                #remove previous intervals
                canvas.delete('all')
                #get starting interval
                i = tier.indexContaining(self.start)
                # not sure why, but this is sometimes None -JNW 2020-01-28
                if i != None:
                    #debug(self.TextGrid, self.current, el, tier, self.start, i)
                    time = tier[i].maxTime
                    frame_i = 0
                    while i < len(tier) and tier[i].minTime <= self.end:
                        if self.start >= tier[i].minTime:
                            strtime = self.start
                        else:
                            strtime = tier[i].minTime
                        if self.end <= tier[i].maxTime:
                            time = self.end
                        length = time - strtime
                        pixel_length = length / duration * self.canvas_width

                        mod = length / 2
                        rel_time = time - self.start
                        loc = (rel_time - mod) / duration * self.canvas_width

                        text = canvas.create_text(loc,
                                                  self.canvas_height / 2,
                                                  justify='center',
                                                  text=tier[i].mark,
                                                  width=pixel_length,
                                                  activefill='blue')
                        minTimetag = "minTime" + str(tier[i].minTime)
                        maxTimetag = "maxTime" + str(tier[i].maxTime)
                        canvas.addtag_withtag(minTimetag, text)
                        canvas.addtag_withtag(maxTimetag, text)
                        #add containted frames to tags
                        while frame_i < len(
                                self.frameTier
                        ) and self.frameTier[frame_i].time <= tier[i].maxTime:
                            if self.frameTier[frame_i].time >= tier[i].minTime:
                                canvas.addtag_withtag(
                                    "frame" + self.frameTier[frame_i].mark,
                                    text)
                                if tier[i].mark != '':
                                    el['canvas-label'].addtag_all(
                                        "frame" + self.frameTier[frame_i].mark)
                            frame_i += 1
                        #pass on selected-ness
                        if self.selectedItem:
                            if self.selectedItem[
                                    0] != self.app.Spectrogram.canvas:
                                # old_selected_tags = self.selectedItem[0].gettags(self.selectedItem[1])
                                if minTimetag in old_selected_tags and maxTimetag in old_selected_tags and canvas == self.selectedItem[
                                        0]:
                                    # I'm not sure why, but when collapsing canvases this sometimes
                                    # changes which tier is selected. Adding canvas == self.selectedItem[0]
                                    # seems to fix this though.
                                    # - D.S. 2020-01-30
                                    self.selectedItem = (canvas, text)
                        #create line
                        loc = rel_time / duration * self.canvas_width
                        i += 1
                        if i < len(tier) and loc < self.canvas_width:
                            canvas.create_line(loc,
                                               0,
                                               loc,
                                               self.canvas_height,
                                               tags='line')
                            time = tier[
                                i].maxTime  #here so that loop doesn't run an extra time

                    #fills labels with info about tiers w/traces
                    self.updateTierLabels()

            elif 'frames' in el:
                frames = el['frames']
                i = 0
                frames.delete('all')
                first_frame_found = False
                while i < len(tier) and tier[i].time <= self.end:
                    # debug(tier[i].time, i,'frame time and frame number (line 1076)')
                    if tier[i].time >= self.start:
                        # x_coord = (tier[i].time-self.start)/duration*self.canvas_width
                        x_coord = ((tier[i].time - self.start) *
                                   self.canvas_width) / duration
                        #determine fill
                        if tier[i].mark in self.app.Data.getCurrentTraceTracedFrames(
                        ):
                            fill = 'black'
                        else:
                            fill = 'gray70'
                        frame = frames.create_line(x_coord,
                                                   0,
                                                   x_coord,
                                                   self.canvas_height,
                                                   tags="frame" + tier[i].mark,
                                                   fill=fill)
                        if first_frame_found == False and i + 1 < len(tier):
                            self.firstFrame = int(tier[i].mark) + 1
                            first_frame_found = True
                            self.frame_len = tier[i + 1].time - tier[i].time
                        CanvasTooltip(frames, frame, text=tier[i].mark)
                    i += 1
                self.lastFrame = int(tier[i - 1].mark)

        self.paintCanvases()
        if hasattr(self.app, 'Spectrogram'):
            # don't try to call this during startup
            # because TextGrid is loaded earlier
            self.app.Spectrogram.reset()

    def updateTimeLabels(self):
        '''

        '''
        self.current = self.TextGrid.getFirst(
            self.frameTierName)[self.app.frame - 1].time
        self.TkWidgets[-1]['times'].itemconfig(1,
                                               text='{:.6f}'.format(
                                                   self.start))
        self.TkWidgets[-1]['times'].itemconfig(2,
                                               text='{:.6f}'.format(self.end))
        self.TkWidgets[-1]['times'].itemconfig(3,
                                               text='{:.6f}'.format(
                                                   self.current))

    def updateTierLabels(self):
        '''

        '''
        for el in self.TkWidgets:
            if 'canvas' in el:
                current_label = el['canvas-label'].find_all()[0]
                nonempty_frames = el['canvas-label'].gettags(current_label)
                el['canvas-label'].itemconfig(
                    current_label,
                    text='{}:\n({}/{})'.format(
                        el['name'], len(self.getTracedFrames(nonempty_frames)),
                        len(nonempty_frames)))

    def my_find_closest(self, widg, x_loc):
        '''
        replaces TkInter's find_closest function, which is buggy, determines
        whether found item is text, line, or label, and returns corresponding item
        '''
        #could be more efficient FIXME
        maybe_item = None
        dist = 999999999999
        for el in widg.find_all():
            obj_x = widg.coords(el)[0]
            if abs(obj_x - x_loc) < dist:
                dist = abs(obj_x - x_loc)
                maybe_item = el

        if widg in self.tier_pairs.keys():  #on tier-label canvas
            #fill selected tier frames
            # self.setSelectedIntvlFrames(widg,item)
            item = maybe_item

        elif widg in self.tier_pairs.values(
        ):  #on canvas with intervals/frames
            if isinstance(maybe_item, int):
                # #if item found is a boundary
                # if len(widg.gettags(maybe_item)) == 0 or widg.gettags(maybe_item) == ('current',):
                if 'line' in widg.gettags(maybe_item):
                    #determine on which side of the line the event occurred
                    if widg.coords(maybe_item)[0] > x_loc:
                        item = maybe_item - 1
                    else:  #i.e. event was on line or to the right of it
                        item = maybe_item + 1
                else:
                    item = maybe_item

                # self.setSelectedIntvlFrames(widg,item)
        else:
            item = maybe_item

        return item

    def setSelectedIntvlFrames(self, tupl):
        ''' '''
        widg, item = tupl
        self.selectedIntvlFrames = []
        for x in widg.gettags(item):
            if x[:5] == 'frame':
                self.selectedIntvlFrames.append(x[5:])

    def wipeFill(self):
        '''
        Turns selected frame and interval back to black
        '''
        for frame in range(1, self.app.frames + 1):
            if str(frame) in self.app.Data.getCurrentTraceTracedFrames():
                fill = 'black'
            else:
                fill = 'gray70'
            self.frames_canvas.itemconfig('frame' + str(frame), fill=fill)
        if self.selectedItem:
            wdg, itm = self.selectedItem
            if wdg.type(itm) != 'text' and wdg.type(itm) != None:
                wdg, itm = self.app.Spectrogram.oldSelected
            wdg.itemconfig(itm, fill='black')
            if len(wdg.find_withtag(itm + 1)) > 0:
                wdg.itemconfig(itm + 1, fill='black')
            if len(wdg.find_withtag(itm - 1)) > 0:
                wdg.itemconfig(itm - 1, fill='black')
            #clicked tier label
            if wdg in self.tier_pairs.keys():
                wdg.itemconfig(1, fill='black')
                self.tier_pairs[wdg].itemconfig('all', fill='black')
                self.frames_canvas.itemconfig('all', fill='black')

    def genFrameList(self, event=None, widg=None, x_loc=None, SI=False):
        '''
        Upon click, reads frames within interval from the tags to the text item of that interval,
        and highlights text of clicked interval
        '''
        self.wipeFill()
        if event:
            widg = event.widget
            x_loc = event.x

        if SI == False:
            item = self.my_find_closest(widg, x_loc)
            self.selectedItem = (widg, item)
            self.setSelectedIntvlFrames(self.selectedItem)

        #automatically updates frame
        if not str(self.app.frame) in self.selectedIntvlFrames:
            if self.selectedIntvlFrames:
                new_frame = int(self.selectedIntvlFrames[0])
            else:
                frame = self.my_find_closest(self.frames_canvas, x_loc)
                framenum = self.frames_canvas.gettags(frame)[0][5:]
                new_frame = int(framenum)
            if self.firstFrame > new_frame:
                new_frame = self.firstFrame
            elif new_frame > self.lastFrame:
                new_frame = self.lastFrame
            self.app.frame = new_frame
            self.app.framesUpdate()
        else:
            self.paintCanvases()
            self.app.Spectrogram.update()

    def collapse(self, event):
        '''
        collapse or uncollapse selected tier
        '''
        widg = event.widget

        if event.num == 1:
            h = self.collapse_height
            if int(widg['height']) == h:
                h = self.canvas_height
        elif event.num == 4 or event.delta > 0:
            h = self.canvas_height
        else:
            h = self.collapse_height

        if int(widg['height']) == h:
            return
        elif h == self.canvas_height:
            mv = (self.canvas_height - self.collapse_height - 14) / 2
        else:
            mv = (self.collapse_height + 14 - self.canvas_height) / 2
        # manually shifting the text by 7 pixels is a rather ugly hack,
        # but it works - DS

        if widg in self.tier_pairs:
            l, c = widg, self.tier_pairs[widg]
        else:
            c = widg
            l = None
            for k in self.tier_pairs:
                if self.tier_pairs[k] == widg:
                    l = k
                    break
        l.configure(height=h)
        c.configure(height=h)
        l.move('all', 0, mv)
        self.app.event_generate('<Configure>')

    def paintCanvases(self):
        '''

        '''
        if self.selectedItem:
            wdg, itm = self.selectedItem
            #paint selected
            if wdg.type(itm) == 'text':
                wdg.itemconfig(itm, fill='blue')
                #paint boundaries of selected
                if itm + 1 in wdg.find_all():
                    wdg.itemconfig(itm + 1, fill='blue')
                if itm - 1 in wdg.find_all():
                    wdg.itemconfig(itm - 1, fill='blue')
            if wdg in self.tier_pairs.keys():  #if on tier-label canvas
                canvas = self.tier_pairs[wdg]
                for el in canvas.find_all():
                    # #make all text intervals blue
                    # if canvas.type(canvas.find_withtag(el)) == 'text':
                    canvas.itemconfig(el, fill='blue')

            #paint frames
            frames = wdg.gettags(itm)
            for frame in frames:
                if frame[:5] == 'frame':
                    frame_obj = self.frames_canvas.find_withtag(frame)
                    #detect whether frame contains any traces
                    framenum = frame[5:]
                    if framenum in self.app.Data.getCurrentTraceTracedFrames():
                        fill = 'blue'
                    else:
                        fill = 'dodger blue'
                    self.frames_canvas.itemconfig(frame_obj, fill=fill)

        #current frame highlighted in red
        if self.app.frame:
            self.highlighted_frame = self.frames_canvas.find_withtag(
                'frame' + str(self.app.frame))
            self.frames_canvas.itemconfig(self.highlighted_frame, fill='red')

    def update(self):
        '''

        '''
        # debug(self.frames_canvas)
        #create list of displayed frames' tags
        itrobj = []
        for itm in self.frames_canvas.find_all():
            itrobj += list(self.frames_canvas.gettags(itm))
        #if selected frame is out of view
        if "frame" + str(self.app.frame) not in itrobj:
            duration = self.end - self.start
            #recenter view on selected frame
            new_time = self.TextGrid.getFirst(
                self.frameTierName)[self.app.frame - 1].time
            self.start = new_time - (duration / 2)
            self.end = new_time + (duration / 2)
            #redraw
            self.fillCanvases()
        self.wipeFill()
        #if selected frame outside selected interval, select interval on same tier containing frame
        if self.selectedItem:
            if self.selectedItem[0] in self.tier_pairs.keys(
            ) or self.selectedItem[0] in self.tier_pairs.values():
                if "frame" + str(
                        self.app.frame) not in self.selectedItem[0].gettags(
                            self.selectedItem[1]
                        ):  #FIXME should also detect if on label canvas
                    widg = self.selectedItem[0]
                    if widg in self.tier_pairs:
                        widg = self.tier_pairs[widg]
                    new_interval = widg.find_withtag("frame" +
                                                     str(self.app.frame))[0]
                    self.selectedItem = (self.selectedItem[0], new_interval)

        # repaint all frames
        self.paintCanvases()
        self.updateTimeLabels()

    def grid(self, event=None):
        '''
        Wrapper for gridding all of our Tk widgets.  This funciton assumes that the tiers (as
        specified in the actual TextGrid files) are in some sort of reasonable order, with the
        default label being drawn on top.
        '''
        for t in range(len(self.TkWidgets)):
            tierWidgets = self.TkWidgets[t]
            if 'label' in tierWidgets:
                tierWidgets['label'].grid(row=t, column=0, sticky='w')
            if 'frames' in tierWidgets:
                tierWidgets['frames'].grid(row=t,
                                           column=2,
                                           sticky='w',
                                           pady=self.app.pady)
                tierWidgets['frames-label'].grid(row=t,
                                                 column=0,
                                                 sticky='w',
                                                 pady=self.app.pady)
            if 'canvas' in tierWidgets:
                tierWidgets['canvas'].grid(row=t,
                                           column=2,
                                           sticky='w',
                                           pady=self.app.pady / 2)
                tierWidgets['canvas-label'].grid(row=t,
                                                 column=0,
                                                 sticky='w',
                                                 pady=self.app.pady / 2)
                self.tier_pairs[
                    tierWidgets['canvas-label']] = tierWidgets['canvas']
            if 'times' in tierWidgets:
                tierWidgets['times'].grid(row=t, column=2, sticky='s')

    def grid_remove(self):
        raise NotImplementedError('cannot grid_remove the TextGridModule')

    def openSearch(self, event=None):
        self.app.Search.openSearch()
Esempio n. 25
0
        if interval.mark == '':
            continue
        print(interval.mark, interval.minTime, interval.maxTime)
        outpath = os.path.join(temp_wav_dir, interval.mark + '.wav')
        extract_audio(wav_path, outpath, interval.minTime, interval.maxTime, padding = padding)
        rep = Mfcc(outpath, freq_lims = (80, 7800), num_coeffs = 12, win_len = 0.025, time_step = 0.01)
        rep.is_windowed = True
        duration = interval.maxTime - interval.minTime
        thresh = unnorm(norm(duration, min_duration, max_duration), min_thresh, max_thresh)
        rep.segment(threshold = thresh)
        print(sorted(rep._segments.keys()))
        padded_begin = interval.minTime - padding
        if padded_begin < 0:
            padded_begin = 0
        for k in sorted(rep._segments.keys()):
            with open(os.path.join(temp_mfcc_dir, '{}.mfcc'.format(seg_ind)), 'wb') as fh:
                pickle.dump(rep[k[0],k[1]], fh)
            with open(os.path.join(temp_mean_dir, '{}.mean'.format(seg_ind)), 'wb') as fh:
                pickle.dump(rep._segments[k], fh)
            segs.append(str(seg_ind))
            seg_ind += 1
            begin = round(k[0] + padded_begin, 3)

            end = round(k[1] + padded_begin,3)
            print(begin, end)
            segmentation_tier.add(begin, end, '{}'.format(seg_ind))
    with open(os.path.join(temp_align_dir, '{}.seg'.format(f)), 'w') as fa:
        fa.write(' '.join(segs))
    tg.append(segmentation_tier)
    tg.write(textgrid_path.replace(data_dir, temp_textgrid_dir))
                    wordintervals.append(x)

            elif i == 1:
                for x in ti:
                    x.maxTime += cur_dur
                    x.minTime += cur_dur
                    phoneintervals.append(x)
                cur_dur += maxtime

    words = IntervalTier(name='words')
    for i in wordintervals:
        words.addInterval(i)
    phones = IntervalTier(name='phones')
    for i in phoneintervals:
        phones.addInterval(i)
    tg1 = TextGrid(maxTime=cur_dur)
    tg1.append(words)
    tg1.append(phones)
    tg1.write(chapteroutpath1, null='')

    speaker_tier = IntervalTier(name=speaker)
    for i in range(len(groupedwavfiles)):
        if i == 1:
            speaker_tier.add(0.0, wavfiletimes[0], groupedlabtext[0])
        else:
            speaker_tier.add(wavfiletimes[i - 2], wavfiletimes[i - 1],
                             groupedlabtext[i - 1])
    tg2 = TextGrid(maxTime=duration)
    tg2.append(speaker_tier)
    tg2.write(chapteroutpath2, null='')
def ctm_to_textgrid(word_ctm, phone_ctm, out_directory, corpus, dictionary, frameshift=0.01):
    textgrid_write_errors = {}
    frameshift = Decimal(str(frameshift))
    if not os.path.exists(out_directory):
        os.makedirs(out_directory, exist_ok=True)
    if not corpus.segments:
        for i, (k, v) in enumerate(sorted(word_ctm.items())):
            maxtime = Decimal(str(corpus.get_wav_duration(k)))
            speaker = list(v.keys())[0]
            v = list(v.values())[0]
            try:
                tg = TextGrid(maxTime=maxtime)
                wordtier = IntervalTier(name='words', maxTime=maxtime)
                phonetier = IntervalTier(name='phones', maxTime=maxtime)
                for interval in v:
                    if maxtime - interval[1] < frameshift:  # Fix rounding issues
                        interval[1] = maxtime
                    wordtier.add(*interval)
                for interval in phone_ctm[k][speaker]:
                    if maxtime - interval[1] < frameshift:
                        interval[1] = maxtime
                    phonetier.add(*interval)
                tg.append(wordtier)
                tg.append(phonetier)
                relative = corpus.file_directory_mapping[k]
                if relative:
                    speaker_directory = os.path.join(out_directory, relative)
                else:
                    speaker_directory = out_directory
                os.makedirs(speaker_directory, exist_ok=True)
                outpath = os.path.join(speaker_directory, k + '.TextGrid')
                tg.write(outpath)
            except Exception as e:
                exc_type, exc_value, exc_traceback = sys.exc_info()
                textgrid_write_errors[k] = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_traceback))
    else:
        silences = {dictionary.optional_silence, dictionary.nonoptional_silence}
        for i, (filename, speaker_dict) in enumerate(sorted(word_ctm.items())):
            maxtime = corpus.get_wav_duration(filename)
            try:
                speaker_directory = os.path.join(out_directory, corpus.file_directory_mapping[filename])
                tg = TextGrid(maxTime=maxtime)
                for speaker in corpus.speaker_ordering[filename]:
                    words = speaker_dict[speaker]
                    word_tier_name = '{} - words'.format(speaker)
                    phone_tier_name = '{} - phones'.format(speaker)
                    word_tier = IntervalTier(name=word_tier_name, maxTime=maxtime)
                    phone_tier = IntervalTier(name=phone_tier_name, maxTime=maxtime)
                    for w in words:
                        word_tier.add(*w)
                    for p in phone_ctm[filename][speaker]:
                        if len(phone_tier) > 0 and phone_tier[-1].mark in silences and p[2] in silences:
                            phone_tier[-1].maxTime = p[1]
                        else:
                            if len(phone_tier) > 0 and p[2] in silences and p[0] < phone_tier[-1].maxTime:
                                p = phone_tier[-1].maxTime, p[1], p[2]
                            elif len(phone_tier) > 0 and p[2] not in silences and p[0] < phone_tier[-1].maxTime and \
                                            phone_tier[-1].mark in silences:
                                phone_tier[-1].maxTime = p[0]
                            phone_tier.add(*p)
                    tg.append(word_tier)
                    tg.append(phone_tier)
                tg.write(os.path.join(speaker_directory, filename + '.TextGrid'))
            except Exception as e:
                exc_type, exc_value, exc_traceback = sys.exc_info()
                textgrid_write_errors[filename] = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_traceback))
    if textgrid_write_errors:
        error_log = os.path.join(out_directory, 'output_errors.txt')
        with open(error_log, 'w', encoding='utf8') as f:
            f.write('The following exceptions were encountered during the ouput of the alignments to TextGrids:\n\n')
            for k,v in textgrid_write_errors.items():
                f.write('{}:\n'.format(k))
                f.write('{}\n\n'.format(v))
def ctm_to_textgrid(word_ctm, phone_ctm, out_directory, corpus):

    if not os.path.exists(out_directory):
        os.makedirs(out_directory, exist_ok=True)
    if not corpus.segments:
        for i,(k,v) in enumerate(word_ctm.items()):
            maxtime = corpus.get_wav_duration(k)
            try:
                tg = TextGrid(maxTime = maxtime)
                wordtier = IntervalTier(name = 'words', maxTime = maxtime)
                phonetier = IntervalTier(name = 'phones', maxTime = maxtime)
                for interval in v:
                    wordtier.add(*interval)
                for interval in phone_ctm[k]:
                    phonetier.add(*interval)
                tg.append(wordtier)
                tg.append(phonetier)
                if corpus.speaker_directories:
                    speaker_directory = os.path.join(out_directory, corpus.utt_speak_mapping[k])
                else:
                    speaker_directory = out_directory
                os.makedirs(speaker_directory, exist_ok=True)
                outpath = os.path.join(speaker_directory, k + '.TextGrid')
                tg.write(outpath)
            except ValueError as e:
                print('Could not write textgrid for {}'.format(k))
                print(e)
    else:
        tgs = {}
        for i,(k,v) in enumerate(word_ctm.items()):
            rec = corpus.segments[k]
            rec, begin, end = rec.split(' ')
            maxtime = corpus.get_wav_duration(k)
            if rec not in tgs:
                tgs[rec] = TextGrid(maxTime = maxtime)
            tg = tgs[rec]
            begin = float(begin)
            speaker = corpus.utt_speak_mapping[k]
            word_tier_name = '{} - words'.format(speaker)
            phone_tier_name = '{} - phones'.format(speaker)
            wordtier = tg.getFirst(word_tier_name)
            if wordtier is None:
                wordtier = IntervalTier(name = word_tier_name, maxTime = maxtime)
                tg.append(wordtier)
            phonetier = tg.getFirst(phone_tier_name)
            if phonetier is None:
                phonetier = IntervalTier(name = phone_tier_name, maxTime = maxtime)
                tg.append(phonetier)
            for interval in v:
                interval = interval[0] + begin, interval[1] + begin, interval[2]
                wordtier.add(*interval)
            for interval in phone_ctm[k]:
                interval = interval[0] + begin, interval[1] + begin, interval[2]
                phonetier.add(*interval)
        for k,v in tgs.items():
            outpath = os.path.join(out_directory, k + '.TextGrid')
            try:
                v.write(outpath)
            except ValueError as e:
                print('Could not write textgrid for {}'.format(k))
                print(e)
Esempio n. 29
0
            for line in time_list:
                line_split = line.split()
                #print(line_split[0], file_id)
                if line_split[0] in file_id:
                    start = float(line_split[1]) / 1000
                    end = float(line_split[2]) / 1000
                    break
                else:
                    continue

        # Make word and speaker tiers
        intervalTiers = {}

        word_name = speaker + " - words"
        word_tier = IntervalTier(word_name, 0, duration)
        intervalTiers[word_name] = word_tier
        intervalTiers[word_name].add(0, duration, word)

        phone_name = speaker + " - phones"
        phone_tier = IntervalTier(phone_name, 0, duration)
        intervalTiers[phone_name] = phone_tier
        intervalTiers[phone_name].add(0, start, "h")
        intervalTiers[phone_name].add(start, end, vowel)
        intervalTiers[phone_name].add(end, duration, "d")

        for key, value in intervalTiers.items():
            tg.append(value)

        export_name = file_id + ".TextGrid"
        tg.write(os.path.join(output_dir, export_name))
Esempio n. 30
0
def ctm_to_textgrid(word_ctm,
                    phone_ctm,
                    out_directory,
                    corpus,
                    dictionary,
                    frameshift=0.01):
    frameshift = Decimal(str(frameshift))
    if not os.path.exists(out_directory):
        os.makedirs(out_directory, exist_ok=True)
    if not corpus.segments:
        for i, (k, v) in enumerate(sorted(word_ctm.items())):
            maxtime = Decimal(str(corpus.get_wav_duration(k)))
            speaker = list(v.keys())[0]
            v = list(v.values())[0]
            try:
                tg = TextGrid(maxTime=maxtime)
                wordtier = IntervalTier(name='words', maxTime=maxtime)
                phonetier = IntervalTier(name='phones', maxTime=maxtime)
                for interval in v:
                    if maxtime - interval[
                            1] < frameshift:  # Fix rounding issues
                        interval[1] = maxtime
                    wordtier.add(*interval)
                for interval in phone_ctm[k][speaker]:
                    if maxtime - interval[1] < frameshift:
                        interval[1] = maxtime
                    phonetier.add(*interval)
                tg.append(wordtier)
                tg.append(phonetier)
                if corpus.speaker_directories:
                    speaker_directory = os.path.join(
                        out_directory, corpus.utt_speak_mapping[k])
                else:
                    speaker_directory = out_directory
                os.makedirs(speaker_directory, exist_ok=True)
                outpath = os.path.join(speaker_directory, k + '.TextGrid')
                tg.write(outpath)
            except ValueError as e:
                print(
                    'There was an error writing the TextGrid for {}, please see below:'
                    .format(k))
                raise
    else:
        silences = {
            dictionary.optional_silence, dictionary.nonoptional_silence
        }
        for i, (filename, speaker_dict) in enumerate(sorted(word_ctm.items())):
            maxtime = corpus.get_wav_duration(filename)
            tg = TextGrid(maxTime=maxtime)
            for speaker, words in speaker_dict.items():
                word_tier_name = '{} - words'.format(speaker)
                phone_tier_name = '{} - phones'.format(speaker)
                word_tier = IntervalTier(name=word_tier_name, maxTime=maxtime)
                phone_tier = IntervalTier(name=phone_tier_name,
                                          maxTime=maxtime)
                for w in words:
                    word_tier.add(*w)
                for p in phone_ctm[filename][speaker]:
                    if len(phone_tier) > 0 and phone_tier[
                            -1].mark in silences and p[2] in silences:
                        phone_tier[-1].maxTime = p[1]
                    else:
                        if len(phone_tier) > 0 and p[2] in silences and p[
                                0] < phone_tier[-1].maxTime:
                            p = phone_tier[-1].maxTime, p[1], p[2]
                        elif len(phone_tier) > 0 and p[2] not in silences and p[0] < phone_tier[-1].maxTime and \
                                        phone_tier[-1].mark in silences:
                            phone_tier[-1].maxTime = p[0]
                        phone_tier.add(*p)
                tg.append(word_tier)
                tg.append(phone_tier)
            tg.write(os.path.join(out_directory, filename + '.TextGrid'))
			for line in time_list:
				line_split = line.split()
				#print(line_split[0], file_id)
				if line_split[0] in file_id:
					start = float(line_split[1])/1000
					end = float(line_split[2])/1000
					break
				else:
					continue

		# Make word and speaker tiers
		intervalTiers = {}

		word_name = speaker + " - words"
		word_tier = IntervalTier(word_name, 0, duration)
		intervalTiers[word_name] = word_tier
		intervalTiers[word_name].add(0, duration, word)

		phone_name = speaker + " - phones"
		phone_tier = IntervalTier(phone_name, 0, duration)
		intervalTiers[phone_name] = phone_tier
		intervalTiers[phone_name].add(0, start, "h")
		intervalTiers[phone_name].add(start, end, vowel)
		intervalTiers[phone_name].add(end, duration, "d")

		for key, value in intervalTiers.items():
			tg.append(value)

		export_name = file_id + ".TextGrid"
		tg.write(os.path.join(output_dir, export_name))
Esempio n. 32
0
                   num_coeffs=12,
                   win_len=0.025,
                   time_step=0.01)
        rep.is_windowed = True
        duration = interval.maxTime - interval.minTime
        thresh = unnorm(norm(duration, min_duration, max_duration), min_thresh,
                        max_thresh)
        rep.segment(threshold=thresh)
        print(sorted(rep._segments.keys()))
        padded_begin = interval.minTime - padding
        if padded_begin < 0:
            padded_begin = 0
        for k in sorted(rep._segments.keys()):
            with open(os.path.join(temp_mfcc_dir, '{}.mfcc'.format(seg_ind)),
                      'wb') as fh:
                pickle.dump(rep[k[0], k[1]], fh)
            with open(os.path.join(temp_mean_dir, '{}.mean'.format(seg_ind)),
                      'wb') as fh:
                pickle.dump(rep._segments[k], fh)
            segs.append(str(seg_ind))
            seg_ind += 1
            begin = round(k[0] + padded_begin, 3)

            end = round(k[1] + padded_begin, 3)
            print(begin, end)
            segmentation_tier.add(begin, end, '{}'.format(seg_ind))
    with open(os.path.join(temp_align_dir, '{}.seg'.format(f)), 'w') as fa:
        fa.write(' '.join(segs))
    tg.append(segmentation_tier)
    tg.write(textgrid_path.replace(data_dir, temp_textgrid_dir))
Esempio n. 33
0
def parse_transcript(path):
    file_name = os.path.splitext(os.path.basename(path))[0]
    tg_path = path.replace(os.path.join(orig_dir, 'txt'),
                           output_dir).replace('.txt', '.TextGrid')
    tg = TextGrid()
    tiers = {}
    continuation = False
    prev_speaker = None
    with open(path, 'r', encoding='utf8') as f:
        for i, line in enumerate(f):
            line = line.strip()
            if i == 0:
                continue
            if not line:
                continue
            if line in ['<I>', '</I>']:
                continue
            if line.startswith('&'):
                continue
            m = re.match(
                r'^<\$(\w)>.*<start=?([0-9:.;l ]+) end6?=([0-9>:.;l ]*)>?[?]?\s+<#>(.+)$',
                line)
            if m is None:
                text = parse_text(line)
                try:
                    tiers[speaker][-1].mark += ' ' + text
                except UnboundLocalError:
                    continue
                    # error
            else:
                speaker_code, start, end, text = m.groups()
                if speaker_code == 'Z':
                    continue
                try:
                    speaker = file_code_to_speaker[(file_name, speaker_code)]
                except KeyError:
                    speaker = 'unknown_{}_{}'.format(file_name, speaker_code)
                if speaker not in tiers:
                    tiers[speaker] = IntervalTier(speaker)
                start = parse_time(start)
                end = parse_time(end)
                text = parse_text(text)
                if text == "Again he's quoting":
                    continue
                if not text:
                    continue
                if end is None:
                    continue
                if start is None:
                    if prev_speaker != speaker:
                        continue
                    continuation = True
                    tiers[speaker][-1].mark += ' ' + text
                if '<' in text.replace('<beep_sound>',
                                       '').replace('<unk>', ''):
                    print(file_name, start, end, text)
                    print(line)
                if continuation or (len(tiers[speaker]) > 0 and
                                    start - tiers[speaker][-1].maxTime < 0.1):
                    tiers[speaker][-1].mark += ' ' + text
                    if not continuation:
                        tiers[speaker][-1].maxTime = end
                    continuation = False
                else:
                    tiers[speaker].add(start, end, text)

                # print(speaker)
                # print(start, end)
                # print(text)
                prev_speaker = speaker
    print(tiers.keys(), [len(x) for x in tiers.values()])
    for v in tiers.values():
        tg.append(v)
    tg.write(tg_path)
Esempio n. 34
0
def ctm_to_textgrid(word_ctm,
                    phone_ctm,
                    out_directory,
                    corpus,
                    dictionary,
                    frameshift=0.01):
    textgrid_write_errors = {}
    frameshift = Decimal(str(frameshift))
    if not os.path.exists(out_directory):
        os.makedirs(out_directory, exist_ok=True)
    if not corpus.segments:
        for i, (k, v) in enumerate(sorted(word_ctm.items())):
            maxtime = Decimal(str(corpus.get_wav_duration(k)))
            speaker = list(v.keys())[0]
            v = list(v.values())[0]
            try:
                tg = TextGrid(maxTime=maxtime)
                wordtier = IntervalTier(name='words', maxTime=maxtime)
                phonetier = IntervalTier(name='phones', maxTime=maxtime)
                for interval in v:
                    if maxtime - interval[
                            1] < frameshift:  # Fix rounding issues
                        interval[1] = maxtime
                    wordtier.add(*interval)
                for interval in phone_ctm[k][speaker]:
                    if maxtime - interval[1] < frameshift:
                        interval[1] = maxtime
                    phonetier.add(*interval)
                tg.append(wordtier)
                tg.append(phonetier)
                if corpus.speaker_directories:
                    speaker_directory = os.path.join(
                        out_directory, corpus.utt_speak_mapping[k])
                else:
                    speaker_directory = out_directory
                os.makedirs(speaker_directory, exist_ok=True)
                outpath = os.path.join(speaker_directory, k + '.TextGrid')
                tg.write(outpath)
            except Exception as e:
                exc_type, exc_value, exc_traceback = sys.exc_info()
                textgrid_write_errors[k] = '\n'.join(
                    traceback.format_exception(exc_type, exc_value,
                                               exc_traceback))
    else:
        silences = {
            dictionary.optional_silence, dictionary.nonoptional_silence
        }
        for i, (filename, speaker_dict) in enumerate(sorted(word_ctm.items())):
            maxtime = corpus.get_wav_duration(filename)
            try:
                tg = TextGrid(maxTime=maxtime)
                for speaker, words in speaker_dict.items():
                    word_tier_name = '{} - words'.format(speaker)
                    phone_tier_name = '{} - phones'.format(speaker)
                    word_tier = IntervalTier(name=word_tier_name,
                                             maxTime=maxtime)
                    phone_tier = IntervalTier(name=phone_tier_name,
                                              maxTime=maxtime)
                    for w in words:
                        word_tier.add(*w)
                    for p in phone_ctm[filename][speaker]:
                        if len(phone_tier) > 0 and phone_tier[
                                -1].mark in silences and p[2] in silences:
                            phone_tier[-1].maxTime = p[1]
                        else:
                            if len(phone_tier) > 0 and p[2] in silences and p[
                                    0] < phone_tier[-1].maxTime:
                                p = phone_tier[-1].maxTime, p[1], p[2]
                            elif len(phone_tier) > 0 and p[2] not in silences and p[0] < phone_tier[-1].maxTime and \
                                            phone_tier[-1].mark in silences:
                                phone_tier[-1].maxTime = p[0]
                            phone_tier.add(*p)
                    tg.append(word_tier)
                    tg.append(phone_tier)
                tg.write(os.path.join(out_directory, filename + '.TextGrid'))
            except Exception as e:
                exc_type, exc_value, exc_traceback = sys.exc_info()
                textgrid_write_errors[filename] = '\n'.join(
                    traceback.format_exception(exc_type, exc_value,
                                               exc_traceback))
    if textgrid_write_errors:
        error_log = os.path.join(out_directory, 'output_errors.txt')
        with open(error_log, 'w', encoding='utf8') as f:
            f.write(
                'The following exceptions were encountered during the ouput of the alignments to TextGrids:\n\n'
            )
            for k, v in textgrid_write_errors.items():
                f.write('{}:\n'.format(k))
                f.write('{}\n\n'.format(v))
			elif i == 1:
				for x in ti:
					x.maxTime += cur_dur
					x.minTime += cur_dur
					phoneintervals.append(x)
				cur_dur += maxtime

	words = IntervalTier(name='words')
	for i in wordintervals:
		words.addInterval(i)
	phones = IntervalTier(name='phones')
	for i in phoneintervals:
		phones.addInterval(i)
	tg1 = TextGrid(maxTime = cur_dur)
	tg1.append(words)
	tg1.append(phones)
	tg1.write(chapteroutpath1, null = '')

	speaker_tier = IntervalTier(name=speaker)
	for i in range(len(groupedwavfiles)):
		if i == 1:
			speaker_tier.add(0.0, wavfiletimes[0], groupedlabtext[0])
		else:
			speaker_tier.add(wavfiletimes[i-2], wavfiletimes[i-1], groupedlabtext[i-1])
	tg2 = TextGrid(maxTime = duration)
	tg2.append(speaker_tier)
	tg2.write(chapteroutpath2, null = '')


            for w in u.word:
                label = w._type_node['label']
                if label in ['<NOISE>', '<VOCNOISE>']:
                    continue
                end = w.end
                if end > duration:
                    end = duration
                word_tier.add(w.begin, end, label)
                utt_word_tier.add(w.begin - begin, end - begin, label)
            for p in u.phone:
                label = p._type_node['label']
                end = p.end
                if end > duration:
                    end = duration
                try:
                    phone_tier.add(p.begin, end, label)
                    utt_phone_tier.add(p.begin - begin, end - begin, label)
                except ValueError:
                    print(label, p.begin, p.end, duration)
                    raise
            durations.append(u.duration)
            utt_tg.append(utt_word_tier)
            utt_tg.append(utt_phone_tier)
            utt_tg.write(utt_tg_path)
        tg.append(utterance_tier)
        tg.write(tg_path)
        tg.append(word_tier)
        tg.append(phone_tier)
        tg.write(full_tg_path)

print(ignored, not_ignored)