From 173da3d05c1e380d98ba99b9870f1c6d9b1f37ab Mon Sep 17 00:00:00 2001 From: JoFrhwld Date: Mon, 4 Aug 2025 15:33:57 -0400 Subject: [PATCH 1/3] fix to saving custom built textgrids --- src/aligned_textgrid/aligned_textgrid.py | 9 +++++- src/aligned_textgrid/points/tiers.py | 6 ++-- src/aligned_textgrid/sequences/tiers.py | 7 +++-- tests/test_output.py | 40 ++++++++++++++++++++++-- 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/aligned_textgrid/aligned_textgrid.py b/src/aligned_textgrid/aligned_textgrid.py index 0265cbd9..44706f1f 100644 --- a/src/aligned_textgrid/aligned_textgrid.py +++ b/src/aligned_textgrid/aligned_textgrid.py @@ -794,9 +794,16 @@ def return_textgrid(self) -> Textgrid: A `praatio` `Textgrid` """ out_tg = Textgrid() + tier_names = [] + dup_idx = 0 for group in self.tier_groups: for tier in group: - out_tg.addTier(tier = tier.return_tier()) + name = tier.name + if name in tier_names: + name = f"{name}_{dup_idx}" + dup_idx += 1 + tier_names += [name] + out_tg.addTier(tier = tier.return_tier(name)) return out_tg def save_textgrid( diff --git a/src/aligned_textgrid/points/tiers.py b/src/aligned_textgrid/points/tiers.py index 9d0a2153..cdbf1f36 100644 --- a/src/aligned_textgrid/points/tiers.py +++ b/src/aligned_textgrid/points/tiers.py @@ -202,14 +202,16 @@ def get_nearest_point( out_idx = self.get_nearest_point_index(time) return self.sequence_list[out_idx] - def return_tier(self) -> PointTier: + def return_tier(self, name:str|None = None) -> PointTier: """Returns SequencePointTier as a `praatio` PointTier Returns: (PointTier): A `praatio` point tier """ + if name is None: + name = self.name all_points = [entry.return_point() for entry in self.sequence_list] - point_tier = PointTier(name = self.name, entries=all_points) + point_tier = PointTier(name = name, entries=all_points) return(point_tier) def save_as_tg( diff --git a/src/aligned_textgrid/sequences/tiers.py b/src/aligned_textgrid/sequences/tiers.py index 702bd631..f68a8728 100644 --- a/src/aligned_textgrid/sequences/tiers.py +++ b/src/aligned_textgrid/sequences/tiers.py @@ -307,7 +307,7 @@ def get_interval_at_time( else: return None - def return_tier(self) -> IntervalTier: + def return_tier(self, name:str|None = None) -> IntervalTier: """Returns a `praatio` interval tier Returns: @@ -315,8 +315,11 @@ def return_tier(self) -> IntervalTier: A `praatio` interval tier. Useful for saving results back as a Praat TextGrid. """ + + if name is None: + name = self.name all_intervals = [entry.return_interval() for entry in self.sequence_list] - interval_tier = IntervalTier(name = self.name, entries = all_intervals) + interval_tier = IntervalTier(name = name, entries = all_intervals) return interval_tier diff --git a/tests/test_output.py b/tests/test_output.py index ab6f86e0..0013eb59 100644 --- a/tests/test_output.py +++ b/tests/test_output.py @@ -1,10 +1,11 @@ -from aligned_textgrid import AlignedTextGrid, Word, Phone +from aligned_textgrid import AlignedTextGrid, Word, Phone, SequenceTier, TierGroup, custom_classes from aligned_textgrid.polar.polar_classes import PrStr, ToBI, \ TurningPoints, Ranges, Levels, Misc from aligned_textgrid.polar.polar_grid import PolarGrid from aligned_textgrid.outputs.to_dataframe import to_df from functools import reduce import cloudpickle +import tempfile class TestDataframes: atg = AlignedTextGrid( @@ -82,4 +83,39 @@ class TestPickle: entry_classes=[Word, Phone] ) def test_pickling(self): - assert cloudpickle.loads(cloudpickle.dumps(self.atg)) \ No newline at end of file + assert cloudpickle.loads(cloudpickle.dumps(self.atg)) + +class TestCustomWrite: + + def test_write(self): + Transcript, = custom_classes(["Transcript"]) + the_dog = Transcript((0, 10, "the dog")) + the_cat = Transcript((10, 25, "dog cat")) + speaker1 = TierGroup([SequenceTier(entry_class=Transcript)]) + speaker2 = TierGroup([SequenceTier(entry_class=Transcript)]) + + speaker1[0].append(the_dog) + speaker2[0].append(the_cat) + atg = AlignedTextGrid([speaker1, speaker2]) + tmp_file = tempfile.TemporaryFile() + atg.save_textgrid(tmp_file.name) + + + # for phone in [DH, AH0]: + # the.append(phone) + + # for phone in [D, AO1, G]: + # dog.append(phone) + + # tier_group = TierGroup([ + # SequenceTier(entry_class=Word), + # SequenceTier(entry_class=Phone) + # ]) + + # tier_group.Word.append(the) + # tier_group.Word.append(dog) + + # atg = AlignedTextGrid([tier_group]) + + + From 1073dd59229178b6497e60599c6d3e82285bd011 Mon Sep 17 00:00:00 2001 From: JoFrhwld Date: Mon, 4 Aug 2025 15:38:04 -0400 Subject: [PATCH 2/3] just return instead of save --- tests/test_output.py | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/tests/test_output.py b/tests/test_output.py index 0013eb59..3314545b 100644 --- a/tests/test_output.py +++ b/tests/test_output.py @@ -5,7 +5,6 @@ from aligned_textgrid.outputs.to_dataframe import to_df from functools import reduce import cloudpickle -import tempfile class TestDataframes: atg = AlignedTextGrid( @@ -97,25 +96,7 @@ def test_write(self): speaker1[0].append(the_dog) speaker2[0].append(the_cat) atg = AlignedTextGrid([speaker1, speaker2]) - tmp_file = tempfile.TemporaryFile() - atg.save_textgrid(tmp_file.name) - - - # for phone in [DH, AH0]: - # the.append(phone) - - # for phone in [D, AO1, G]: - # dog.append(phone) - - # tier_group = TierGroup([ - # SequenceTier(entry_class=Word), - # SequenceTier(entry_class=Phone) - # ]) - - # tier_group.Word.append(the) - # tier_group.Word.append(dog) - - # atg = AlignedTextGrid([tier_group]) + assert atg.return_textgrid() From dcd28a390e04a7a0d8006d28630c8f68accc8a08 Mon Sep 17 00:00:00 2001 From: JoFrhwld Date: Mon, 4 Aug 2025 15:42:01 -0400 Subject: [PATCH 3/3] version bump --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index bcedd0e7..04af7c62 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aligned_textgrid" -version = "0.8.0" +version = "0.8.1" description = "Classes for defining sequential information from TextGrids" authors = ["JoFrhwld ", "chrisbrickhouse "] license = "GPL-3.0-or-later"