Skip to content

Commit 12bb59d

Browse files
committed
Merge branch 'release/4.5'
2 parents ffbbb37 + e7321ad commit 12bb59d

File tree

4 files changed

+109
-22
lines changed

4 files changed

+109
-22
lines changed

doc/source/changelog.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
Changelog
33
#########
44

5+
Version 4.5 (2022-08-24)
6+
~~~~~~~~~~~~~~~~~~~~~~~~
7+
8+
- feat: add Annotation.write_lab method (@FrancescoBonzi)
9+
- feat: add Annotation.to_{rttm|lab} and Timeline.to_uem serializers (@juanmc2005)
10+
- setup: exclude tests from package (@kimdwkimdw)
11+
512
Version 4.4 (2022-03-09)
613
~~~~~~~~~~~~~~~~~~~~~~~~
714

pyannote/core/annotation.py

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ def __init__(self, uri: Optional[str] = None, modality: Optional[str] = None):
187187
# key: label
188188
# value: timeline
189189
self._labels: Dict[Label, Timeline] = {}
190-
self._labelNeedsUpdate: [Label, bool] = {}
190+
self._labelNeedsUpdate: Dict[Label, bool] = {}
191191

192192
# timeline meant to store all annotated segments
193193
self._timeline: Timeline = None
@@ -364,19 +364,14 @@ def __contains__(self, included: Union[Segment, Timeline]):
364364
"""
365365
return included in self.get_timeline(copy=False)
366366

367-
def write_rttm(self, file: TextIO):
368-
"""Dump annotation to file using RTTM format
369-
370-
Parameters
371-
----------
372-
file : file object
367+
def _iter_rttm(self) -> Iterator[Text]:
368+
"""Generate lines for an RTTM file for this annotation
373369
374-
Usage
375-
-----
376-
>>> with open('file.rttm', 'w') as file:
377-
... annotation.write_rttm(file)
370+
Returns
371+
-------
372+
iterator: Iterator[str]
373+
An iterator over RTTM text lines
378374
"""
379-
380375
uri = self.uri if self.uri else "<NA>"
381376
if isinstance(uri, Text) and " " in uri:
382377
msg = (
@@ -391,10 +386,76 @@ def write_rttm(self, file: TextIO):
391386
f'containing spaces (got: "{label}").'
392387
)
393388
raise ValueError(msg)
394-
line = (
389+
yield (
395390
f"SPEAKER {uri} 1 {segment.start:.3f} {segment.duration:.3f} "
396391
f"<NA> <NA> {label} <NA> <NA>\n"
397392
)
393+
394+
def to_rttm(self) -> Text:
395+
"""Serialize annotation as a string using RTTM format
396+
397+
Returns
398+
-------
399+
serialized: str
400+
RTTM string
401+
"""
402+
return "".join([line for line in self._iter_rttm()])
403+
404+
def write_rttm(self, file: TextIO):
405+
"""Dump annotation to file using RTTM format
406+
407+
Parameters
408+
----------
409+
file : file object
410+
411+
Usage
412+
-----
413+
>>> with open('file.rttm', 'w') as file:
414+
... annotation.write_rttm(file)
415+
"""
416+
for line in self._iter_rttm():
417+
file.write(line)
418+
419+
def _iter_lab(self) -> Iterator[Text]:
420+
"""Generate lines for a LAB file for this annotation
421+
422+
Returns
423+
-------
424+
iterator: Iterator[str]
425+
An iterator over LAB text lines
426+
"""
427+
for segment, _, label in self.itertracks(yield_label=True):
428+
if isinstance(label, Text) and " " in label:
429+
msg = (
430+
f"Space-separated LAB file format does not allow labels "
431+
f'containing spaces (got: "{label}").'
432+
)
433+
raise ValueError(msg)
434+
yield f"{segment.start:.3f} {segment.start + segment.duration:.3f} {label}\n"
435+
436+
def to_lab(self) -> Text:
437+
"""Serialize annotation as a string using LAB format
438+
439+
Returns
440+
-------
441+
serialized: str
442+
LAB string
443+
"""
444+
return "".join([line for line in self._iter_lab()])
445+
446+
def write_lab(self, file: TextIO):
447+
"""Dump annotation to file using LAB format
448+
449+
Parameters
450+
----------
451+
file : file object
452+
453+
Usage
454+
-----
455+
>>> with open('file.lab', 'w') as file:
456+
... annotation.write_lab(file)
457+
"""
458+
for line in self._iter_lab():
398459
file.write(line)
399460

400461
def crop(self, support: Support, mode: CropMode = "intersection") -> "Annotation":

pyannote/core/timeline.py

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,32 @@ def to_annotation(self,
10691069

10701070
return annotation
10711071

1072+
def _iter_uem(self) -> Iterator[Text]:
1073+
"""Generate lines for a UEM file for this timeline
1074+
1075+
Returns
1076+
-------
1077+
iterator: Iterator[str]
1078+
An iterator over UEM text lines
1079+
"""
1080+
uri = self.uri if self.uri else "<NA>"
1081+
if isinstance(uri, Text) and ' ' in uri:
1082+
msg = (f'Space-separated UEM file format does not allow file URIs '
1083+
f'containing spaces (got: "{uri}").')
1084+
raise ValueError(msg)
1085+
for segment in self:
1086+
yield f"{uri} 1 {segment.start:.3f} {segment.end:.3f}\n"
1087+
1088+
def to_uem(self) -> Text:
1089+
"""Serialize timeline as a string using UEM format
1090+
1091+
Returns
1092+
-------
1093+
serialized: str
1094+
UEM string
1095+
"""
1096+
return "".join([line for line in self._iter_uem()])
1097+
10721098
def write_uem(self, file: TextIO):
10731099
"""Dump timeline to file using UEM format
10741100
@@ -1081,14 +1107,7 @@ def write_uem(self, file: TextIO):
10811107
>>> with open('file.uem', 'w') as file:
10821108
... timeline.write_uem(file)
10831109
"""
1084-
1085-
uri = self.uri if self.uri else "<NA>"
1086-
if isinstance(uri, Text) and ' ' in uri:
1087-
msg = (f'Space-separated UEM file format does not allow file URIs '
1088-
f'containing spaces (got: "{uri}").')
1089-
raise ValueError(msg)
1090-
for segment in self:
1091-
line = f"{uri} 1 {segment.start:.3f} {segment.end:.3f}\n"
1110+
for line in self._iter_uem():
10921111
file.write(line)
10931112

10941113
def for_json(self):

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
# package
3636
namespace_packages=['pyannote'],
37-
packages=find_packages(),
37+
packages=find_packages(exclude=["tests"]),
3838
install_requires=[
3939
'sortedcontainers >= 2.0.4',
4040
'numpy >= 1.10.4',

0 commit comments

Comments
 (0)