Anchor-annotator 0.4.0__py3-none-any.whl → 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {Anchor_annotator-0.4.0.dist-info → Anchor_annotator-0.5.0.dist-info}/METADATA +1 -1
- Anchor_annotator-0.5.0.dist-info/RECORD +22 -0
- anchor/_version.py +2 -2
- anchor/main.py +174 -60
- anchor/models.py +34 -18
- anchor/plot.py +304 -119
- anchor/resources_rc.py +6475 -4801
- anchor/settings.py +177 -92
- anchor/ui_error_dialog.py +15 -16
- anchor/ui_main_window.py +40 -612
- anchor/ui_preferences.py +75 -44
- anchor/undo.py +0 -1
- anchor/widgets.py +74 -92
- anchor/workers.py +27 -1
- Anchor_annotator-0.4.0.dist-info/RECORD +0 -22
- {Anchor_annotator-0.4.0.dist-info → Anchor_annotator-0.5.0.dist-info}/LICENSE +0 -0
- {Anchor_annotator-0.4.0.dist-info → Anchor_annotator-0.5.0.dist-info}/WHEEL +0 -0
- {Anchor_annotator-0.4.0.dist-info → Anchor_annotator-0.5.0.dist-info}/top_level.txt +0 -0
anchor/plot.py
CHANGED
@@ -162,8 +162,8 @@ class UtteranceClusterView(pg.PlotWidget):
|
|
162
162
|
def __init__(self, *args):
|
163
163
|
super().__init__(*args)
|
164
164
|
self.settings = AnchorSettings()
|
165
|
-
|
166
|
-
self.setBackground(
|
165
|
+
plot_theme = self.settings.plot_theme
|
166
|
+
self.setBackground(plot_theme.background_color)
|
167
167
|
self.corpus_model = None
|
168
168
|
self.speaker_model: SpeakerModel = None
|
169
169
|
self.selection_model: FileSelectionModel = None
|
@@ -378,8 +378,8 @@ class AudioPlotItem(pg.PlotItem):
|
|
378
378
|
self.setDefaultPadding(0)
|
379
379
|
self.setClipToView(True)
|
380
380
|
|
381
|
-
self.getAxis("bottom").setPen(self.settings.
|
382
|
-
self.getAxis("bottom").setTextPen(self.settings.
|
381
|
+
self.getAxis("bottom").setPen(self.settings.plot_theme.break_line_color)
|
382
|
+
self.getAxis("bottom").setTextPen(self.settings.plot_theme.break_line_color)
|
383
383
|
self.getAxis("bottom").setTickFont(self.settings.small_font)
|
384
384
|
rect = QtCore.QRectF()
|
385
385
|
rect.setTop(top_point)
|
@@ -437,6 +437,7 @@ class SpeakerTierItem(pg.PlotItem):
|
|
437
437
|
a.setText("Create utterance")
|
438
438
|
a.triggered.connect(functools.partial(item.create_utterance, begin=begin, end=end))
|
439
439
|
menu.addAction(a)
|
440
|
+
|
440
441
|
menu.setStyleSheet(item.settings.menu_style_sheet)
|
441
442
|
menu.exec_(event.screenPos())
|
442
443
|
|
@@ -461,9 +462,13 @@ class UtteranceView(QtWidgets.QWidget):
|
|
461
462
|
|
462
463
|
# self.break_line.setZValue(30)
|
463
464
|
self.audio_layout = pg.GraphicsLayoutWidget()
|
465
|
+
self.audio_layout.viewport().setAttribute(
|
466
|
+
QtCore.Qt.WidgetAttribute.WA_AcceptTouchEvents, False
|
467
|
+
)
|
464
468
|
self.audio_layout.centralWidget.layout.setContentsMargins(0, 0, 0, 0)
|
465
469
|
self.audio_layout.centralWidget.layout.setSpacing(0)
|
466
|
-
self.
|
470
|
+
plot_theme = self.settings.plot_theme
|
471
|
+
self.audio_layout.setBackground(plot_theme.background_color)
|
467
472
|
self.audio_plot = AudioPlots(2, 1, 0)
|
468
473
|
self.audio_plot_item = AudioPlotItem(2, 0)
|
469
474
|
self.audio_plot_item.addItem(self.audio_plot)
|
@@ -474,9 +479,13 @@ class UtteranceView(QtWidgets.QWidget):
|
|
474
479
|
self.show_transcription = True
|
475
480
|
self.show_alignment = True
|
476
481
|
self.speaker_tier_layout = pg.GraphicsLayoutWidget()
|
482
|
+
self.speaker_tier_layout.viewport().setAttribute(
|
483
|
+
QtCore.Qt.WidgetAttribute.WA_AcceptTouchEvents, False
|
484
|
+
)
|
477
485
|
self.speaker_tier_layout.setAspectLocked(False)
|
478
486
|
self.speaker_tier_layout.centralWidget.layout.setContentsMargins(0, 0, 0, 0)
|
479
487
|
self.speaker_tier_layout.centralWidget.layout.setSpacing(0)
|
488
|
+
self.speaker_tier_layout.setBackground(plot_theme.background_color)
|
480
489
|
self.speaker_tiers: dict[SpeakerTier] = {}
|
481
490
|
self.speaker_tier_items = {}
|
482
491
|
self.search_term = None
|
@@ -526,6 +535,25 @@ class UtteranceView(QtWidgets.QWidget):
|
|
526
535
|
self.selection_model.waveformReady.connect(self.finalize_loading_auto_wave_form)
|
527
536
|
self.selection_model.speakerRequested.connect(self.set_default_speaker)
|
528
537
|
self.file_model.selectionRequested.connect(self.finalize_loading_utterances)
|
538
|
+
self.file_model.speakersChanged.connect(self.finalize_loading_utterances)
|
539
|
+
self.corpus_model.refreshTiers.connect(self.finalize_loading_utterances)
|
540
|
+
|
541
|
+
def refresh_theme(self):
|
542
|
+
self.audio_layout.setBackground(self.settings.plot_theme.background_color)
|
543
|
+
self.speaker_tier_layout.setBackground(self.settings.plot_theme.background_color)
|
544
|
+
self.audio_plot.wave_form.update_theme()
|
545
|
+
self.audio_plot.spectrogram.update_theme()
|
546
|
+
self.audio_plot.pitch_track.update_theme()
|
547
|
+
self.audio_plot_item.getAxis("bottom").setPen(self.settings.plot_theme.break_line_color)
|
548
|
+
self.audio_plot_item.getAxis("bottom").setTextPen(
|
549
|
+
self.settings.plot_theme.break_line_color
|
550
|
+
)
|
551
|
+
|
552
|
+
def refresh(self):
|
553
|
+
self.finalize_loading_utterances()
|
554
|
+
self.finalize_loading_auto_wave_form()
|
555
|
+
self.finalize_loading_pitch_track()
|
556
|
+
self.finalize_loading_spectrogram()
|
529
557
|
|
530
558
|
def finalize_loading_utterances(self):
|
531
559
|
if self.file_model.file is None:
|
@@ -536,7 +564,10 @@ class UtteranceView(QtWidgets.QWidget):
|
|
536
564
|
self.speaker_tier_items = {}
|
537
565
|
self.speaker_tier_layout.clear()
|
538
566
|
available_speakers = {}
|
539
|
-
|
567
|
+
num_visible_speakers = min(
|
568
|
+
len(self.file_model.speakers), self.settings.value(self.settings.TIER_MAX_SPEAKERS)
|
569
|
+
)
|
570
|
+
speaker_tier_height = (self.separator_point - self.bottom_point) / num_visible_speakers
|
540
571
|
for i, speaker_id in enumerate(self.file_model.speakers):
|
541
572
|
speaker_name = self.corpus_model.get_speaker_name(speaker_id)
|
542
573
|
top_point = i * speaker_tier_height
|
@@ -574,8 +605,10 @@ class UtteranceView(QtWidgets.QWidget):
|
|
574
605
|
if tier.speaker_id == self.default_speaker_id:
|
575
606
|
scroll_to = i
|
576
607
|
row_height = self.tier_scroll_area.height()
|
577
|
-
self.speaker_tier_layout.setFixedHeight(
|
578
|
-
|
608
|
+
self.speaker_tier_layout.setFixedHeight(
|
609
|
+
len(self.speaker_tiers) * row_height / num_visible_speakers
|
610
|
+
)
|
611
|
+
if len(self.file_model.speakers) > num_visible_speakers:
|
579
612
|
self.tier_scroll_area.verticalScrollBar().setSingleStep(row_height)
|
580
613
|
self.tier_scroll_area.verticalScrollBar().setPageStep(row_height)
|
581
614
|
self.tier_scroll_area.verticalScrollBar().setMinimum(0)
|
@@ -589,7 +622,6 @@ class UtteranceView(QtWidgets.QWidget):
|
|
589
622
|
0, 0, self.settings.scroll_bar_height, 0
|
590
623
|
)
|
591
624
|
if scroll_to is not None:
|
592
|
-
# self.tier_scroll_area.scrollContentsBy(0, scroll_to * tier_height)
|
593
625
|
self.tier_scroll_area.verticalScrollBar().setValue(
|
594
626
|
scroll_to * self.tier_scroll_area.height()
|
595
627
|
)
|
@@ -1061,8 +1093,9 @@ class TranscriberErrorHighlighter(QtGui.QSyntaxHighlighter):
|
|
1061
1093
|
super().__init__(*args)
|
1062
1094
|
self.alignment = None
|
1063
1095
|
self.settings = AnchorSettings()
|
1064
|
-
|
1065
|
-
self.
|
1096
|
+
|
1097
|
+
self.keyword_color = self.settings.plot_theme.error_color
|
1098
|
+
self.keyword_text_color = self.settings.plot_theme.error_text_color
|
1066
1099
|
self.highlight_format = QtGui.QTextCharFormat()
|
1067
1100
|
self.highlight_format.setBackground(self.keyword_color)
|
1068
1101
|
self.highlight_format.setForeground(self.keyword_text_color)
|
@@ -1206,6 +1239,15 @@ class IntervalTextRegion(pg.GraphicsObject):
|
|
1206
1239
|
self.rect.setBottom(self.top_point - self.height)
|
1207
1240
|
self._generate_picture()
|
1208
1241
|
|
1242
|
+
def setSelected(self, selected):
|
1243
|
+
if selected:
|
1244
|
+
new_brush = self.selected_brush
|
1245
|
+
else:
|
1246
|
+
new_brush = self.background_brush
|
1247
|
+
if new_brush != self.currentBrush:
|
1248
|
+
self.currentBrush = new_brush
|
1249
|
+
self._generate_picture()
|
1250
|
+
|
1209
1251
|
def _generate_picture(self):
|
1210
1252
|
painter = QtGui.QPainter(self.picture)
|
1211
1253
|
painter.setPen(self.border)
|
@@ -1286,7 +1328,9 @@ class TextAttributeRegion(pg.GraphicsObject):
|
|
1286
1328
|
self.picture = QtGui.QPicture()
|
1287
1329
|
self.mouseHovering = False
|
1288
1330
|
self.selected = False
|
1289
|
-
self.
|
1331
|
+
self.background_brush = self.parentItem().background_brush
|
1332
|
+
self.selected_brush = self.parentItem().selected_brush
|
1333
|
+
self.currentBrush = self.parentItem().currentBrush
|
1290
1334
|
self.text.setPos((self.begin + self.end) / 2, self.top_point - (self.height / 2))
|
1291
1335
|
self.begin_line = pg.InfiniteLine()
|
1292
1336
|
self.rect = QtCore.QRectF(
|
@@ -1296,9 +1340,18 @@ class TextAttributeRegion(pg.GraphicsObject):
|
|
1296
1340
|
height=self.height,
|
1297
1341
|
)
|
1298
1342
|
self.rect.setTop(self.top_point)
|
1299
|
-
self.rect.setBottom(self.
|
1343
|
+
self.rect.setBottom(self.bottom_point)
|
1300
1344
|
self._generate_picture()
|
1301
1345
|
|
1346
|
+
def setSelected(self, selected):
|
1347
|
+
if selected:
|
1348
|
+
new_brush = self.selected_brush
|
1349
|
+
else:
|
1350
|
+
new_brush = self.background_brush
|
1351
|
+
if new_brush != self.currentBrush:
|
1352
|
+
self.currentBrush = new_brush
|
1353
|
+
self._generate_picture()
|
1354
|
+
|
1302
1355
|
def _generate_picture(self):
|
1303
1356
|
painter = QtGui.QPainter(self.picture)
|
1304
1357
|
painter.setPen(self.border)
|
@@ -1428,18 +1481,23 @@ class Highlighter(QtGui.QSyntaxHighlighter):
|
|
1428
1481
|
def highlightBlock(self, text):
|
1429
1482
|
self.settings.sync()
|
1430
1483
|
self.spellcheck_format.setUnderlineColor(self.settings.error_color)
|
1431
|
-
tokenizers = self.dictionary_model.corpus_model.corpus.get_tokenizers()
|
1432
|
-
dictionary_id = self.dictionary_model.corpus_model.corpus.get_dict_id_for_speaker(
|
1433
|
-
self.speaker_id
|
1434
|
-
)
|
1435
1484
|
words = self.WORDS
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1485
|
+
try:
|
1486
|
+
tokenizers = self.dictionary_model.corpus_model.corpus.get_tokenizers()
|
1487
|
+
dictionary_id = self.dictionary_model.corpus_model.corpus.get_dict_id_for_speaker(
|
1488
|
+
self.speaker_id
|
1489
|
+
)
|
1490
|
+
if isinstance(tokenizers, dict) and dictionary_id is not None:
|
1491
|
+
tokenizer = self.dictionary_model.corpus_model.corpus.get_tokenizer(dictionary_id)
|
1492
|
+
else:
|
1493
|
+
tokenizer = tokenizers
|
1494
|
+
if isinstance(tokenizer, SimpleTokenizer):
|
1495
|
+
extra_symbols = "".join(tokenizer.punctuation) + "".join(
|
1496
|
+
tokenizer.word_break_markers
|
1497
|
+
)
|
1498
|
+
words = rf"[^\s{extra_symbols}]+"
|
1499
|
+
except Exception:
|
1500
|
+
pass
|
1443
1501
|
if self.dictionary_model is not None and self.dictionary_model.word_sets:
|
1444
1502
|
for word_object in re.finditer(words, text):
|
1445
1503
|
if not self.dictionary_model.check_word(word_object.group(), self.speaker_id):
|
@@ -1470,8 +1528,6 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1470
1528
|
audioSelected = QtCore.Signal(object, object)
|
1471
1529
|
viewRequested = QtCore.Signal(object, object)
|
1472
1530
|
|
1473
|
-
settings = AnchorSettings()
|
1474
|
-
|
1475
1531
|
def __init__(
|
1476
1532
|
self,
|
1477
1533
|
item: CtmInterval,
|
@@ -1485,6 +1541,8 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1485
1541
|
pg.GraphicsObject.__init__(self)
|
1486
1542
|
self.item = item
|
1487
1543
|
|
1544
|
+
self.settings = AnchorSettings()
|
1545
|
+
|
1488
1546
|
self.item_min = self.item.begin
|
1489
1547
|
self.item_max = self.item.end
|
1490
1548
|
if selection_model.settings.right_to_left:
|
@@ -1497,15 +1555,15 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1497
1555
|
self.top_point = top_point
|
1498
1556
|
self.span = (self.bottom_point, self.top_point)
|
1499
1557
|
self.text_margin_pixels = 2
|
1558
|
+
self.height = abs(self.top_point - self.bottom_point)
|
1500
1559
|
|
1501
|
-
self.
|
1502
|
-
self.
|
1503
|
-
self.
|
1504
|
-
self.moving_line_color = self.settings.value(self.settings.ERROR_COLOR)
|
1560
|
+
self.interval_background_color = self.settings.plot_theme.interval_background_color
|
1561
|
+
self.hover_line_color = self.settings.plot_theme.hover_line_color
|
1562
|
+
self.moving_line_color = self.settings.plot_theme.moving_line_color
|
1505
1563
|
|
1506
|
-
self.break_line_color = self.settings.
|
1507
|
-
self.text_color = self.settings.
|
1508
|
-
self.selected_interval_color = self.settings.
|
1564
|
+
self.break_line_color = self.settings.plot_theme.break_line_color
|
1565
|
+
self.text_color = self.settings.plot_theme.text_color
|
1566
|
+
self.selected_interval_color = self.settings.plot_theme.selected_interval_color
|
1509
1567
|
self.plot_text_font = self.settings.big_font
|
1510
1568
|
self.setCursor(QtCore.Qt.CursorShape.SizeAllCursor)
|
1511
1569
|
self.pen = pg.mkPen(self.break_line_color, width=3)
|
@@ -1531,15 +1589,42 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1531
1589
|
self.swapMode = "sort"
|
1532
1590
|
self.clipItem = None
|
1533
1591
|
self._boundingRectCache = None
|
1534
|
-
self.setBrush(self.background_brush)
|
1535
1592
|
self.movable = False
|
1536
1593
|
self.cached_visible_duration = None
|
1537
1594
|
self.cached_view = None
|
1595
|
+
self.currentBrush = self.background_brush
|
1596
|
+
self.picture = QtGui.QPicture()
|
1597
|
+
self.rect = QtCore.QRectF(
|
1598
|
+
left=self.item_min,
|
1599
|
+
top=self.top_point,
|
1600
|
+
width=self.item_max - self.item_min,
|
1601
|
+
height=self.height,
|
1602
|
+
)
|
1603
|
+
self.rect.setTop(self.top_point)
|
1604
|
+
self.rect.setLeft(self.item_min)
|
1605
|
+
self.rect.setRight(self.item_max)
|
1606
|
+
self.rect.setBottom(self.bottom_point)
|
1607
|
+
self._generate_picture()
|
1608
|
+
self.sigRegionChanged.connect(self.update_bounds)
|
1609
|
+
self.sigRegionChangeFinished.connect(self.update_bounds)
|
1538
1610
|
|
1539
|
-
def
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1611
|
+
def update_bounds(self):
|
1612
|
+
beg, end = self.getRegion()
|
1613
|
+
self.rect.setLeft(beg)
|
1614
|
+
self.rect.setRight(end)
|
1615
|
+
self._generate_picture()
|
1616
|
+
|
1617
|
+
def _generate_picture(self):
|
1618
|
+
if self.selection_model is None:
|
1619
|
+
return
|
1620
|
+
painter = QtGui.QPainter(self.picture)
|
1621
|
+
painter.setPen(self.border_pen)
|
1622
|
+
painter.setBrush(self.currentBrush)
|
1623
|
+
painter.drawRect(self.rect)
|
1624
|
+
painter.end()
|
1625
|
+
|
1626
|
+
def paint(self, painter, *args):
|
1627
|
+
painter.drawPicture(0, 0, self.picture)
|
1543
1628
|
|
1544
1629
|
def mouseClickEvent(self, ev: QtGui.QMouseEvent):
|
1545
1630
|
if ev.button() != QtCore.Qt.MouseButton.LeftButton:
|
@@ -1559,10 +1644,12 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1559
1644
|
|
1560
1645
|
def setSelected(self, selected: bool):
|
1561
1646
|
if selected:
|
1562
|
-
|
1647
|
+
new_brush = pg.mkBrush(self.selected_interval_color)
|
1563
1648
|
else:
|
1564
|
-
|
1565
|
-
|
1649
|
+
new_brush = pg.mkBrush(self.interval_background_color)
|
1650
|
+
if new_brush != self.currentBrush:
|
1651
|
+
self.currentBrush = new_brush
|
1652
|
+
self._generate_picture()
|
1566
1653
|
self.update()
|
1567
1654
|
|
1568
1655
|
def setMouseHover(self, hover: bool):
|
@@ -1578,6 +1665,26 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1578
1665
|
if self.selected and not deselect and not reset:
|
1579
1666
|
return
|
1580
1667
|
|
1668
|
+
def boundingRect(self):
|
1669
|
+
try:
|
1670
|
+
visible_begin = max(self.item_min, self.selection_model.plot_min)
|
1671
|
+
visible_end = min(self.item_max, self.selection_model.plot_max)
|
1672
|
+
except TypeError:
|
1673
|
+
visible_begin = self.item_min
|
1674
|
+
visible_end = self.item_max
|
1675
|
+
br = QtCore.QRectF(self.picture.boundingRect())
|
1676
|
+
br.setLeft(visible_begin)
|
1677
|
+
br.setRight(visible_end)
|
1678
|
+
|
1679
|
+
br.setTop(self.top_point)
|
1680
|
+
br.setBottom(self.bottom_point + 0.01)
|
1681
|
+
br = br.normalized()
|
1682
|
+
|
1683
|
+
if self._boundingRectCache != br:
|
1684
|
+
self._boundingRectCache = br
|
1685
|
+
self.prepareGeometryChange()
|
1686
|
+
return br
|
1687
|
+
|
1581
1688
|
|
1582
1689
|
class AlignmentRegion(MfaRegion):
|
1583
1690
|
def __init__(
|
@@ -1611,49 +1718,43 @@ class AlignmentRegion(MfaRegion):
|
|
1611
1718
|
self.text.textItem.document().setDefaultTextOption(options)
|
1612
1719
|
self.text.setParentItem(self)
|
1613
1720
|
self.per_tier_range = self.top_point - self.bottom_point
|
1721
|
+
self.currentBrush = pg.mkBrush((0, 0, 0, 0))
|
1722
|
+
self.selection_model.viewChanged.connect(self.check_visibility)
|
1723
|
+
self.check_visibility()
|
1614
1724
|
|
1615
|
-
def
|
1725
|
+
def setSelected(self, selected: bool):
|
1726
|
+
if selected:
|
1727
|
+
self.text.setColor(self.settings.plot_theme.selected_text_color)
|
1728
|
+
else:
|
1729
|
+
self.text.setColor(self.settings.plot_theme.text_color)
|
1730
|
+
|
1731
|
+
def check_visibility(self):
|
1616
1732
|
if (self.item_max - self.item_min) / (
|
1617
1733
|
self.selection_model.max_time - self.selection_model.min_time
|
1618
1734
|
) < 0.001:
|
1619
1735
|
self.hide()
|
1620
1736
|
else:
|
1621
|
-
self.
|
1622
|
-
super().viewRangeChanged()
|
1623
|
-
|
1624
|
-
def boundingRect(self):
|
1625
|
-
br = QtCore.QRectF(self.viewRect()) # bounds of containing ViewBox mapped to local coords.
|
1626
|
-
vb = self.getViewBox()
|
1627
|
-
|
1628
|
-
pixel_size = vb.viewPixelSize()
|
1629
|
-
|
1630
|
-
br.setLeft(self.item_min)
|
1631
|
-
br.setRight(self.item_max)
|
1632
|
-
|
1633
|
-
br.setTop(self.top_point)
|
1634
|
-
# br.setBottom(self.top_point-self.per_tier_range)
|
1635
|
-
br.setBottom(self.bottom_point + 0.01)
|
1636
|
-
try:
|
1737
|
+
vb = self.getViewBox()
|
1637
1738
|
visible_begin = max(self.item_min, self.selection_model.plot_min)
|
1638
1739
|
visible_end = min(self.item_max, self.selection_model.plot_max)
|
1639
|
-
|
1640
|
-
return br
|
1641
|
-
visible_duration = visible_end - visible_begin
|
1642
|
-
x_margin_px = 8
|
1643
|
-
available_text_width = visible_duration / pixel_size[0] - (2 * x_margin_px)
|
1644
|
-
self.text.setVisible(available_text_width > 10)
|
1645
|
-
if visible_duration != self.cached_visible_duration:
|
1646
|
-
self.cached_visible_duration = visible_duration
|
1647
|
-
|
1740
|
+
visible_duration = visible_end - visible_begin
|
1648
1741
|
self.text.setPos(
|
1649
1742
|
visible_begin + (visible_duration / 2), self.top_point - (self.per_tier_range / 2)
|
1650
1743
|
)
|
1651
|
-
|
1744
|
+
if vb is None:
|
1745
|
+
self.text.setVisible(
|
1746
|
+
(visible_end - visible_begin)
|
1747
|
+
/ (self.selection_model.max_time - self.selection_model.min_time)
|
1748
|
+
> 0.005
|
1749
|
+
)
|
1750
|
+
else:
|
1751
|
+
pixel_size = vb.viewPixelSize()[0]
|
1752
|
+
if pixel_size != 0:
|
1753
|
+
x_margin_px = 8
|
1754
|
+
available_text_width = visible_duration / pixel_size - (2 * x_margin_px)
|
1652
1755
|
|
1653
|
-
|
1654
|
-
self.
|
1655
|
-
self.prepareGeometryChange()
|
1656
|
-
return br
|
1756
|
+
self.text.setVisible(available_text_width > 10)
|
1757
|
+
self.show()
|
1657
1758
|
|
1658
1759
|
|
1659
1760
|
class PhoneRegion(AlignmentRegion):
|
@@ -1665,10 +1766,14 @@ class PhoneRegion(AlignmentRegion):
|
|
1665
1766
|
selection_model: CorpusSelectionModel,
|
1666
1767
|
bottom_point: float = 0,
|
1667
1768
|
top_point: float = 1,
|
1769
|
+
color=None,
|
1668
1770
|
):
|
1669
1771
|
super().__init__(
|
1670
1772
|
phone_interval, corpus_model, file_model, selection_model, bottom_point, top_point
|
1671
1773
|
)
|
1774
|
+
if color is not None:
|
1775
|
+
self.currentBrush = pg.mkBrush(color)
|
1776
|
+
self._generate_picture()
|
1672
1777
|
|
1673
1778
|
|
1674
1779
|
class WordRegion(AlignmentRegion):
|
@@ -1686,6 +1791,7 @@ class WordRegion(AlignmentRegion):
|
|
1686
1791
|
super().__init__(
|
1687
1792
|
word_interval, corpus_model, file_model, selection_model, bottom_point, top_point
|
1688
1793
|
)
|
1794
|
+
self._generate_picture()
|
1689
1795
|
|
1690
1796
|
def mouseClickEvent(self, ev: QtGui.QMouseEvent):
|
1691
1797
|
search_term = TextFilterQuery(self.item.label, word=True)
|
@@ -1779,7 +1885,7 @@ class UtteranceRegion(MfaRegion):
|
|
1779
1885
|
per_tier_range=self.per_tier_range,
|
1780
1886
|
dictionary_model=self.dictionary_model,
|
1781
1887
|
speaker_id=self.item.speaker_id,
|
1782
|
-
border=pg.mkPen(self.settings.
|
1888
|
+
border=pg.mkPen(self.settings.plot_theme.break_line_color),
|
1783
1889
|
)
|
1784
1890
|
self.text.setParentItem(self)
|
1785
1891
|
|
@@ -1823,7 +1929,7 @@ class UtteranceRegion(MfaRegion):
|
|
1823
1929
|
tier_top_point,
|
1824
1930
|
self.per_tier_range,
|
1825
1931
|
self.selection_model,
|
1826
|
-
border=pg.mkPen(self.settings.
|
1932
|
+
border=pg.mkPen(self.settings.plot_theme.break_line_color),
|
1827
1933
|
dictionary_model=dictionary_model,
|
1828
1934
|
search_term=search_term,
|
1829
1935
|
speaker_id=utterance.speaker_id,
|
@@ -1852,9 +1958,25 @@ class UtteranceRegion(MfaRegion):
|
|
1852
1958
|
|
1853
1959
|
if intervals is None:
|
1854
1960
|
continue
|
1961
|
+
min_confidence = None
|
1962
|
+
max_confidence = None
|
1963
|
+
cmap = pg.ColorMap(
|
1964
|
+
None,
|
1965
|
+
[
|
1966
|
+
self.settings.plot_theme.error_color,
|
1967
|
+
self.settings.plot_theme.interval_background_color,
|
1968
|
+
],
|
1969
|
+
)
|
1970
|
+
cmap.linearize()
|
1971
|
+
if "phone_intervals" in lookup:
|
1972
|
+
for interval in intervals:
|
1973
|
+
if interval.confidence is None:
|
1974
|
+
continue
|
1975
|
+
if min_confidence is None or interval.confidence < min_confidence:
|
1976
|
+
min_confidence = interval.confidence
|
1977
|
+
if max_confidence is None or interval.confidence > max_confidence:
|
1978
|
+
max_confidence = interval.confidence
|
1855
1979
|
for interval in intervals:
|
1856
|
-
# if (interval.end - interval.begin) /(self.selection_model.max_time -self.selection_model.min_time) < 0.01:
|
1857
|
-
# continue
|
1858
1980
|
if lookup == "transcription_text":
|
1859
1981
|
interval_reg = TranscriberTextRegion(
|
1860
1982
|
self,
|
@@ -1864,13 +1986,21 @@ class UtteranceRegion(MfaRegion):
|
|
1864
1986
|
tier_top_point,
|
1865
1987
|
self.per_tier_range,
|
1866
1988
|
self.selection_model,
|
1867
|
-
border=pg.mkPen(self.settings.
|
1989
|
+
border=pg.mkPen(self.settings.plot_theme.break_line_color),
|
1868
1990
|
alignment=alignment,
|
1869
1991
|
dictionary_model=dictionary_model,
|
1870
1992
|
search_term=search_term,
|
1871
1993
|
speaker_id=utterance.speaker_id,
|
1872
1994
|
)
|
1995
|
+
interval_reg.setParentItem(self)
|
1996
|
+
interval_reg.audioSelected.connect(self.setSelected)
|
1873
1997
|
elif "phone_intervals" in lookup:
|
1998
|
+
color = None
|
1999
|
+
if interval.confidence is not None:
|
2000
|
+
normalized_confidence = (interval.confidence - min_confidence) / (
|
2001
|
+
max_confidence - min_confidence
|
2002
|
+
)
|
2003
|
+
color = cmap.map(normalized_confidence)
|
1874
2004
|
interval_reg = PhoneRegion(
|
1875
2005
|
interval,
|
1876
2006
|
self.corpus_model,
|
@@ -1878,8 +2008,10 @@ class UtteranceRegion(MfaRegion):
|
|
1878
2008
|
selection_model=selection_model,
|
1879
2009
|
top_point=tier_top_point,
|
1880
2010
|
bottom_point=tier_bottom_point,
|
2011
|
+
color=color,
|
1881
2012
|
)
|
1882
2013
|
interval_reg.setParentItem(self)
|
2014
|
+
interval_reg.audioSelected.connect(self.setSelected)
|
1883
2015
|
elif "word_intervals" in lookup:
|
1884
2016
|
interval_reg = WordRegion(
|
1885
2017
|
interval,
|
@@ -1891,18 +2023,19 @@ class UtteranceRegion(MfaRegion):
|
|
1891
2023
|
)
|
1892
2024
|
interval_reg.setParentItem(self)
|
1893
2025
|
interval_reg.highlightRequested.connect(self.highlighter.setSearchTerm)
|
2026
|
+
interval_reg.audioSelected.connect(self.setSelected)
|
1894
2027
|
|
1895
2028
|
else:
|
1896
2029
|
interval_reg = IntervalTextRegion(
|
1897
2030
|
interval,
|
1898
2031
|
self.text_color,
|
1899
|
-
border=pg.mkPen(self.settings.
|
2032
|
+
border=pg.mkPen(self.settings.plot_theme.break_line_color, width=3),
|
1900
2033
|
top_point=tier_top_point,
|
1901
2034
|
height=self.per_tier_range,
|
1902
|
-
# font=self.settings.font,
|
1903
2035
|
background_brush=self.background_brush,
|
1904
|
-
selected_brush=pg.mkBrush(self.
|
2036
|
+
selected_brush=pg.mkBrush(self.selected_interval_color),
|
1905
2037
|
)
|
2038
|
+
interval_reg.audioSelected.connect(self.setSelected)
|
1906
2039
|
interval_reg.setParentItem(self)
|
1907
2040
|
|
1908
2041
|
interval_reg.audioSelected.connect(self.audioSelected.emit)
|
@@ -1912,6 +2045,27 @@ class UtteranceRegion(MfaRegion):
|
|
1912
2045
|
self.show()
|
1913
2046
|
self.available_speakers = available_speakers
|
1914
2047
|
|
2048
|
+
def show(self):
|
2049
|
+
for intervals in self.extra_tier_intervals.values():
|
2050
|
+
for interval in intervals:
|
2051
|
+
if (
|
2052
|
+
self.selection_model.min_time
|
2053
|
+
< interval.item.end
|
2054
|
+
<= self.selection_model.max_time
|
2055
|
+
or self.selection_model.min_time
|
2056
|
+
<= interval.item.begin
|
2057
|
+
< self.selection_model.max_time
|
2058
|
+
):
|
2059
|
+
interval.show()
|
2060
|
+
else:
|
2061
|
+
interval.hide()
|
2062
|
+
super().show()
|
2063
|
+
|
2064
|
+
def setSelected(self, selected: bool):
|
2065
|
+
if selected:
|
2066
|
+
self.text_edit.setFocus()
|
2067
|
+
super().setSelected(selected)
|
2068
|
+
|
1915
2069
|
def change_editing(self, editable: bool):
|
1916
2070
|
self.lines[0].movable = editable
|
1917
2071
|
self.lines[1].movable = editable
|
@@ -1979,7 +2133,10 @@ class UtteranceRegion(MfaRegion):
|
|
1979
2133
|
menu.exec_(ev.screenPos())
|
1980
2134
|
|
1981
2135
|
def update_tier_visibility(self, checked):
|
1982
|
-
|
2136
|
+
sender = self.sender()
|
2137
|
+
if not isinstance(sender, QtGui.QAction):
|
2138
|
+
return
|
2139
|
+
tier_name = sender.text().split(maxsplit=1)[-1]
|
1983
2140
|
self.settings.setValue(self.settings.tier_visibility_mapping[tier_name], checked)
|
1984
2141
|
self.settings.sync()
|
1985
2142
|
self.corpus_model.refreshTiers.emit()
|
@@ -1994,7 +2151,10 @@ class UtteranceRegion(MfaRegion):
|
|
1994
2151
|
self.file_model.update_utterance_speaker(self.item, speaker_id)
|
1995
2152
|
|
1996
2153
|
def update_speaker(self):
|
1997
|
-
|
2154
|
+
sender = self.sender()
|
2155
|
+
if not isinstance(sender, QtGui.QAction):
|
2156
|
+
return
|
2157
|
+
speaker_name = sender.text()
|
1998
2158
|
if speaker_name == "New speaker":
|
1999
2159
|
speaker_id = 0
|
2000
2160
|
else:
|
@@ -2150,7 +2310,7 @@ class WaveForm(pg.PlotCurveItem):
|
|
2150
2310
|
self.top_point = top_point
|
2151
2311
|
self.bottom_point = bottom_point
|
2152
2312
|
self.mid_point = (self.top_point + self.bottom_point) / 2
|
2153
|
-
pen = pg.mkPen(self.settings.
|
2313
|
+
pen = pg.mkPen(self.settings.plot_theme.wave_line_color, width=1)
|
2154
2314
|
super(WaveForm, self).__init__()
|
2155
2315
|
self.setPen(pen)
|
2156
2316
|
self.channel = 0
|
@@ -2158,6 +2318,10 @@ class WaveForm(pg.PlotCurveItem):
|
|
2158
2318
|
self.selection_model = None
|
2159
2319
|
self.setAcceptHoverEvents(False)
|
2160
2320
|
|
2321
|
+
def update_theme(self):
|
2322
|
+
pen = pg.mkPen(self.settings.plot_theme.wave_line_color, width=1)
|
2323
|
+
self.setPen(pen)
|
2324
|
+
|
2161
2325
|
def hoverEvent(self, ev):
|
2162
2326
|
return
|
2163
2327
|
|
@@ -2171,7 +2335,7 @@ class PitchTrack(pg.PlotCurveItem):
|
|
2171
2335
|
self.top_point = top_point
|
2172
2336
|
self.bottom_point = bottom_point
|
2173
2337
|
self.mid_point = (self.top_point + self.bottom_point) / 2
|
2174
|
-
pen = pg.mkPen(self.settings.
|
2338
|
+
pen = pg.mkPen(self.settings.plot_theme.pitch_color, width=3)
|
2175
2339
|
super().__init__()
|
2176
2340
|
self.setPen(pen)
|
2177
2341
|
self.channel = 0
|
@@ -2180,19 +2344,25 @@ class PitchTrack(pg.PlotCurveItem):
|
|
2180
2344
|
self.setAcceptHoverEvents(False)
|
2181
2345
|
self.min_label = pg.TextItem(
|
2182
2346
|
str(self.settings.PITCH_MIN_F0),
|
2183
|
-
self.settings.
|
2347
|
+
self.settings.plot_theme.pitch_color,
|
2184
2348
|
anchor=(1, 1),
|
2185
2349
|
)
|
2186
2350
|
self.min_label.setFont(self.settings.font)
|
2187
2351
|
self.min_label.setParentItem(self)
|
2188
2352
|
self.max_label = pg.TextItem(
|
2189
2353
|
str(self.settings.PITCH_MAX_F0),
|
2190
|
-
self.settings.
|
2354
|
+
self.settings.plot_theme.pitch_color,
|
2191
2355
|
anchor=(1, 0),
|
2192
2356
|
)
|
2193
2357
|
self.max_label.setFont(self.settings.font)
|
2194
2358
|
self.max_label.setParentItem(self)
|
2195
2359
|
|
2360
|
+
def update_theme(self):
|
2361
|
+
pen = pg.mkPen(self.settings.plot_theme.pitch_color, width=3)
|
2362
|
+
self.setPen(pen)
|
2363
|
+
self.min_label.setColor(self.settings.plot_theme.pitch_color)
|
2364
|
+
self.max_label.setColor(self.settings.plot_theme.pitch_color)
|
2365
|
+
|
2196
2366
|
def hoverEvent(self, ev):
|
2197
2367
|
return
|
2198
2368
|
|
@@ -2215,7 +2385,11 @@ class Spectrogram(pg.ImageItem):
|
|
2215
2385
|
self.channel = 0
|
2216
2386
|
super(Spectrogram, self).__init__()
|
2217
2387
|
self.cmap = pg.ColorMap(
|
2218
|
-
None,
|
2388
|
+
None,
|
2389
|
+
[
|
2390
|
+
self.settings.plot_theme.background_color,
|
2391
|
+
self.settings.plot_theme.spectrogram_color,
|
2392
|
+
],
|
2219
2393
|
)
|
2220
2394
|
self.cmap.linearize()
|
2221
2395
|
self.color_bar = pg.ColorBarItem(colorMap=self.cmap)
|
@@ -2226,6 +2400,19 @@ class Spectrogram(pg.ImageItem):
|
|
2226
2400
|
self.cached_channel = None
|
2227
2401
|
self.stft = None
|
2228
2402
|
|
2403
|
+
def update_theme(self):
|
2404
|
+
self.cmap = pg.ColorMap(
|
2405
|
+
None,
|
2406
|
+
[
|
2407
|
+
self.settings.plot_theme.background_color,
|
2408
|
+
self.settings.plot_theme.spectrogram_color,
|
2409
|
+
],
|
2410
|
+
)
|
2411
|
+
self.cmap.linearize()
|
2412
|
+
self.color_bar.setColorMap(self.cmap)
|
2413
|
+
self.color_bar.setImageItem(self)
|
2414
|
+
self.update()
|
2415
|
+
|
2229
2416
|
def set_models(self, selection_model: CorpusSelectionModel):
|
2230
2417
|
self.selection_model = selection_model
|
2231
2418
|
|
@@ -2287,8 +2474,12 @@ class SelectionArea(pg.LinearRegionItem):
|
|
2287
2474
|
self.setVisible(False)
|
2288
2475
|
else:
|
2289
2476
|
self.setRegion([begin, end])
|
2290
|
-
self.lines[0].label.setText(
|
2291
|
-
|
2477
|
+
self.lines[0].label.setText(
|
2478
|
+
f"{begin:.3f}", self.settings.plot_theme.selected_range_color
|
2479
|
+
)
|
2480
|
+
self.lines[1].label.setText(
|
2481
|
+
f"{end:.3f}", self.settings.plot_theme.selected_range_color
|
2482
|
+
)
|
2292
2483
|
self.setVisible(True)
|
2293
2484
|
|
2294
2485
|
|
@@ -2306,17 +2497,17 @@ class AudioPlots(pg.GraphicsObject):
|
|
2306
2497
|
self.wave_form.setParentItem(self)
|
2307
2498
|
self.spectrogram.setParentItem(self)
|
2308
2499
|
self.pitch_track.setParentItem(self)
|
2309
|
-
color = self.settings.
|
2500
|
+
color = self.settings.plot_theme.selected_range_color
|
2310
2501
|
color.setAlphaF(0.25)
|
2311
2502
|
self.selection_brush = pg.mkBrush(color)
|
2312
|
-
self.background_pen = pg.mkPen(self.settings.
|
2313
|
-
self.background_brush = pg.mkBrush(self.settings.
|
2503
|
+
self.background_pen = pg.mkPen(self.settings.plot_theme.break_line_color)
|
2504
|
+
self.background_brush = pg.mkBrush(self.settings.plot_theme.background_color)
|
2314
2505
|
self.selection_area = SelectionArea(
|
2315
2506
|
top_point=self.top_point,
|
2316
2507
|
bottom_point=self.bottom_point,
|
2317
2508
|
brush=self.selection_brush,
|
2318
2509
|
clipItem=self,
|
2319
|
-
pen=pg.mkPen(self.settings.
|
2510
|
+
pen=pg.mkPen(self.settings.plot_theme.selected_interval_color),
|
2320
2511
|
)
|
2321
2512
|
self.selection_area.setParentItem(self)
|
2322
2513
|
|
@@ -2331,7 +2522,11 @@ class AudioPlots(pg.GraphicsObject):
|
|
2331
2522
|
self.update_line = pg.InfiniteLine(
|
2332
2523
|
pos=-20,
|
2333
2524
|
span=(0, 1),
|
2334
|
-
pen=pg.mkPen(
|
2525
|
+
pen=pg.mkPen(
|
2526
|
+
self.settings.plot_theme.selected_interval_color,
|
2527
|
+
width=3,
|
2528
|
+
style=QtCore.Qt.PenStyle.DashLine,
|
2529
|
+
),
|
2335
2530
|
movable=False, # We have our own code to handle dragless moving.
|
2336
2531
|
)
|
2337
2532
|
self.update_line.setParentItem(self)
|
@@ -2419,7 +2614,7 @@ class AudioPlots(pg.GraphicsObject):
|
|
2419
2614
|
self.selection_area.setVisible(True)
|
2420
2615
|
self.selection_model.select_audio(min_time, max_time)
|
2421
2616
|
else:
|
2422
|
-
self.selection_model.request_start_time(ev.pos().x())
|
2617
|
+
self.selection_model.request_start_time(ev.pos().x(), update=True)
|
2423
2618
|
ev.accept()
|
2424
2619
|
|
2425
2620
|
def hoverEvent(self, ev):
|
@@ -2502,7 +2697,9 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2502
2697
|
self.speaker_name = speaker_name
|
2503
2698
|
self.speaker_index = 0
|
2504
2699
|
self.top_point = top_point
|
2505
|
-
self.speaker_label = pg.TextItem(
|
2700
|
+
self.speaker_label = pg.TextItem(
|
2701
|
+
self.speaker_name, color=self.settings.plot_theme.break_line_color
|
2702
|
+
)
|
2506
2703
|
self.speaker_label.setFont(self.settings.font)
|
2507
2704
|
self.speaker_label.setParentItem(self)
|
2508
2705
|
self.speaker_label.setZValue(40)
|
@@ -2510,8 +2707,8 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2510
2707
|
self.annotation_range = self.top_point - self.bottom_point
|
2511
2708
|
self.extra_tiers = {}
|
2512
2709
|
self.visible_utterances: dict[str, UtteranceRegion] = {}
|
2513
|
-
self.background_brush = pg.mkBrush(self.settings.
|
2514
|
-
self.border = pg.mkPen(self.settings.
|
2710
|
+
self.background_brush = pg.mkBrush(self.settings.plot_theme.background_color)
|
2711
|
+
self.border = pg.mkPen(self.settings.plot_theme.break_line_color)
|
2515
2712
|
self.picture = QtGui.QPicture()
|
2516
2713
|
self.has_visible_utterances = False
|
2517
2714
|
self.has_selected_utterances = False
|
@@ -2526,28 +2723,14 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2526
2723
|
self.corpus_model.refreshUtteranceText.connect(self.refreshTexts)
|
2527
2724
|
self.selection_model.selectionChanged.connect(self.update_select)
|
2528
2725
|
self.selection_model.model().utterancesReady.connect(self.refresh)
|
2529
|
-
self.file_model.speakersChanged.connect(self.update_available_speakers)
|
2530
2726
|
self.available_speakers = {}
|
2531
2727
|
|
2532
|
-
def update_available_speakers(self):
|
2533
|
-
self.available_speakers = {}
|
2534
|
-
for speaker_id in self.file_model.speakers:
|
2535
|
-
speaker_name = self.corpus_model.get_speaker_name(speaker_id)
|
2536
|
-
self.available_speakers[speaker_name] = speaker_id
|
2537
|
-
for reg in self.visible_utterances.values():
|
2538
|
-
reg.available_speakers = self.available_speakers
|
2539
|
-
|
2540
2728
|
def wheelEvent(self, ev):
|
2541
2729
|
self.receivedWheelEvent.emit(ev)
|
2542
2730
|
|
2543
2731
|
def create_utterance(self, begin, end):
|
2544
2732
|
self.file_model.create_utterance(self.speaker_id, begin, end)
|
2545
2733
|
|
2546
|
-
def setSearchterm(self, term):
|
2547
|
-
self.search_term = term
|
2548
|
-
for reg in self.visible_utterances.values():
|
2549
|
-
reg.highlighter.setSearchTerm(term)
|
2550
|
-
|
2551
2734
|
def boundingRect(self):
|
2552
2735
|
return QtCore.QRectF(self.picture.boundingRect())
|
2553
2736
|
|
@@ -2610,14 +2793,16 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2610
2793
|
visible_ids = [x.id for x in model_visible_utterances]
|
2611
2794
|
for reg in self.visible_utterances.values():
|
2612
2795
|
reg.hide()
|
2796
|
+
|
2797
|
+
item_min, item_max = reg.getRegion()
|
2613
2798
|
if (
|
2614
|
-
self.selection_model.min_time -
|
2615
|
-
or
|
2799
|
+
self.selection_model.min_time - item_max > 15
|
2800
|
+
or item_min - self.selection_model.max_time > 15
|
2616
2801
|
or (
|
2617
2802
|
reg.item.id not in visible_ids
|
2618
2803
|
and (
|
2619
|
-
|
2620
|
-
or
|
2804
|
+
item_min < self.selection_model.max_time
|
2805
|
+
or item_max > self.selection_model.min_time
|
2621
2806
|
)
|
2622
2807
|
)
|
2623
2808
|
):
|
@@ -2706,10 +2891,10 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2706
2891
|
if r == reg:
|
2707
2892
|
continue
|
2708
2893
|
other_begin, other_end = r.getRegion()
|
2709
|
-
if other_begin <= beg < other_end:
|
2894
|
+
if other_begin <= beg < other_end or beg <= other_begin < other_end < end:
|
2710
2895
|
reg.setRegion([other_end, end])
|
2711
2896
|
break
|
2712
|
-
if other_begin < end <= other_end:
|
2897
|
+
if other_begin < end <= other_end or end > other_begin > other_end > beg:
|
2713
2898
|
reg.setRegion([beg, other_begin])
|
2714
2899
|
break
|
2715
2900
|
reg.text.begin, reg.text.end = reg.getRegion()
|
@@ -2732,7 +2917,7 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2732
2917
|
if new_begin == utt.begin and new_end == utt.end:
|
2733
2918
|
return
|
2734
2919
|
self.selection_model.model().update_utterance_times(utt, begin=new_begin, end=new_end)
|
2735
|
-
self.selection_model.
|
2920
|
+
self.selection_model.request_start_time(new_begin)
|
2736
2921
|
reg.text.begin = new_begin
|
2737
2922
|
reg.text.end = new_end
|
2738
2923
|
reg.update()
|