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
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
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