Anchor-annotator 0.4.0__py3-none-any.whl → 0.6.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.6.0.dist-info}/METADATA +1 -1
- Anchor_annotator-0.6.0.dist-info/RECORD +22 -0
- anchor/_version.py +2 -2
- anchor/main.py +180 -68
- anchor/models.py +34 -18
- anchor/plot.py +302 -119
- anchor/resources_rc.py +6656 -4801
- anchor/settings.py +178 -93
- 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 +145 -112
- anchor/workers.py +29 -1
- Anchor_annotator-0.4.0.dist-info/RECORD +0 -22
- {Anchor_annotator-0.4.0.dist-info → Anchor_annotator-0.6.0.dist-info}/LICENSE +0 -0
- {Anchor_annotator-0.4.0.dist-info → Anchor_annotator-0.6.0.dist-info}/WHEEL +0 -0
- {Anchor_annotator-0.4.0.dist-info → Anchor_annotator-0.6.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,7 @@ class TextAttributeRegion(pg.GraphicsObject):
|
|
1286
1328
|
self.picture = QtGui.QPicture()
|
1287
1329
|
self.mouseHovering = False
|
1288
1330
|
self.selected = False
|
1289
|
-
self.currentBrush = self.parentItem().
|
1331
|
+
self.currentBrush = self.parentItem().currentBrush
|
1290
1332
|
self.text.setPos((self.begin + self.end) / 2, self.top_point - (self.height / 2))
|
1291
1333
|
self.begin_line = pg.InfiniteLine()
|
1292
1334
|
self.rect = QtCore.QRectF(
|
@@ -1296,9 +1338,15 @@ class TextAttributeRegion(pg.GraphicsObject):
|
|
1296
1338
|
height=self.height,
|
1297
1339
|
)
|
1298
1340
|
self.rect.setTop(self.top_point)
|
1299
|
-
self.rect.setBottom(self.
|
1341
|
+
self.rect.setBottom(self.bottom_point)
|
1300
1342
|
self._generate_picture()
|
1301
1343
|
|
1344
|
+
def setSelected(self, selected):
|
1345
|
+
new_brush = self.parentItem().currentBrush
|
1346
|
+
if new_brush != self.currentBrush:
|
1347
|
+
self.currentBrush = new_brush
|
1348
|
+
self._generate_picture()
|
1349
|
+
|
1302
1350
|
def _generate_picture(self):
|
1303
1351
|
painter = QtGui.QPainter(self.picture)
|
1304
1352
|
painter.setPen(self.border)
|
@@ -1428,18 +1476,23 @@ class Highlighter(QtGui.QSyntaxHighlighter):
|
|
1428
1476
|
def highlightBlock(self, text):
|
1429
1477
|
self.settings.sync()
|
1430
1478
|
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
1479
|
words = self.WORDS
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1480
|
+
try:
|
1481
|
+
tokenizers = self.dictionary_model.corpus_model.corpus.get_tokenizers()
|
1482
|
+
dictionary_id = self.dictionary_model.corpus_model.corpus.get_dict_id_for_speaker(
|
1483
|
+
self.speaker_id
|
1484
|
+
)
|
1485
|
+
if isinstance(tokenizers, dict) and dictionary_id is not None:
|
1486
|
+
tokenizer = self.dictionary_model.corpus_model.corpus.get_tokenizer(dictionary_id)
|
1487
|
+
else:
|
1488
|
+
tokenizer = tokenizers
|
1489
|
+
if isinstance(tokenizer, SimpleTokenizer):
|
1490
|
+
extra_symbols = "".join(tokenizer.punctuation) + "".join(
|
1491
|
+
tokenizer.word_break_markers
|
1492
|
+
)
|
1493
|
+
words = rf"[^\s{extra_symbols}]+"
|
1494
|
+
except Exception:
|
1495
|
+
pass
|
1443
1496
|
if self.dictionary_model is not None and self.dictionary_model.word_sets:
|
1444
1497
|
for word_object in re.finditer(words, text):
|
1445
1498
|
if not self.dictionary_model.check_word(word_object.group(), self.speaker_id):
|
@@ -1470,8 +1523,6 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1470
1523
|
audioSelected = QtCore.Signal(object, object)
|
1471
1524
|
viewRequested = QtCore.Signal(object, object)
|
1472
1525
|
|
1473
|
-
settings = AnchorSettings()
|
1474
|
-
|
1475
1526
|
def __init__(
|
1476
1527
|
self,
|
1477
1528
|
item: CtmInterval,
|
@@ -1485,6 +1536,8 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1485
1536
|
pg.GraphicsObject.__init__(self)
|
1486
1537
|
self.item = item
|
1487
1538
|
|
1539
|
+
self.settings = AnchorSettings()
|
1540
|
+
|
1488
1541
|
self.item_min = self.item.begin
|
1489
1542
|
self.item_max = self.item.end
|
1490
1543
|
if selection_model.settings.right_to_left:
|
@@ -1497,15 +1550,15 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1497
1550
|
self.top_point = top_point
|
1498
1551
|
self.span = (self.bottom_point, self.top_point)
|
1499
1552
|
self.text_margin_pixels = 2
|
1553
|
+
self.height = abs(self.top_point - self.bottom_point)
|
1500
1554
|
|
1501
|
-
self.
|
1502
|
-
self.
|
1503
|
-
self.
|
1504
|
-
self.moving_line_color = self.settings.value(self.settings.ERROR_COLOR)
|
1555
|
+
self.interval_background_color = self.settings.plot_theme.interval_background_color
|
1556
|
+
self.hover_line_color = self.settings.plot_theme.hover_line_color
|
1557
|
+
self.moving_line_color = self.settings.plot_theme.moving_line_color
|
1505
1558
|
|
1506
|
-
self.break_line_color = self.settings.
|
1507
|
-
self.text_color = self.settings.
|
1508
|
-
self.selected_interval_color = self.settings.
|
1559
|
+
self.break_line_color = self.settings.plot_theme.break_line_color
|
1560
|
+
self.text_color = self.settings.plot_theme.text_color
|
1561
|
+
self.selected_interval_color = self.settings.plot_theme.selected_interval_color
|
1509
1562
|
self.plot_text_font = self.settings.big_font
|
1510
1563
|
self.setCursor(QtCore.Qt.CursorShape.SizeAllCursor)
|
1511
1564
|
self.pen = pg.mkPen(self.break_line_color, width=3)
|
@@ -1531,15 +1584,42 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1531
1584
|
self.swapMode = "sort"
|
1532
1585
|
self.clipItem = None
|
1533
1586
|
self._boundingRectCache = None
|
1534
|
-
self.setBrush(self.background_brush)
|
1535
1587
|
self.movable = False
|
1536
1588
|
self.cached_visible_duration = None
|
1537
1589
|
self.cached_view = None
|
1590
|
+
self.currentBrush = self.background_brush
|
1591
|
+
self.picture = QtGui.QPicture()
|
1592
|
+
self.rect = QtCore.QRectF(
|
1593
|
+
left=self.item_min,
|
1594
|
+
top=self.top_point,
|
1595
|
+
width=self.item_max - self.item_min,
|
1596
|
+
height=self.height,
|
1597
|
+
)
|
1598
|
+
self.rect.setTop(self.top_point)
|
1599
|
+
self.rect.setLeft(self.item_min)
|
1600
|
+
self.rect.setRight(self.item_max)
|
1601
|
+
self.rect.setBottom(self.bottom_point)
|
1602
|
+
self._generate_picture()
|
1603
|
+
self.sigRegionChanged.connect(self.update_bounds)
|
1604
|
+
self.sigRegionChangeFinished.connect(self.update_bounds)
|
1538
1605
|
|
1539
|
-
def
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1606
|
+
def update_bounds(self):
|
1607
|
+
beg, end = self.getRegion()
|
1608
|
+
self.rect.setLeft(beg)
|
1609
|
+
self.rect.setRight(end)
|
1610
|
+
self._generate_picture()
|
1611
|
+
|
1612
|
+
def _generate_picture(self):
|
1613
|
+
if self.selection_model is None:
|
1614
|
+
return
|
1615
|
+
painter = QtGui.QPainter(self.picture)
|
1616
|
+
painter.setPen(self.border_pen)
|
1617
|
+
painter.setBrush(self.currentBrush)
|
1618
|
+
painter.drawRect(self.rect)
|
1619
|
+
painter.end()
|
1620
|
+
|
1621
|
+
def paint(self, painter, *args):
|
1622
|
+
painter.drawPicture(0, 0, self.picture)
|
1543
1623
|
|
1544
1624
|
def mouseClickEvent(self, ev: QtGui.QMouseEvent):
|
1545
1625
|
if ev.button() != QtCore.Qt.MouseButton.LeftButton:
|
@@ -1559,10 +1639,12 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1559
1639
|
|
1560
1640
|
def setSelected(self, selected: bool):
|
1561
1641
|
if selected:
|
1562
|
-
|
1642
|
+
new_brush = pg.mkBrush(self.selected_interval_color)
|
1563
1643
|
else:
|
1564
|
-
|
1565
|
-
|
1644
|
+
new_brush = pg.mkBrush(self.interval_background_color)
|
1645
|
+
if new_brush != self.currentBrush:
|
1646
|
+
self.currentBrush = new_brush
|
1647
|
+
self._generate_picture()
|
1566
1648
|
self.update()
|
1567
1649
|
|
1568
1650
|
def setMouseHover(self, hover: bool):
|
@@ -1578,6 +1660,26 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1578
1660
|
if self.selected and not deselect and not reset:
|
1579
1661
|
return
|
1580
1662
|
|
1663
|
+
def boundingRect(self):
|
1664
|
+
try:
|
1665
|
+
visible_begin = max(self.item_min, self.selection_model.plot_min)
|
1666
|
+
visible_end = min(self.item_max, self.selection_model.plot_max)
|
1667
|
+
except TypeError:
|
1668
|
+
visible_begin = self.item_min
|
1669
|
+
visible_end = self.item_max
|
1670
|
+
br = QtCore.QRectF(self.picture.boundingRect())
|
1671
|
+
br.setLeft(visible_begin)
|
1672
|
+
br.setRight(visible_end)
|
1673
|
+
|
1674
|
+
br.setTop(self.top_point)
|
1675
|
+
br.setBottom(self.bottom_point + 0.01)
|
1676
|
+
br = br.normalized()
|
1677
|
+
|
1678
|
+
if self._boundingRectCache != br:
|
1679
|
+
self._boundingRectCache = br
|
1680
|
+
self.prepareGeometryChange()
|
1681
|
+
return br
|
1682
|
+
|
1581
1683
|
|
1582
1684
|
class AlignmentRegion(MfaRegion):
|
1583
1685
|
def __init__(
|
@@ -1611,49 +1713,43 @@ class AlignmentRegion(MfaRegion):
|
|
1611
1713
|
self.text.textItem.document().setDefaultTextOption(options)
|
1612
1714
|
self.text.setParentItem(self)
|
1613
1715
|
self.per_tier_range = self.top_point - self.bottom_point
|
1716
|
+
self.currentBrush = pg.mkBrush((0, 0, 0, 0))
|
1717
|
+
self.selection_model.viewChanged.connect(self.check_visibility)
|
1718
|
+
self.check_visibility()
|
1719
|
+
|
1720
|
+
def setSelected(self, selected: bool):
|
1721
|
+
if selected:
|
1722
|
+
self.text.setColor(self.settings.plot_theme.selected_text_color)
|
1723
|
+
else:
|
1724
|
+
self.text.setColor(self.settings.plot_theme.text_color)
|
1614
1725
|
|
1615
|
-
def
|
1726
|
+
def check_visibility(self):
|
1616
1727
|
if (self.item_max - self.item_min) / (
|
1617
1728
|
self.selection_model.max_time - self.selection_model.min_time
|
1618
1729
|
) < 0.001:
|
1619
1730
|
self.hide()
|
1620
1731
|
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:
|
1732
|
+
vb = self.getViewBox()
|
1637
1733
|
visible_begin = max(self.item_min, self.selection_model.plot_min)
|
1638
1734
|
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
|
-
|
1735
|
+
visible_duration = visible_end - visible_begin
|
1648
1736
|
self.text.setPos(
|
1649
1737
|
visible_begin + (visible_duration / 2), self.top_point - (self.per_tier_range / 2)
|
1650
1738
|
)
|
1651
|
-
|
1739
|
+
if vb is None:
|
1740
|
+
self.text.setVisible(
|
1741
|
+
(visible_end - visible_begin)
|
1742
|
+
/ (self.selection_model.max_time - self.selection_model.min_time)
|
1743
|
+
> 0.005
|
1744
|
+
)
|
1745
|
+
else:
|
1746
|
+
pixel_size = vb.viewPixelSize()[0]
|
1747
|
+
if pixel_size != 0:
|
1748
|
+
x_margin_px = 8
|
1749
|
+
available_text_width = visible_duration / pixel_size - (2 * x_margin_px)
|
1652
1750
|
|
1653
|
-
|
1654
|
-
self.
|
1655
|
-
self.prepareGeometryChange()
|
1656
|
-
return br
|
1751
|
+
self.text.setVisible(available_text_width > 10)
|
1752
|
+
self.show()
|
1657
1753
|
|
1658
1754
|
|
1659
1755
|
class PhoneRegion(AlignmentRegion):
|
@@ -1665,10 +1761,14 @@ class PhoneRegion(AlignmentRegion):
|
|
1665
1761
|
selection_model: CorpusSelectionModel,
|
1666
1762
|
bottom_point: float = 0,
|
1667
1763
|
top_point: float = 1,
|
1764
|
+
color=None,
|
1668
1765
|
):
|
1669
1766
|
super().__init__(
|
1670
1767
|
phone_interval, corpus_model, file_model, selection_model, bottom_point, top_point
|
1671
1768
|
)
|
1769
|
+
if color is not None:
|
1770
|
+
self.currentBrush = pg.mkBrush(color)
|
1771
|
+
self._generate_picture()
|
1672
1772
|
|
1673
1773
|
|
1674
1774
|
class WordRegion(AlignmentRegion):
|
@@ -1686,6 +1786,7 @@ class WordRegion(AlignmentRegion):
|
|
1686
1786
|
super().__init__(
|
1687
1787
|
word_interval, corpus_model, file_model, selection_model, bottom_point, top_point
|
1688
1788
|
)
|
1789
|
+
self._generate_picture()
|
1689
1790
|
|
1690
1791
|
def mouseClickEvent(self, ev: QtGui.QMouseEvent):
|
1691
1792
|
search_term = TextFilterQuery(self.item.label, word=True)
|
@@ -1779,7 +1880,7 @@ class UtteranceRegion(MfaRegion):
|
|
1779
1880
|
per_tier_range=self.per_tier_range,
|
1780
1881
|
dictionary_model=self.dictionary_model,
|
1781
1882
|
speaker_id=self.item.speaker_id,
|
1782
|
-
border=pg.mkPen(self.settings.
|
1883
|
+
border=pg.mkPen(self.settings.plot_theme.break_line_color),
|
1783
1884
|
)
|
1784
1885
|
self.text.setParentItem(self)
|
1785
1886
|
|
@@ -1823,7 +1924,7 @@ class UtteranceRegion(MfaRegion):
|
|
1823
1924
|
tier_top_point,
|
1824
1925
|
self.per_tier_range,
|
1825
1926
|
self.selection_model,
|
1826
|
-
border=pg.mkPen(self.settings.
|
1927
|
+
border=pg.mkPen(self.settings.plot_theme.break_line_color),
|
1827
1928
|
dictionary_model=dictionary_model,
|
1828
1929
|
search_term=search_term,
|
1829
1930
|
speaker_id=utterance.speaker_id,
|
@@ -1852,9 +1953,25 @@ class UtteranceRegion(MfaRegion):
|
|
1852
1953
|
|
1853
1954
|
if intervals is None:
|
1854
1955
|
continue
|
1956
|
+
min_confidence = None
|
1957
|
+
max_confidence = None
|
1958
|
+
cmap = pg.ColorMap(
|
1959
|
+
None,
|
1960
|
+
[
|
1961
|
+
self.settings.plot_theme.error_color,
|
1962
|
+
self.settings.plot_theme.interval_background_color,
|
1963
|
+
],
|
1964
|
+
)
|
1965
|
+
cmap.linearize()
|
1966
|
+
if "phone_intervals" in lookup:
|
1967
|
+
for interval in intervals:
|
1968
|
+
if interval.confidence is None:
|
1969
|
+
continue
|
1970
|
+
if min_confidence is None or interval.confidence < min_confidence:
|
1971
|
+
min_confidence = interval.confidence
|
1972
|
+
if max_confidence is None or interval.confidence > max_confidence:
|
1973
|
+
max_confidence = interval.confidence
|
1855
1974
|
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
1975
|
if lookup == "transcription_text":
|
1859
1976
|
interval_reg = TranscriberTextRegion(
|
1860
1977
|
self,
|
@@ -1864,13 +1981,21 @@ class UtteranceRegion(MfaRegion):
|
|
1864
1981
|
tier_top_point,
|
1865
1982
|
self.per_tier_range,
|
1866
1983
|
self.selection_model,
|
1867
|
-
border=pg.mkPen(self.settings.
|
1984
|
+
border=pg.mkPen(self.settings.plot_theme.break_line_color),
|
1868
1985
|
alignment=alignment,
|
1869
1986
|
dictionary_model=dictionary_model,
|
1870
1987
|
search_term=search_term,
|
1871
1988
|
speaker_id=utterance.speaker_id,
|
1872
1989
|
)
|
1990
|
+
interval_reg.setParentItem(self)
|
1991
|
+
interval_reg.audioSelected.connect(self.setSelected)
|
1873
1992
|
elif "phone_intervals" in lookup:
|
1993
|
+
color = None
|
1994
|
+
if interval.confidence is not None and max_confidence != min_confidence:
|
1995
|
+
normalized_confidence = (interval.confidence - min_confidence) / (
|
1996
|
+
max_confidence - min_confidence
|
1997
|
+
)
|
1998
|
+
color = cmap.map(normalized_confidence)
|
1874
1999
|
interval_reg = PhoneRegion(
|
1875
2000
|
interval,
|
1876
2001
|
self.corpus_model,
|
@@ -1878,8 +2003,10 @@ class UtteranceRegion(MfaRegion):
|
|
1878
2003
|
selection_model=selection_model,
|
1879
2004
|
top_point=tier_top_point,
|
1880
2005
|
bottom_point=tier_bottom_point,
|
2006
|
+
color=color,
|
1881
2007
|
)
|
1882
2008
|
interval_reg.setParentItem(self)
|
2009
|
+
interval_reg.audioSelected.connect(self.setSelected)
|
1883
2010
|
elif "word_intervals" in lookup:
|
1884
2011
|
interval_reg = WordRegion(
|
1885
2012
|
interval,
|
@@ -1891,18 +2018,19 @@ class UtteranceRegion(MfaRegion):
|
|
1891
2018
|
)
|
1892
2019
|
interval_reg.setParentItem(self)
|
1893
2020
|
interval_reg.highlightRequested.connect(self.highlighter.setSearchTerm)
|
2021
|
+
interval_reg.audioSelected.connect(self.setSelected)
|
1894
2022
|
|
1895
2023
|
else:
|
1896
2024
|
interval_reg = IntervalTextRegion(
|
1897
2025
|
interval,
|
1898
2026
|
self.text_color,
|
1899
|
-
border=pg.mkPen(self.settings.
|
2027
|
+
border=pg.mkPen(self.settings.plot_theme.break_line_color, width=3),
|
1900
2028
|
top_point=tier_top_point,
|
1901
2029
|
height=self.per_tier_range,
|
1902
|
-
# font=self.settings.font,
|
1903
2030
|
background_brush=self.background_brush,
|
1904
|
-
selected_brush=pg.mkBrush(self.
|
2031
|
+
selected_brush=pg.mkBrush(self.selected_interval_color),
|
1905
2032
|
)
|
2033
|
+
interval_reg.audioSelected.connect(self.setSelected)
|
1906
2034
|
interval_reg.setParentItem(self)
|
1907
2035
|
|
1908
2036
|
interval_reg.audioSelected.connect(self.audioSelected.emit)
|
@@ -1912,6 +2040,30 @@ class UtteranceRegion(MfaRegion):
|
|
1912
2040
|
self.show()
|
1913
2041
|
self.available_speakers = available_speakers
|
1914
2042
|
|
2043
|
+
def show(self):
|
2044
|
+
for intervals in self.extra_tier_intervals.values():
|
2045
|
+
for interval in intervals:
|
2046
|
+
if (
|
2047
|
+
self.selection_model.min_time
|
2048
|
+
< interval.item.end
|
2049
|
+
<= self.selection_model.max_time
|
2050
|
+
or self.selection_model.min_time
|
2051
|
+
<= interval.item.begin
|
2052
|
+
< self.selection_model.max_time
|
2053
|
+
):
|
2054
|
+
interval.show()
|
2055
|
+
else:
|
2056
|
+
interval.hide()
|
2057
|
+
super().show()
|
2058
|
+
|
2059
|
+
def setSelected(self, selected: bool):
|
2060
|
+
if selected:
|
2061
|
+
if not self.selected:
|
2062
|
+
self.text_edit.setFocus()
|
2063
|
+
else:
|
2064
|
+
self.text_edit.clearFocus()
|
2065
|
+
super().setSelected(selected)
|
2066
|
+
|
1915
2067
|
def change_editing(self, editable: bool):
|
1916
2068
|
self.lines[0].movable = editable
|
1917
2069
|
self.lines[1].movable = editable
|
@@ -1979,7 +2131,10 @@ class UtteranceRegion(MfaRegion):
|
|
1979
2131
|
menu.exec_(ev.screenPos())
|
1980
2132
|
|
1981
2133
|
def update_tier_visibility(self, checked):
|
1982
|
-
|
2134
|
+
sender = self.sender()
|
2135
|
+
if not isinstance(sender, QtGui.QAction):
|
2136
|
+
return
|
2137
|
+
tier_name = sender.text().split(maxsplit=1)[-1]
|
1983
2138
|
self.settings.setValue(self.settings.tier_visibility_mapping[tier_name], checked)
|
1984
2139
|
self.settings.sync()
|
1985
2140
|
self.corpus_model.refreshTiers.emit()
|
@@ -1994,7 +2149,10 @@ class UtteranceRegion(MfaRegion):
|
|
1994
2149
|
self.file_model.update_utterance_speaker(self.item, speaker_id)
|
1995
2150
|
|
1996
2151
|
def update_speaker(self):
|
1997
|
-
|
2152
|
+
sender = self.sender()
|
2153
|
+
if not isinstance(sender, QtGui.QAction):
|
2154
|
+
return
|
2155
|
+
speaker_name = sender.text()
|
1998
2156
|
if speaker_name == "New speaker":
|
1999
2157
|
speaker_id = 0
|
2000
2158
|
else:
|
@@ -2150,7 +2308,7 @@ class WaveForm(pg.PlotCurveItem):
|
|
2150
2308
|
self.top_point = top_point
|
2151
2309
|
self.bottom_point = bottom_point
|
2152
2310
|
self.mid_point = (self.top_point + self.bottom_point) / 2
|
2153
|
-
pen = pg.mkPen(self.settings.
|
2311
|
+
pen = pg.mkPen(self.settings.plot_theme.wave_line_color, width=1)
|
2154
2312
|
super(WaveForm, self).__init__()
|
2155
2313
|
self.setPen(pen)
|
2156
2314
|
self.channel = 0
|
@@ -2158,6 +2316,10 @@ class WaveForm(pg.PlotCurveItem):
|
|
2158
2316
|
self.selection_model = None
|
2159
2317
|
self.setAcceptHoverEvents(False)
|
2160
2318
|
|
2319
|
+
def update_theme(self):
|
2320
|
+
pen = pg.mkPen(self.settings.plot_theme.wave_line_color, width=1)
|
2321
|
+
self.setPen(pen)
|
2322
|
+
|
2161
2323
|
def hoverEvent(self, ev):
|
2162
2324
|
return
|
2163
2325
|
|
@@ -2171,7 +2333,7 @@ class PitchTrack(pg.PlotCurveItem):
|
|
2171
2333
|
self.top_point = top_point
|
2172
2334
|
self.bottom_point = bottom_point
|
2173
2335
|
self.mid_point = (self.top_point + self.bottom_point) / 2
|
2174
|
-
pen = pg.mkPen(self.settings.
|
2336
|
+
pen = pg.mkPen(self.settings.plot_theme.pitch_color, width=3)
|
2175
2337
|
super().__init__()
|
2176
2338
|
self.setPen(pen)
|
2177
2339
|
self.channel = 0
|
@@ -2180,19 +2342,25 @@ class PitchTrack(pg.PlotCurveItem):
|
|
2180
2342
|
self.setAcceptHoverEvents(False)
|
2181
2343
|
self.min_label = pg.TextItem(
|
2182
2344
|
str(self.settings.PITCH_MIN_F0),
|
2183
|
-
self.settings.
|
2345
|
+
self.settings.plot_theme.pitch_color,
|
2184
2346
|
anchor=(1, 1),
|
2185
2347
|
)
|
2186
2348
|
self.min_label.setFont(self.settings.font)
|
2187
2349
|
self.min_label.setParentItem(self)
|
2188
2350
|
self.max_label = pg.TextItem(
|
2189
2351
|
str(self.settings.PITCH_MAX_F0),
|
2190
|
-
self.settings.
|
2352
|
+
self.settings.plot_theme.pitch_color,
|
2191
2353
|
anchor=(1, 0),
|
2192
2354
|
)
|
2193
2355
|
self.max_label.setFont(self.settings.font)
|
2194
2356
|
self.max_label.setParentItem(self)
|
2195
2357
|
|
2358
|
+
def update_theme(self):
|
2359
|
+
pen = pg.mkPen(self.settings.plot_theme.pitch_color, width=3)
|
2360
|
+
self.setPen(pen)
|
2361
|
+
self.min_label.setColor(self.settings.plot_theme.pitch_color)
|
2362
|
+
self.max_label.setColor(self.settings.plot_theme.pitch_color)
|
2363
|
+
|
2196
2364
|
def hoverEvent(self, ev):
|
2197
2365
|
return
|
2198
2366
|
|
@@ -2215,7 +2383,11 @@ class Spectrogram(pg.ImageItem):
|
|
2215
2383
|
self.channel = 0
|
2216
2384
|
super(Spectrogram, self).__init__()
|
2217
2385
|
self.cmap = pg.ColorMap(
|
2218
|
-
None,
|
2386
|
+
None,
|
2387
|
+
[
|
2388
|
+
self.settings.plot_theme.background_color,
|
2389
|
+
self.settings.plot_theme.spectrogram_color,
|
2390
|
+
],
|
2219
2391
|
)
|
2220
2392
|
self.cmap.linearize()
|
2221
2393
|
self.color_bar = pg.ColorBarItem(colorMap=self.cmap)
|
@@ -2226,6 +2398,19 @@ class Spectrogram(pg.ImageItem):
|
|
2226
2398
|
self.cached_channel = None
|
2227
2399
|
self.stft = None
|
2228
2400
|
|
2401
|
+
def update_theme(self):
|
2402
|
+
self.cmap = pg.ColorMap(
|
2403
|
+
None,
|
2404
|
+
[
|
2405
|
+
self.settings.plot_theme.background_color,
|
2406
|
+
self.settings.plot_theme.spectrogram_color,
|
2407
|
+
],
|
2408
|
+
)
|
2409
|
+
self.cmap.linearize()
|
2410
|
+
self.color_bar.setColorMap(self.cmap)
|
2411
|
+
self.color_bar.setImageItem(self)
|
2412
|
+
self.update()
|
2413
|
+
|
2229
2414
|
def set_models(self, selection_model: CorpusSelectionModel):
|
2230
2415
|
self.selection_model = selection_model
|
2231
2416
|
|
@@ -2287,8 +2472,12 @@ class SelectionArea(pg.LinearRegionItem):
|
|
2287
2472
|
self.setVisible(False)
|
2288
2473
|
else:
|
2289
2474
|
self.setRegion([begin, end])
|
2290
|
-
self.lines[0].label.setText(
|
2291
|
-
|
2475
|
+
self.lines[0].label.setText(
|
2476
|
+
f"{begin:.3f}", self.settings.plot_theme.selected_range_color
|
2477
|
+
)
|
2478
|
+
self.lines[1].label.setText(
|
2479
|
+
f"{end:.3f}", self.settings.plot_theme.selected_range_color
|
2480
|
+
)
|
2292
2481
|
self.setVisible(True)
|
2293
2482
|
|
2294
2483
|
|
@@ -2306,17 +2495,17 @@ class AudioPlots(pg.GraphicsObject):
|
|
2306
2495
|
self.wave_form.setParentItem(self)
|
2307
2496
|
self.spectrogram.setParentItem(self)
|
2308
2497
|
self.pitch_track.setParentItem(self)
|
2309
|
-
color = self.settings.
|
2498
|
+
color = self.settings.plot_theme.selected_range_color
|
2310
2499
|
color.setAlphaF(0.25)
|
2311
2500
|
self.selection_brush = pg.mkBrush(color)
|
2312
|
-
self.background_pen = pg.mkPen(self.settings.
|
2313
|
-
self.background_brush = pg.mkBrush(self.settings.
|
2501
|
+
self.background_pen = pg.mkPen(self.settings.plot_theme.break_line_color)
|
2502
|
+
self.background_brush = pg.mkBrush(self.settings.plot_theme.background_color)
|
2314
2503
|
self.selection_area = SelectionArea(
|
2315
2504
|
top_point=self.top_point,
|
2316
2505
|
bottom_point=self.bottom_point,
|
2317
2506
|
brush=self.selection_brush,
|
2318
2507
|
clipItem=self,
|
2319
|
-
pen=pg.mkPen(self.settings.
|
2508
|
+
pen=pg.mkPen(self.settings.plot_theme.selected_interval_color),
|
2320
2509
|
)
|
2321
2510
|
self.selection_area.setParentItem(self)
|
2322
2511
|
|
@@ -2331,7 +2520,11 @@ class AudioPlots(pg.GraphicsObject):
|
|
2331
2520
|
self.update_line = pg.InfiniteLine(
|
2332
2521
|
pos=-20,
|
2333
2522
|
span=(0, 1),
|
2334
|
-
pen=pg.mkPen(
|
2523
|
+
pen=pg.mkPen(
|
2524
|
+
self.settings.plot_theme.selected_interval_color,
|
2525
|
+
width=3,
|
2526
|
+
style=QtCore.Qt.PenStyle.DashLine,
|
2527
|
+
),
|
2335
2528
|
movable=False, # We have our own code to handle dragless moving.
|
2336
2529
|
)
|
2337
2530
|
self.update_line.setParentItem(self)
|
@@ -2419,7 +2612,7 @@ class AudioPlots(pg.GraphicsObject):
|
|
2419
2612
|
self.selection_area.setVisible(True)
|
2420
2613
|
self.selection_model.select_audio(min_time, max_time)
|
2421
2614
|
else:
|
2422
|
-
self.selection_model.request_start_time(ev.pos().x())
|
2615
|
+
self.selection_model.request_start_time(ev.pos().x(), update=True)
|
2423
2616
|
ev.accept()
|
2424
2617
|
|
2425
2618
|
def hoverEvent(self, ev):
|
@@ -2502,7 +2695,9 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2502
2695
|
self.speaker_name = speaker_name
|
2503
2696
|
self.speaker_index = 0
|
2504
2697
|
self.top_point = top_point
|
2505
|
-
self.speaker_label = pg.TextItem(
|
2698
|
+
self.speaker_label = pg.TextItem(
|
2699
|
+
self.speaker_name, color=self.settings.plot_theme.break_line_color
|
2700
|
+
)
|
2506
2701
|
self.speaker_label.setFont(self.settings.font)
|
2507
2702
|
self.speaker_label.setParentItem(self)
|
2508
2703
|
self.speaker_label.setZValue(40)
|
@@ -2510,8 +2705,8 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2510
2705
|
self.annotation_range = self.top_point - self.bottom_point
|
2511
2706
|
self.extra_tiers = {}
|
2512
2707
|
self.visible_utterances: dict[str, UtteranceRegion] = {}
|
2513
|
-
self.background_brush = pg.mkBrush(self.settings.
|
2514
|
-
self.border = pg.mkPen(self.settings.
|
2708
|
+
self.background_brush = pg.mkBrush(self.settings.plot_theme.background_color)
|
2709
|
+
self.border = pg.mkPen(self.settings.plot_theme.break_line_color)
|
2515
2710
|
self.picture = QtGui.QPicture()
|
2516
2711
|
self.has_visible_utterances = False
|
2517
2712
|
self.has_selected_utterances = False
|
@@ -2526,28 +2721,14 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2526
2721
|
self.corpus_model.refreshUtteranceText.connect(self.refreshTexts)
|
2527
2722
|
self.selection_model.selectionChanged.connect(self.update_select)
|
2528
2723
|
self.selection_model.model().utterancesReady.connect(self.refresh)
|
2529
|
-
self.file_model.speakersChanged.connect(self.update_available_speakers)
|
2530
2724
|
self.available_speakers = {}
|
2531
2725
|
|
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
2726
|
def wheelEvent(self, ev):
|
2541
2727
|
self.receivedWheelEvent.emit(ev)
|
2542
2728
|
|
2543
2729
|
def create_utterance(self, begin, end):
|
2544
2730
|
self.file_model.create_utterance(self.speaker_id, begin, end)
|
2545
2731
|
|
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
2732
|
def boundingRect(self):
|
2552
2733
|
return QtCore.QRectF(self.picture.boundingRect())
|
2553
2734
|
|
@@ -2610,14 +2791,16 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2610
2791
|
visible_ids = [x.id for x in model_visible_utterances]
|
2611
2792
|
for reg in self.visible_utterances.values():
|
2612
2793
|
reg.hide()
|
2794
|
+
|
2795
|
+
item_min, item_max = reg.getRegion()
|
2613
2796
|
if (
|
2614
|
-
self.selection_model.min_time -
|
2615
|
-
or
|
2797
|
+
self.selection_model.min_time - item_max > 15
|
2798
|
+
or item_min - self.selection_model.max_time > 15
|
2616
2799
|
or (
|
2617
2800
|
reg.item.id not in visible_ids
|
2618
2801
|
and (
|
2619
|
-
|
2620
|
-
or
|
2802
|
+
item_min < self.selection_model.max_time
|
2803
|
+
or item_max > self.selection_model.min_time
|
2621
2804
|
)
|
2622
2805
|
)
|
2623
2806
|
):
|
@@ -2706,10 +2889,10 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2706
2889
|
if r == reg:
|
2707
2890
|
continue
|
2708
2891
|
other_begin, other_end = r.getRegion()
|
2709
|
-
if other_begin <= beg < other_end:
|
2892
|
+
if other_begin <= beg < other_end or beg <= other_begin < other_end < end:
|
2710
2893
|
reg.setRegion([other_end, end])
|
2711
2894
|
break
|
2712
|
-
if other_begin < end <= other_end:
|
2895
|
+
if other_begin < end <= other_end or end > other_begin > other_end > beg:
|
2713
2896
|
reg.setRegion([beg, other_begin])
|
2714
2897
|
break
|
2715
2898
|
reg.text.begin, reg.text.end = reg.getRegion()
|
@@ -2732,7 +2915,7 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2732
2915
|
if new_begin == utt.begin and new_end == utt.end:
|
2733
2916
|
return
|
2734
2917
|
self.selection_model.model().update_utterance_times(utt, begin=new_begin, end=new_end)
|
2735
|
-
self.selection_model.
|
2918
|
+
self.selection_model.request_start_time(new_begin)
|
2736
2919
|
reg.text.begin = new_begin
|
2737
2920
|
reg.text.end = new_end
|
2738
2921
|
reg.update()
|