praatio.textgrid API documentation

# praatio.textgrid

Functions for reading/writing/manipulating textgrid files.

This file links the main data structures for representing Textgrid data: Textgrid, IntervalTier, and PointTier

A Textgrid is a container for multiple annotation tiers. Tiers can contain either interval data (IntervalTier) or point data (PointTier). Tiers in a Textgrid are ordered and must contain a unique name.

openTextgrid() can be used to open a textgrid file. Textgrid.save() can be used to save a Textgrid object to a file.

Historically, these three classes lived in this file. To make maintance easier, they were split off. You can still access them from this file as before, but please check out the respective files for more documentation on each class: IntervalTier in data_classes/interval_tier.py PointTier in data_classes/point_tier.py Textgrid in data_classes/textgrid.py

see the examples/ directory for examples using textgrid.py

View Source

      1"""
      2Functions for reading/writing/manipulating textgrid files.
      3
      4This file links the main data structures for representing Textgrid data:
      5Textgrid, IntervalTier, and PointTier
      6
      7A Textgrid is a container for multiple annotation tiers.  Tiers can contain
      8either interval data (IntervalTier) or point data (PointTier).
      9Tiers in a Textgrid are ordered and must contain a unique name.
     10
     11openTextgrid() can be used to open a textgrid file.
     12Textgrid.save() can be used to save a Textgrid object to a file.
     13
     14Historically, these three classes lived in this file. To
     15make maintance easier, they were split off.  You can still access
     16them from this file as before, but please check out the respective
     17files for more documentation on each class:
     18IntervalTier in data_classes/interval_tier.py
     19PointTier in data_classes/point_tier.py
     20Textgrid in data_classes/textgrid.py
     21
     22see the **examples/** directory for examples using textgrid.py
     23"""
     24
     25import io
     26from typing import (
     27    Union,
     28    Type,
     29)
     30
     31from typing_extensions import Literal
     32
     33
     34from praatio.utilities.constants import (
     35    INTERVAL_TIER,
     36)
     37from praatio.data_classes.interval_tier import IntervalTier
     38from praatio.data_classes.point_tier import PointTier
     39from praatio.data_classes.textgrid import Textgrid
     40from praatio.utilities import textgrid_io
     41from praatio.utilities import utils
     42from praatio.utilities import constants
     43from praatio.utilities import errors
     44
     45
     46def openTextgrid(
     47    fnFullPath: str,
     48    includeEmptyIntervals: bool,
     49    reportingMode: Literal["silence", "warning", "error"] = "warning",
     50    duplicateNamesMode: Literal["error", "rename"] = "error",
     51) -> Textgrid:
     52    """Opens a textgrid file (.TextGrid and .json are both fine)
     53
     54    https://www.fon.hum.uva.nl/praat/manual/TextGrid_file_formats.html
     55
     56    Args:
     57        fnFullPath: the path to the textgrid to open
     58        includeEmptyIntervals: if False, points and intervals with
     59             an empty label '' are not included in the returned Textgrid
     60
     61    Returns:
     62        A Textgrid
     63
     64    Raises:
     65        DuplicateTierName: The textgrid contains multiple tiers with the same name
     66    """
     67    utils.validateOption("reportingMode", reportingMode, constants.ErrorReportingMode)
     68    utils.validateOption(
     69        "duplicateNamesMode", duplicateNamesMode, constants.DuplicateNames
     70    )
     71    try:
     72        with io.open(fnFullPath, "r", encoding="utf-16") as fd:
     73            data = fd.read()
     74    except UnicodeError:
     75        with io.open(fnFullPath, "r", encoding="utf-8") as fd:
     76            data = fd.read()
     77
     78    tgAsDict = textgrid_io.parseTextgridStr(data, includeEmptyIntervals)
     79
     80    tierNames = []
     81    for tier in tgAsDict["tiers"]:
     82        name = tier["name"]
     83        if name in tierNames:
     84            if duplicateNamesMode == constants.DuplicateNames.ERROR:
     85                raise errors.DuplicateTierName(
     86                    f"Your textgrid contains tiers with the same name '{name}'. "
     87                    "This is not allowed. It is recommended that you rename them. "
     88                    "If you set openTextgrid(..., duplicateNamesMode='rename'), praatio "
     89                    "will automatically append numbers to the end of tiers to ensure they "
     90                    "are unique."
     91                )
     92            elif duplicateNamesMode == constants.DuplicateNames.RENAME:
     93                newName = name
     94                i = 2
     95                while newName in tierNames:
     96                    newName = f"{name}_{i}"
     97                    i += 1
     98                name = newName
     99                tier["name"] = name
    100        tierNames.append(name)
    101
    102    return _dictionaryToTg(tgAsDict, reportingMode)
    103
    104
    105def _dictionaryToTg(
    106    tgAsDict: dict, reportingMode: Literal["silence", "warning", "error"]
    107) -> Textgrid:
    108    """Converts a dictionary representation of a textgrid to a Textgrid"""
    109    utils.validateOption("reportingMode", reportingMode, constants.ErrorReportingMode)
    110
    111    tg = Textgrid()
    112    tg.minTimestamp = tgAsDict["xmin"]
    113    tg.maxTimestamp = tgAsDict["xmax"]
    114
    115    for tierAsDict in tgAsDict["tiers"]:
    116        klass: Union[Type[PointTier], Type[IntervalTier]]
    117        if tierAsDict["class"] == INTERVAL_TIER:
    118            klass = IntervalTier
    119        else:
    120            klass = PointTier
    121        tier = klass(
    122            tierAsDict["name"],
    123            tierAsDict["entries"],
    124            tierAsDict["xmin"],
    125            tierAsDict["xmax"],
    126        )
    127        tg.addTier(tier, reportingMode=reportingMode)
    128
    129    return tg

