Anchor-annotator 0.6.0__py3-none-any.whl → 0.7.1__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.6.0.dist-info → Anchor_annotator-0.7.1.dist-info}/METADATA +1 -1
- Anchor_annotator-0.7.1.dist-info/RECORD +22 -0
- {Anchor_annotator-0.6.0.dist-info → Anchor_annotator-0.7.1.dist-info}/WHEEL +1 -1
- anchor/_version.py +2 -2
- anchor/db.py +1 -0
- anchor/main.py +25 -2
- anchor/models.py +103 -58
- anchor/plot.py +384 -360
- anchor/settings.py +9 -3
- anchor/ui_main_window.py +10 -0
- anchor/undo.py +18 -18
- anchor/widgets.py +27 -13
- anchor/workers.py +2483 -2462
- Anchor_annotator-0.6.0.dist-info/RECORD +0 -22
- {Anchor_annotator-0.6.0.dist-info → Anchor_annotator-0.7.1.dist-info}/LICENSE +0 -0
- {Anchor_annotator-0.6.0.dist-info → Anchor_annotator-0.7.1.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: Anchor_annotator
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.7.1
|
4
4
|
Summary: Anchor annotator is a program for inspecting corpora for the Montreal Forced Aligner and correcting transcriptions and pronunciations.
|
5
5
|
Home-page: https://github.com/MontrealCorpusTools/Anchor-annotator
|
6
6
|
Author: Montreal Corpus Tools
|
@@ -0,0 +1,22 @@
|
|
1
|
+
anchor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
anchor/__main__.py,sha256=5ufG8lcx2x1am-04xI991AG7saJd24dxPw5JzjmB878,45
|
3
|
+
anchor/_version.py,sha256=5-skCoU2Vu44uYeNEApDjjGE2Q26ndIh5lKJuVOeL88,411
|
4
|
+
anchor/command_line.py,sha256=EucG805HyWk_zkMO9RXv9Yj0I0JVdDLZb1_DX2_ISjM,503
|
5
|
+
anchor/db.py,sha256=LlZzAy4bjmJIu0v4ev5Qjg_Fh2n9sMsKI2nAY1pwd0A,5057
|
6
|
+
anchor/main.py,sha256=Lyr3ppr-nzxaU7ZmWXc-luMsOtRBbV4ebCzk3rygur4,127781
|
7
|
+
anchor/models.py,sha256=35l7Kw3LVy-_ozdV_0ApSkKyCPViBwBmAukoq-jw90o,97668
|
8
|
+
anchor/plot.py,sha256=dXQi930DyQDFfvtezxXYeB1dzJ51_B-LIN3EG9wkjb0,113466
|
9
|
+
anchor/resources_rc.py,sha256=tzJHrJw3MpjAlnj-DtCmaR4A8gAaLF966XEXs5HNIjc,8464375
|
10
|
+
anchor/settings.py,sha256=N2gRFQEpY4pLYgcDz1Aq-2c7CfmbNxmRmVcPijrHsCo,52118
|
11
|
+
anchor/ui_corpus_manager.py,sha256=e3ybOd4UdYarrLBATxI8vIFnioa4R_BHrbsEz5mJ5eA,8564
|
12
|
+
anchor/ui_error_dialog.py,sha256=HKbjGT_jtdb9jfn9THQMbl1fmcdWyjYDazM4hCwZ5Yo,3931
|
13
|
+
anchor/ui_main_window.py,sha256=XK91lhFAIEURZ6nwxIA74X-8j-P76JuJsN-ahun65rw,37043
|
14
|
+
anchor/ui_preferences.py,sha256=g3tcjAMFKIAqUJNEke7ww4LkdeTFA1zb8_lrhF6k5fo,43271
|
15
|
+
anchor/undo.py,sha256=T8CJpSZVZbItpU7KMZU2F49mNv1wo0rvMWtNIEbieeo,32856
|
16
|
+
anchor/widgets.py,sha256=ub-E1TBLi_NjU1f9BtRwW1KLqQ98reX32CqoNVj5g2I,159302
|
17
|
+
anchor/workers.py,sha256=ciVOlK15MiDq7juAivcQB6PEiEs7DemP0BOrcpnm2to,182624
|
18
|
+
Anchor_annotator-0.7.1.dist-info/LICENSE,sha256=C0oIsblENEgWQ7XMNdYoXyXsIA5wa3YF0I9lK3H7A1s,1076
|
19
|
+
Anchor_annotator-0.7.1.dist-info/METADATA,sha256=tRdJQ8AXN8tgQ1owO7lLjc6kedsEIfGrzmSDpwYEd_0,1500
|
20
|
+
Anchor_annotator-0.7.1.dist-info/WHEEL,sha256=-oYQCr74JF3a37z2nRlQays_SX2MqOANoqVjBBAP2yE,91
|
21
|
+
Anchor_annotator-0.7.1.dist-info/top_level.txt,sha256=wX6ZKxImGRZKFQjs3f6XYw_TfbAp6Xs3SmbLfLbFAJ0,7
|
22
|
+
Anchor_annotator-0.7.1.dist-info/RECORD,,
|
anchor/_version.py
CHANGED
anchor/db.py
CHANGED
@@ -105,6 +105,7 @@ class AnchorCorpus(AnchorSqlBase):
|
|
105
105
|
custom_mapping_path = Column(PathType, nullable=True)
|
106
106
|
reference_directory = Column(PathType, nullable=True)
|
107
107
|
current = Column(Boolean, nullable=False, default=False, index=True)
|
108
|
+
# last_used = Column(DateTime, nullable=False, server_default=sqlalchemy.func.now(), index=True)
|
108
109
|
|
109
110
|
acoustic_model_id = Column(Integer, ForeignKey("acoustic_model.id"), index=True, nullable=True)
|
110
111
|
acoustic_model = relationship("AcousticModel", back_populates="corpora")
|
anchor/main.py
CHANGED
@@ -404,9 +404,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
404
404
|
elif function == "Diarizing utterances":
|
405
405
|
worker = workers.SpeakerDiarizationWorker(self.corpus_model.session, **extra_args[0])
|
406
406
|
worker.signals.result.connect(finished_function)
|
407
|
-
elif function == "
|
407
|
+
elif function == "Diarizing speakers":
|
408
|
+
worker = workers.SpeakerUtterancesWorker(self.corpus_model.session, **extra_args[0])
|
409
|
+
worker.signals.result.connect(finished_function)
|
410
|
+
elif function == "Counting utterance diarization results":
|
408
411
|
worker = workers.SpeakerDiarizationWorker(self.corpus_model.session, **extra_args[0])
|
409
412
|
worker.signals.result.connect(finished_function)
|
413
|
+
elif function == "Counting speaker diarization results":
|
414
|
+
worker = workers.SpeakerUtterancesWorker(self.corpus_model.session, **extra_args[0])
|
415
|
+
worker.signals.result.connect(finished_function)
|
410
416
|
elif function == "Merging speakers":
|
411
417
|
self.set_application_state("loading")
|
412
418
|
worker = workers.MergeSpeakersWorker(self.corpus_model.session, **extra_args[0])
|
@@ -718,7 +724,6 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
718
724
|
def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
|
719
725
|
for worker in self.workers:
|
720
726
|
worker.stopped.set()
|
721
|
-
self.file_selection_model.clean_up_for_close()
|
722
727
|
self.file_utterances_model.clean_up_for_close()
|
723
728
|
self.settings.setValue(
|
724
729
|
AnchorSettings.UTTERANCES_VISIBLE, self.ui.utteranceDockWidget.isVisible()
|
@@ -763,6 +768,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
763
768
|
return
|
764
769
|
if self.thread_pool.activeThreadCount() > 0:
|
765
770
|
return
|
771
|
+
if self.file_selection_model.thread_pool.activeThreadCount() > 0:
|
772
|
+
return
|
766
773
|
if self.corpus_model.session is not None:
|
767
774
|
self.corpus_model.session = None
|
768
775
|
self.corpus_model.corpus.cleanup_connections()
|
@@ -849,8 +856,10 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
849
856
|
self.ui.transcriptionWidget.button.setDefaultAction(self.ui.transcribeCorpusAct)
|
850
857
|
self.ui.utteranceListWidget.oov_button.setDefaultAction(self.ui.oovsOnlyAct)
|
851
858
|
self.ui.alignmentWidget.button.setDefaultAction(self.ui.alignCorpusAct)
|
859
|
+
self.ui.alignmentWidget.verify_button.setDefaultAction(self.ui.verifyTranscriptsAct)
|
852
860
|
|
853
861
|
self.ui.alignCorpusAct.triggered.connect(self.begin_alignment)
|
862
|
+
self.ui.verifyTranscriptsAct.triggered.connect(self.begin_verify_transcripts)
|
854
863
|
self.ui.diarizationWidget.refresh_ivectors_action.triggered.connect(
|
855
864
|
self.begin_refresh_ivectors
|
856
865
|
)
|
@@ -1322,6 +1331,9 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1322
1331
|
self.corpus_model.has_reference_alignments = True
|
1323
1332
|
elif w.workflow_type is WorkflowType.transcription:
|
1324
1333
|
self.corpus_model.has_transcribed_alignments = True
|
1334
|
+
elif w.workflow_type is WorkflowType.transcript_verification:
|
1335
|
+
self.corpus_model.has_transcribed_alignments = True
|
1336
|
+
self.corpus_model.has_transcript_verification_alignments = True
|
1325
1337
|
elif w.workflow_type is WorkflowType.per_speaker_transcription:
|
1326
1338
|
self.corpus_model.has_per_speaker_transcribed_alignments = True
|
1327
1339
|
|
@@ -1405,6 +1417,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1405
1417
|
self.set_application_state("loading")
|
1406
1418
|
self.ui.loadingScreen.setCorpusName("Performing alignment...")
|
1407
1419
|
|
1420
|
+
def begin_verify_transcripts(self):
|
1421
|
+
self.enableMfaActions(False)
|
1422
|
+
self.alignment_worker.set_params(
|
1423
|
+
self.corpus_model.corpus, self.acoustic_model, self.ui.alignmentWidget.parameters()
|
1424
|
+
)
|
1425
|
+
self.alignment_worker.start()
|
1426
|
+
self.set_application_state("loading")
|
1427
|
+
self.ui.loadingScreen.setCorpusName("Verifying transcriptions...")
|
1428
|
+
|
1408
1429
|
def begin_refresh_ivectors(self):
|
1409
1430
|
self.enableMfaActions(False)
|
1410
1431
|
self.compute_ivectors_worker.set_params(self.corpus_model, reset=False)
|
@@ -1558,6 +1579,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1558
1579
|
)
|
1559
1580
|
self.corpus_model.update_data()
|
1560
1581
|
self.check_actions()
|
1582
|
+
self.corpus_model.update_latest_alignment_workflow()
|
1561
1583
|
self.set_application_state("loaded")
|
1562
1584
|
|
1563
1585
|
def finalize_utterance_alignment(self, utterance_id: int):
|
@@ -2530,6 +2552,7 @@ class OptionsDialog(QtWidgets.QDialog):
|
|
2530
2552
|
self.ui.tabWidget.setCurrentIndex(0)
|
2531
2553
|
# self.setFont(self.settings.font)
|
2532
2554
|
# self.setStyleSheet(self.settings.style_sheet)
|
2555
|
+
self.update_preset_theme()
|
2533
2556
|
|
2534
2557
|
def set_theme(self, theme):
|
2535
2558
|
self.ui.primaryBaseEdit.set_color(theme[self.settings.PRIMARY_BASE_COLOR])
|
anchor/models.py
CHANGED
@@ -22,8 +22,8 @@ from montreal_forced_aligner.corpus.acoustic_corpus import (
|
|
22
22
|
AcousticCorpus,
|
23
23
|
AcousticCorpusWithPronunciations,
|
24
24
|
)
|
25
|
-
from montreal_forced_aligner.data import PhoneType, WordType
|
26
|
-
from montreal_forced_aligner.db import File, Phone, Speaker, Utterance
|
25
|
+
from montreal_forced_aligner.data import PhoneType, WordType, WorkflowType
|
26
|
+
from montreal_forced_aligner.db import CorpusWorkflow, File, Phone, Speaker, Utterance, Word
|
27
27
|
from montreal_forced_aligner.dictionary.mixins import (
|
28
28
|
DEFAULT_CLITIC_MARKERS,
|
29
29
|
DEFAULT_COMPOUND_MARKERS,
|
@@ -97,14 +97,13 @@ class TextFilterQuery:
|
|
97
97
|
if not text.endswith(word_break_set):
|
98
98
|
text += word_break_set
|
99
99
|
if posix:
|
100
|
-
text = text.replace(r"\b",
|
100
|
+
text = text.replace(r"\b", r"\y")
|
101
101
|
if text.startswith(r"\b"):
|
102
102
|
text = rf"((?<={WORD_BREAK_REGEX_SET})|(?<=^))" + text[2:]
|
103
103
|
if text.endswith(r"\b"):
|
104
104
|
text = text[:-2] + rf"((?={WORD_BREAK_REGEX_SET})|(?=$))"
|
105
|
-
if
|
106
|
-
|
107
|
-
text = "(?i)" + text
|
105
|
+
if not self.case_sensitive:
|
106
|
+
text = "(?i)" + text
|
108
107
|
return text
|
109
108
|
|
110
109
|
|
@@ -202,10 +201,10 @@ class FileUtterancesModel(QtCore.QAbstractListModel):
|
|
202
201
|
self.reversed_indices = {}
|
203
202
|
self.speaker_channel_mapping = {}
|
204
203
|
self.corpus_model: CorpusModel = None
|
205
|
-
self.
|
206
|
-
|
207
|
-
self.
|
208
|
-
self.
|
204
|
+
self.closing = False
|
205
|
+
|
206
|
+
self.thread_pool = QtCore.QThreadPool()
|
207
|
+
self.thread_pool.setMaxThreadCount(4)
|
209
208
|
|
210
209
|
def get_utterance(self, utterance_id: int) -> Utterance:
|
211
210
|
try:
|
@@ -217,8 +216,7 @@ class FileUtterancesModel(QtCore.QAbstractListModel):
|
|
217
216
|
self.corpus_model = corpus_model
|
218
217
|
|
219
218
|
def clean_up_for_close(self):
|
220
|
-
self.
|
221
|
-
self.speaker_tier_worker.stop()
|
219
|
+
self.closing = True
|
222
220
|
|
223
221
|
def set_file(self, file_id):
|
224
222
|
self.file = (
|
@@ -226,11 +224,13 @@ class FileUtterancesModel(QtCore.QAbstractListModel):
|
|
226
224
|
)
|
227
225
|
self.y = None
|
228
226
|
self.get_utterances()
|
229
|
-
self.
|
230
|
-
|
231
|
-
self.
|
227
|
+
waveform_worker = workers.WaveformWorker(self.file.sound_file.sound_file_path)
|
228
|
+
waveform_worker.signals.result.connect(self.finalize_loading_wave_form)
|
229
|
+
self.thread_pool.start(waveform_worker)
|
232
230
|
|
233
231
|
def finalize_loading_utterances(self, results):
|
232
|
+
if self.closing:
|
233
|
+
return
|
234
234
|
utterances, file_id = results
|
235
235
|
if file_id != self.file.id:
|
236
236
|
return
|
@@ -246,6 +246,8 @@ class FileUtterancesModel(QtCore.QAbstractListModel):
|
|
246
246
|
self.utterancesReady.emit()
|
247
247
|
|
248
248
|
def finalize_loading_wave_form(self, results):
|
249
|
+
if self.closing:
|
250
|
+
return
|
249
251
|
y, file_path = results
|
250
252
|
if self.file is None or file_path != self.file.sound_file.sound_file_path:
|
251
253
|
return
|
@@ -264,15 +266,17 @@ class FileUtterancesModel(QtCore.QAbstractListModel):
|
|
264
266
|
self.endRemoveRows()
|
265
267
|
if self.file is None:
|
266
268
|
return
|
267
|
-
|
268
|
-
|
269
|
-
self.
|
270
|
-
|
271
|
-
|
269
|
+
speaker_tier_worker = workers.SpeakerTierWorker(
|
270
|
+
self.corpus_model.session,
|
271
|
+
self.file.id,
|
272
|
+
query_alignment=(
|
273
|
+
self.corpus_model.has_alignments
|
274
|
+
or self.corpus_model.has_reference_alignments
|
275
|
+
or self.corpus_model.has_transcribed_alignments
|
276
|
+
),
|
272
277
|
)
|
273
|
-
|
274
|
-
self.
|
275
|
-
self.speaker_tier_worker.start()
|
278
|
+
speaker_tier_worker.signals.result.connect(self.finalize_loading_utterances)
|
279
|
+
self.thread_pool.start(speaker_tier_worker)
|
276
280
|
|
277
281
|
def create_utterance(self, speaker_id: Optional[int], begin: float, end: float):
|
278
282
|
if not self.corpus_model.editable:
|
@@ -602,18 +606,17 @@ class FileSelectionModel(QtCore.QItemSelectionModel):
|
|
602
606
|
self.waveform_x = None
|
603
607
|
self.waveform_y = None
|
604
608
|
self.requested_utterance_id = None
|
605
|
-
self.
|
606
|
-
|
607
|
-
self.
|
608
|
-
self.
|
609
|
-
self.spectrogram_worker.signals.result.connect(self.finalize_loading_spectrogram)
|
610
|
-
self.pitch_track_worker.signals.result.connect(self.finalize_loading_pitch_track)
|
609
|
+
self.closing = False
|
610
|
+
|
611
|
+
self.thread_pool = QtCore.QThreadPool()
|
612
|
+
self.thread_pool.setMaxThreadCount(self.settings.value(self.settings.PLOT_THREAD_COUNT))
|
611
613
|
self.model().waveformReady.connect(self.load_audio_selection)
|
612
614
|
self.model().utterancesReady.connect(self.finalize_set_new_file)
|
613
615
|
self.viewChanged.connect(self.load_audio_selection)
|
614
616
|
self.model().selectionRequested.connect(self.update_selected_utterances)
|
615
617
|
self.view_change_timer = QtCore.QTimer()
|
616
|
-
self.view_change_timer.
|
618
|
+
self.view_change_timer.setSingleShot(True)
|
619
|
+
self.view_change_timer.setInterval(10)
|
617
620
|
self.view_change_timer.timeout.connect(self.send_selection_update)
|
618
621
|
|
619
622
|
def selected_utterances(self):
|
@@ -633,18 +636,17 @@ class FileSelectionModel(QtCore.QItemSelectionModel):
|
|
633
636
|
y = self.model().y[begin_samp:end_samp, self.selected_channel]
|
634
637
|
else:
|
635
638
|
y = self.model().y[begin_samp:end_samp]
|
636
|
-
|
637
|
-
self.spectrogram_worker.set_params(
|
639
|
+
spectrogram_worker = workers.SpectrogramWorker(
|
638
640
|
y,
|
639
641
|
self.model().file.sound_file.sample_rate,
|
640
642
|
self.min_time,
|
641
643
|
self.max_time,
|
642
644
|
self.selected_channel,
|
643
645
|
)
|
644
|
-
|
646
|
+
spectrogram_worker.signals.result.connect(self.finalize_loading_spectrogram)
|
647
|
+
self.thread_pool.start(spectrogram_worker)
|
645
648
|
|
646
|
-
|
647
|
-
self.pitch_track_worker.set_params(
|
649
|
+
pitch_track_worker = workers.PitchWorker(
|
648
650
|
y,
|
649
651
|
self.model().file.sound_file.sample_rate,
|
650
652
|
self.min_time,
|
@@ -653,10 +655,10 @@ class FileSelectionModel(QtCore.QItemSelectionModel):
|
|
653
655
|
self.bottom_point,
|
654
656
|
self.separator_point,
|
655
657
|
)
|
656
|
-
|
658
|
+
pitch_track_worker.signals.result.connect(self.finalize_loading_pitch_track)
|
659
|
+
self.thread_pool.start(pitch_track_worker)
|
657
660
|
|
658
|
-
|
659
|
-
self.auto_waveform_worker.set_params(
|
661
|
+
auto_waveform_worker = workers.AutoWaveformWorker(
|
660
662
|
y,
|
661
663
|
self.separator_point,
|
662
664
|
self.top_point,
|
@@ -664,12 +666,11 @@ class FileSelectionModel(QtCore.QItemSelectionModel):
|
|
664
666
|
self.max_time,
|
665
667
|
self.selected_channel,
|
666
668
|
)
|
667
|
-
|
669
|
+
auto_waveform_worker.signals.result.connect(self.finalize_loading_auto_wave_form)
|
670
|
+
self.thread_pool.start(auto_waveform_worker)
|
668
671
|
|
669
672
|
def clean_up_for_close(self):
|
670
|
-
self.
|
671
|
-
self.pitch_track_worker.stop()
|
672
|
-
self.auto_waveform_worker.stop()
|
673
|
+
self.closing = True
|
673
674
|
|
674
675
|
@property
|
675
676
|
def plot_min(self):
|
@@ -684,6 +685,8 @@ class FileSelectionModel(QtCore.QItemSelectionModel):
|
|
684
685
|
return self.max_time
|
685
686
|
|
686
687
|
def finalize_loading_spectrogram(self, results):
|
688
|
+
if self.closing:
|
689
|
+
return
|
687
690
|
if results is None:
|
688
691
|
self.spectrogram = None
|
689
692
|
self.min_db = None
|
@@ -691,28 +694,28 @@ class FileSelectionModel(QtCore.QItemSelectionModel):
|
|
691
694
|
self.spectrogramReady.emit()
|
692
695
|
return
|
693
696
|
stft, channel, begin, end, min_db, max_db = results
|
697
|
+
if begin != self.min_time or end != self.max_time:
|
698
|
+
return
|
694
699
|
if self.settings.right_to_left:
|
695
700
|
stft = np.flip(stft, 1)
|
696
|
-
begin, end = -end, -begin
|
697
|
-
if begin != self.plot_min or end != self.plot_max:
|
698
|
-
return
|
699
701
|
self.spectrogram = stft
|
700
702
|
self.min_db = self.min_db
|
701
703
|
self.max_db = self.max_db
|
702
704
|
self.spectrogramReady.emit()
|
703
705
|
|
704
706
|
def finalize_loading_pitch_track(self, results):
|
707
|
+
if self.closing:
|
708
|
+
return
|
705
709
|
if results is None:
|
706
710
|
self.pitch_track_y = None
|
707
711
|
self.pitch_track_x = None
|
708
712
|
self.pitchTrackReady.emit()
|
709
713
|
return
|
710
714
|
pitch_track, voicing_track, channel, begin, end, min_f0, max_f0 = results
|
715
|
+
if begin != self.min_time or end != self.max_time:
|
716
|
+
return
|
711
717
|
if self.settings.right_to_left:
|
712
718
|
pitch_track = np.flip(pitch_track, 0)
|
713
|
-
begin, end = -end, -begin
|
714
|
-
if begin != self.plot_min or end != self.plot_max:
|
715
|
-
return
|
716
719
|
self.pitch_track_y = pitch_track
|
717
720
|
if pitch_track is None:
|
718
721
|
return
|
@@ -725,23 +728,24 @@ class FileSelectionModel(QtCore.QItemSelectionModel):
|
|
725
728
|
self.pitchTrackReady.emit()
|
726
729
|
|
727
730
|
def finalize_loading_auto_wave_form(self, results):
|
731
|
+
if self.closing:
|
732
|
+
return
|
728
733
|
y, begin, end, channel = results
|
734
|
+
if begin != self.min_time or end != self.max_time:
|
735
|
+
return
|
729
736
|
if self.settings.right_to_left:
|
730
737
|
y = np.flip(y, 0)
|
731
|
-
begin, end = -end, -begin
|
732
|
-
if begin != self.plot_min or end != self.plot_max:
|
733
|
-
return
|
734
738
|
x = np.linspace(start=self.plot_min, stop=self.plot_max, num=y.shape[0])
|
735
739
|
self.waveform_x = x
|
736
740
|
self.waveform_y = y
|
737
741
|
self.waveformReady.emit()
|
738
742
|
|
739
743
|
def select_audio(self, begin, end):
|
740
|
-
if end is not None and end - begin < 0.
|
744
|
+
if end is not None and end - begin < 0.025:
|
741
745
|
end = None
|
742
746
|
self.selected_min_time = begin
|
743
747
|
self.selected_max_time = end
|
744
|
-
if self.selected_min_time != self.min_time:
|
748
|
+
if self.selected_min_time != self.min_time or end is not None:
|
745
749
|
self.selectionAudioChanged.emit(False)
|
746
750
|
|
747
751
|
def request_start_time(self, start_time, update=False):
|
@@ -881,7 +885,6 @@ class FileSelectionModel(QtCore.QItemSelectionModel):
|
|
881
885
|
self.view_change_timer.start()
|
882
886
|
|
883
887
|
def send_selection_update(self):
|
884
|
-
self.view_change_timer.stop()
|
885
888
|
self.viewChanged.emit(self.min_time, self.max_time)
|
886
889
|
|
887
890
|
def set_current_file(self, file_id, begin, end, utterance_id, speaker_id, force_update=False):
|
@@ -1916,14 +1919,30 @@ class DiarizationModel(TableModel):
|
|
1916
1919
|
self.runFunction.emit("Reassigning utterances for speaker", self.update_data, [kwargs])
|
1917
1920
|
|
1918
1921
|
def update_result_count(self):
|
1919
|
-
self.
|
1920
|
-
|
1921
|
-
|
1922
|
+
if self.in_speakers:
|
1923
|
+
self.runFunction.emit(
|
1924
|
+
"Counting speaker diarization results",
|
1925
|
+
self.finalize_result_count,
|
1926
|
+
[self.count_kwargs],
|
1927
|
+
)
|
1928
|
+
else:
|
1929
|
+
self.runFunction.emit(
|
1930
|
+
"Counting utterance diarization results",
|
1931
|
+
self.finalize_result_count,
|
1932
|
+
[self.count_kwargs],
|
1933
|
+
)
|
1922
1934
|
|
1923
1935
|
def update_data(self):
|
1924
1936
|
if not self.corpus_model.corpus.has_any_ivectors():
|
1925
1937
|
return
|
1926
|
-
|
1938
|
+
if self.in_speakers:
|
1939
|
+
self.runFunction.emit(
|
1940
|
+
"Diarizing speakers", self.finish_update_data, [self.query_kwargs]
|
1941
|
+
)
|
1942
|
+
else:
|
1943
|
+
self.runFunction.emit(
|
1944
|
+
"Diarizing utterances", self.finish_update_data, [self.query_kwargs]
|
1945
|
+
)
|
1927
1946
|
|
1928
1947
|
|
1929
1948
|
class CorpusModel(TableModel):
|
@@ -2040,6 +2059,31 @@ class CorpusModel(TableModel):
|
|
2040
2059
|
self.has_reference_alignments = False
|
2041
2060
|
self.has_transcribed_alignments = False
|
2042
2061
|
self.has_per_speaker_transcribed_alignments = False
|
2062
|
+
self.has_transcript_verification_alignments = False
|
2063
|
+
self.latest_alignment_workflow = None
|
2064
|
+
|
2065
|
+
def update_latest_alignment_workflow(self):
|
2066
|
+
with self.corpus.session() as session:
|
2067
|
+
query = (
|
2068
|
+
session.query(CorpusWorkflow.id)
|
2069
|
+
.filter(CorpusWorkflow.workflow_type.in_(WorkflowType.alignment_workflows()))
|
2070
|
+
.order_by(sqlalchemy.desc(CorpusWorkflow.time_stamp))
|
2071
|
+
.limit(1)
|
2072
|
+
).first()
|
2073
|
+
if query is not None:
|
2074
|
+
query = query[0]
|
2075
|
+
self.latest_alignment_workflow = query
|
2076
|
+
|
2077
|
+
def get_interjection_count(self):
|
2078
|
+
if self.corpus is None:
|
2079
|
+
return 0
|
2080
|
+
with self.corpus.session() as session:
|
2081
|
+
count = (
|
2082
|
+
session.query(sqlalchemy.func.count(Word.id))
|
2083
|
+
.filter(Word.word_type == WordType.interjection)
|
2084
|
+
.first()[0]
|
2085
|
+
)
|
2086
|
+
return count
|
2043
2087
|
|
2044
2088
|
def get_speaker_name(self, speaker_id: int):
|
2045
2089
|
if speaker_id not in self.speaker_id_mapping:
|
@@ -2326,6 +2370,7 @@ class CorpusModel(TableModel):
|
|
2326
2370
|
self.refresh_files()
|
2327
2371
|
self.refresh_speakers()
|
2328
2372
|
self.refresh_utterances()
|
2373
|
+
self.update_latest_alignment_workflow()
|
2329
2374
|
|
2330
2375
|
def search(
|
2331
2376
|
self,
|