def openTextgrid( fnFullPath: str, includeEmptyIntervals: bool, reportingMode: Literal['silence', 'warning', 'error'] = 'warning', duplicateNamesMode: Literal['error', 'rename'] = 'error') -> praatio.data_classes.textgrid.Textgrid: View Source

     47def openTextgrid(
     48    fnFullPath: str,
     49    includeEmptyIntervals: bool,
     50    reportingMode: Literal["silence", "warning", "error"] = "warning",
     51    duplicateNamesMode: Literal["error", "rename"] = "error",
     52) -> Textgrid:
     53    """Opens a textgrid file (.TextGrid and .json are both fine)
     54
     55    https://www.fon.hum.uva.nl/praat/manual/TextGrid_file_formats.html
     56
     57    Args:
     58        fnFullPath: the path to the textgrid to open
     59        includeEmptyIntervals: if False, points and intervals with
     60             an empty label '' are not included in the returned Textgrid
     61
     62    Returns:
     63        A Textgrid
     64
     65    Raises:
     66        DuplicateTierName: The textgrid contains multiple tiers with the same name
     67    """
     68    utils.validateOption("reportingMode", reportingMode, constants.ErrorReportingMode)
     69    utils.validateOption(
     70        "duplicateNamesMode", duplicateNamesMode, constants.DuplicateNames
     71    )
     72    try:
     73        with io.open(fnFullPath, "r", encoding="utf-16") as fd:
     74            data = fd.read()
     75    except UnicodeError:
     76        with io.open(fnFullPath, "r", encoding="utf-8") as fd:
     77            data = fd.read()
     78
     79    tgAsDict = textgrid_io.parseTextgridStr(data, includeEmptyIntervals)
     80
     81    tierNames = []
     82    for tier in tgAsDict["tiers"]:
     83        name = tier["name"]
     84        if name in tierNames:
     85            if duplicateNamesMode == constants.DuplicateNames.ERROR:
     86                raise errors.DuplicateTierName(
     87                    f"Your textgrid contains tiers with the same name '{name}'. "
     88                    "This is not allowed. It is recommended that you rename them. "
     89                    "If you set openTextgrid(..., duplicateNamesMode='rename'), praatio "
     90                    "will automatically append numbers to the end of tiers to ensure they "
     91                    "are unique."
     92                )
     93            elif duplicateNamesMode == constants.DuplicateNames.RENAME:
     94                newName = name
     95                i = 2
     96                while newName in tierNames:
     97                    newName = f"{name}_{i}"
     98                    i += 1
     99                name = newName
    100                tier["name"] = name
    101        tierNames.append(name)
    102
    103    return _dictionaryToTg(tgAsDict, reportingMode)

Opens a textgrid file (.TextGrid and .json are both fine)

https://www.fon.hum.uva.nl/praat/manual/TextGrid_file_formats.html

###### Arguments:

- fnFullPath: the path to the textgrid to open
- includeEmptyIntervals: if False, points and intervals with an empty label '' are not included in the returned Textgrid

###### Returns:

> A Textgrid

###### Raises:

- DuplicateTierName: The textgrid contains multiple tiers with the same name